home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume43
/
tclmidi
/
part07
< prev
next >
Wrap
Internet Message Format
|
1994-07-21
|
63KB
From: durian@boogie.com (Mike Durian)
Newsgroups: comp.sources.misc
Subject: v43i115: tclmidi - A language for manipulating MIDI files, v2.0, Part07/14
Date: 21 Jul 1994 19:27:07 -0500
Organization: Sterling Software
Sender: kent@sparky.sterling.com
Approved: kent@sparky.sterling.com
Message-ID: <30n3or$75n@sparky.sterling.com>
X-Md4-Signature: e18001a857a4c4fb796d48a35b451447
Submitted-by: durian@boogie.com (Mike Durian)
Posting-number: Volume 43, Issue 115
Archive-name: tclmidi/part07
Environment: POSIX, (BSDI, NetBSD, LINUX, SVR4 for optional driver), C++, TCL
Supersedes: tclm: Volume 37, Issue 43-47
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# Contents: tclmidi-2.0/Makefile tclmidi-2.0/device/MPU401Copy.C
# tclmidi-2.0/drivers/LINUX/midi.h tclmidi-2.0/drivers/SVR4/midi.h
# tclmidi-2.0/events/EventUtil.C tclmidi-2.0/events/MetaSeqName.C
# tclmidi-2.0/smf/SMFTrack.C tclmidi-2.0/tclmEvent.h
# Wrapped by kent@sparky on Thu Jul 21 19:05:15 1994
PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 7 (of 14)."'
if test -f 'tclmidi-2.0/Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tclmidi-2.0/Makefile'\"
else
echo shar: Extracting \"'tclmidi-2.0/Makefile'\" \(6421 characters\)
sed "s/^X//" >'tclmidi-2.0/Makefile' <<'END_OF_FILE'
X# Pick your favorite C and C++ compilers
XCXX = g++
XCC = gcc2
X
X# Remove the USE_MPU401 define if you haven't installed the mpu401
X# driver I've supplied. You won't be able to play or record, but
X# you'll still be able to maninpulate the songs.
X# Here is a list of the possible defines
X# -DUSE_MPU401 Include support for the MPU401 MIDI card
X# -DUSE_MPU401COPY Include support for the MPU401 MIDI card
X# Copies play file before playing - slower
X# startup and file can't be modified while
X# playing, but better performance while playing
X# -DSVR4 You are running a SVR4 system
X# -DLINUX You are running a LINUX system
X# -DBSD You are running a BSD system
X# -Dosf1 You are running a DEC Alpha
X#
X# One of the SVR4, LINUX or BSD flags must be defined if you are
X# also defining USE_MPU401 or USE_MPU401COPY.
X#
X# Feel free to add any other flags you like. Such as -O, -g
X#
X# Don McKillican dmckilli@qc.bell.ca says the CFLAGS for the Dec Alpha
X# using cxx should be
X# CFLAGS = -I/usr/include/cxx -O -Dosf1 -D__STDC__
X
XCFLAGS = -Wall -O -DBSD -DUSE_MPU401COPY
X
X# where to put the executables
XBINDIR = /usr/local/bin
X
X# where to put the libraries
XLIBDIR = /usr/local/lib
X
X# where to put the header file
XINCDIR = /usr/local/include
X
X# where to put the man pages
XMANPATH = /usr/local/man
X
X# where the TCL library resides
XTCLLIBDIR = /usr/lib
X
X# where the TCL header file resides
XTCLHDRDIR = /usr/include
X
X# any extra libraries you might need
X# BSD/386 1.1 wants gnulib to resolve ___eprintf
XEXTRALIB = -lgnulib
X
X# SVR4 doesn't need ranlib, set it to true
X#RANLIB = true
XRANLIB = ranlib
X
X# if you want to build a version of tclmidi that works with tk,
X# set the following and "make tkmidi"
XXINCDIR = /usr/X11/include
XXLIBDIR = /usr/X11/lib
X
X#
X# You shouldn't need to change anything else
X#
X
XLFLAGS = -L. -Lrb -L$(TCLLIBDIR) -ltcl -ltclmidi -lmidi++ -lrb -lm $(EXTRALIB)
XTKLFLAGS = -L. -Lrb -L$(TCLLIBDIR) -ltk -ltcl -ltclmidi -lmidi++ -lrb -lm \
X -L$(XLIBDIR) -lX11 $(EXTRALIB)
XINCDIRS = -Ievents -Isong -Ismf -Idevice -Irb -I$(TCLHDRDIR)
X
XTCLMFILES = tclmCmd.o tclmUtil.o tclmEvent.o tclmPlay.o TclmInterp.o
XAPPINIT = tclmAppInit.o
XTKAPPINIT = tkmAppInit.o
X
X.SUFFIXES: .C $(SUFFIXES)
X
X.C.o:
X $(CXX) $(CFLAGS) $(INCDIRS) -c -o $@ $<
X
Xall: tclmidi
X
Xevents/objs: FORCE
X cd events; make objs CXX=$(CXX) CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)"
X
Xsmf/objs: FORCE
X cd smf; make objs CXX=$(CXX) CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)"
X
Xsong/objs: FORCE
X cd song; make objs CXX=$(CXX) CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)"
X
Xdevice/objs: FORCE
X cd device; make objs CXX=$(CXX) CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)"
X
Xrb/librb.a: FORCE
X cd rb; make librb.a CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)"
X
Xlibmidi++.a: events/objs smf/objs song/objs device/objs
X -rm libmidi++.a
X ar ru libmidi++.a events/*.o smf/*.o song/*.o device/*.o
X $(RANLIB) libmidi++.a
X
Xlibtclmidi.a: $(TCLMFILES)
X -rm libtclmidi.a
X ar ru libtclmidi.a $(TCLMFILES)
X $(RANLIB) libtclmidi.a
X
Xtclmidi: libmidi++.a rb/librb.a libtclmidi.a $(APPINIT)
X $(CXX) -o tclmidi $(APPINIT) $(LFLAGS)
X
Xtkmidi: libmidi++.a rb/librb.a libtclmidi.a $(TKAPPINIT)
X $(CXX) -o tkmidi $(TKAPPINIT) $(TKLFLAGS)
X
XtkmAppInit.o: tkmAppInit.C
X $(CXX) $(CFLAGS) $(INCDIRS) -I$(XINCDIR) -c -o $@ $<
X
Xinstall: tclmidi
X cp tclmidi mplay mrec minfo midtotcl $(BINDIR)
X cp libtclmidi.a libmidi++.a $(LIBDIR)
X cp tclmidi.h $(INCDIR)
X $(RANLIB) $(LIBDIR)/libtclmidi.a
X $(RANLIB) $(LIBDIR)/libmidi++.a
X
Xinstall-tkmidi: tkmidi
X cp tkmidi $(BINDIR)
X
Xinstall-man-cooked:
X cd man; make install-cooked MANPATH="$(MANPATH)"
X
Xinstall-man-raw:
X cd man; make install-raw MANPATH="$(MANPATH)"
X
Xclean:
X -rm *.o *.a
X cd events; make clean
X cd smf; make clean
X cd song; make clean
X cd device; make clean
X cd rb; make clean
X cd man; make clean
X
XFORCE:
X
XtclmCmd.o: tclmidi.h TclmInterp.h song/Song.h song/EventTree.h events/Event.h \
X smf/SMFTrack.h device/MidiDevice.h tclmEvent.h events/AllEvents.h \
X events/NormalEvent.h events/Note.h events/NoteOff.h \
X events/NoteOn.h events/KeyPressure.h events/Parameter.h events/Program.h \
X events/ChanPressure.h events/PitchWheel.h events/SystemExcl.h \
X events/MetaEvent.h events/MetaSeqNum.h events/MetaText.h \
X events/MetaCopy.h events/MetaSeqName.h events/MetaInstName.h \
X events/MetaLyric.h events/MetaMarker.h events/MetaCue.h \
X events/MetaChanPrefix.h events/MetaPortNum.h events/MetaEOT.h \
X events/MetaTempo.h events/MetaSMPTE.h events/MetaTime.h events/MetaKey.h \
X events/MetaSeqSpec.h events/MetaUnknown.h \
X patchlevel.h
XtclmEvent.o: tclmidi.h TclmInterp.h song/Song.h song/EventTree.h \
X events/Event.h smf/SMFTrack.h device/MidiDevice.h tclmEvent.h \
X events/AllEvents.h events/NormalEvent.h events/Note.h events/NoteOff.h \
X events/NoteOn.h events/KeyPressure.h events/Parameter.h events/Program.h \
X events/ChanPressure.h events/PitchWheel.h events/SystemExcl.h \
X events/MetaEvent.h events/MetaSeqNum.h events/MetaText.h \
X events/MetaCopy.h events/MetaSeqName.h events/MetaInstName.h \
X events/MetaLyric.h events/MetaMarker.h events/MetaCue.h \
X events/MetaChanPrefix.h events/MetaPortNum.h events/MetaEOT.h \
X events/MetaTempo.h events/MetaSMPTE.h events/MetaTime.h events/MetaKey.h \
X events/MetaSeqSpec.h events/MetaUnknown.h
XtclmPlay.o: tclmidi.h TclmInterp.h song/Song.h song/EventTree.h events/Event.h \
X smf/SMFTrack.h device/MidiDevice.h tclmEvent.h events/AllEvents.h \
X events/NormalEvent.h events/Note.h events/NoteOff.h \
X events/NoteOn.h events/KeyPressure.h events/Parameter.h events/Program.h \
X events/ChanPressure.h events/PitchWheel.h events/SystemExcl.h \
X events/MetaEvent.h events/MetaSeqNum.h events/MetaText.h \
X events/MetaCopy.h events/MetaSeqName.h events/MetaInstName.h \
X events/MetaLyric.h events/MetaMarker.h events/MetaCue.h \
X events/MetaChanPrefix.h events/MetaPortNum.h events/MetaEOT.h \
X events/MetaTempo.h events/MetaSMPTE.h events/MetaTime.h events/MetaKey.h \
X events/MetaSeqSpec.h events/MetaUnknown.h \
X device/MPU401.h device/MPU401Copy.h device/MidiDevice.h
XTclmInterp.o: TclmInterp.h song/Song.h song/EventTree.h events/Event.h \
X smf/SMFTrack.h device/MidiDevice.h
XtclmAppInit.o: tclmidi.h TclmInterp.h song/Song.h song/EventTree.h \
X events/Event.h smf/SMFTrack.h device/MidiDevice.h
END_OF_FILE
if test 6421 -ne `wc -c <'tclmidi-2.0/Makefile'`; then
echo shar: \"'tclmidi-2.0/Makefile'\" unpacked with wrong size!
fi
# end of 'tclmidi-2.0/Makefile'
fi
if test -f 'tclmidi-2.0/device/MPU401Copy.C' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tclmidi-2.0/device/MPU401Copy.C'\"
else
echo shar: Extracting \"'tclmidi-2.0/device/MPU401Copy.C'\" \(13877 characters\)
sed "s/^X//" >'tclmidi-2.0/device/MPU401Copy.C' <<'END_OF_FILE'
X/*-
X * Copyright (c) 1993, 1994 Michael B. Durian. All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X * must display the following acknowledgement:
X * This product includes software developed by Michael B. Durian.
X * 4. The name of the the Author may be used to endorse or promote
X * products derived from this software without specific prior written
X * permission.
X *
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X#ifdef USE_MPU401COPY
X#include <assert.h>
X#include <stdlib.h>
X#include <unistd.h>
X#include <string.h>
X#include <strstream.h>
X#include <fcntl.h>
X#include <signal.h>
X#include <errno.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/ioctl.h>
X
X#ifdef SVR4
X#include <sys/filio.h>
X#include <sys/midi.h>
X#endif
X
X#ifdef LINUX
X#include <linux/termios.h>
X#include <linux/midi.h>
X#endif
X
X#ifdef BSD
X#include <i386/isa/midiioctl.h>
X#endif
X
X#include "MPU401Copy.h"
X#include "EventUtil.h"
X#include "Note.h"
X
Xtypedef void Sigfunc(int);
X
Xstatic MPU401Copy *CurrentMPU401 = 0;
Xstatic Sigfunc *posixsignal(int signo, Sigfunc *func);
X
XMPU401Copy::MPU401Copy() : fd(-1), last_rec_time(0), finished(0),
X last_record_rs(0), playbuf(0), playbufptr(0), playbufend(0)
X{
X
X assert(CurrentMPU401 == 0);
X CurrentMPU401 = this;
X posixsignal(SIGIO, SIG_IGN);
X}
X
XMPU401Copy::MPU401Copy(const char *dev) : MidiDevice(dev), fd(-1),
X last_rec_time(0), finished(0), last_record_rs(0), playbuf(0),
X playbufptr(0), playbufend(0)
X{
X
X assert(CurrentMPU401 == 0);
X CurrentMPU401 = this;
X posixsignal(SIGIO, SIG_IGN);
X}
X
XMPU401Copy::~MPU401Copy()
X{
X
X if (fd != -1)
X Stop();
X play_track.Empty();
X CurrentMPU401 = 0;
X}
X
Xint
XMPU401Copy::Play(Song *s, int r)
X{
X ostrstream err;
X const char *name;
X char *str;
X int arg;
X
X // open the device
X if (fd != -1) {
X SetError("Device already open");
X return (0);
X }
X if ((name = GetName()) == 0) {
X SetError("No device set");
X return (0);
X }
X
X // set repeat
X SetRepeat(r);
X
X // initialize track/event info
X if (!BuildSMF(play_track, s)) {
X SetError("Out of memory");
X return (0);
X }
X playbufptr = playbuf = play_track.PeekByte();
X playbufend = &playbuf[play_track.GetLength()];
X
X should_stop = 0;
X finished = 0;
X
X // set up async stuff
X posixsignal(SIGIO, MPU401CopySigIO);
X
X // open device
X if ((fd = open(name, O_WRONLY | O_NONBLOCK)) == -1) {
X err << "open failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X
X#ifndef LINUX
X /* Linux doesn't allow F_SETOWN except for sockets - bug */
X if (fcntl(fd, F_SETOWN, getpid()) == -1) {
X err << "fcntl F_SETOWN failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X#else
X arg = getpid();
X if (ioctl(fd, TIOCSPGRP, &arg) == -1) {
X err << "ioctl TIOCSPGRP failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X#endif
X
X // set division
X arg = s->GetDivision();
X if (ioctl(fd, MSDIVISION, &arg) == -1) {
X err << "ioctl MSDIVISION failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X
X arg = GetMidiThru();
X if (ioctl(fd, MTHRU, &arg) == -1) {
X err << "ioctl MTHRU failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X
X // the following should be a fcntl FIOASYNC call, but the
X // FIOASYNC ioctl doesn't always get passed down to the driver
X // properly under all OSes (read Linux), thus we use the MASYNC
X // entry point.
X arg = 1;
X if (ioctl(fd, MASYNC, &arg) == -1) {
X err << "ioctl MASYNC failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X
X return (1);
X}
X
Xint
XMPU401Copy::Record(Song *rs, Song *ps, int r)
X{
X ostrstream err;
X const char *name;
X char *str;
X int arg;
X
X if (fd != -1)
X return (0);
X if ((name = GetName()) == 0)
X return (0);
X
X rec_song = rs;
X last_rec_time = 0;
X last_record_rs = 0;
X if (ps == 0) {
X play_track.Empty();
X playbuf = 0;
X playbufptr = 0;
X playbufend = 0;
X if ((fd = open(name, O_RDONLY)) == -1) {
X err << "open failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X arg = rec_song->GetDivision();
X if (ioctl(fd, MSDIVISION, &arg) == -1) {
X err << "ioctl MSDIVISION failed: " << strerror(errno)
X << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X } else {
X
X // initialize track/event info
X if (!BuildSMF(play_track, ps)) {
X SetError("Out of memory");
X return (0);
X }
X
X playbufptr = playbuf = play_track.PeekByte();
X playbufend = &playbuf[play_track.GetLength()];
X
X if ((fd = open(name, O_RDWR | O_NONBLOCK)) == -1) {
X err << "open failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X
X // set division
X arg = ps->GetDivision();
X if (ioctl(fd, MSDIVISION, &arg) == -1) {
X err << "ioctl MSDIVISION failed: " << strerror(errno)
X << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X
X // start record timer when first event is scheduled to play
X arg = 1;
X if (ioctl(fd, MRECONPLAY, &arg) == -1) {
X err << "ioctl MRECONPLAY failed: " << strerror(errno)
X << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X
X should_stop = 0;
X finished = 0;
X }
X
X // set repeat
X SetRepeat(r);
X
X // set up async stuff
X posixsignal(SIGIO, MPU401CopySigIO);
X#ifndef LINUX
X /* Linux doesn't allow F_SETOWN except for sockets - bug */
X if (fcntl(fd, F_SETOWN, getpid()) == -1) {
X err << "fcntl F_SETOWN failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X#else
X arg = getpid();
X if (ioctl(fd, TIOCSPGRP, &arg) == -1) {
X err << "ioctl TIOCSPGRP failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X#endif
X arg = GetMidiThru();
X if (ioctl(fd, MTHRU, &arg) == -1) {
X err << "ioctl MTHRU failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X
X // the following should be a fcntl FIOASYNC call, but the
X // FIOASYNC ioctl doesn't always get passed down to the driver
X // properly under all OSes (read Linux), thus we use the MASYNC
X // entry point.
X arg = 1;
X if (ioctl(fd, MASYNC, &arg) == -1) {
X err << "ioctl MASYNC failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X
X return (1);
X}
X
Xint
XMPU401Copy::Stop(void)
X{
X ostrstream err;
X char *str;
X int arg;
X
X finished = 1;
X should_stop = 0;
X if (fd == -1)
X return (1);
X
X posixsignal(SIGIO, SIG_IGN);
X
X arg = 0;
X if (ioctl(fd, MASYNC, &arg) == -1) {
X err << "ioctl MASYNC failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X
X if (ioctl(fd, MGPLAYQ, &arg) == -1) {
X err << "ioctl MGPLAYQ failed: " << strerror(errno) << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X // flush queues
X if (arg != 0)
X if (ioctl(fd, MDRAIN, NULL) == -1) {
X err << "ioctl MDRAIN failed: " << strerror(errno)
X << ends;
X str = err.str();
X SetError(str);
X delete str;
X return (0);
X }
X
X close (fd);
X fd = -1;
X
X play_track.Empty();
X playbuf = 0;
X playbufptr = 0;
X playbufend = 0;
X rec_song = 0;
X return (1);
X}
X
Xint
XMPU401Copy::Wait(void)
X{
X sigset_t sigset;
X
X if (play_track.GetLength() == 0)
X return (1);
X if (finished)
X return (1);
X finished = 0;
X sigemptyset(&sigset);
X do
X sigsuspend(&sigset);
X while (!finished);
X return (1);
X}
X
X/*
X * Since this routine is called ASYNC, we just print out errors
X * instead of putting them in SetError
X */
Xvoid
XMPU401CopySigIO(int notused)
X{
X struct timeval t;
X fd_set rset, wset;
X MPU401Copy *mpu;
X MidiDeviceCallback callback;
X const char *errstr;
X
X mpu = CurrentMPU401;
X if (mpu == 0 || mpu->fd == -1)
X return;
X
X FD_ZERO(&rset);
X FD_ZERO(&wset);
X FD_SET(mpu->fd, &rset);
X FD_SET(mpu->fd, &wset);
X t.tv_sec = 0;
X t.tv_usec = 0;
X
X // poll to find out what caused the SIGIO
X if (select(mpu->fd + 1, &rset, &wset, 0, &t) == -1) {
X cerr << "error selecting MPU401Copy: " << strerror(errno)
X << "\n";
X return;
X }
X
X // check for record event
X if (FD_ISSET(mpu->fd, &rset)) {
X if (mpu->rec_song != 0) {
X int num_read;
X EventType etype;
X unsigned char event[MaxEventSize];
X SMFTrack track;
X Event *e, *first_e;
X
X // read event
X // This involves dynamic allocation, but
X // what can we do? Events might be larger
X // than can fit in the event buffer.
X do {
X if ((num_read = read(mpu->fd, event,
X MaxEventSize)) == -1) {
X cerr << "error reading MPU401Copy "
X "event: " << strerror(errno)
X << "\n";
X return;
X }
X track.PutData(event, num_read);
X } while (num_read == MaxEventSize);
X
X // process events
X track.SetRunningState(mpu->last_record_rs);
X first_e = 0;
X /*
X * XXX This is a problem. ReadEventFromSMFTrack
X * calls new to create the event. New uses
X * malloc which is not reentrant. I don't know
X * how to get around this.
X */
X while ((e = ReadEventFromSMFTrack(track,
X mpu->last_rec_time, errstr)) != 0) {
X Event *new_e;
X
X if (first_e == 0)
X first_e = e;
X new_e = mpu->rec_song->PutEvent(0, *e);
X delete e;
X if (new_e == 0) {
X continue;
X }
X etype = new_e->GetType();
X // put links on noteoffs
X if ((etype == NOTEON &&
X ((NoteEvent *)new_e)->GetVelocity() == 0)
X || etype == NOTEOFF)
X mpu->rec_song->SetNotePair(0, new_e);
X }
X if (errstr != 0)
X cerr << "Error while recording: " << errstr
X << "\n";
X mpu->last_record_rs = track.GetRunningState();
X if ((callback = mpu->GetRecordCallback()) != 0)
X callback(first_e);
X }
X }
X
X if (FD_ISSET(mpu->fd, &wset)) {
X if (mpu->play_track.GetLength() != 0 && !mpu->finished) {
X if (!mpu->Send()) {
X cerr << "Couldn't write play event\n";
X exit(1);
X }
X }
X }
X}
X
Xint
XMPU401Copy::Send()
X{
X int numleft, numwritten;
X int arg;
X
X if (should_stop) {
X if (ioctl(fd, MGPLAYQ, &arg) == -1) {
X cerr << "MPU401Copy: ioctl MGPLAY failed: " <<
X strerror(errno) << "\n";
X return (0);
X }
X if (arg == 0) {
X // the sigio we just caught signifies all events
X // have been played
X finished = 1;
X return (1);
X }
X }
X if (playbuf == 0)
X return (0);
X numleft = playbufend - playbufptr;
X if ((numwritten = write(fd, playbufptr, numleft)) == -1) {
X cerr << "Couldn't write: " << strerror(errno) << "\n";
X return (0);
X }
X playbufptr += numwritten;
X numleft -= numwritten;
X if (numleft == 0) {
X if (!GetRepeat()) {
X should_stop = 1;
X return (1);
X } else {
X playbufptr = playbuf;
X numleft = playbufend - playbufptr;
X }
X }
X return (1);
X}
X
Xint
XMPU401Copy::BuildSMF(SMFTrack &smftrack, Song *s)
X{
X unsigned long firsttime, lasttime, t;
X int empty, i, lowest, numtracks;
X Event *e, **trackevents;
X const char *errstr;
X
X numtracks = s->GetNumTracks();
X trackevents = new Event *[numtracks];
X if (trackevents == 0)
X return (0);
X empty = 1;
X // get first events in each track
X for (i = 0; i < numtracks; i++) {
X trackevents[i] = s->GetTrack(i).GetFirstEvent();
X if (trackevents[i] != 0)
X empty = 0;
X }
X lasttime = 0;
X while (!empty) {
X /* find track with lowest numbered event */
X lowest = -1;
X /* quiet warning */
X firsttime = 0;
X for (i = 0; i < numtracks; i++) {
X if (trackevents[i] == 0)
X continue;
X if (lowest == -1) {
X firsttime = trackevents[i]->GetTime();
X lowest = i;
X } else {
X t = trackevents[i]->GetTime();
X if (t < firsttime) {
X firsttime = t;
X lowest = i;
X }
X }
X }
X if (lowest == -1) {
X empty = 1;
X break;
X }
X /* stick events into SMF */
X for (e = trackevents[lowest]; e != 0; e = e->GetNextEvent()) {
X if (!WriteEventToSMFTrack(smftrack, lasttime, e,
X errstr))
X return (0);
X }
X /* update trackevents pointer */
X trackevents[lowest] = s->GetTrack(lowest).NextEvents(
X trackevents[lowest]);
X }
X delete trackevents;
X return (1);
X}
X
Xostream &
Xoperator<<(ostream &os, const MPU401Copy &mpu)
X{
X
X os << mpu.GetName();
X if (mpu.playbuf != 0)
X os << " Playing";
X if (mpu.rec_song != 0)
X os << " Recording";
X return (os);
X}
X
XSigfunc *
Xposixsignal(int signo, Sigfunc *func)
X{
X struct sigaction act, oact;
X
X sigemptyset(&oact.sa_mask);
X sigemptyset(&act.sa_mask);
X act.sa_handler = func;
X act.sa_flags = 0;
X
X if (signo == SIGALRM) {
X#ifdef SA_INTERRUPT
X act.sa_flags |= SA_INTERRUPT; /* SunOS */
X#endif
X } else {
X#ifdef SA_RESTART
X act.sa_flags |= SA_RESTART; /* SVR4, 4.4BSD */
X#endif
X }
X
X if (sigaction(signo, &act, &oact) < 0)
X return (SIG_ERR);
X return (oact.sa_handler);
X}
X#endif
END_OF_FILE
if test 13877 -ne `wc -c <'tclmidi-2.0/device/MPU401Copy.C'`; then
echo shar: \"'tclmidi-2.0/device/MPU401Copy.C'\" unpacked with wrong size!
fi
# end of 'tclmidi-2.0/device/MPU401Copy.C'
fi
if test -f 'tclmidi-2.0/drivers/LINUX/midi.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tclmidi-2.0/drivers/LINUX/midi.h'\"
else
echo shar: Extracting \"'tclmidi-2.0/drivers/LINUX/midi.h'\" \(6775 characters\)
sed "s/^X//" >'tclmidi-2.0/drivers/LINUX/midi.h' <<'END_OF_FILE'
X/*-
X * Copyright (c) 1993, 1994 Michael B. Durian. All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X * must display the following acknowledgement:
X * This product includes software developed by Michael B. Durian.
X * 4. The name of the the Author may be used to endorse or promote
X * products derived from this software without specific prior written
X * permission.
X *
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X#ifndef MIDI_H
X#define MIDI_H
X/*
X * MIDI MPU401 ioctls
X */
X#define DSPIOCTL ('m' << 8)
X#define MRESET (DSPIOCTL | 0x01) /* no read, no write */
X#define MDRAIN (DSPIOCTL | 0x02) /* no read, no write */
X#define MFLUSH (DSPIOCTL | 0x03) /* no read, no write */
X#define MGPLAYQ (DSPIOCTL | 0x04) /* read int */
X#define MGRECQ (DSPIOCTL | 0x05) /* read int */
X#define MSDIVISION (DSPIOCTL | 0x06) /* write int */
X#define MGDIVISION (DSPIOCTL | 0x07) /* read int */
X#define MGQAVAIL (DSPIOCTL | 0x08) /* read int */
X/*
X * I'd argue that this ioctl is only necessary because of a
X * bug in the Linux kernel. They ioctl handler processes the
X * FIOASYNC ioctl and does not check the underlying driver to
X * see if other actions should be performed. The MASYNC ioctl
X * command is really just FIOASYNC.
X */
X#define MASYNC (DSPIOCTL | 0x09) /* write int */
X#define MTHRU (DSPIOCTL | 0x0a) /* write int */
X#define MRECONPLAY (DSPIOCTL | 0x0b) /* write int */
X
X
X
X#ifdef __KERNEL__
X/*
X * midi port offsets
X */
X#define MIDI_DATA 0
X#define MIDI_STATUS 1
X#define MIDI_COMMAND 1
X
X
X/*
X * midi data transfer status bits
X */
X#define MIDI_RDY_RCV (1 << 6)
X#define MIDI_DATA_AVL (1 << 7)
X
X/*
X * midi status flags
X */
X#define MIDI_UNAVAILABLE (1 << 0) /* not in uart mode */
X#define MIDI_READING (1 << 1) /* open for reading */
X#define MIDI_WRITING (1 << 2) /* open for writing */
X#define MIDI_CALLBACK_ISSUED (1 << 3) /* waiting for a timer to expire */
X#define MIDI_RD_BLOCK (1 << 4) /* read will block */
X#define MIDI_WR_BLOCK (1 << 5) /* write will block */
X#define MIDI_WR_ABORT (1 << 6) /* write should abort */
X#define MIDI_OPEN (1 << 7) /* device is open */
X#define MIDI_FLUSH_SLEEP (1 << 8) /* blocking on flush */
X#define MIDI_RD_SLEEP (1 << 9) /* blocking on read */
X#define MIDI_WR_SLEEP (1 << 10) /* blocking on write */
X#define MIDI_BUFFER_SLEEP (1 << 11) /* blocking on buffer */
X#define MIDI_NEED_ACK (1 << 12) /* command needs and ack */
X#define MIDI_ASYNC (1 << 13) /* send sigios */
X#define MIDI_SENDIO (1 << 14) /* a sigio should be send at low h2o */
X#define MIDI_NONBLOCK (1 << 15) /* non blocking mode */
X#define MIDI_SELOUT (1 << 16) /* wait for a select output */
X#define MIDI_SELIN (1 << 17) /* wait for a select input */
X#define MIDI_THRU (1 << 18) /* copy in port to out port? */
X#define MIDI_RECONPLAY (1 << 19) /* start record timer on play */
X
X/*
X * These are the various input data states
X */
Xtypedef enum {START, NEEDDATA1, NEEDDATA2, SYSEX, SYSTEM1, SYSTEM2} InputState;
X
X/*
X * midi command values
X */
X#define MIDI_RESET 0xff
X#define MIDI_UART 0x3f
X#define MIDI_ACK 0xfe
X#define MIDI_TRIES 20000
X
X/*
X * most events are short, so we use the static array,
X * but occationally we get a long event (sysex) and
X * we dynamically allocate that
X */
X#define STYNAMIC_SIZE 4
X#define STYNAMIC_ALLOC 256
X
Xstruct stynamic {
X short allocated;
X short len;
X u_char datas[4];
X u_char *datad;
X};
X
X/*
X * data from the board that hasn't formed a complete event yet
X */
Xstruct partial_event {
X struct stynamic event; /* the data */
X u_long jiffs; /* try out using jiffies */
X long tempo; /* tempo setting when event arrived */
X InputState state; /* what we are expecting next */
X u_char rs; /* the midi running state */
X};
X
X/*
X * the internal representation of an event
X */
Xtypedef enum {NORMAL, TEMPO, TIMESIG, SYSX} EventType;
X
Xstruct event {
X u_long time; /* time until event in kernel clicks */
X long tempo; /*
X * not used in play events, but contains
X * the tempo setting current when the
X * incoming event arrived. Used for
X * convert kernel ticks to smf ticks
X */
X EventType type;
X struct stynamic data;
X};
X
X/*
X * A event queue, used for both incoming and outgoing
X */
X#define MIDI_Q_SIZE 150
X#define MIDI_LOW_WATER 40
X
Xstruct event_queue {
X int count;
X struct event events[MIDI_Q_SIZE];
X struct event *end;
X struct event *head;
X struct event *tail;
X};
X
Xstruct midi_softc { /* Driver status information */
X /*
X * various wait queues - why can't linux use addresses
X * like everybody else
X */
X struct wait_queue *flush_waitq;
X struct wait_queue *read_waitq;
X struct wait_queue *write_waitq;
X struct wait_queue *selin_waitq;
X struct wait_queue *selout_waitq;
X struct wait_queue *forever_waitq;
X /* who's running us */
X struct task_struct *owner;
X /* midi specific stuff */
X struct event_queue *rqueue;
X struct event_queue *wqueue;
X struct stynamic rpartial;
X struct stynamic wpartial;
X struct partial_event partial_event;
X u_long prev_incoming; /* try using jiffies */
X struct timer_list timer;
X volatile long status;
X long long premainder;
X long long rremainder;
X long ptempo; /* usec / beat */
X long rtempo; /* usec / beat */
X long prev_rtempo;
X int pgid;
X int addr;
X int intr;
X int division;
X int wpartialpos;
X long write_noop_time;
X short noteon[0x80]; /*
X * each element is a different pitch
X * each bit is a different channel
X */
X u_char readrs;
X u_char writers;
X u_char noteonrs;
X};
X
Xstruct midi_config {
X int addr;
X int intr;
X};
X
X/* for mem.c */
Xextern long midiinit(long);
X
X#endif
X#endif
END_OF_FILE
if test 6775 -ne `wc -c <'tclmidi-2.0/drivers/LINUX/midi.h'`; then
echo shar: \"'tclmidi-2.0/drivers/LINUX/midi.h'\" unpacked with wrong size!
fi
# end of 'tclmidi-2.0/drivers/LINUX/midi.h'
fi
if test -f 'tclmidi-2.0/drivers/SVR4/midi.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tclmidi-2.0/drivers/SVR4/midi.h'\"
else
echo shar: Extracting \"'tclmidi-2.0/drivers/SVR4/midi.h'\" \(5896 characters\)
sed "s/^X//" >'tclmidi-2.0/drivers/SVR4/midi.h' <<'END_OF_FILE'
X/*-
X * Copyright (c) 1993, 1994 Michael B. Durian. All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X * must display the following acknowledgement:
X * This product includes software developed by Michael B. Durian.
X * 4. The name of the the Author may be used to endorse or promote
X * products derived from this software without specific prior written
X * permission.
X *
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X/*
X * MIDI MPU401 ioctls
X */
X#define DSPIOCTL ('m' << 8)
X#define MRESET (DSPIOCTL | 0x01) /* no read, no write */
X#define MDRAIN (DSPIOCTL | 0x02) /* no read, no write */
X#define MFLUSH (DSPIOCTL | 0x03) /* no read, no write */
X#define MGPLAYQ (DSPIOCTL | 0x04) /* read int */
X#define MGRECQ (DSPIOCTL | 0x05) /* read int */
X#define MSDIVISION (DSPIOCTL | 0x06) /* write int */
X#define MGDIVISION (DSPIOCTL | 0x07) /* read int */
X#define MGQAVAIL (DSPIOCTL | 0x08) /* read int */
X#define MASYNC (DSPIOCTL | 0x09) /* write int */
X#define MTHRU (DSPIOCTL | 0x0a) /* write int */
X#define MRECONPLAY (DSPIOCTL | 0x0b) /* write int */
X
X
X
X#ifdef INKERNEL
X/*
X * midi port offsets
X */
X#define MIDI_DATA 0
X#define MIDI_STATUS 1
X#define MIDI_COMMAND 1
X
X
X/*
X * midi data transfer status bits
X */
X#define MIDI_RDY_RCV (1 << 6)
X#define MIDI_DATA_AVL (1 << 7)
X
X/*
X * midi status flags
X */
X#define MIDI_UNAVAILABLE (1 << 0) /* not in uart mode */
X#define MIDI_READING (1 << 1) /* open for reading */
X#define MIDI_WRITING (1 << 2) /* open for writing */
X#define MIDI_CALLBACK_ISSUED (1 << 3) /* waiting for a timer to expire */
X#define MIDI_RD_BLOCK (1 << 4) /* read will block */
X#define MIDI_WR_BLOCK (1 << 5) /* write will block */
X#define MIDI_WR_ABORT (1 << 6) /* write should abort */
X#define MIDI_OPEN (1 << 7) /* device is open */
X#define MIDI_FLUSH_SLEEP (1 << 8) /* blocking on flush */
X#define MIDI_RD_SLEEP (1 << 9) /* blocking on read */
X#define MIDI_WR_SLEEP (1 << 10) /* blocking on write */
X#define MIDI_BUFFER_SLEEP (1 << 11) /* blocking on buffer */
X#define MIDI_NEED_ACK (1 << 12) /* command needs and ack */
X#define MIDI_ASYNC (1 << 13) /* send sigios */
X#define MIDI_SENDIO (1 << 14) /* a sigio should be send at low h2o */
X#define MIDI_NONBLOCK (1 << 15) /* non blocking mode */
X#define MIDI_THRU (1 << 16) /* copy in port to out port? */
X#define MIDI_RECONPLAY (1 << 17) /* clear record timer on play? */
X
X/*
X * These are the various input data states
X */
Xtypedef enum {START, NEEDDATA1, NEEDDATA2, SYSEX, SYSTEM1, SYSTEM2} InputState;
X
X/*
X * midi command values
X */
X#define MIDI_RESET 0xff
X#define MIDI_UART 0x3f
X#define MIDI_ACK 0xfe
X#define MIDI_TRIES 5000
X
X/*
X * most events are short, so we use the static array,
X * but occationally we get a long event (sysex) and
X * we dynamically allocate that
X */
X#define STYNAMIC_SIZE 4
X#define STYNAMIC_ALLOC 256
X
Xstruct stynamic {
X short allocated;
X short len;
X u_char datas[4];
X u_char *datad;
X};
X
X/*
X * data from the board that hasn't formed a complete event yet
X */
Xstruct partial_event {
X struct stynamic event; /* the data */
X clock_t time; /* when the event occured */
X long tempo; /* tempo setting when event arrived */
X InputState state; /* what we are expecting next */
X u_char rs; /* the midi running state */
X};
X
X/*
X * the internal representation of an event
X */
Xtypedef enum {NORMAL, TEMPO, TIMESIG, SYSX} EventType;
X
Xstruct event {
X u_long time; /* time until event in smf clicks */
X long tempo; /*
X * not used in play events, but contains
X * the tempo setting current when the
X * incoming event arrived. Used for
X * convert kernel ticks to smf ticks
X */
X
X EventType type;
X struct stynamic data;
X};
X
X/*
X * A event queue, used for both incoming and outgoing
X */
X#define MIDI_Q_SIZE 150
X#define MIDI_LOW_WATER 40
X
Xstruct event_queue {
X int count;
X struct event events[MIDI_Q_SIZE];
X struct event *end;
X struct event *head;
X struct event *tail;
X};
X
Xstruct midi_softc { /* Driver status information */
X struct pollhead pollhead;
X proc_t *owner;
X /* midi specific stuff */
X struct event_queue *rqueue;
X struct event_queue *wqueue;
X struct stynamic rpartial;
X struct stynamic wpartial;
X struct partial_event partial_event;
X clock_t prev_incoming;
X volatile long status;
X long long premainder;
X long long rremainder;
X long ptempo; /* usec / beat */
X long rtempo; /* usec / beat */
X long prev_rtempo;
X int pgid;
X int addr;
X int intr;
X int division;
X int timeout_id;
X int wpartialpos;
X long write_noop_time;
X short noteon[0x80]; /*
X * each element is a different pitch
X * each bit is a different channel
X */
X u_char readrs;
X u_char writers;
X u_char noteonrs;
X};
X#endif
END_OF_FILE
if test 5896 -ne `wc -c <'tclmidi-2.0/drivers/SVR4/midi.h'`; then
echo shar: \"'tclmidi-2.0/drivers/SVR4/midi.h'\" unpacked with wrong size!
fi
# end of 'tclmidi-2.0/drivers/SVR4/midi.h'
fi
if test -f 'tclmidi-2.0/events/EventUtil.C' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tclmidi-2.0/events/EventUtil.C'\"
else
echo shar: Extracting \"'tclmidi-2.0/events/EventUtil.C'\" \(7082 characters\)
sed "s/^X//" >'tclmidi-2.0/events/EventUtil.C' <<'END_OF_FILE'
X/*-
X * Copyright (c) 1993, 1994 Michael B. Durian. All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X * must display the following acknowledgement:
X * This product includes software developed by Michael B. Durian.
X * 4. The name of the the Author may be used to endorse or promote
X * products derived from this software without specific prior written
X * permission.
X *
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X#include "EventUtil.h"
X#include "AllEvents.h"
X
XEvent *
XReadEventFromSMFTrack(SMFTrack &track, long &last_t, const char *&errstr)
X{
X long t;
X Event *event;
X const unsigned char *ptr;
X unsigned char state;
X
X errstr = 0;
X event = 0;
X if ((t = track.GetVarValue()) == -1)
X return(0);
X
X t += last_t;
X last_t = t;
X
X // try to determine event type
X if ((ptr = track.PeekByte()) == 0) {
X errstr = "Incomplete event";
X return (0);
X }
X
X if (*ptr & 0x80) {
X // It's a new state - go ahead a get it
X state = *track.GetByte();
X // and change running state
X track.SetRunningState(state);
X } else {
X // we're using the running state
X state = track.GetRunningState();
X if (!(state & 0x80)) {
X errstr = "Making use of invalid running state";
X return (0);
X }
X }
X
X if (state == 0xf0) {
X // reset running state
X track.SetRunningState(0);
X event = new SystemExclusiveEvent(0);
X if (event == 0) {
X errstr = "Out of memory";
X return (0);
X }
X } else if (state == 0xf7) {
X // reset running state
X track.SetRunningState(0);
X event = new SystemExclusiveEvent(1);
X if (event == 0) {
X errstr = "Out of memory";
X return (0);
X }
X } else if (state == 0xff) {
X // reset running state
X track.SetRunningState(0);
X // meta event - determined by next byte
X if ((ptr = track.GetByte()) == 0) {
X errstr = "Incomplete Meta event";
X return (0);
X }
X switch (*ptr) {
X case 0x00:
X event = new MetaSequenceNumberEvent();
X break;
X case 0x01: case 0x08: case 0x09: case 0x0a:
X case 0x0b: case 0x0c: case 0x0d: case 0x0e:
X case 0x0f:
X event = new MetaTextEvent();
X break;
X case 0x02:
X event = new MetaCopyrightEvent();
X break;
X case 0x03:
X event = new MetaSequenceNameEvent();
X break;
X case 0x04:
X event = new MetaInstrumentNameEvent();
X break;
X case 0x05:
X event = new MetaLyricEvent();
X break;
X case 0x06:
X event = new MetaMarkerEvent();
X break;
X case 0x07:
X event = new MetaCueEvent();
X break;
X case 0x20:
X event = new MetaChannelPrefixEvent();
X break;
X case 0x21:
X event = new MetaPortNumberEvent();
X break;
X case 0x2f:
X event = new MetaEndOfTrackEvent();
X break;
X case 0x51:
X event = new MetaTempoEvent();
X break;
X case 0x54:
X event = new MetaSMPTEEvent();
X break;
X case 0x58:
X event = new MetaTimeEvent();
X break;
X case 0x59:
X event = new MetaKeyEvent();
X break;
X case 0x7f:
X event = new
X MetaSequencerSpecificEvent();
X break;
X default:
X event = new MetaUnknownEvent(*ptr);
X break;
X }
X if (event == 0) {
X errstr = "Out of memory";
X return (0);
X }
X } else {
X switch (state & 0xf0) {
X case 0x80:
X event = new NoteOffEvent();
X break;
X case 0x90:
X event = new NoteOnEvent();
X break;
X case 0xa0:
X event = new KeyPressureEvent();
X break;
X case 0xb0:
X event = new ParameterEvent();
X break;
X case 0xc0:
X event = new ProgramEvent();
X break;
X case 0xd0:
X event = new ChannelPressureEvent();
X break;
X case 0xe0:
X event = new PitchWheelEvent();
X break;
X }
X if (event == 0) {
X errstr = "Out of memory";
X return (0);
X }
X ((NormalEvent *)event)->SetChannel(state & 0x0f);
X }
X
X // Now event points to the correct event
X // Set the time
X event->SetTime(t);
X // Now read the event
X if ((errstr = event->SMFRead(track)) == 0)
X return (event);
X else {
X delete event;
X return (0);
X }
X}
X
Xint
XWriteEventToSMFTrack(SMFTrack &track, long &last_t, const Event *event,
X const char *&errstr)
X{
X EventType type;
X long t;
X
X errstr = 0;
X t = event->GetTime() - last_t;
X last_t = event->GetTime();
X
X if (!track.PutFixValue(t)) {
X errstr = "Out of memory";
X return (0);
X }
X
X type = event->GetType();
X if (type == SYSTEMEXCLUSIVE) {
X if (((SystemExclusiveEvent *)event)->GetContinued() == 1) {
X if (!track.PutByte(0xf7)) {
X errstr = "Out of memory";
X return (0);
X }
X } else {
X if (!track.PutByte(0xf0)) {
X errstr = "Out of memory";
X return (0);
X }
X }
X // clear running state
X track.SetRunningState(0);
X } else if (type >= NOTEOFF && type <= PITCHWHEEL) {
X unsigned char state;
X
X state = 0x80 + (type - NOTEOFF) * 0x10 +
X ((NormalEvent *)event)->GetChannel();
X
X if (state != track.GetRunningState()) {
X if (!track.PutByte(state)) {
X errstr = "Out of memory";
X return (0);
X }
X track.SetRunningState(state);
X }
X } else {
X // meta events
X unsigned char metatype;
X
X if (!track.PutByte(0xff)) {
X errstr = "Out of memory";
X return (0);
X }
X if (type >= METATEXT && type <= METACUE)
X metatype = 0x01 + (type - METATEXT);
X else {
X switch (type) {
X case METASEQUENCENUMBER:
X metatype = 0x00;
X break;
X case METACHANNELPREFIX:
X metatype = 0x20;
X break;
X case METAPORTNUMBER:
X metatype = 0x21;
X break;
X case METAENDOFTRACK:
X metatype = 0x2f;
X break;
X case METATEMPO:
X metatype = 0x51;
X break;
X case METASMPTE:
X metatype = 0x54;
X break;
X case METATIME:
X metatype = 0x58;
X break;
X case METAKEY:
X metatype = 0x59;
X break;
X case METASEQUENCERSPECIFIC:
X metatype = 0x7f;
X break;
X case METAUNKNOWN:
X metatype =
X ((MetaUnknownEvent *)event)->GetMetaType();
X break;
X default:
X /* shut up warning */
X metatype = 0x00;
X break;
X }
X }
X if (!track.PutByte(metatype)) {
X errstr = "Out of memory";
X return (0);
X }
X // clear running state
X track.SetRunningState(0);
X }
X
X if ((errstr = event->SMFWrite(track)) == 0)
X return (1);
X else
X return (0);
X}
END_OF_FILE
if test 7082 -ne `wc -c <'tclmidi-2.0/events/EventUtil.C'`; then
echo shar: \"'tclmidi-2.0/events/EventUtil.C'\" unpacked with wrong size!
fi
# end of 'tclmidi-2.0/events/EventUtil.C'
fi
if test -f 'tclmidi-2.0/events/MetaSeqName.C' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tclmidi-2.0/events/MetaSeqName.C'\"
else
echo shar: Extracting \"'tclmidi-2.0/events/MetaSeqName.C'\" \(2416 characters\)
sed "s/^X//" >'tclmidi-2.0/events/MetaSeqName.C' <<'END_OF_FILE'
X/*-
X * Copyright (c) 1993, 1994 Michael B. Durian. All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X * must display the following acknowledgement:
X * This product includes software developed by Michael B. Durian.
X * 4. The name of the the Author may be used to endorse or promote
X * products derived from this software without specific prior written
X * permission.
X *
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X#include "MetaSeqName.h"
X
XMetaSequenceNameEvent::MetaSequenceNameEvent()
X{
X}
X
XMetaSequenceNameEvent::MetaSequenceNameEvent(unsigned long t, const char *str) :
X MetaTextEvent(t, str)
X{
X}
X
XMetaSequenceNameEvent::MetaSequenceNameEvent(const MetaSequenceNameEvent &e) :
X MetaTextEvent(e)
X{
X}
X
XMetaSequenceNameEvent::~MetaSequenceNameEvent()
X{
X}
X
XMetaSequenceNameEvent &
XMetaSequenceNameEvent::operator=(const MetaSequenceNameEvent &e)
X{
X
X (MetaTextEvent)*this = (MetaTextEvent)e;
X return (*this);
X}
X
Xchar *
XMetaSequenceNameEvent::GetEventStr(void) const
X{
X
X return (MetaTextEvent::GetEventStr());
X}
X
Xostream &
Xoperator<<(ostream &os, const MetaSequenceNameEvent &e)
X{
X char *str;
X
X os << (str = e.GetEventStr());
X delete str;
X return (os);
X}
END_OF_FILE
if test 2416 -ne `wc -c <'tclmidi-2.0/events/MetaSeqName.C'`; then
echo shar: \"'tclmidi-2.0/events/MetaSeqName.C'\" unpacked with wrong size!
fi
# end of 'tclmidi-2.0/events/MetaSeqName.C'
fi
if test -f 'tclmidi-2.0/smf/SMFTrack.C' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tclmidi-2.0/smf/SMFTrack.C'\"
else
echo shar: Extracting \"'tclmidi-2.0/smf/SMFTrack.C'\" \(6784 characters\)
sed "s/^X//" >'tclmidi-2.0/smf/SMFTrack.C' <<'END_OF_FILE'
X/*-
X * Copyright (c) 1993, 1994 Michael B. Durian. All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X * must display the following acknowledgement:
X * This product includes software developed by Michael B. Durian.
X * 4. The name of the the Author may be used to endorse or promote
X * products derived from this software without specific prior written
X * permission.
X *
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X#include <assert.h>
X#include <string.h>
X#include "SMFTrack.h"
X#include "SMFUtils.h"
X#include <iomanip.h>
X
XSMFTrack::SMFTrack() : allocated(0L), length(0L), run_state(0), start(0),
X pos(0), end(0), static_buf(0)
X{
X}
X
XSMFTrack::SMFTrack(unsigned char *data, long len) : length(len), run_state(0),
X static_buf(0)
X{
X
X allocated = (len / StreamBlockSize + 1) * StreamBlockSize;
X start = new unsigned char[allocated];
X assert (start != 0);
X pos = start;
X memcpy(start, data, len);
X end = &start[len];
X}
X
XSMFTrack::SMFTrack(const SMFTrack &t) : length(t.length),
X run_state(t.run_state), allocated(t.allocated), static_buf(t.static_buf)
X{
X
X if (t.static_buf)
X start = t.start;
X else {
X start = new unsigned char[allocated];
X assert (start != 0);
X memcpy(start, t.start, length);
X }
X pos = start + (t.pos - t.start);
X end = start + (t.end - t.start);
X}
X
XSMFTrack::~SMFTrack()
X{
X
X if (start != 0 && !static_buf)
X delete start;
X}
X
X/*
X * SGI's C++ compiler can't handle inline function with
X * ifs in them, thus these are outlined
X */
Xconst unsigned char *
XSMFTrack::GetByte(void)
X{
X
X if (pos == end)
X return (0);
X else
X return (pos++);
X}
X
Xconst unsigned char *
XSMFTrack::PeekByte(void) const
X{
X
X if (pos == end)
X return (0);
X else
X return (pos);
X}
X
Xvoid
XSMFTrack::StaticBuffer(unsigned char *buf, long len, int init)
X{
X
X if (!static_buf)
X delete start;
X start = buf;
X allocated = len;
X pos = start;
X if (init) {
X length = len;
X end = &start[length];
X } else {
X length = 0;
X end = start;
X }
X static_buf = 1;
X}
X
Xvoid
XSMFTrack::DynamicBuffer(void)
X{
X
X start = 0;
X length = 0;
X pos = 0;
X end = 0;
X allocated = 0;
X static_buf = 0;
X}
X
Xconst unsigned char *
XSMFTrack::GetData(long len)
X{
X unsigned char *retptr;
X
X if (pos + len > end)
X return (0);
X else {
X retptr = pos;
X pos += len;
X return (retptr);
X }
X}
X
Xlong
XSMFTrack::GetVarValue(void)
X{
X long fix;
X unsigned char *init_pos;
X
X fix = 0;
X init_pos = pos;
X if (pos == end)
X return (-1);
X if (*pos & 0x80)
X do {
X if (pos == end) {
X pos = init_pos;
X return (-1);
X }
X fix = (fix << 7) + (*pos &0x7f);
X } while (*pos++ & 0x80);
X else
X fix = *pos++;
X return (fix);
X}
X
Xint
XSMFTrack::PutByte(unsigned char b)
X{
X
X if (length + 1 > allocated) {
X if (!IncreaseSize(1))
X return (0);
X }
X *end++ = b;
X length++;
X return (1);
X}
X
Xint
XSMFTrack::PutData(unsigned char *data, long len)
X{
X
X if (length + len > allocated) {
X if (static_buf)
X return (0);
X else {
X if (!IncreaseSize(len))
X return (0);
X }
X }
X memcpy(end, data, len);
X end += len;
X length += len;
X return (1);
X}
X
Xint
XSMFTrack::PutFixValue(long val)
X{
X unsigned char buf[4];
X unsigned char *bptr;
X
X buf[0] = buf[1] = buf[2] = buf[3] = 0;
X bptr = buf;
X *bptr++ = val & 0x7f;
X while ((val >>= 7) > 0) {
X *bptr |= 0x80;
X *bptr++ += (val & 0x7f);
X }
X do {
X if (!PutByte(*--bptr))
X return (0);
X } while (bptr != buf);
X return (1);
X}
X
XSMFTrack &
XSMFTrack::operator=(const SMFTrack &t)
X{
X
X if (start != 0 && !static_buf)
X delete start;
X
X allocated = t.allocated;
X length = t.length;
X run_state = t.run_state;
X static_buf = t.static_buf;
X if (t.static_buf)
X start = t.start;
X else {
X start = new unsigned char[allocated];
X assert (start != 0);
X memcpy(start, t.start, length);
X }
X pos = start + (t.pos - t.start);
X end = start + (t.end - t.start);
X return (*this);
X}
X
Xvoid
XSMFTrack::Empty(void)
X{
X
X if (start != 0 && !static_buf)
X delete start;
X allocated = 0;
X length = 0;
X start = 0;
X pos = 0;
X end = 0;
X run_state = 0;
X}
X
Xint
XSMFTrack::Read(int fd)
X{
X char id[4];
X
X Empty();
X if (MRead(fd, id, 4) != 4)
X return (0);
X if (strncmp(id, "MTrk", 4) != 0)
X return (0);
X if (MRead(fd, (char *)&length, 4) != 4)
X return (0);
X length = mtohl(length);
X if (!static_buf)
X if (!IncreaseSize(length))
X return (0);
X if (MRead(fd, (char *)start, length) != length)
X return (0);
X pos = start;
X end = &start[length];
X return (1);
X}
X
Xint
XSMFTrack::Write(int fd) const
X{
X long mlength;
X
X if (MWrite(fd, "MTrk", 4) != 4)
X return (0);
X mlength = htoml(length);
X if (MWrite(fd, (char *)&mlength, 4) != 4)
X return (0);
X if (MWrite(fd, (char *)start, length) != length)
X return (0);
X return (1);
X}
X
Xint
XSMFTrack::IncreaseSize(long len)
X{
X unsigned char *new_start;
X
X if (static_buf)
X return (0);
X allocated += (len / StreamBlockSize + 1) * StreamBlockSize;
X new_start = new unsigned char [allocated];
X if (new_start == 0)
X return (0);
X if (start == 0) {
X pos = new_start;
X end = new_start;
X } else {
X memcpy(new_start, start, length);
X pos = new_start + (pos - start);
X end = new_start + (end - start);
X delete start;
X }
X start = new_start;
X return (1);
X}
X
Xostream &
Xoperator<<(ostream &os, const SMFTrack &t)
X{
X long i, prev_flags;
X int prev_width;
X unsigned char *ptr;
X
X os << "Length: " << t.length << "Running State: " << (int)t.run_state
X << "\n";
X prev_flags = os.setf(ios::showbase | ios::hex | ios::internal);
X prev_width = os.width();
X
X ptr = t.pos;
X while (ptr != t.end) {
X for (i = 0; i < 16 && ptr != t.end; i++)
X os << hex << setw(4) << setfill('0')
X << (int)*ptr++ << " ";
X os << "\n";
X }
X os.flags(prev_flags);
X os.width(prev_width);
X return (os);
X}
END_OF_FILE
if test 6784 -ne `wc -c <'tclmidi-2.0/smf/SMFTrack.C'`; then
echo shar: \"'tclmidi-2.0/smf/SMFTrack.C'\" unpacked with wrong size!
fi
# end of 'tclmidi-2.0/smf/SMFTrack.C'
fi
if test -f 'tclmidi-2.0/tclmEvent.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tclmidi-2.0/tclmEvent.h'\"
else
echo shar: Extracting \"'tclmidi-2.0/tclmEvent.h'\" \(5860 characters\)
sed "s/^X//" >'tclmidi-2.0/tclmEvent.h' <<'END_OF_FILE'
X/*-
X * Copyright (c) 1993, 1994 Michael B. Durian. All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X * must display the following acknowledgement:
X * This product includes software developed by Michael B. Durian.
X * 4. The name of the the Author may be used to endorse or promote
X * products derived from this software without specific prior written
X * permission.
X *
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X#ifndef TCLMEVENT_H
X#define TCLMEVENT_H
X
X#include "AllEvents.h"
X
Xextern void Tclm_PrintEvent(ostream &buf, Event *e);
Xextern char *Tclm_PrintNoteOff(NoteOffEvent *e);
Xextern char *Tclm_PrintNoteOn(NoteOnEvent *e);
Xextern char *Tclm_PrintNote(NoteOnEvent *e);
Xextern char *Tclm_PrintKeyPressure(KeyPressureEvent *e);
Xextern char *Tclm_PrintParameter(ParameterEvent *e);
Xextern char *Tclm_PrintProgram(ProgramEvent *e);
Xextern char *Tclm_PrintChannelPressure(ChannelPressureEvent *e);
Xextern char *Tclm_PrintPitchWheel(PitchWheelEvent *e);
Xextern char *Tclm_PrintSystemExclusive(SystemExclusiveEvent *e);
Xextern char *Tclm_PrintMetaSequenceNumber(MetaSequenceNumberEvent *e);
Xextern char *Tclm_PrintMetaText(MetaTextEvent *e);
Xextern char *Tclm_PrintMetaCopyright(MetaCopyrightEvent *e);
Xextern char *Tclm_PrintMetaSequenceName(MetaSequenceNameEvent *e);
Xextern char *Tclm_PrintMetaInstrumentName(MetaInstrumentNameEvent *e);
Xextern char *Tclm_PrintMetaLyric(MetaLyricEvent *e);
Xextern char *Tclm_PrintMetaMarker(MetaMarkerEvent *e);
Xextern char *Tclm_PrintMetaCue(MetaCueEvent *e);
Xextern char *Tclm_PrintMetaChannelPrefix(MetaChannelPrefixEvent *e);
Xextern char *Tclm_PrintMetaPortNumber(MetaPortNumberEvent *e);
Xextern char *Tclm_PrintMetaEndOfTrack(MetaEndOfTrackEvent *e);
Xextern char *Tclm_PrintMetaTempo(MetaTempoEvent *e);
Xextern char *Tclm_PrintMetaSMPTE(MetaSMPTEEvent *e);
Xextern char *Tclm_PrintMetaTime(MetaTimeEvent *e);
Xextern char *Tclm_PrintMetaKey(MetaKeyEvent *e);
Xextern char *Tclm_PrintMetaSequencerSpecific(MetaSequencerSpecificEvent *e);
Xextern char *Tclm_PrintMetaUnknown(MetaUnknownEvent *e);
Xextern Event *Tclm_ParseEvent(Tcl_Interp *interp, char *str);
Xextern Event *Tclm_ParseNoteOff(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseNoteOn(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseNote(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseKeyPressure(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseParameter(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseProgram(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseChannelPressure(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParsePitchWheel(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseSystemExclusive(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaSequenceNumber(Tcl_Interp *interp, long time,
X int argc, char *argv[]);
Xextern Event *Tclm_ParseMetaText(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaCopyright(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaSequenceName(Tcl_Interp *interp, long time,
X int argc, char *argv[]);
Xextern Event *Tclm_ParseMetaInstrumentName(Tcl_Interp *interp, long time,
X int argc, char *argv[]);
Xextern Event *Tclm_ParseMetaLyric(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaMarker(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaCue(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaChannelPrefix(Tcl_Interp *interp, long time,
X int argc, char *argv[]);
Xextern Event *Tclm_ParseMetaPortNumber(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaEndOfTrack(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaTempo(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaSMPTE(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaTime(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaKey(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
Xextern Event *Tclm_ParseMetaSequencerSpecific(Tcl_Interp *interp, long time,
X int argc, char *argv[]);
Xextern Event *Tclm_ParseMetaUnknown(Tcl_Interp *interp, long time, int argc,
X char *argv[]);
X#endif
END_OF_FILE
if test 5860 -ne `wc -c <'tclmidi-2.0/tclmEvent.h'`; then
echo shar: \"'tclmidi-2.0/tclmEvent.h'\" unpacked with wrong size!
fi
# end of 'tclmidi-2.0/tclmEvent.h'
fi
echo shar: End of archive 7 \(of 14\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 14 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...