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

v97i006: MM [1.1] - Bars & Pipes Tool for monitoring MIDI events, Part 01/01

2 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 06
Archive-name: music/mm-1.1/part01
URL: http://www.it.uq.edu.au/~richard/music/bars-and-pipes/index.html#programs

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

Pop MIDI Monitor into a pipeline. It will monitor MIDI events.
If its window is open, it'll show you the MIDI events.

Each event is accompanied by its time, any relevant data fields,
and in the case of MIDI_NOTEON events, the duration. The information
for each type of MIDI event is described in the Rules for Tools
documentation.

#!/bin/sh
# This is music/mm-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 10/27/1997 18:53 UTC by z...@ibx.com
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 1233 -rw------- dmakefile
# 10155 -rw------- mm.c
# 3960 -rw------- mm.ptool
# 1344 -rw------- mm.readme
# 2170 -rw------- myheader.h
#
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 = mm
X
#
# The source files that you need to build the tool.
#
MYSRCS = mm.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 1233 -eq "$Wc_c" ||
echo 'dmakefile: original size 1233, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= mm.c ==============
if test -f 'mm.c' -a X"$1" != X"-c"; then
echo 'x - skipping mm.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting mm.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'mm.c' &&
/*
X MM: A Bars and Pipes MIDI Monitor.
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 (22 September 1997)
X Added event type reporting.
X
X 1.1 (22 September 1997)
X Code improvement.
X
X 1.0 (15 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 MM_NAME "MIDI Monitor 1.2"
#define MM_ID MAKE_IDS("MMON")
#define MM_TYPE (TOOL_NORMAL | TOOL_NOTPAD)
X
__chip static UWORD mm[] = {
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, 0xfc00,
X 0x17db, 0xec00,
X 0xd399, 0xcf00,
X 0xd55a, 0xaf00,
X 0xd6db, 0x6f00,
X 0xd7db, 0xef00,
X 0x17db, 0xec00,
X 0x1fff, 0xfc00,
X 0x1fff, 0xfc00,
X 0x0, 0x0,
X
X /*------ plane # 2: --------*/
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0824, 0x1000,
X 0x0c66, 0x3000,
X 0x0aa5, 0x5000,
X 0x0924, 0x9000,
X 0x0824, 0x1000,
X 0x0824, 0x1000,
X 0x0, 0x0,
X 0x0, 0x0,
X 0x0, 0x0,
X
};
X
static struct Image mm_image = {
X 0,0,
X 24 , 12 , 3 ,
X &mm[0],
X 0x1f,0x00,
X NULL
};
X
#define LINE_LENGTH 55
#define NUM_LINES 20
X
#define WINDOW_WIDTH (LINE_LENGTH * 8) + 10
#define WINDOW_HEIGHT (NUM_LINES * 10) + 15
X
struct MMTool {
X struct Tool tool;
X
X int line;
X
X char lines[NUM_LINES][LINE_LENGTH];
};
X
static struct ToolMaster master;
X
extern struct Functions *functions;
X
static void
mm_tool_init(struct MMTool *tool)
{
X tool->tool.touched = TOUCH_INIT;
X
X tool->line = 0;
X
X for (int i = 0; i < NUM_LINES; i++)
X {
X for (int j = 0; j < LINE_LENGTH - 1; j++)
X {
X tool->lines[i][j] = ' ';
X }
X tool->lines[i][LINE_LENGTH - 1] = '\0';
X }
}
X
static void
display_lines(struct MMTool *tool)
{
X struct RastPort *rp = tool->tool.window->RPort;
X
X SetAPen(rp, 1);
X SetBPen(rp, 0);
X SetDrMd(rp, JAM2);
X
X int line = tool->line;
X
X for (int i = 0;
X i < NUM_LINES;
X i++)
X {
X Move(rp, 7, WINDOW_HEIGHT - 5 - i * 10);
X
X Text(rp, tool->lines[line], LINE_LENGTH - 1);
X line = (line == 0) ? NUM_LINES - 1 : line - 1;
X }
}
X
/* Returns a text string given a midi note number. */
static void
note_to_name(unsigned char note, char *note_name)
{
X static char *note_names[] = {
X "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "Bb", "B"
X };
X
X sprintf(note_name, "%s%1ld", note_names[note % 12], (int) note / 12);
}
X
__geta4
static struct Event *
processeventcode(struct Event *event)
{
X struct MMTool *tool = (struct MMTool *) event->tool;
X struct NoteEvent *note = (struct NoteEvent *) event;
X
X char time_string[MBC_STRING_LENGTH];
X
X if (!tool->tool.touched)
X {
X mm_tool_init(tool);
X }
X
X tool->line = (tool->line + 1) % NUM_LINES;
X
X (*functions->timetostring)(&(tool->tool.track->clip),
X note->time, time_string);
X
X switch (note->status)
X {
X case MIDI_NOTEOFF:
X {
X char note_name[10];
X
X note_to_name(note->value, note_name);
X
X sprintf(tool->lines[tool->line], "MIDI_NOTEOFF 0x%02lx %s %ld (%s)",
X note->type & 0xff,
X time_string,
X note->value, note_name);
X }
X break;
X case MIDI_NOTEON:
X {
X char note_name[10];
X char duration_string[MBC_STRING_LENGTH];
X
X note_to_name(note->value, note_name);
X (*functions->lengthtostring)(&(tool->tool.track->clip),
X note->time,
X note->duration,
X duration_string);
X
X sprintf(tool->lines[tool->line], "MIDI_NOTEON 0x%02lx %s %ld (%s) %ld %s",
X note->type & 0xff,
X time_string,
X note->value, note_name,
X note->velocity,
X duration_string);
X }
X break;
X case MIDI_PTOUCH:
X {
X char note_name[10];
X
X note_to_name(note->value, note_name);
X
X sprintf(tool->lines[tool->line], "MIDI_PTOUCH 0x%02lx %s %ld (%s) %ld",
X note->type & 0xff,
X time_string,
X note->value, note_name,
X note->velocity);
X }
X break;
X case MIDI_CCHANGE:
X sprintf(tool->lines[tool->line], "MIDI_CCHANGE 0x%02lx %s %ld %ld",
X note->type & 0xff,
X time_string,
X event->byte1,
X event->byte2);
X break;
X case MIDI_PCHANGE:
X sprintf(tool->lines[tool->line], "MIDI_PCHANGE 0x%02lx %s %ld",
X note->type & 0xff,
X time_string,
X event->byte1);
X break;
X case MIDI_MTOUCH:
X sprintf(tool->lines[tool->line], "MIDI_MTOUCH 0x%02lx %s %ld",
X note->type & 0xff,
X time_string,
X event->byte1);
X break;
X case MIDI_PBEND:
X {
X sprintf(tool->lines[tool->line], "MIDI_PBEND 0x%02lx %s 0x%lx 0x%lx (0x%lx)",
X note->type & 0xff,
X time_string,
X event->byte1, event->byte2,
X (event->byte2 << 7) + event->byte1);
X }
X break;
X case MIDI_SYSX:
X sprintf(tool->lines[tool->line], "MIDI_SYSX 0x%02lx %s",
X note->type & 0xff,
X time_string);
X break;
X case MIDI_MTC:
X sprintf(tool->lines[tool->line], "MIDI_MTC 0x%02lx %s",
X note->type & 0xff,
X time_string);
X break;
X case MIDI_SONGPP:
X sprintf(tool->lines[tool->line], "MIDI_SONGPP 0x%02lx %s",
X note->type & 0xff,
X time_string);
X break;
X case MIDI_SONGS:
X sprintf(tool->lines[tool->line], "MIDI_SONGS 0x%02lx %s",
X note->type & 0xff,
X time_string);
X break;
X case MIDI_EOX:
X sprintf(tool->lines[tool->line], "MIDI_EOX 0x%02lx %s",
X note->type & 0xff,
X time_string);
X break;
X case MIDI_CLOCK:
X sprintf(tool->lines[tool->line], "MIDI_CLOCK 0x%02lx %s",
X note->type & 0xff,
X time_string);
X break;
X case MIDI_START:
X sprintf(tool->lines[tool->line], "MIDI_START 0x%02lx %s",
X note->type & 0xff,
X time_string);
X break;
X case MIDI_CONTINUE:
X sprintf(tool->lines[tool->line], "MIDI_CONTINUE 0x%02lx %s",
X note->type & 0xff,
X time_string);
X break;
X case MIDI_STOP:
X sprintf(tool->lines[tool->line], "MIDI_STOP 0x%02lx %s",
X note->type & 0xff,
X time_string);
X break;
X case MIDI_SENSE:
X sprintf(tool->lines[tool->line], "MIDI_SENSE 0x%02lx %s",
X note->type & 0xff,
X time_string);
X break;
X }
X
X for (int i = strlen(tool->lines[tool->line]);
X i < LINE_LENGTH - 1;
X i++)
X {
X tool->lines[tool->line][i] = ' ';
X }
X
X tool->lines[tool->line][LINE_LENGTH - 1] = '\0';
X
X if (tool->tool.window)
X {
X display_lines(tool);
X }
X
X event->tool = event->tool->next;
X
X return(event);
}
X
struct NewWindow MMNewWindowStructure1 = {
X 20, 20,
X WINDOW_WIDTH, WINDOW_HEIGHT,
X 0,6,
X GADGETDOWN+GADGETUP+CLOSEWINDOW,
X WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+ACTIVATE+NOCAREREFRESH,
X NULL,
X NULL,
X "MIDI Monitor",
X NULL,
X NULL,
X 5,5,
X -1,-1,
X CUSTOMSCREEN
};
X
__geta4
static void
edittoolcode(struct MMTool *tool)
{
X struct IntuiMessage *message;
X struct Window *window;
X long class, code;
X struct Gadget *gadget;
X struct NewWindow *newwindow;
X MMNewWindowStructure1.Screen = functions->screen;
X
X if (tool->tool.touched & TOUCH_EDIT)
X {
X MMNewWindowStructure1.LeftEdge = tool->tool.left;
X MMNewWindowStructure1.TopEdge = tool->tool.top;
X MMNewWindowStructure1.Width = tool->tool.width;
X MMNewWindowStructure1.Height = tool->tool.height;
X }
X
X if (!tool->tool.touched)
X {
X mm_tool_init(tool);
X }
X
X newwindow = (struct NewWindow *)
X (*functions->DupeNewWindow)(&MMNewWindowStructure1);
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 MM_NAME,(short)-1,(short)-1,0,0);
X
X display_lines(tool);
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 /* Nothing. */
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 (*functions->EmbossWindowOff)(window);
X (*functions->FlashyCloseWindow)(window);
X (*functions->DeleteNewWindow)(newwindow);
}
X
struct ToolMaster *
inittoolmaster()
{
X memset((char *)&master,0,sizeof(struct ToolMaster));
X master.toolid = MM_ID;
X master.image = &mm_image;
X strcpy(master.name, MM_NAME);
X master.edittool = (void_prototype) edittoolcode;
X master.processevent = (event_prototype) processeventcode;
X master.tooltype = MM_TYPE;
X master.toolsize = sizeof(struct MMTool);
X return(&master);
}
SHAR_EOF
chmod 0600 mm.c ||
echo 'restore of mm.c failed'
Wc_c="`wc -c < 'mm.c'`"
test 10155 -eq "$Wc_c" ||
echo 'mm.c: original size 10155, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= mm.ptool ==============
if test -f 'mm.ptool' -a X"$1" != X"-c"; then
echo 'x - skipping mm.ptool (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting mm.ptool (Binary)'
sed 's/^X//' << 'SHAR_EOF' > _shar_tmp_.tmp &&
begin 600 mm.ptool
<encoded_portion_removed>
end
SHAR_EOF
echo 'uudecoding file mm.ptool' &&
uudecode < _shar_tmp_.tmp && rm -f _shar_tmp_.tmp &&
chmod 0600 mm.ptool ||
echo 'restore of mm.ptool failed'
Wc_c="`wc -c < 'mm.ptool'`"
test 3960 -eq "$Wc_c" ||
echo 'mm.ptool: original size 3960, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= mm.readme ==============
if test -f 'mm.readme' -a X"$1" != X"-c"; then
echo 'x - skipping mm.readme (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting mm.readme (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'mm.readme' &&
Short: Bars & Pipes Tool for monitoring MIDI events.
Author: Richard Hagen (R.H...@mailbox.uq.edu.au)
Uploader: Richard Hagen (R.H...@mailbox.uq.edu.au)
Version: 1.1 (22 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
MIDI Monitor: A Bars and Pipes Tool for monitoring MIDI events.
X
Version: 1.1 (22 September 1997)
X
Author: Richard Hagen
X R.H...@mailbox.uq.edu.au
X
Distribution: Freeware. See the copyright notice in mm.c.
X
Requirements for running:
X Bars and Pipes Professional
X
Requirements for recompiling:
X DICE (or some other C compiler)
X bars.h and toolstart.c from the Rules for Tools Kit
X
Usage:
X Pop MIDI Monitor into a pipeline. It will monitor MIDI events.
X If its window is open, it'll show you the MIDI events.
X
X Each event is accompanied by its time, any relevant data fields,
X and in the case of MIDI_NOTEON events, the duration. The information
X for each type of MIDI event is described in the Rules for Tools
X documentation.
X
Useful for:
X Watching the river go by.
X
History:
X 1.1 (22 September 1997)
X Code improvement.
X
X 1.0 (15 September 1997)
X Initial Release
X
richard
R.H...@mailbox.uq.edu.au
22 September 1997
X
X
X
X
X
X
X
X
SHAR_EOF
chmod 0600 mm.readme ||
echo 'restore of mm.readme failed'
Wc_c="`wc -c < 'mm.readme'`"
test 1344 -eq "$Wc_c" ||
echo 'mm.readme: original size 1344, 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
exit 0
--
Bill Zimmer - z...@ibx.com

0 new messages