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

v97i007: Notemapper [1.0] - Bars & Pipes Accessory for mapping MIDI notes, Part 01/01

0 views
Skip to first unread message

Richard Hagen

unread,
Oct 27, 1997, 3:00:00 AM10/27/97
to

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

[ Executable (notemapper.paccess) included. ...zim ]

Note Mapper uses a Note Map to map from one MIDI note to another.
You can edit the map from within the Note Mapper.

#!/bin/sh
# This is music/notemapper-1.0, 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 10/27/1997 18:59 UTC by z...@ibx.com
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 1288 -rw------- dmakefile
# 2288 -rw------- myheader.h
# 23169 -rw------- notemapper.c
# 7012 -rw------- notemapper.paccess
# 1674 -rw------- notemapper.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 accessory.
#
ACCESS = notemapper
X
#
# The source files that you need to build the accessory.
#
MYSRCS = notemapper.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 accessory is linked
# together.)
#
PACCESS = $(ACCESS).paccess
README = $(ACCESS).readme
ARCHIVE = $(ACCESS).lha
X
SRCS = toolstart.c $(MYSRCS)
OBJS = $(SRCS:*.c:*.o)
X
all: $(PACCESS)
X
$(PACCESS): $(OBJS)
X dlink $(OBJS) $(LIBS) -o $(PACCESS)
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 $(PACCESS) $(ARCHIVE)
X
distribution: $(ARCHIVE)
X
$(ARCHIVE): clobber $(PACCESS) clean
X lha a $(ARCHIVE) dmakefile $(PACCESS) $(MYHDRS) $(MYSRCS) $(README)
X
X
X
SHAR_EOF
chmod 0600 dmakefile ||
echo 'restore of dmakefile failed'
Wc_c="`wc -c < 'dmakefile'`"
test 1288 -eq "$Wc_c" ||
echo 'dmakefile: original size 1288, 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
/* Maximum CC value. */
#define CC_VALUE_MAX 127
X
/* Number of CC values. */
#define CC_VALUE_NUM (CC_VALUE_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 2288 -eq "$Wc_c" ||
echo 'myheader.h: original size 2288, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= notemapper.c ==============
if test -f 'notemapper.c' -a X"$1" != X"-c"; then
echo 'x - skipping notemapper.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting notemapper.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'notemapper.c' &&
/*
X Note Mapper: A Bars & Pipes Accessory for mapping MIDI notes to other MIDI notes.
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 Version 1.0 (6 October 1997)
X Initial Release.
*/
X
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include <libraries/gadtools.h>
#include <exec/memory.h>
#include <stdarg.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>
X
#include "bars.h"
X
#include "myheader.h"
X
#define NOTE_MAPPER_NAME "Note Mapper 1.0"
#define NOTE_MAPPER_ID_STRING "NTMP"
X
#define NOTE_MAPPER_ID MAKE_IDS(NOTE_MAPPER_ID_STRING)
X
/* -------------------------------------------------------------------- */
/* ICON IMAGERY */
/* -------------------------------------------------------------------- */
X
/* Normal icon. */
static const __chip UWORD note_mapper_image_data[] = {
X /* Plane #0 */
X 0x0, 0x0,
X 0x0400, 0x0,
X 0x0600, 0x0,
X 0x0500, 0x0,
X 0x0400, 0x4000,
X 0x0400, 0x6000,
X 0x0400, 0x5000,
X 0x0400, 0x4000,
X 0x0400, 0x4000,
X 0x1400, 0x4000,
X 0x2800, 0x4000,
X 0x1001, 0x4000,
X 0x0002, 0x8000,
X 0x0001, 0x0,
X 0x0, 0x0,
X
X /* Plane #1 */
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0030, 0x0,
X 0x0018, 0x0,
X 0x00fc, 0x0,
X 0x0018, 0x0,
X 0x0030, 0x0,
X 0x1000, 0x0,
X 0x0, 0x0,
X 0x0001, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X
X /* Plane #2 */
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0030, 0x0,
X 0x0018, 0x0,
X 0x00fc, 0x0,
X 0x0018, 0x0,
X 0x0030, 0x0,
X 0x1000, 0x0,
X 0x0, 0x0,
X 0x0001, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X
};
X
static const struct Image note_mapper_image = {
X 0, 0,
X 22, 15, 3,
X note_mapper_image_data,
X 0x1f, 0x00,
X NULL
};
X
/* Selected icon. */
static const __chip UWORD note_mapper_onimage_data[] = {
X /* Plane #0 */
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0030, 0x0,
X 0x0018, 0x0,
X 0x00fc, 0x0,
X 0x0018, 0x0,
X 0x0030, 0x0,
X 0x1000, 0x0,
X 0x0, 0x0,
X 0x0001, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X
X /* Plane #1 */
X 0x0, 0x0,
X 0x0400, 0x0,
X 0x0600, 0x0,
X 0x0500, 0x0,
X 0x0400, 0x4000,
X 0x0400, 0x6000,
X 0x0400, 0x5000,
X 0x0400, 0x4000,
X 0x0400, 0x4000,
X 0x1400, 0x4000,
X 0x2800, 0x4000,
X 0x1001, 0x4000,
X 0x0002, 0x8000,
X 0x0001, 0x0,
X 0x0, 0x0,
X
X /* Plane #2 */
X 0x0, 0x0,
X 0x0400, 0x0,
X 0x0600, 0x0,
X 0x0500, 0x0,
X 0x0400, 0x4000,
X 0x0400, 0x6000,
X 0x0400, 0x5000,
X 0x0400, 0x4000,
X 0x0400, 0x4000,
X 0x1400, 0x4000,
X 0x2800, 0x4000,
X 0x1001, 0x4000,
X 0x0002, 0x8000,
X 0x0001, 0x0,
X 0x0, 0x0,
X
};
X
static const struct Image note_mapper_onimage = {
X 1, 0,
X 22, 15, 3,
X note_mapper_onimage_data,
X 0x1f, 0x00,
X NULL
};
X
/* Global Bars & Pipes functions pointer. */
extern struct Functions *functions;
X
/* Title for error requester. */
static const char *error_title = "Note Mapper Error";
X
/* Puts up a simple requester for relaying error messages. */
static void
accessory_error(struct Window *window, /* Window to open requester in. */
X const char *s) /* String to put in the requester. */
{
X const struct EasyStruct easy = {
X sizeof(struct EasyStruct),
X 0,
X error_title,
X s,
X "OK"
X };
X
X (void) EasyRequest(window, &easy, NULL);
}
X
/* A map from program change # to program change #. */
typedef BYTE NoteMap[MIDI_NOTE_NUM];
X
struct NoteMapper {
X struct Accessory accessory;
X UBYTE display;
X NoteMap note_map;
};
X
static void
note_map_load(long file, NoteMap note_map)
{
X char file_id[ID_LEN]; /* File ID. */
X
X /* Ensure that the file id is one for a note map. */
X if ((*functions->fastread)(file, file_id, ID_LEN) < ID_LEN)
X {
X /* Failed to read the correct number of bytes for the file id. */
X return;
X }
X if (!STREQN(file_id, NOTE_MAPPER_ID_STRING, ID_LEN))
X {
X /* Incorrect id */
X return;
X }
X
X (*functions->fastread)(file, note_map, sizeof(NoteMap));
}
X
static void
note_map_save(long file, NoteMap note_map)
{
X (*functions->fastwrite)(file, NOTE_MAPPER_ID_STRING, ID_LEN);
X (*functions->fastwrite)(file, note_map, sizeof(NoteMap));
}
X
static void
note_map_clear(NoteMap note_map)
{
X for (int i = 0; i < MIDI_NOTE_NUM; i++)
X {
X note_map[i] = (UBYTE) i;
X }
}
X
static void
note_map_randomise(NoteMap note_map)
{
X for (int i = 0; i < MIDI_NOTE_NUM; i++)
X {
X note_map[i] = (*functions->random)(MIDI_NOTE_NUM);
X }
}
X
static void
note_map_track(struct Track *track, BYTE note_map[])
{
X /* For each event in the list. */
X for (struct Event *event = track->clip.events.first;
X event;
X event = event->next)
X {
X /* If it's an event that refers to a note. */
X if (event->type == EVENT_VOICE &&
X (event->status == MIDI_NOTEON ||
X event->status == MIDI_NOTEOFF ||
X event->status == MIDI_PTOUCH))
X {
X /* Map it... */
X event->byte1 = note_map[event->byte1];
X }
X }
}
X
/* -------------------------------------------------------------------- */
/* INTERFACE */
/* -------------------------------------------------------------------- */
X
#define LOAD_NOTE_MAP_GADGET 1
#define SAVE_NOTE_MAP_GADGET 2
#define MAP_SONG_GADGET 3
#define MAP_TRACK_GADGET 4
#define CLEAR_NOTE_MAP_GADGET 5
#define RANDOMISE_GADGET 6
X
#define SCROLLER_GADGET 7
#define SCROLLERDOWN_GADGET 8
#define SCROLLERUP_GADGET 9
X
/* Number of first note gadget. */
#define FIRST_NOTE_GADGET (SCROLLERUP_GADGET + 1)
X
/* Number of patches seen at once. */
#define NUM_NOTE_GADGETS 16
X
#define GADGET_LEFT 80
X
/* Load note_map gadget. */
static const struct IntuiText itext1 = {
X 4,0,JAM1,
X 4,1,
X NULL,
X "Load Note Map",
X NULL
};
X
static const struct Gadget gadget1 = {
X NULL,
X 8, 14,
X 112, 9,
X (ULONG) NULL,
X RELVERIFY+GADGIMMEDIATE,
X BOOLGADGET,
X NULL,
X NULL,
X &itext1,
X (ULONG) NULL,
X NULL,
X LOAD_NOTE_MAP_GADGET,
X NULL
};
X
/* Save note_map gadget. */
static const struct IntuiText itext2 = {
X 4,0,JAM1,
X 4,1,
X NULL,
X "Save Note Map",
X NULL
};
X
static const struct Gadget gadget2 = {
X &gadget1,
X 8, 25,
X 112, 9,
X (ULONG) NULL,
X RELVERIFY+GADGIMMEDIATE,
X BOOLGADGET,
X NULL,
X NULL,
X &itext2,
X (ULONG) NULL,
X NULL,
X SAVE_NOTE_MAP_GADGET,
X NULL
};
X
/* Map selected track gadget. */
static const struct IntuiText itext3 = {
X 4,0,JAM1,
X 20,1,
X NULL,
X "Map Track",
X NULL
};
X
static const struct Gadget gadget3 = {
X &gadget2,
X 8, 36,
X 112, 9,
X (ULONG) NULL,
X RELVERIFY+GADGIMMEDIATE,
X BOOLGADGET,
X NULL,
X NULL,
X &itext3,
X (ULONG) NULL,
X NULL,
X MAP_TRACK_GADGET,
X NULL
};
X
/* Map song gadget. */
static const struct IntuiText itext4 = {
X 4,0,JAM1,
X 8,1,
X NULL,
X "Map Song",
X NULL
};
X
static const struct Gadget gadget4 = {
X &gadget3,
X 204, 14,
X 80, 9,
X (ULONG) NULL,
X RELVERIFY+GADGIMMEDIATE,
X BOOLGADGET,
X NULL,
X NULL,
X &itext4,
X (ULONG) NULL,
X NULL,
X MAP_SONG_GADGET,
X NULL
};
X
/* Clear map gadget. */
static const struct IntuiText itext5 = {
X 4,0,JAM1,
X 4, 1,
X NULL,
X "Clear Map",
X NULL
};
X
static const struct Gadget gadget5 = {
X &gadget4,
X 204, 25,
X 80, 9,
X (ULONG) NULL,
X RELVERIFY+GADGIMMEDIATE,
X BOOLGADGET,
X NULL,
X NULL,
X &itext5,
X (ULONG) NULL,
X NULL,
X CLEAR_NOTE_MAP_GADGET,
X NULL
};
X
/* Randomise gadget. */
static const struct IntuiText itext6 = {
X 4,0,JAM1,
X 4, 1,
X NULL,
X "Randomise",
X NULL
};
X
static const struct Gadget gadget6 = {
X &gadget5,
X 204, 36,
X 80, 9,
X (ULONG) NULL,
X RELVERIFY+GADGIMMEDIATE,
X BOOLGADGET,
X NULL,
X NULL,
X &itext6,
X (ULONG) NULL,
X NULL,
X RANDOMISE_GADGET,
X NULL
};
X
/* Patch select scroller. */
static const struct PropInfo scroller_gadget_info = {
X AUTOKNOB+FREEHORIZ,
X -16384, -1,
X 16384, -1,
};
X
static const struct Image scroller_gadget_image = {
X 0,0,
X 102, 6,
X 0,
X NULL,
X 0x0000,0x0000,
X NULL
X };
X
static const struct Gadget scroller_gadget = {
X &gadget6,
X 106, 49,
X 100, 10,
X GFLG_GADGHBOX|GFLG_GADGHIMAGE,
X RELVERIFY|GADGIMMEDIATE,
X PROPGADGET,
X (APTR)&scroller_gadget_image,
X NULL,
X NULL,
X NULL,
X &scroller_gadget_info,
X SCROLLER_GADGET,
X NULL
X };
X
/* Top Of the note gadgets. */
#define NOTE_GADGETS_TOP 62
X
/* Initial templates for the gadget values. */
static const struct PropInfo init_note_gadget_info = {
X AUTOKNOB+FREEHORIZ,
X -16384, -1,
X 16384, -1,
};
X
static const struct Image init_note_gadget_image = {
X 0,0,
X 102,6,
X 0,
X NULL,
X 0x0000,0x0000,
X NULL
X };
X
static const struct Gadget init_note_gadget = {
X NULL, /* Initialised below. */
X 106, NOTE_GADGETS_TOP, /* Altered below. */
X 100,10,
X GFLG_GADGHBOX|GFLG_GADGHIMAGE,
X RELVERIFY|GADGIMMEDIATE,
X PROPGADGET,
X NULL, /* Initialised below. */
X NULL,
X NULL,
X NULL,
X NULL, /* Initialised below. */
X 0, /* Initialised below. */
X NULL
X };
X
/* All initialised in note_mapper_open(). */
static struct Gadget note_gadget[NUM_NOTE_GADGETS];
X
struct NoteMapper note_mapper;
X
/* Close the note_mapper window. */
__geta4 /* Callback function. */
note_mapper_close(void)
{
X /* Ensure that we have something to close. */
X if (note_mapper.accessory.window)
X {
X struct IntuiMessage *message;
X
X (*functions->EmbossOff)(note_mapper.accessory.window,LOAD_NOTE_MAP_GADGET);
X (*functions->EmbossOff)(note_mapper.accessory.window,SAVE_NOTE_MAP_GADGET);
X (*functions->EmbossOff)(note_mapper.accessory.window,MAP_SONG_GADGET);
X (*functions->EmbossOff)(note_mapper.accessory.window,MAP_TRACK_GADGET);
X (*functions->EmbossOff)(note_mapper.accessory.window,CLEAR_NOTE_MAP_GADGET);
X (*functions->EmbossOff)(note_mapper.accessory.window,RANDOMISE_GADGET);
X
X (*functions->FatEmbossedPropOff)(note_mapper.accessory.window,
X SCROLLER_GADGET, SCROLLERDOWN_GADGET,
X SCROLLERUP_GADGET);
X
X for (int j = 0; j < NUM_NOTE_GADGETS; j++)
X {
X const short gadget = (j * 3) + FIRST_NOTE_GADGET;
X (*functions->FatEmbossedPropOff)(note_mapper.accessory.window,
X gadget, gadget + 1, gadget + 2);
X }
X
X (*functions->EmbossWindowOff)(note_mapper.accessory.window);
X
X /* Remember where we were in case we're reopened later. */
X note_mapper.accessory.left = note_mapper.accessory.window->LeftEdge;
X note_mapper.accessory.top = note_mapper.accessory.window->TopEdge;
X
X /* Make it hard to send us messages and eat up any that are pending. */
X note_mapper.accessory.window->UserPort = 0;
X ModifyIDCMP(note_mapper.accessory.window,0);
X WaitTOF();
X WaitTOF();
X WaitTOF();
X WaitTOF();
X WaitTOF();
X Forbid();
X while (message = (struct IntuiMessage *)GetMsg(functions->window->UserPort))
X {
X ReplyMsg((struct Message *)message);
X }
X (*functions->FlashyCloseWindow)(note_mapper.accessory.window);
X note_mapper.accessory.window = NULL;
X Permit();
X }
X
X return(1);
}
X
#define NOTE_NAME_LEN 5
X
/* Returns a text string given a midi note number. */
static char *
note_name(UBYTE note)
{
X static char name[NOTE_NAME_LEN];
X
X static const char *note_names[] = {
X "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "Bb", "B"
X };
X
X sprintf(name, "%s%1ld", note_names[note % 12], (int) note / 12);
X
X return name;
}
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 ULONG value) /* The value to display. */
{
X char text[20];
X struct RastPort *rp = window->RPort;
X SetAPen(rp, 1);
X SetBPen(rp, 0);
X SetDrMd(rp, JAM2);
X
X Move(rp, 212, NOTE_GADGETS_TOP + 8 + ((gadget->GadgetID - FIRST_NOTE_GADGET) / 3) * 12);
X sprintf(text, "%3ld: %-4s", value, note_name(value));
X Text(rp, text, 9);
X
X return value;
}
X
__geta4
long
scroller_display_routine(struct Window *window,
X struct Gadget *gadget,
X ULONG value)
{
X char text[20];
X struct RastPort *rp = window->RPort;
X
X SetAPen(rp, 1);
X SetBPen(rp, 0);
X SetDrMd(rp, JAM2);
X
X Move(rp, 36, 56);
X sprintf(text, "%3ld: %-4s",
X value * NUM_NOTE_GADGETS, note_name(value * NUM_NOTE_GADGETS));
X Text(rp, text, 8);
X
X Move(rp, 212, 56);
X sprintf(text, "%3ld: %-4s", (value + 1) * NUM_NOTE_GADGETS - 1,
X note_name((value + 1) * NUM_NOTE_GADGETS - 1));
X Text(rp, text, 9);
X return value;
X
X return 0;
}
X
static void
note_display(struct NoteMapper *nm)
{
X UBYTE note = nm->display * NUM_NOTE_GADGETS;
X
X (*functions->DrawEmbossedProp)(nm->accessory.window, SCROLLER_GADGET);
X for (int i = 0; i < NUM_NOTE_GADGETS; i++, note++)
X {
X const short id = FIRST_NOTE_GADGET + i * 3;
X
X char text[20];
X struct RastPort *rp = nm->accessory.window->RPort;
X
X SetAPen(rp, 1);
X SetBPen(rp, 0);
X SetDrMd(rp, JAM2);
X
X Move(rp, 7, NOTE_GADGETS_TOP + 8 + i * 12);
X sprintf(text, "%3ld: %-4s ->",
X i + nm->display * NUM_NOTE_GADGETS,
X note_name(note));
X Text(rp, text, 12);
X
X (*functions->ModifyEmbossedProp)(nm->accessory.window,
X id, nm->note_map[note], 0, 0, 0, 0, 0);
X (*functions->DrawEmbossedProp)(nm->accessory.window, id);
X }
}
X
/* Open the note_mapper window. */
__geta4 /* Callback function. */
note_mapper_open(void)
{
X /* Use v37+ style window tags to specify the new window. */
X const struct TagItem tags[] = {
X {WA_Left, note_mapper.accessory.left},
X {WA_Top, note_mapper.accessory.top},
X {WA_Width, 292},
X {WA_Height, NOTE_GADGETS_TOP + (NUM_NOTE_GADGETS * 12) + 2},
X {WA_DetailPen, 5},
X {WA_BlockPen, 1},
X {WA_IDCMP, GADGETDOWN|GADGETUP|CLOSEWINDOW},
X {WA_DragBar, FALSE},
X {WA_DepthGadget, FALSE},
X {WA_CloseGadget, FALSE},
X {WA_Activate, TRUE},
X {WA_NoCareRefresh, TRUE},
X {WA_Borderless, TRUE},
X {WA_Gadgets, (ULONG) &note_gadget[NUM_NOTE_GADGETS - 1]},
X {WA_Checkmark, (ULONG) NULL},
X {WA_Title, (ULONG) NULL},
X {WA_ScreenTitle, (ULONG) NOTE_MAPPER_NAME},
X {WA_CustomScreen, (ULONG) functions->screen}
X };
X
X struct Gadget *next = &scroller_gadget;
X for (int i = 0; i < NUM_NOTE_GADGETS; i++)
X {
X memcpy((char *)&note_gadget[i],
X (char *)&init_note_gadget, sizeof(struct Gadget));
X
X note_gadget[i].NextGadget = next;
X note_gadget[i].TopEdge = NOTE_GADGETS_TOP + i * 12;
X note_gadget[i].GadgetRender = (APTR)&init_note_gadget_image;
X note_gadget[i].SpecialInfo = (APTR)&init_note_gadget_info;
X note_gadget[i].GadgetID = (i * 3) + FIRST_NOTE_GADGET;
X
X next = &note_gadget[i];
X }
X
X /* Attempt to open the window, and check to see if we were successful. */
X note_mapper.accessory.window = (struct Window *)OpenWindowTagList(NULL, &tags);
X if (note_mapper.accessory.window)
X {
X /* Set up communication. */
X note_mapper.accessory.window->UserPort = functions->window->UserPort;
X ModifyIDCMP(note_mapper.accessory.window,functions->window->IDCMPFlags);
X
X (*functions->EmbossWindowOn)(note_mapper.accessory.window,
X WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG,
X NOTE_MAPPER_NAME,(short)-1,(short)-1,0,0);
X (*functions->EmbossOn)(note_mapper.accessory.window,LOAD_NOTE_MAP_GADGET,1);
X (*functions->EmbossOn)(note_mapper.accessory.window,SAVE_NOTE_MAP_GADGET,1);
X (*functions->EmbossOn)(note_mapper.accessory.window,MAP_TRACK_GADGET,1);
X (*functions->EmbossOn)(note_mapper.accessory.window,MAP_SONG_GADGET,1);
X (*functions->EmbossOn)(note_mapper.accessory.window,CLEAR_NOTE_MAP_GADGET,1);
X (*functions->EmbossOn)(note_mapper.accessory.window,RANDOMISE_GADGET,1);
X for (int j = 0; j < NUM_NOTE_GADGETS; j++)
X {
X const short gadget = (j * 3) + FIRST_NOTE_GADGET;
X (*functions->FatEmbossedPropOn)(note_mapper.accessory.window,
X gadget, gadget + 1, gadget + 2,
X (no_prototype) display_routine,
X 128, 1);
X }
X
X (*functions->FatEmbossedPropOn)(note_mapper.accessory.window,
X SCROLLER_GADGET, SCROLLERDOWN_GADGET,
X SCROLLERUP_GADGET,
X (no_prototype) scroller_display_routine,
X (MIDI_NOTE_NUM / NUM_NOTE_GADGETS),
X 2);
X }
X
X note_display(&note_mapper);
X
X return((long)note_mapper.accessory.window);
}
X
static long
drag_embossed_prop(struct Window *window,
X short id)
{
X long value = (*functions->DragEmbossedProp)(window, id);
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 long value = (*functions->ShiftEmbossedProp)(window, id, shift, 0);
X (*functions->DrawEmbossedProp)(window, id);
X
X return value;
}
X
/* Gather and process user input from the note_mapper window. */
__geta4 /* Callback function. */
note_mapper_edit(struct IntuiMessage *message) /* Message to process. */
{
X struct Window *window = message->IDCMPWindow;
X struct Gadget *gadget;
X long class,code;
X
X class = message->Class;
X code = message->Code;
X gadget = (struct Gadget *) message->IAddress;
X ReplyMsg((struct Message *)message);
X class = (*functions->SystemGadgets)(window,class,gadget,code);
X
X if (class == CLOSEWINDOW)
X {
X (void) note_mapper_close();
X return 0;
X }
X else if (class == GADGETDOWN)
X {
X const short id = gadget->GadgetID;
X switch (id)
X {
X case LOAD_NOTE_MAP_GADGET:
X {
X char filename[255];
X
X /* Get the filename */
X (*functions->FileName)(filename,"Load Note Map File:","notemap",
X functions->screen,
X FILES_OPEN|FILES_DELETE|FILES_TYPE,0,0);
X if (filename[0])
X {
X /* Attempt to open the file and check to see if we
X succeeded. */
X long file = (*functions->fastopen)(filename,MODE_OLDFILE);
X if (file != -1)
X {
X if ((*functions->areyousure)("replace the Note Map?"))
X {
X (*functions->openwait)();
X note_map_load(file, note_mapper.note_map);
X note_display(&note_mapper);
X (*functions->closewait)();
X }
X (*functions->fastclose)(file);
X }
X else
X {
X accessory_error(note_mapper.accessory.window,
X "Couldn't open file for reading");
X }
X }
X }
X break;
X case SAVE_NOTE_MAP_GADGET:
X {
X char filename[255];
X
X /* Get the filename */
X (*functions->FileName)(filename,"Save Note Map File:","notemap",
X functions->screen,
X FILES_SAVE|FILES_DELETE|FILES_TYPE,0,0);
X if (filename[0])
X {
X /* Attempt to open the file and check to see if we
X succeeded. */
X long file = (*functions->fastopen)(filename,MODE_NEWFILE);
X if (file != -1)
X {
X (*functions->openwait)();
X note_map_save(file, note_mapper.note_map);
X (*functions->closewait)();
X (*functions->fastclose)(file);
X }
X else
X {
X accessory_error(note_mapper.accessory.window,
X "Couldn't open file for saving");
X }
X }
X }
X break;
X case MAP_TRACK_GADGET:
X if (functions->groupid != 0) /* Group selected? */
X {
X (*functions->openwait)();
X
X for (struct Track *track = functions->tracklist;
X track;
X track = track->next)
X {
X char string[10];
X sprintf(string, "%ld", track->group);
X DEBUG(string);
X
X if (track->group & (1 << (functions->groupid-1)))
X {
X note_map_track(track, note_mapper.note_map);
X }
X }
X (*functions->display)(0x1000000);
X (*functions->closewait)();
X }
X else if (functions->selectedtrack) /* Track selected? */
X {
X (*functions->openwait)();
X note_map_track(functions->selectedtrack, note_mapper.note_map);
X (*functions->display)(0x1000000);
X (*functions->closewait)();
X }
X else /* No track or group selected. */
X {
X accessory_error(note_mapper.accessory.window,
X "You must select a track (or group) for mapping");
X }
X break;
X case MAP_SONG_GADGET:
X (*functions->openwait)();
X for (struct Track *track = functions->tracklist;
X track;
X track = track->next)
X {
X note_map_track(track, note_mapper.note_map);
X }
X (*functions->display)(0x1000000);
X (*functions->closewait)();
X break;
X case CLEAR_NOTE_MAP_GADGET:
X if ((*functions->areyousure)("clear the Note Map?"))
X {
X (*functions->openwait)();
X note_map_clear(note_mapper.note_map);
X note_display(&note_mapper);
X (*functions->closewait)();
X }
X break;
X case RANDOMISE_GADGET:
X if ((*functions->areyousure)("randomise the Note Map?"))
X {
X (*functions->openwait)();
X note_map_randomise(note_mapper.note_map);
X note_display(&note_mapper);
X (*functions->closewait)();
X }
X break;
X case SCROLLER_GADGET:
X note_mapper.display = (UBYTE) drag_embossed_prop(note_mapper.accessory.window,
X SCROLLER_GADGET);
X note_display(&note_mapper);
X break;
X case SCROLLERDOWN_GADGET:
X note_mapper.display = (UBYTE) shift_embossed_prop(note_mapper.accessory.window,
X SCROLLER_GADGET, -1);
X note_display(&note_mapper);
X break;
X case SCROLLERUP_GADGET:
X note_mapper.display = (UBYTE) shift_embossed_prop(note_mapper.accessory.window,
X SCROLLER_GADGET, 1);
X note_display(&note_mapper);
X break;
X default: /* Note select gadgets. */
X {
X const UBYTE note = (note_mapper.display * NUM_NOTE_GADGETS) +
X (id - FIRST_NOTE_GADGET) / 3;
X switch ((id - FIRST_NOTE_GADGET) % 3)
X {
X case 0:
X note_mapper.note_map[note] =
X (UBYTE) drag_embossed_prop(note_mapper.accessory.window, id);
X break;
X case 1:
X note_mapper.note_map[note] =
X (UBYTE) shift_embossed_prop(note_mapper.accessory.window, id - 1, -1);
X break;
X case 2:
X note_mapper.note_map[note] =
X (UBYTE) shift_embossed_prop(note_mapper.accessory.window, id - 2, 1);
X break;
X }
X }
X }
X }
X else if (class == GADGETUP)
X {
X /* Nothing. */
X }
X
X return 1;
}
X
struct Accessory *
inittoolmaster(void)
{
X memset((char *)&note_mapper,0,sizeof(struct NoteMapper));
X note_mapper.accessory.left = 50;
X note_mapper.accessory.top = 0;
X note_mapper.accessory.id = NOTE_MAPPER_ID;
X note_mapper.accessory.next = 0;
X note_mapper.accessory.image = &note_mapper_image;
X note_mapper.accessory.onimage = &note_mapper_onimage;
X note_mapper.accessory.open = note_mapper_open;
X note_mapper.accessory.close = note_mapper_close;
X note_mapper.accessory.edit = (no_prototype) note_mapper_edit;
X strcpy(note_mapper.accessory.name, NOTE_MAPPER_NAME);
X
X note_mapper.display = 0;
X note_map_clear(note_mapper.note_map);
X
X return(&note_mapper.accessory);
}
SHAR_EOF
chmod 0600 notemapper.c ||
echo 'restore of notemapper.c failed'
Wc_c="`wc -c < 'notemapper.c'`"
test 23169 -eq "$Wc_c" ||
echo 'notemapper.c: original size 23169, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= notemapper.paccess ==============
if test -f 'notemapper.paccess' -a X"$1" != X"-c"; then
echo 'x - skipping notemapper.paccess (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting notemapper.paccess (Binary)'
sed 's/^X//' << 'SHAR_EOF' > _shar_tmp_.tmp &&
begin 600 notemapper.paccess
<encoded_portion_removed>
end
SHAR_EOF
echo 'uudecoding file notemapper.paccess' &&
uudecode < _shar_tmp_.tmp && rm -f _shar_tmp_.tmp &&
chmod 0600 notemapper.paccess ||
echo 'restore of notemapper.paccess failed'
Wc_c="`wc -c < 'notemapper.paccess'`"
test 7012 -eq "$Wc_c" ||
echo 'notemapper.paccess: original size 7012, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= notemapper.readme ==============
if test -f 'notemapper.readme' -a X"$1" != X"-c"; then
echo 'x - skipping notemapper.readme (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting notemapper.readme (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'notemapper.readme' &&
Short: Bars & Pipes Accessory for mapping MIDI notes to other MIDI notes, en mass.
Author: Richard Hagen (R.H...@mailbox.uq.edu.au)
Uploader: Richard Hagen (R.H...@mailbox.uq.edu.au)
Version: 1.0 (6 October 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
Note Mapper: A Bars and Pipes Accessory for mapping MIDI notes to other MIDI notes, en masse.
X
Version: 1.0 (6 October 1997)
X
Author: Richard Hagen
X R.H...@mailbox.uq.edu.au
X
Distribution: Freeware. See the copyright notice in notemapper.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 Note Mapper uses a Note Map to map from one
X MIDI note to another. You can edit the map
X from within the Note Mapper.
X
X Note Mapper is controlled by *stacks* of gadgets!
X
X The button gadgets should be fairly easy to figure out.
X
X The first proportional gadget selects the range of notes to display.
X For instance, to display the mapping for notes 32 to 47, you
X move this gadget to show this range.
X
X The 16 gadgets below this edit the individual note mappings in the
X selected range.
X
X Note Mapper maps all MIDI events that specify a note number:
X MIDI_NOTEON
X Note on events.
X MIDI_NOTEOFF
X Note off events.
X MIDI_PTOUCH
X Poly aftertouch events.
X
Useful for:
X Converting GM drum tracks into something nicer.
X
History:
X 1.0 (6 October 1997)
X Initial release.
X
richard
R.H...@mailbox.uq.edu.au
X
X
X
X
SHAR_EOF
chmod 0600 notemapper.readme ||
echo 'restore of notemapper.readme failed'
Wc_c="`wc -c < 'notemapper.readme'`"
test 1674 -eq "$Wc_c" ||
echo 'notemapper.readme: original size 1674, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
exit 0
--
Bill Zimmer - z...@ibx.com

0 new messages