Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

v97i009: PC2 [1.1] - Bars and Pipes Tool for Program Changes, Part 01/01

2 views
Skip to first unread message

Richard Hagen

unread,
Nov 18, 1997, 3:00:00 AM11/18/97
to

Submitted-by: Richard Hagen <R.H...@mailbox.uq.edu.au>
Posting-number: Volume 97, Issue 09
Archive-name: music/PC2-1.1/part01
URL: http://www.it.uq.edu.au/~richard/music/bars-and-pipes/index.html#programs

[ Executable (pc2.ptool) included. ...zim ]

Program Change 2: A Bars and Pipes Tool for program changes that require
two program change messages

#!/bin/sh
# This is music/PC2-1.1, a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 11/18/1997 17:31 UTC by z...@ibx.com
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 1235 -rw------- dmakefile
# 2170 -rw------- myheader.h
# 16825 -rw------- pc2.c
# 4588 -rw------- pc2.ptool
# 2169 -rw------- pc2.readme
#
if test -r _shar_seq_.tmp; then
echo 'Must unpack archives in sequence!'
echo Please unpack part `cat _shar_seq_.tmp` next
exit 1
fi
# ============= dmakefile ==============
if test -f 'dmakefile' -a X"$1" != X"-c"; then
echo 'x - skipping dmakefile (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting dmakefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'dmakefile' &&
#
# The name of the tool.
#
TOOL = pc2
X
#
# The source files that you need to build the tool.
#
MYSRCS = pc2.c
X
MYHDRS = myheader.h
X
#
# You might want to tinker with the compiler flags and libraries.
#
# -3.0 - Compile for a 3.0 system (optional)
# -mc - Small code model
# -md - Small data model
#
CFLAGS = -3.0 -mc -md
X
#
# Required libraries
#
# amiga30s.lib - The small code version of the Amiga library
# cs.lib - The small code version of the C library
#
LIBS = amiga30s.lib cs.lib
X
#
# You shouldn't have to touch anything below here.
#
# (FYI: (It's important that toolstart.c gets listed first... toolstart.o
# has to be the first thing mentioned when the tool is linked
# together.)
#
PTOOL = $(TOOL).ptool
README = $(TOOL).readme
ARCHIVE = $(TOOL).lha
X
SRCS = toolstart.c $(MYSRCS)
OBJS = $(SRCS:*.c:*.o)
X
all: $(PTOOL)
X
$(PTOOL): $(OBJS)
X dlink $(OBJS) $(LIBS) -o $(PTOOL)
X
$(OBJS): $(SRCS)
X dcc $(CFLAGS) -c %(right) -o %(left)
X
# I use emacs, so I tend to have a lot of backup files ending in ``!''
# lying around.
clean:
X delete $(OBJS) *!
X
clobber: clean
X delete $(PTOOL) $(ARCHIVE)
X
distribution: $(ARCHIVE)
X
$(ARCHIVE): clobber $(PTOOL) clean
X lha a $(ARCHIVE) dmakefile $(PTOOL) $(MYHDRS) $(MYSRCS) $(README)
X
X
X
SHAR_EOF
chmod 0600 dmakefile ||
echo 'restore of dmakefile failed'
Wc_c="`wc -c < 'dmakefile'`"
test 1235 -eq "$Wc_c" ||
echo 'dmakefile: original size 1235, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= myheader.h ==============
if test -f 'myheader.h' -a X"$1" != X"-c"; then
echo 'x - skipping myheader.h (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting myheader.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'myheader.h' &&
/*
X myheader.h - Useful #defines and typedefs for tool/accessory programs.
*/
X
#ifndef MYHEADER_H
#define MYHEADER_H
X
/* Length of tool/accessory id. */
#define ID_LEN 4
X
/* Make an id out of four characters. */
#define MAKE_ID(a, b, c, d) ((ULONG) ((((a << 8) + b << 8) + c << 8) + d))
X
/* Make an id out of a string. */
#define MAKE_IDS(s) (MAKE_ID(s[0], s[1], s[2], s[3]))
X
/* Split an id into four characters. */
#define SPLIT_ID(id, a, b, c, d) \
do { \
X a = (UBYTE) ((id >> 24) & 0xff); \
X b = (UBYTE) ((id >> 16) & 0xff); \
X c = (UBYTE) ((id >> 8) & 0xff); \
X d = (UBYTE) (id & 0xff); \
} while (0)
X
/* Split an id into a string. */
#define SPLIT_IDS(id, s) \
do { \
X SPLIT_ID(id, s[0], s[1], s[2], s[3]); \
} while (0)
X
/* Maximum MIDI note # */
#define MIDI_NOTE_MAX (127)
X
/* Number of MIDI notes. */
#define MIDI_NOTE_NUM (MIDI_NOTE_MAX + 1)
X
/* Maximum program change number. */
#define PC_CHANGE_MAX 127
X
/* Number of program changes. */
#define PC_CHANGE_NUM (PC_CHANGE_MAX + 1)
X
/* Flags for use in the BRB file requester. */
#define FILES_DELETE 1 /* Delete button */
#define FILES_OPEN 2 /* Open button */
#define FILES_SAVE 4 /* Save button */
#define FILES_TEST 8 /* ??? */
#define FILES_TYPE 16 /* Type string gadget */
#define FILES_PATH 32 /* Path string gadget */
X
/* Initial placement of tool/accessory windows. */
#define INITIAL_LEFT 50
#define INITIAL_TOP 50
X
/* Unprototyping cast. */
typedef __geta4 long (*no_prototype)();
X
/* Void cast. */
typedef __geta4 void (*void_prototype)();
X
/* Event *cast. */
typedef __geta4 struct Event *(*event_prototype)();
X
/* For non-stdio debugging messages. */
#define DEBUG(message) \
do { \
X struct EasyStruct es = { \
X sizeof(struct EasyStruct), \
X 0, \
X "Debugging information", \
X "Message: %s", \
X "OK" \
X }; \
X (void) EasyRequest(functions->window, &es, 0, message); \
} while (0)
X
#define NOTE_LENGTH(x) (768 >> (x))
X
#define MBC_STRING_LENGTH 12
X
#define CLOCKSPERMEASURE 768L
X
#define STREQ(x, y) (strcmp((x), (y)) == 0)
#define STREQN(x, y, n) (strncmp((x), (y), (n)) == 0)
X
#endif /* MYHEADER_H */
SHAR_EOF
chmod 0600 myheader.h ||
echo 'restore of myheader.h failed'
Wc_c="`wc -c < 'myheader.h'`"
test 2170 -eq "$Wc_c" ||
echo 'myheader.h: original size 2170, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= pc2.c ==============
if test -f 'pc2.c' -a X"$1" != X"-c"; then
echo 'x - skipping pc2.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting pc2.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'pc2.c' &&
/*
X Program Change 2: A Bars and Pipes tool for generating program changes that
X require two program change messages to be sent.
X
X Copyright (C) 1997 Richard Hagen
X
X This code is released into the Public Domain, and may be freely
X distributed in its original form.
X
X It is supplied ``as is'', and comes with no warranty.
X This program code was released because it might be useful as a
X starting point for other programmers. However, if any damage arises
X from its use, the original author will not be held liable.
X
X You are free to use and modify this code to your heart's content,
X provided you acknowledge me as the original author in any code
X that you might distribute which is based largely on this code.
X
X I acknowledge that the design of this accessory is influenced
X strongly by the example code supplied with the Rules for Tools
X package. However, I have made substantial contributions of my
X own.
X
X Richard Hagen
X ric...@it.uq.edu.au
X
X History:
X 1.2 (29 September 1997)
X Bug fix.
X
X 1.1 (22 September 1997)
X Output of note on patch change. Added Test button.
X
X 1.0 (22 September 1997)
X Initial Release
*/
X
#include <libraries/dos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <exec/memory.h>
#include <string.h>
#include <intuition/intuition.h>
X
#include "bars.h"
#include "myheader.h"
X
#define PC2_NAME "Program Change 2 1.1"
X
#define PC2_ID MAKE_IDS("PCPC")
#define PC2_TYPE (TOOL_NORMAL | TOOL_NOTPAD)
X
__chip static UWORD pc2[] = {
X /*------ plane # 0: --------*/
X 0x0, 0x0,
X 0x3fff, 0xfc00,
X 0x2000, 0x0400,
X 0x2000, 0x0400,
X 0x2000, 0x0400,
X 0x2000, 0x0400,
X 0x2000, 0x0400,
X 0x2000, 0x0400,
X 0x2000, 0x0400,
X 0x2000, 0x0400,
X 0x3fff, 0xfc00,
X 0x0, 0x0,
X
X /*------ plane # 1: --------*/
X 0x0, 0x0,
X 0x0, 0x0,
X 0x1fff, 0xf800,
X 0x1838, 0x7800,
X 0xd993, 0x3b00,
X 0xd993, 0xfb00,
X 0xd833, 0xfb00,
X 0xd9f3, 0x3b00,
X 0x19f8, 0x7800,
X 0x1fff, 0xf800,
X 0x1fff, 0xf800,
X 0x0, 0x0,
X
X /*------ plane # 2: --------*/
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x1000,
X 0x07c7, 0xa800,
X 0x066c, 0xc800,
X 0x066c, 0x1800,
X 0x07cc, 0x3800,
X 0x060c, 0xc000,
X 0x0607, 0x8000,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0
};
X
static struct Image pc2_image = {
X 0,0,
X 24 , 12 , 3 ,
X &pc2[0],
X 0x1f,0x00,
X NULL
};
X
struct PC2Tool {
X struct Tool tool;
X
X UBYTE bank;
X UBYTE program;
X UBYTE delay;
};
X
static struct ToolMaster master;
X
extern struct Functions *functions;
X
static void
pc2_tool_init(struct PC2Tool *tool)
{
X tool->tool.touched = TOUCH_INIT;
X
X tool->bank = 0;
X tool->program = 0;
X tool->delay = 1;
}
X
static void
send_pc(struct PC2Tool *tool,
X const long time)
{
X struct Event *bank_event = (struct Event *)(*functions->allocevent)();
X if (bank_event)
X {
X struct Event *program_event = (struct Event *)(*functions->allocevent)();
X if (program_event)
X {
X bank_event->type = program_event->type = EVENT_VOICE;
X bank_event->status = program_event->status = MIDI_PCHANGE;
X bank_event->byte1 = tool->bank;
X program_event->byte1 = tool->program;
X bank_event->time = time;
X program_event->time = time + tool->delay;
X bank_event->tool = program_event->tool = tool->tool.next;
X bank_event->next = program_event->next = NULL;
X (*functions->qevent)(bank_event);
X (*functions->qevent)(program_event);
X }
X else
X {
X (*functions->freeevent)(bank_event);
X }
X }
}
X
/* Called whenever something happens in the transport. */
__geta4 /* Callback. */
void transportcode(long command, /* Transport command. */
X long time, /* Start time for command. */
X long end) /* End time for command. */
{
X switch (command)
X {
X case TC_START:
X case TC_PLAY:
X /* Find all the PC2Tools and get them to do their thing. */
X for (struct Track *track = functions->tracklist;
X track;
X track = track->next)
X {
X for (struct Tool *tool = track->toollist;
X tool;
X tool = tool->next)
X {
X if (tool && (tool->toolid == PC2_ID))
X {
X struct PC2Tool *pc2_tool = (struct PC2Tool *) tool;
X
X if (!pc2_tool->tool.touched)
X {
X pc2_tool_init(pc2_tool);
X }
X
X send_pc(pc2_tool, time);
X }
X }
X }
X break;
X default:
X break;
X }
}
X
__geta4
static struct Event *
processeventcode(struct Event *event)
{
X event->tool = event->tool->next;
X return(event);
}
X
#define BANK_GADGET 1
#define BANKDOWN_GADGET 2
#define BANKUP_GADGET 3
X
#define PROGRAM_GADGET 4
#define PROGRAMDOWN_GADGET 5
#define PROGRAMUP_GADGET 6
X
#define DELAY_GADGET 7
#define DELAYDOWN_GADGET 8
#define DELAYUP_GADGET 9
X
#define WRITE_GADGET 10
X
#define TEST_GADGET 11
X
/* Bank gadget. */
struct PropInfo PC2PC2Gadget1SInfo = {
X AUTOKNOB+FREEHORIZ,
X -16384, -1,
X 16384, -1,
};
X
struct Image PC2Image1 = {
X 0,0,
X 102,6,
X 0,
X NULL,
X 0x0000,0x0000,
X NULL
};
X
struct IntuiText PC2IText1 = {
X 2,0,JAM1,
X -72,1,
X NULL,
X "Bank:",
X NULL
};
X
struct Gadget PC2Gadget1 = {
X NULL,
X 79,14,
X 100,10,
X GFLG_GADGHBOX|GFLG_GADGHIMAGE,
X RELVERIFY|GADGIMMEDIATE,
X PROPGADGET,
X (APTR)&PC2Image1,
X NULL,
X &PC2IText1,
X NULL,
X (APTR)&PC2PC2Gadget1SInfo,
X BANK_GADGET,
X NULL
};
X
/* Program gadget. */
struct PropInfo PC2PC2Gadget2SInfo = {
X AUTOKNOB+FREEHORIZ,
X -16384, -1,
X 16384, -1,
};
X
struct Image PC2Image2 = {
X 0,0,
X 102,6,
X 0,
X NULL,
X 0x0000,0x0000,
X NULL
};
X
struct IntuiText PC2IText2 = {
X 2,0,JAM1,
X -72, 1,
X NULL,
X "Program:",
X NULL
};
X
struct Gadget PC2Gadget2 = {
X &PC2Gadget1,
X 79,26,
X 100,10,
X GFLG_GADGHBOX|GFLG_GADGHIMAGE,
X RELVERIFY|GADGIMMEDIATE,
X PROPGADGET,
X (APTR)&PC2Image2,
X NULL,
X &PC2IText2,
X NULL,
X (APTR)&PC2PC2Gadget2SInfo,
X PROGRAM_GADGET,
X NULL
};
X
/* Delay gadget. */
struct PropInfo PC2PC2Gadget3SInfo = {
X AUTOKNOB+FREEHORIZ,
X -16384, -1,
X 16384, -1,
};
X
struct Image PC2Image3 = {
X 0,0,
X 102,6,
X 0,
X NULL,
X 0x0000,0x0000,
X NULL
};
X
struct IntuiText PC2IText3 = {
X 2,0,JAM1,
X -72, 1,
X NULL,
X "Delay:",
X NULL
};
X
struct Gadget PC2Gadget3 = {
X &PC2Gadget2,
X 79,38,
X 100,10,
X GFLG_GADGHBOX|GFLG_GADGHIMAGE,
X RELVERIFY|GADGIMMEDIATE,
X PROPGADGET,
X (APTR)&PC2Image3,
X NULL,
X &PC2IText3,
X NULL,
X (APTR)&PC2PC2Gadget3SInfo,
X DELAY_GADGET,
X NULL
};
X
/* Write to track gadget. */
SHORT PC2BorderVectors4[] = {
X 0,0,
X 118,0,
X 118,12,
X 0,12,
X 0,0
};
X
struct Border PC2Border4 = {
X -1,-1,
X 3,0,JAM1,
X 5,
X PC2BorderVectors4,
X NULL
};
X
struct IntuiText PC2IText4 = {
X 4,0,JAM1,
X 4,1,
X NULL,
X "Write to Track",
X NULL
X };
X
struct Gadget PC2Gadget4 = {
X &PC2Gadget3,
X 7,50,
X 118,11,
X GFLG_GADGHBOX|GFLG_GADGHIMAGE,
X RELVERIFY|GADGIMMEDIATE,
X BOOLGADGET,
X (APTR)&PC2Border4,
X NULL,
X &PC2IText4,
X NULL,
X NULL,
X WRITE_GADGET,
X NULL
X };
X
/* Test gadget. */
SHORT PC2BorderVectors5[] = {
X 0,0,
X 42,0,
X 42,12,
X 0,12,
X 0,0
};
X
struct Border PC2Border5 = {
X -1,-1,
X 3,0,JAM1,
X 5,
X PC2BorderVectors5,
X NULL
};
X
struct IntuiText PC2IText5 = {
X 4,0,JAM1,
X 4,1,
X NULL,
X "Test",
X NULL
X };
X
struct Gadget PC2Gadget5 = {
X &PC2Gadget4,
X 173,50,
X 40,11,
X GFLG_GADGHBOX|GFLG_GADGHIMAGE,
X RELVERIFY|GADGIMMEDIATE,
X BOOLGADGET,
X (APTR)&PC2Border5,
X NULL,
X &PC2IText5,
X NULL,
X NULL,
X TEST_GADGET,
X NULL
X };
X
struct NewWindow PC2NewWindowStructure1 = {
X 75,85,
X 220, 65,
X 0,6,
X GADGETDOWN+GADGETUP+CLOSEWINDOW,
X WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+ACTIVATE+NOCAREREFRESH,
X &PC2Gadget5,
X NULL,
X "Program Change 2",
X NULL,
X NULL,
X 5,5,
X -1,-1,
X CUSTOMSCREEN
};
X
/* Writes the value of a proportional slider. Thank goodness
X all the sliders are identical in range and behaviour! */
__geta4 /* Callback. */
long display_routine(struct Window *window, /* Window where the gadget lives. */
X struct Gadget *gadget, /* The gadget itself. */
X unsigned long value) /* The value to display. */
{
X char text[10];
X struct RastPort *rp = window->RPort;
X Move(rp, 187, 21 + ((gadget->GadgetID - 1) / 3) * 12);
X SetAPen(rp, 1);
X SetBPen(rp, 0);
X SetDrMd(rp, JAM2);
X sprintf(text, "%3ld", value);
X Text(rp, text, 3);
X return value;
}
X
static long
drag_embossed_prop(struct Window *window,
X short id,
X UBYTE min)
{
X long value = (*functions->DragEmbossedProp)(window, id);
X if (value < min)
X {
X value = min;
X (*functions->ModifyEmbossedProp)(window, id,
X value, 0, 0, 0, 0, 0);
X }
X (*functions->DrawEmbossedProp)(window, id);
X
X return value;
}
X
static long
shift_embossed_prop(struct Window *window,
X short id,
X short shift,
X UBYTE min)
{
X long value = (*functions->ShiftEmbossedProp)(window, id, shift, 0);
X if (value < min)
X {
X value = min;
X (*functions->ModifyEmbossedProp)(window, id,
X value, 0, 0, 0, 0, 0);
X }
X (*functions->DrawEmbossedProp)(window, id);
X
X return value;
}
X
static BOOL
lock_clip(struct Clip *clip)
{
X Forbid();
X if (clip->locked == 0)
X {
X clip->locked = 1;
X Permit();
X return TRUE;
X }
X else
X {
X Permit();
X return FALSE;
X }
}
X
static void
unlock_clip(struct Clip *clip)
{
X clip->locked = 0;
}
X
static void
send_note(struct PC2Tool *tool,
X const long time,
X const UBYTE note)
{
X struct NoteEvent *on_event = (struct NoteEvent *)(*functions->allocevent)();
X if (on_event)
X {
X struct NoteEvent *off_event = (struct NoteEvent *)(*functions->allocevent)();
X if (off_event)
X {
X on_event->next = off_event->next = NULL;
X on_event->type = off_event->type = EVENT_VOICE;
X on_event->status = MIDI_NOTEON;
X off_event->status = MIDI_NOTEOFF;
X on_event->value = off_event->value = note;
X on_event->velocity = 64;
X on_event->time = time;
X off_event->time = time + 96;
X on_event->tool = off_event->tool = tool->tool.next;
X (*functions->qevent)(on_event);
X (*functions->qevent)(off_event);
X }
X else
X {
X (*functions->freeevent)(on_event);
X }
X }
}
X
static void
send_pc_and_note(struct PC2Tool *tool,
X const long time,
X const UBYTE note)
{
X send_pc(tool, time);
X send_note(tool, time + 2 * (tool->delay), note);
}
X
__geta4
static void
edittoolcode(struct PC2Tool *tool)
{
X struct IntuiMessage *message;
X struct Window *window;
X long class, code;
X struct Gadget *gadget;
X struct NewWindow *newwindow;
X PC2NewWindowStructure1.Screen = functions->screen;
X
X if (tool->tool.touched & TOUCH_EDIT)
X {
X PC2NewWindowStructure1.LeftEdge = tool->tool.left;
X PC2NewWindowStructure1.TopEdge = tool->tool.top;
X PC2NewWindowStructure1.Width = tool->tool.width;
X PC2NewWindowStructure1.Height = tool->tool.height;
X }
X
X if (!tool->tool.touched)
X {
X pc2_tool_init(tool);
X }
X
X newwindow = (struct NewWindow *)
X (*functions->DupeNewWindow)(&PC2NewWindowStructure1);
X if (!newwindow)
X {
X return;
X }
X newwindow->Title = 0;
X newwindow->Flags |= BORDERLESS;
X newwindow->Flags &= ~0xF;
X newwindow->BlockPen = 0;
X newwindow->DetailPen = 0;
X
X window = (struct Window *) (*functions->FlashyOpenWindow)(newwindow);
X if (!window)
X {
X return;
X }
X
X tool->tool.window = window;
X (*functions->EmbossWindowOn)(window,WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG,
X PC2_NAME,(short)-1,(short)-1,0,0);
X
X for (short i = BANK_GADGET;
X i <= PROGRAM_GADGET;
X i += 3)
X {
X (*functions->FatEmbossedPropOn)(window,i, i + 1, i + 2,
X (no_prototype) display_routine,
X 128, 1);
X }
X
X (*functions->FatEmbossedPropOn)(window,
X DELAY_GADGET,
X DELAYDOWN_GADGET,
X DELAYUP_GADGET,
X (no_prototype) display_routine,
X 9, 1);
X
X (*functions->EmbossOn)(window, WRITE_GADGET, 1);
X (*functions->EmbossOn)(window, TEST_GADGET, 1);
X
X (*functions->ModifyEmbossedProp)(window, BANK_GADGET,
X tool->bank, 0, 0, 0, 0, 0);
X (*functions->ModifyEmbossedProp)(window, PROGRAM_GADGET,
X tool->program, 0, 0, 0, 0, 0);
X (*functions->ModifyEmbossedProp)(window, DELAY_GADGET,
X tool->delay, 0, 0, 0, 0, 0);
X
X for (short i = BANK_GADGET;
X i <= DELAY_GADGET;
X i += 3)
X {
X (*functions->DrawEmbossedProp)(window, i);
X }
X
X send_pc_and_note(tool, functions->timenow, 60);
X
X for (;;)
X {
X message = (struct IntuiMessage *) (*functions->GetIntuiMessage)(window);
X class = message->Class;
X code = message->Code;
X gadget = (struct Gadget *) message->IAddress;
X class = (*functions->SystemGadgets)(window,class,gadget,code);
X
X ReplyMsg((struct Message *)message);
X if (class == CLOSEWINDOW)
X {
X break;
X }
X else if (class == GADGETDOWN)
X {
X const short id = gadget->GadgetID;
X switch (id)
X {
X case BANK_GADGET:
X tool->bank = (UBYTE) drag_embossed_prop(window, BANK_GADGET, 0);
X send_pc_and_note(tool, functions->timenow, 60);
X break;
X case BANKDOWN_GADGET:
X tool->bank = (UBYTE) shift_embossed_prop(window, BANK_GADGET, -1, 0);
X send_pc_and_note(tool, functions->timenow, 60);
X break;
X case BANKUP_GADGET:
X tool->bank = (UBYTE) shift_embossed_prop(window, BANK_GADGET, 1, 0);
X send_pc_and_note(tool, functions->timenow, 60);
X break;
X case PROGRAM_GADGET:
X tool->program = (UBYTE) drag_embossed_prop(window, PROGRAM_GADGET, 0);
X send_pc_and_note(tool, functions->timenow, 60);
X break;
X case PROGRAMDOWN_GADGET:
X tool->program =
X (UBYTE) shift_embossed_prop(window, PROGRAM_GADGET, -1, 0);
X send_pc_and_note(tool, functions->timenow, 60);
X break;
X case PROGRAMUP_GADGET:
X tool->program =
X (UBYTE) shift_embossed_prop(window, PROGRAM_GADGET, 1, 0);
X send_pc_and_note(tool, functions->timenow, 60);
X break;
X case DELAY_GADGET:
X tool->delay = (UBYTE) drag_embossed_prop(window, DELAY_GADGET, 1);
X send_pc_and_note(tool, functions->timenow, 60);
X break;
X case DELAYDOWN_GADGET:
X tool->delay = (UBYTE) shift_embossed_prop(window, DELAY_GADGET, -1, 1);
X send_pc_and_note(tool, functions->timenow, 60);
X break;
X case DELAYUP_GADGET:
X tool->delay = (UBYTE) shift_embossed_prop(window, DELAY_GADGET, 1, 1);
X send_pc_and_note(tool, functions->timenow, 60);
X break;
X case WRITE_GADGET:
X if (!functions->running)
X {
X const long time = functions->starttime;
X struct Event *bank_event =
X (struct Event *)(*functions->allocevent)();
X if (bank_event)
X {
X struct Event *program_event =
X (struct Event *)(*functions->allocevent)();
X if (program_event)
X {
X bank_event->type = program_event->type = EVENT_VOICE;
X bank_event->status = program_event->status = MIDI_PCHANGE;
X bank_event->byte1 = tool->bank;
X program_event->byte1 = tool->program;
X bank_event->time = time;
X program_event->time = time + tool->delay;
X bank_event->tool = program_event->tool = tool->tool.next;
X bank_event->next = program_event;
X program_event->next = NULL;
X
X if (lock_clip(&(tool->tool.track->clip)))
X {
X program_event->next =
X tool->tool.track->clip.events.first;
X tool->tool.track->clip.events.first =
X (struct Event *)(*functions->sorteventlist)(bank_event);
X unlock_clip(&(tool->tool.track->clip));
X }
X else
X {
X (*functions->freelist)(bank_event);
X }
X }
X else
X {
X (*functions->freeevent)(bank_event);
X }
X }
X }
X break;
X case TEST_GADGET:
X {
X long time = functions->timenow;
X send_pc(tool, time);
X time += tool->delay << 1;
X for (int i = 24; i <= 84; i += 4, time += 96)
X {
X send_note(tool, time, i);
X }
X }
X break;
X }
X }
X else if (class == GADGETUP)
X {
X /* Nothing. */
X }
X }
X tool->tool.window = 0;
X tool->tool.left = window->LeftEdge;
X tool->tool.top = window->TopEdge;
X tool->tool.width = window->Width;
X tool->tool.height = window->Height;
X tool->tool.touched = TOUCH_INIT | TOUCH_EDIT;
X
X for (short i = BANK_GADGET;
X i <= DELAY_GADGET;
X i += 3)
X {
X (*functions->FatEmbossedPropOff)(window,i, i + 1, i + 2);
X }
X
X (*functions->EmbossOff)(window, WRITE_GADGET);
X (*functions->EmbossOff)(window, TEST_GADGET);
X
X (*functions->EmbossWindowOff)(window);
X (*functions->FlashyCloseWindow)(window);
X (*functions->DeleteNewWindow)(newwindow);
}
X
__geta4
static void
removetool()
{
X (*functions->removetransport)(transportcode);
}
X
struct ToolMaster *
inittoolmaster()
{
X memset((char *)&master,0,sizeof(struct ToolMaster));
X master.toolid = PC2_ID;
X master.image = &pc2_image;
X strcpy(master.name, PC2_NAME);
X master.edittool = (void_prototype) edittoolcode;
X master.processevent = (event_prototype) processeventcode;
X master.tooltype = PC2_TYPE;
X master.toolsize = sizeof(struct PC2Tool);
X master.removetool = removetool;
X (*functions->installtransport)(transportcode);
X return(&master);
}
SHAR_EOF
chmod 0600 pc2.c ||
echo 'restore of pc2.c failed'
Wc_c="`wc -c < 'pc2.c'`"
test 16825 -eq "$Wc_c" ||
echo 'pc2.c: original size 16825, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= pc2.ptool ==============
if test -f 'pc2.ptool' -a X"$1" != X"-c"; then
echo 'x - skipping pc2.ptool (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting pc2.ptool (Binary)'
sed 's/^X//' << 'SHAR_EOF' > _shar_tmp_.tmp &&
begin 600 pc2.ptool
<encoded_portion_removed>
end
SHAR_EOF
echo 'uudecoding file pc2.ptool' &&
uudecode < _shar_tmp_.tmp && rm -f _shar_tmp_.tmp &&
chmod 0600 pc2.ptool ||
echo 'restore of pc2.ptool failed'
Wc_c="`wc -c < 'pc2.ptool'`"
test 4588 -eq "$Wc_c" ||
echo 'pc2.ptool: original size 4588, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= pc2.readme ==============
if test -f 'pc2.readme' -a X"$1" != X"-c"; then
echo 'x - skipping pc2.readme (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting pc2.readme (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'pc2.readme' &&
Short: Bars & Pipes Tool for program changes that require two program change messages.
Author: Richard Hagen (R.H...@mailbox.uq.edu.au)
Uploader: Richard Hagen (R.H...@mailbox.uq.edu.au)
Version: 1.1 (29 September 1997)
Type: mus/midi
Requires: Bars and Pipes Professional
Distribution: Freely distributable by anyone, anywhere.
URL: http://www.it.uq.edu.au/~richard/music/bars-and-pipes/index.html
X
Program Change 2: A Bars and Pipes Tool for program changes that require two program
change messages
X
Version: 1.1 (29 September 1997)
X
Author: Richard Hagen
X R.H...@mailbox.uq.edu.au
X
Distribution: Freeware. See the copyright notice in pc2.c.
X
Requirements for running:
X Bars and Pipes Professional
X
Requirements for recompiling:
X DICE (or some other C compiler).
X toolstart.c and bars.h from the Rules for Tools package.
X
Usage:
X Program Change 2 (PC2) is used in the pipeline. You can't
X use it as a padtool.
X
X Its operation is controlled by five gadgets:
X
X Bank (proportional gadget, range [0 .. 127])
X This is the first program change message that gets sent. Usually
X this selects the bank that you want.
X Program (proportional gadget, range [0 .. 127])
X This is the second program change message that gets sent. Usually
X this selects the actual patch or program that you want.
X Delay (proportional gadget, range [1 .. 8])
X This specifies the length of the delay (in clock ticks) between
X sending the first program change and sending the second.
X Write To Track (boolean gadget)
X This causes the patch change selected to be written to the
X track at the current Song Position flag's position.
X Test (boolean gadget)
X Sends out some note messages over a few octaves to test
X the selected patch.
X
Useful for:
X Generating program changes for some synths with too many program
X memories :-)
X
Limitation:
X Write To Track doesn't function if the transport is running.
X Inserting events into a track's clip while the transport is
X running gives me the willies!
X
History:
X 1.1 (29 September 1997)
X Tightened up timing.
X
X 1.0 (22 September 1997)
X Initial release.
X
richard
R.H...@mailbox.uq.edu.au
29 September 1997
X
X
X
SHAR_EOF
chmod 0600 pc2.readme ||
echo 'restore of pc2.readme failed'
Wc_c="`wc -c < 'pc2.readme'`"
test 2169 -eq "$Wc_c" ||
echo 'pc2.readme: original size 2169, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
exit 0
--
Bill Zimmer - z...@ibx.com

0 new messages