home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume43 / tclmidi / part07 < prev    next >
Internet Message Format  |  1994-07-21  |  63KB

  1. From: durian@boogie.com (Mike Durian)
  2. Newsgroups: comp.sources.misc
  3. Subject: v43i115:  tclmidi - A language for manipulating MIDI files, v2.0, Part07/14
  4. Date: 21 Jul 1994 19:27:07 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <30n3or$75n@sparky.sterling.com>
  9. X-Md4-Signature: e18001a857a4c4fb796d48a35b451447
  10.  
  11. Submitted-by: durian@boogie.com (Mike Durian)
  12. Posting-number: Volume 43, Issue 115
  13. Archive-name: tclmidi/part07
  14. Environment: POSIX, (BSDI, NetBSD, LINUX, SVR4 for optional driver), C++, TCL
  15. Supersedes: tclm: Volume 37, Issue 43-47
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  tclmidi-2.0/Makefile tclmidi-2.0/device/MPU401Copy.C
  22. #   tclmidi-2.0/drivers/LINUX/midi.h tclmidi-2.0/drivers/SVR4/midi.h
  23. #   tclmidi-2.0/events/EventUtil.C tclmidi-2.0/events/MetaSeqName.C
  24. #   tclmidi-2.0/smf/SMFTrack.C tclmidi-2.0/tclmEvent.h
  25. # Wrapped by kent@sparky on Thu Jul 21 19:05:15 1994
  26. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  27. echo If this archive is complete, you will see the following message:
  28. echo '          "shar: End of archive 7 (of 14)."'
  29. if test -f 'tclmidi-2.0/Makefile' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'tclmidi-2.0/Makefile'\"
  31. else
  32.   echo shar: Extracting \"'tclmidi-2.0/Makefile'\" \(6421 characters\)
  33.   sed "s/^X//" >'tclmidi-2.0/Makefile' <<'END_OF_FILE'
  34. X# Pick your favorite C and C++ compilers
  35. XCXX = g++
  36. XCC = gcc2
  37. X
  38. X# Remove the USE_MPU401 define if you haven't installed the mpu401
  39. X# driver I've supplied.  You won't be able to play or record, but
  40. X# you'll still be able to maninpulate the songs.
  41. X# Here is a list of the possible defines
  42. X#   -DUSE_MPU401        Include support for the MPU401 MIDI card
  43. X#   -DUSE_MPU401COPY    Include support for the MPU401 MIDI card
  44. X#                       Copies play file before playing - slower
  45. X#                       startup and file can't be modified while
  46. X#                       playing, but better performance while playing
  47. X#   -DSVR4              You are running a SVR4 system 
  48. X#   -DLINUX             You are running a LINUX system
  49. X#   -DBSD        You are running a BSD system
  50. X#   -Dosf1              You are running a DEC Alpha
  51. X#
  52. X# One of the SVR4, LINUX or BSD flags must be defined if you are
  53. X# also defining USE_MPU401 or USE_MPU401COPY.
  54. X#
  55. X# Feel free to add any other flags you like.  Such as -O, -g
  56. X#
  57. X# Don McKillican dmckilli@qc.bell.ca says the CFLAGS for the Dec Alpha
  58. X# using cxx should be
  59. X#       CFLAGS = -I/usr/include/cxx -O -Dosf1 -D__STDC__
  60. X
  61. XCFLAGS = -Wall -O -DBSD -DUSE_MPU401COPY
  62. X
  63. X# where to put the executables
  64. XBINDIR = /usr/local/bin
  65. X
  66. X# where to put the libraries
  67. XLIBDIR = /usr/local/lib
  68. X
  69. X# where to put the header file
  70. XINCDIR = /usr/local/include
  71. X
  72. X# where to put the man pages
  73. XMANPATH = /usr/local/man
  74. X
  75. X# where the TCL library resides
  76. XTCLLIBDIR = /usr/lib
  77. X
  78. X# where the TCL header file resides
  79. XTCLHDRDIR = /usr/include
  80. X
  81. X# any extra libraries you might need
  82. X# BSD/386 1.1 wants gnulib to resolve ___eprintf
  83. XEXTRALIB = -lgnulib
  84. X
  85. X# SVR4 doesn't need ranlib, set it to true
  86. X#RANLIB = true
  87. XRANLIB = ranlib
  88. X
  89. X# if you want to build a version of tclmidi that works with tk,
  90. X# set the following and "make tkmidi"
  91. XXINCDIR = /usr/X11/include
  92. XXLIBDIR = /usr/X11/lib
  93. X
  94. X#
  95. X# You shouldn't need to change anything else
  96. X#
  97. X
  98. XLFLAGS = -L. -Lrb -L$(TCLLIBDIR) -ltcl -ltclmidi -lmidi++ -lrb -lm $(EXTRALIB)
  99. XTKLFLAGS = -L. -Lrb -L$(TCLLIBDIR) -ltk -ltcl -ltclmidi -lmidi++ -lrb -lm \
  100. X    -L$(XLIBDIR) -lX11 $(EXTRALIB)
  101. XINCDIRS = -Ievents -Isong -Ismf -Idevice -Irb -I$(TCLHDRDIR)
  102. X
  103. XTCLMFILES = tclmCmd.o tclmUtil.o tclmEvent.o tclmPlay.o TclmInterp.o
  104. XAPPINIT = tclmAppInit.o
  105. XTKAPPINIT = tkmAppInit.o
  106. X
  107. X.SUFFIXES: .C $(SUFFIXES)
  108. X
  109. X.C.o:
  110. X    $(CXX) $(CFLAGS) $(INCDIRS) -c -o $@ $<
  111. X
  112. Xall: tclmidi
  113. X
  114. Xevents/objs: FORCE
  115. X    cd events; make objs CXX=$(CXX) CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)"
  116. X
  117. Xsmf/objs: FORCE
  118. X    cd smf; make objs CXX=$(CXX) CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)"
  119. X
  120. Xsong/objs: FORCE
  121. X    cd song; make objs CXX=$(CXX) CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)"
  122. X
  123. Xdevice/objs: FORCE
  124. X    cd device; make objs CXX=$(CXX) CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)"
  125. X
  126. Xrb/librb.a: FORCE
  127. X    cd rb; make librb.a CFLAGS="$(CFLAGS)" RANLIB="$(RANLIB)"
  128. X
  129. Xlibmidi++.a: events/objs smf/objs song/objs device/objs
  130. X    -rm libmidi++.a
  131. X    ar ru libmidi++.a events/*.o smf/*.o song/*.o device/*.o
  132. X    $(RANLIB) libmidi++.a
  133. X
  134. Xlibtclmidi.a: $(TCLMFILES)
  135. X    -rm libtclmidi.a
  136. X    ar ru libtclmidi.a $(TCLMFILES)
  137. X    $(RANLIB) libtclmidi.a
  138. X
  139. Xtclmidi: libmidi++.a rb/librb.a libtclmidi.a $(APPINIT)
  140. X    $(CXX) -o tclmidi $(APPINIT) $(LFLAGS)
  141. X
  142. Xtkmidi: libmidi++.a rb/librb.a libtclmidi.a $(TKAPPINIT)
  143. X    $(CXX) -o tkmidi $(TKAPPINIT) $(TKLFLAGS)
  144. X
  145. XtkmAppInit.o: tkmAppInit.C
  146. X    $(CXX) $(CFLAGS) $(INCDIRS) -I$(XINCDIR) -c -o $@ $<
  147. X
  148. Xinstall: tclmidi
  149. X    cp tclmidi mplay mrec minfo midtotcl $(BINDIR)
  150. X    cp libtclmidi.a libmidi++.a $(LIBDIR)
  151. X    cp tclmidi.h $(INCDIR)
  152. X    $(RANLIB) $(LIBDIR)/libtclmidi.a
  153. X    $(RANLIB) $(LIBDIR)/libmidi++.a
  154. X
  155. Xinstall-tkmidi: tkmidi
  156. X    cp tkmidi $(BINDIR)
  157. X
  158. Xinstall-man-cooked:
  159. X    cd man; make install-cooked MANPATH="$(MANPATH)"
  160. X
  161. Xinstall-man-raw:
  162. X    cd man; make install-raw MANPATH="$(MANPATH)"
  163. X
  164. Xclean:
  165. X    -rm *.o *.a
  166. X    cd events; make clean
  167. X    cd smf; make clean
  168. X    cd song; make clean
  169. X    cd device; make clean
  170. X    cd rb; make clean
  171. X    cd man; make clean
  172. X
  173. XFORCE:
  174. X
  175. XtclmCmd.o: tclmidi.h TclmInterp.h song/Song.h song/EventTree.h events/Event.h \
  176. X    smf/SMFTrack.h device/MidiDevice.h tclmEvent.h events/AllEvents.h \
  177. X    events/NormalEvent.h events/Note.h events/NoteOff.h \
  178. X    events/NoteOn.h events/KeyPressure.h events/Parameter.h events/Program.h \
  179. X    events/ChanPressure.h events/PitchWheel.h events/SystemExcl.h \
  180. X    events/MetaEvent.h events/MetaSeqNum.h events/MetaText.h \
  181. X    events/MetaCopy.h events/MetaSeqName.h events/MetaInstName.h \
  182. X    events/MetaLyric.h events/MetaMarker.h events/MetaCue.h \
  183. X    events/MetaChanPrefix.h events/MetaPortNum.h events/MetaEOT.h \
  184. X    events/MetaTempo.h events/MetaSMPTE.h events/MetaTime.h events/MetaKey.h \
  185. X    events/MetaSeqSpec.h events/MetaUnknown.h \
  186. X    patchlevel.h
  187. XtclmEvent.o: tclmidi.h TclmInterp.h song/Song.h song/EventTree.h \
  188. X    events/Event.h smf/SMFTrack.h device/MidiDevice.h tclmEvent.h \
  189. X    events/AllEvents.h events/NormalEvent.h events/Note.h events/NoteOff.h \
  190. X    events/NoteOn.h events/KeyPressure.h events/Parameter.h events/Program.h \
  191. X    events/ChanPressure.h events/PitchWheel.h events/SystemExcl.h \
  192. X    events/MetaEvent.h events/MetaSeqNum.h events/MetaText.h \
  193. X    events/MetaCopy.h events/MetaSeqName.h events/MetaInstName.h \
  194. X    events/MetaLyric.h events/MetaMarker.h events/MetaCue.h \
  195. X    events/MetaChanPrefix.h events/MetaPortNum.h events/MetaEOT.h \
  196. X    events/MetaTempo.h events/MetaSMPTE.h events/MetaTime.h events/MetaKey.h \
  197. X    events/MetaSeqSpec.h events/MetaUnknown.h
  198. XtclmPlay.o: tclmidi.h TclmInterp.h song/Song.h song/EventTree.h events/Event.h \
  199. X    smf/SMFTrack.h device/MidiDevice.h tclmEvent.h events/AllEvents.h \
  200. X    events/NormalEvent.h events/Note.h events/NoteOff.h \
  201. X    events/NoteOn.h events/KeyPressure.h events/Parameter.h events/Program.h \
  202. X    events/ChanPressure.h events/PitchWheel.h events/SystemExcl.h \
  203. X    events/MetaEvent.h events/MetaSeqNum.h events/MetaText.h \
  204. X    events/MetaCopy.h events/MetaSeqName.h events/MetaInstName.h \
  205. X    events/MetaLyric.h events/MetaMarker.h events/MetaCue.h \
  206. X    events/MetaChanPrefix.h events/MetaPortNum.h events/MetaEOT.h \
  207. X    events/MetaTempo.h events/MetaSMPTE.h events/MetaTime.h events/MetaKey.h \
  208. X    events/MetaSeqSpec.h events/MetaUnknown.h \
  209. X    device/MPU401.h device/MPU401Copy.h device/MidiDevice.h
  210. XTclmInterp.o: TclmInterp.h song/Song.h song/EventTree.h events/Event.h \
  211. X    smf/SMFTrack.h device/MidiDevice.h
  212. XtclmAppInit.o: tclmidi.h TclmInterp.h song/Song.h song/EventTree.h \
  213. X    events/Event.h smf/SMFTrack.h device/MidiDevice.h
  214. END_OF_FILE
  215.   if test 6421 -ne `wc -c <'tclmidi-2.0/Makefile'`; then
  216.     echo shar: \"'tclmidi-2.0/Makefile'\" unpacked with wrong size!
  217.   fi
  218.   # end of 'tclmidi-2.0/Makefile'
  219. fi
  220. if test -f 'tclmidi-2.0/device/MPU401Copy.C' -a "${1}" != "-c" ; then 
  221.   echo shar: Will not clobber existing file \"'tclmidi-2.0/device/MPU401Copy.C'\"
  222. else
  223.   echo shar: Extracting \"'tclmidi-2.0/device/MPU401Copy.C'\" \(13877 characters\)
  224.   sed "s/^X//" >'tclmidi-2.0/device/MPU401Copy.C' <<'END_OF_FILE'
  225. X/*-
  226. X * Copyright (c) 1993, 1994 Michael B. Durian.  All rights reserved.
  227. X *
  228. X * Redistribution and use in source and binary forms, with or without
  229. X * modification, are permitted provided that the following conditions
  230. X * are met:
  231. X * 1. Redistributions of source code must retain the above copyright
  232. X *    notice, this list of conditions and the following disclaimer.
  233. X * 2. Redistributions in binary form must reproduce the above copyright
  234. X *    notice, this list of conditions and the following disclaimer in the
  235. X *    documentation and/or other materials provided with the distribution.
  236. X * 3. All advertising materials mentioning features or use of this software
  237. X *    must display the following acknowledgement:
  238. X *    This product includes software developed by Michael B. Durian.
  239. X * 4. The name of the the Author may be used to endorse or promote 
  240. X *    products derived from this software without specific prior written 
  241. X *    permission.
  242. X *
  243. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  244. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  245. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  246. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  247. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  248. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  249. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  250. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  251. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  252. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  253. X * SUCH DAMAGE.
  254. X */
  255. X#ifdef USE_MPU401COPY
  256. X#include <assert.h>
  257. X#include <stdlib.h>
  258. X#include <unistd.h>
  259. X#include <string.h>
  260. X#include <strstream.h>
  261. X#include <fcntl.h>
  262. X#include <signal.h>
  263. X#include <errno.h>
  264. X#include <sys/types.h>
  265. X#include <sys/time.h>
  266. X#include <sys/ioctl.h>
  267. X
  268. X#ifdef SVR4
  269. X#include <sys/filio.h>
  270. X#include <sys/midi.h>
  271. X#endif
  272. X
  273. X#ifdef LINUX
  274. X#include <linux/termios.h>
  275. X#include <linux/midi.h>
  276. X#endif
  277. X
  278. X#ifdef BSD
  279. X#include <i386/isa/midiioctl.h>
  280. X#endif
  281. X
  282. X#include "MPU401Copy.h"
  283. X#include "EventUtil.h"
  284. X#include "Note.h"
  285. X
  286. Xtypedef void Sigfunc(int);
  287. X
  288. Xstatic MPU401Copy *CurrentMPU401 = 0;
  289. Xstatic Sigfunc *posixsignal(int signo, Sigfunc *func);
  290. X
  291. XMPU401Copy::MPU401Copy() : fd(-1), last_rec_time(0), finished(0),
  292. X    last_record_rs(0), playbuf(0), playbufptr(0), playbufend(0)
  293. X{
  294. X
  295. X    assert(CurrentMPU401 == 0);
  296. X    CurrentMPU401 = this;
  297. X    posixsignal(SIGIO, SIG_IGN);
  298. X}
  299. X
  300. XMPU401Copy::MPU401Copy(const char *dev) : MidiDevice(dev), fd(-1),
  301. X    last_rec_time(0), finished(0), last_record_rs(0), playbuf(0),
  302. X    playbufptr(0), playbufend(0)
  303. X{
  304. X
  305. X    assert(CurrentMPU401 == 0);
  306. X    CurrentMPU401 = this;
  307. X    posixsignal(SIGIO, SIG_IGN);
  308. X}
  309. X
  310. XMPU401Copy::~MPU401Copy()
  311. X{
  312. X    
  313. X    if (fd != -1)
  314. X        Stop();
  315. X    play_track.Empty();
  316. X    CurrentMPU401 = 0;
  317. X}
  318. X
  319. Xint
  320. XMPU401Copy::Play(Song *s, int r)
  321. X{
  322. X    ostrstream err;
  323. X    const char *name;
  324. X    char *str;
  325. X    int arg;
  326. X
  327. X    // open the device
  328. X    if (fd != -1) {
  329. X        SetError("Device already open");
  330. X        return (0);
  331. X    }
  332. X    if ((name = GetName()) == 0) {
  333. X        SetError("No device set");
  334. X        return (0);
  335. X    }
  336. X
  337. X    // set repeat
  338. X    SetRepeat(r);
  339. X
  340. X    // initialize track/event info
  341. X    if (!BuildSMF(play_track, s)) {
  342. X        SetError("Out of memory");
  343. X        return (0);
  344. X    }
  345. X    playbufptr = playbuf = play_track.PeekByte();
  346. X    playbufend = &playbuf[play_track.GetLength()];
  347. X
  348. X    should_stop = 0;
  349. X    finished = 0;
  350. X
  351. X    // set up async stuff
  352. X    posixsignal(SIGIO, MPU401CopySigIO);
  353. X
  354. X    // open device
  355. X    if ((fd = open(name, O_WRONLY | O_NONBLOCK)) == -1) {
  356. X        err << "open failed: " << strerror(errno) << ends;
  357. X        str = err.str();
  358. X        SetError(str);
  359. X        delete str;
  360. X        return (0);
  361. X    }
  362. X
  363. X#ifndef LINUX
  364. X    /* Linux doesn't allow F_SETOWN except for sockets - bug */
  365. X    if (fcntl(fd, F_SETOWN, getpid()) == -1) {
  366. X        err << "fcntl F_SETOWN failed: " << strerror(errno) << ends;
  367. X        str = err.str();
  368. X        SetError(str);
  369. X        delete str;
  370. X        return (0);
  371. X    }
  372. X#else
  373. X    arg = getpid();
  374. X    if (ioctl(fd, TIOCSPGRP, &arg) == -1) {
  375. X        err << "ioctl TIOCSPGRP failed: " << strerror(errno) << ends;
  376. X        str = err.str();
  377. X        SetError(str);
  378. X        delete str;
  379. X        return (0);
  380. X    }
  381. X#endif
  382. X
  383. X    // set division
  384. X    arg = s->GetDivision();
  385. X    if (ioctl(fd, MSDIVISION, &arg) == -1) {
  386. X        err << "ioctl MSDIVISION failed: " << strerror(errno) << ends;
  387. X        str = err.str();
  388. X        SetError(str);
  389. X        delete str;
  390. X        return (0);
  391. X    }
  392. X
  393. X    arg = GetMidiThru();
  394. X    if (ioctl(fd, MTHRU, &arg) == -1) {
  395. X        err << "ioctl MTHRU failed: " << strerror(errno) << ends;
  396. X        str = err.str();
  397. X        SetError(str);
  398. X        delete str;
  399. X        return (0);
  400. X    }
  401. X
  402. X    // the following should be a fcntl FIOASYNC call, but the
  403. X    // FIOASYNC ioctl doesn't always get passed down to the driver
  404. X    // properly under all OSes (read Linux), thus we use the MASYNC
  405. X    // entry point.
  406. X    arg = 1;
  407. X    if (ioctl(fd, MASYNC, &arg) == -1) {
  408. X        err << "ioctl MASYNC failed: " << strerror(errno) << ends;
  409. X        str = err.str();
  410. X        SetError(str);
  411. X        delete str;
  412. X        return (0);
  413. X    }
  414. X
  415. X    return (1);
  416. X}
  417. X
  418. Xint
  419. XMPU401Copy::Record(Song *rs, Song *ps, int r)
  420. X{
  421. X    ostrstream err;
  422. X    const char *name;
  423. X    char *str;
  424. X    int arg;
  425. X
  426. X    if (fd != -1)
  427. X        return (0);
  428. X    if ((name = GetName()) == 0)
  429. X        return (0);
  430. X
  431. X    rec_song = rs;
  432. X    last_rec_time = 0;
  433. X    last_record_rs = 0;
  434. X    if (ps == 0) {
  435. X        play_track.Empty();
  436. X        playbuf = 0;
  437. X        playbufptr = 0;
  438. X        playbufend = 0;
  439. X        if ((fd = open(name, O_RDONLY)) == -1) {
  440. X            err << "open failed: " << strerror(errno) << ends;
  441. X            str = err.str();
  442. X            SetError(str);
  443. X            delete str;
  444. X            return (0);
  445. X        }
  446. X        arg = rec_song->GetDivision();
  447. X        if (ioctl(fd, MSDIVISION, &arg) == -1) {
  448. X            err << "ioctl MSDIVISION failed: " << strerror(errno)
  449. X                << ends;
  450. X            str = err.str();
  451. X            SetError(str);
  452. X            delete str;
  453. X            return (0);
  454. X        }
  455. X    } else {
  456. X
  457. X        // initialize track/event info
  458. X        if (!BuildSMF(play_track, ps)) {
  459. X            SetError("Out of memory");
  460. X            return (0);
  461. X        }
  462. X
  463. X        playbufptr = playbuf = play_track.PeekByte();
  464. X        playbufend = &playbuf[play_track.GetLength()];
  465. X
  466. X        if ((fd = open(name, O_RDWR | O_NONBLOCK)) == -1) {
  467. X            err << "open failed: " << strerror(errno) << ends;
  468. X            str = err.str();
  469. X            SetError(str);
  470. X            delete str;
  471. X            return (0);
  472. X        }
  473. X
  474. X        // set division
  475. X        arg = ps->GetDivision();
  476. X        if (ioctl(fd, MSDIVISION, &arg) == -1) {
  477. X            err << "ioctl MSDIVISION failed: " << strerror(errno)
  478. X                << ends;
  479. X            str = err.str();
  480. X            SetError(str);
  481. X            delete str;
  482. X            return (0);
  483. X        }
  484. X
  485. X        // start record timer when first event is scheduled to play
  486. X        arg = 1;
  487. X        if (ioctl(fd, MRECONPLAY, &arg) == -1) {
  488. X            err << "ioctl MRECONPLAY failed: " << strerror(errno)
  489. X                << ends;
  490. X            str = err.str();
  491. X            SetError(str);
  492. X            delete str;
  493. X            return (0);
  494. X        }
  495. X
  496. X        should_stop = 0;
  497. X        finished = 0;
  498. X    }
  499. X
  500. X    // set repeat
  501. X    SetRepeat(r);
  502. X
  503. X    // set up async stuff
  504. X    posixsignal(SIGIO, MPU401CopySigIO);
  505. X#ifndef LINUX
  506. X    /* Linux doesn't allow F_SETOWN except for sockets - bug */
  507. X    if (fcntl(fd, F_SETOWN, getpid()) == -1) {
  508. X        err << "fcntl F_SETOWN failed: " << strerror(errno) << ends;
  509. X        str = err.str();
  510. X        SetError(str);
  511. X        delete str;
  512. X        return (0);
  513. X    }
  514. X#else
  515. X    arg = getpid();
  516. X    if (ioctl(fd, TIOCSPGRP, &arg) == -1) {
  517. X        err << "ioctl TIOCSPGRP failed: " << strerror(errno) << ends;
  518. X        str = err.str();
  519. X        SetError(str);
  520. X        delete str;
  521. X        return (0);
  522. X    }
  523. X#endif
  524. X    arg = GetMidiThru();
  525. X    if (ioctl(fd, MTHRU, &arg) == -1) {
  526. X        err << "ioctl MTHRU failed: " << strerror(errno) << ends;
  527. X        str = err.str();
  528. X        SetError(str);
  529. X        delete str;
  530. X        return (0);
  531. X    }
  532. X
  533. X    // the following should be a fcntl FIOASYNC call, but the
  534. X    // FIOASYNC ioctl doesn't always get passed down to the driver
  535. X    // properly under all OSes (read Linux), thus we use the MASYNC
  536. X    // entry point.
  537. X    arg = 1;
  538. X    if (ioctl(fd, MASYNC, &arg) == -1) {
  539. X        err << "ioctl MASYNC failed: " << strerror(errno) << ends;
  540. X        str = err.str();
  541. X        SetError(str);
  542. X        delete str;
  543. X        return (0);
  544. X    }
  545. X
  546. X    return (1);
  547. X}
  548. X
  549. Xint
  550. XMPU401Copy::Stop(void)
  551. X{
  552. X    ostrstream err;
  553. X    char *str;
  554. X    int arg;
  555. X
  556. X    finished = 1;
  557. X    should_stop = 0;
  558. X    if (fd == -1)
  559. X        return (1);
  560. X
  561. X    posixsignal(SIGIO, SIG_IGN);
  562. X
  563. X    arg = 0;
  564. X    if (ioctl(fd, MASYNC, &arg) == -1) {
  565. X        err << "ioctl MASYNC failed: " << strerror(errno) << ends;
  566. X        str = err.str();
  567. X        SetError(str);
  568. X        delete str;
  569. X        return (0);
  570. X    }
  571. X
  572. X    if (ioctl(fd, MGPLAYQ, &arg) == -1) {
  573. X        err << "ioctl MGPLAYQ failed: " << strerror(errno) << ends;
  574. X        str = err.str();
  575. X        SetError(str);
  576. X        delete str;
  577. X        return (0);
  578. X    }
  579. X    // flush queues
  580. X    if (arg != 0)
  581. X        if (ioctl(fd, MDRAIN, NULL) == -1) {
  582. X            err << "ioctl MDRAIN failed: " << strerror(errno)
  583. X                << ends;
  584. X            str = err.str();
  585. X            SetError(str);
  586. X            delete str;
  587. X            return (0);
  588. X        }
  589. X
  590. X    close (fd);
  591. X    fd = -1;
  592. X
  593. X    play_track.Empty();
  594. X    playbuf = 0;
  595. X    playbufptr = 0;
  596. X    playbufend = 0;
  597. X    rec_song = 0;
  598. X    return (1);
  599. X}
  600. X
  601. Xint
  602. XMPU401Copy::Wait(void)
  603. X{
  604. X    sigset_t sigset;
  605. X
  606. X    if (play_track.GetLength() == 0)
  607. X        return (1);
  608. X    if (finished)
  609. X        return (1);
  610. X    finished = 0;
  611. X    sigemptyset(&sigset);
  612. X    do
  613. X        sigsuspend(&sigset);
  614. X    while (!finished);
  615. X    return (1);
  616. X}
  617. X
  618. X/*
  619. X * Since this routine is called ASYNC, we just print out errors
  620. X * instead of putting them in SetError
  621. X */
  622. Xvoid
  623. XMPU401CopySigIO(int notused)
  624. X{
  625. X    struct timeval t;
  626. X    fd_set rset, wset;
  627. X    MPU401Copy *mpu;
  628. X    MidiDeviceCallback callback;
  629. X    const char *errstr;
  630. X
  631. X    mpu = CurrentMPU401;
  632. X    if (mpu == 0 || mpu->fd == -1)
  633. X        return;
  634. X
  635. X    FD_ZERO(&rset);
  636. X    FD_ZERO(&wset);
  637. X    FD_SET(mpu->fd, &rset);
  638. X    FD_SET(mpu->fd, &wset);
  639. X    t.tv_sec = 0;
  640. X    t.tv_usec = 0;
  641. X
  642. X    // poll to find out what caused the SIGIO
  643. X    if (select(mpu->fd + 1, &rset, &wset, 0, &t) == -1) {
  644. X        cerr << "error selecting MPU401Copy: " << strerror(errno)
  645. X            << "\n";
  646. X        return;
  647. X    }
  648. X
  649. X    // check for record event
  650. X    if (FD_ISSET(mpu->fd, &rset)) {
  651. X        if (mpu->rec_song != 0) {
  652. X            int num_read;
  653. X            EventType etype;
  654. X            unsigned char event[MaxEventSize];
  655. X            SMFTrack track;
  656. X            Event *e, *first_e;
  657. X
  658. X            // read event
  659. X            // This involves dynamic allocation, but
  660. X            // what can we do?  Events might be larger
  661. X            // than can fit in the event buffer.
  662. X            do {
  663. X                if ((num_read = read(mpu->fd, event,
  664. X                    MaxEventSize)) == -1) {
  665. X                    cerr << "error reading MPU401Copy "
  666. X                        "event: " << strerror(errno)
  667. X                        << "\n";
  668. X                    return;
  669. X                }
  670. X                track.PutData(event, num_read);
  671. X            } while (num_read == MaxEventSize);
  672. X
  673. X            // process events
  674. X            track.SetRunningState(mpu->last_record_rs);
  675. X            first_e = 0;
  676. X            /*
  677. X             * XXX This is a problem.  ReadEventFromSMFTrack
  678. X             * calls new to create the event.  New uses
  679. X             * malloc which is not reentrant.  I don't know
  680. X             * how to get around this.
  681. X             */
  682. X            while ((e = ReadEventFromSMFTrack(track,
  683. X                mpu->last_rec_time, errstr)) != 0) {
  684. X                Event *new_e;
  685. X
  686. X                if (first_e == 0)
  687. X                    first_e = e;
  688. X                new_e = mpu->rec_song->PutEvent(0, *e);
  689. X                delete e;
  690. X                if (new_e == 0) {
  691. X                    continue;
  692. X                }
  693. X                etype = new_e->GetType();
  694. X                // put links on noteoffs
  695. X                if ((etype == NOTEON &&
  696. X                    ((NoteEvent *)new_e)->GetVelocity() == 0)
  697. X                    || etype == NOTEOFF)
  698. X                    mpu->rec_song->SetNotePair(0, new_e);
  699. X            }
  700. X            if (errstr != 0)
  701. X                cerr << "Error while recording: " << errstr
  702. X                    << "\n";
  703. X            mpu->last_record_rs = track.GetRunningState();
  704. X            if ((callback = mpu->GetRecordCallback()) != 0)
  705. X                callback(first_e);
  706. X        }
  707. X    }
  708. X
  709. X    if (FD_ISSET(mpu->fd, &wset)) {
  710. X        if (mpu->play_track.GetLength() != 0 && !mpu->finished) {
  711. X            if (!mpu->Send()) {
  712. X                cerr << "Couldn't write play event\n";
  713. X                exit(1);
  714. X            }
  715. X        }
  716. X    }
  717. X}
  718. X
  719. Xint
  720. XMPU401Copy::Send()
  721. X{
  722. X    int numleft, numwritten;
  723. X    int arg;
  724. X
  725. X    if (should_stop) {
  726. X        if (ioctl(fd, MGPLAYQ, &arg) == -1) {
  727. X            cerr << "MPU401Copy: ioctl MGPLAY failed: " <<
  728. X                strerror(errno) << "\n";
  729. X            return (0);
  730. X        }
  731. X        if (arg == 0) {
  732. X            // the sigio we just caught signifies all events
  733. X            // have been played 
  734. X            finished = 1;
  735. X            return (1);
  736. X        }
  737. X    }
  738. X    if (playbuf == 0)
  739. X        return (0);
  740. X    numleft = playbufend - playbufptr;
  741. X    if ((numwritten = write(fd, playbufptr, numleft)) == -1) {
  742. X        cerr << "Couldn't write: " << strerror(errno) << "\n";
  743. X        return (0);
  744. X    }
  745. X    playbufptr += numwritten;
  746. X    numleft -= numwritten;
  747. X    if (numleft == 0) {
  748. X        if (!GetRepeat()) {
  749. X            should_stop = 1;
  750. X            return (1);
  751. X        } else {
  752. X            playbufptr = playbuf;
  753. X            numleft = playbufend - playbufptr;
  754. X        }
  755. X    }
  756. X    return (1);
  757. X}
  758. X
  759. Xint
  760. XMPU401Copy::BuildSMF(SMFTrack &smftrack, Song *s)
  761. X{
  762. X    unsigned long firsttime, lasttime, t;
  763. X    int empty, i, lowest, numtracks;
  764. X    Event *e, **trackevents;
  765. X    const char *errstr;
  766. X
  767. X    numtracks = s->GetNumTracks();
  768. X    trackevents = new Event *[numtracks];
  769. X    if (trackevents == 0)
  770. X        return (0);
  771. X    empty = 1;
  772. X    // get first events in each track
  773. X    for (i = 0; i < numtracks; i++) {
  774. X        trackevents[i] = s->GetTrack(i).GetFirstEvent();
  775. X        if (trackevents[i] != 0)
  776. X            empty = 0;
  777. X    }
  778. X    lasttime = 0;
  779. X    while (!empty) {
  780. X        /* find track with lowest numbered event */
  781. X        lowest = -1;
  782. X        /* quiet warning */
  783. X        firsttime = 0;
  784. X        for (i = 0; i < numtracks; i++) {
  785. X            if (trackevents[i] == 0)
  786. X                continue;
  787. X            if (lowest == -1) {
  788. X                firsttime = trackevents[i]->GetTime();
  789. X                lowest = i;
  790. X            } else {
  791. X                t = trackevents[i]->GetTime();
  792. X                if (t < firsttime) {
  793. X                    firsttime = t;
  794. X                    lowest = i;
  795. X                }
  796. X            }
  797. X        }
  798. X        if (lowest == -1) {
  799. X            empty = 1;
  800. X            break;
  801. X        }
  802. X        /* stick events into SMF */
  803. X        for (e = trackevents[lowest]; e != 0; e = e->GetNextEvent()) {
  804. X            if (!WriteEventToSMFTrack(smftrack, lasttime, e,
  805. X                errstr))
  806. X                return (0);
  807. X        }
  808. X        /* update trackevents pointer */
  809. X        trackevents[lowest] = s->GetTrack(lowest).NextEvents(
  810. X            trackevents[lowest]);
  811. X    }
  812. X    delete trackevents;
  813. X    return (1);
  814. X}
  815. X
  816. Xostream &
  817. Xoperator<<(ostream &os, const MPU401Copy &mpu)
  818. X{
  819. X
  820. X    os << mpu.GetName();
  821. X    if (mpu.playbuf != 0)
  822. X        os << " Playing";
  823. X    if (mpu.rec_song != 0)
  824. X        os << " Recording";
  825. X    return (os);
  826. X}
  827. X
  828. XSigfunc *
  829. Xposixsignal(int signo, Sigfunc *func)
  830. X{
  831. X    struct sigaction act, oact;
  832. X
  833. X    sigemptyset(&oact.sa_mask);
  834. X    sigemptyset(&act.sa_mask);
  835. X    act.sa_handler = func;
  836. X    act.sa_flags = 0;
  837. X
  838. X    if (signo == SIGALRM) {
  839. X#ifdef SA_INTERRUPT
  840. X        act.sa_flags |= SA_INTERRUPT;    /* SunOS */
  841. X#endif
  842. X    } else {
  843. X#ifdef SA_RESTART
  844. X        act.sa_flags |= SA_RESTART;    /* SVR4, 4.4BSD */
  845. X#endif
  846. X    }
  847. X
  848. X    if (sigaction(signo, &act, &oact) < 0)
  849. X        return (SIG_ERR);
  850. X    return (oact.sa_handler);
  851. X}
  852. X#endif
  853. END_OF_FILE
  854.   if test 13877 -ne `wc -c <'tclmidi-2.0/device/MPU401Copy.C'`; then
  855.     echo shar: \"'tclmidi-2.0/device/MPU401Copy.C'\" unpacked with wrong size!
  856.   fi
  857.   # end of 'tclmidi-2.0/device/MPU401Copy.C'
  858. fi
  859. if test -f 'tclmidi-2.0/drivers/LINUX/midi.h' -a "${1}" != "-c" ; then 
  860.   echo shar: Will not clobber existing file \"'tclmidi-2.0/drivers/LINUX/midi.h'\"
  861. else
  862.   echo shar: Extracting \"'tclmidi-2.0/drivers/LINUX/midi.h'\" \(6775 characters\)
  863.   sed "s/^X//" >'tclmidi-2.0/drivers/LINUX/midi.h' <<'END_OF_FILE'
  864. X/*-
  865. X * Copyright (c) 1993, 1994 Michael B. Durian.  All rights reserved.
  866. X *
  867. X * Redistribution and use in source and binary forms, with or without
  868. X * modification, are permitted provided that the following conditions
  869. X * are met:
  870. X * 1. Redistributions of source code must retain the above copyright
  871. X *    notice, this list of conditions and the following disclaimer.
  872. X * 2. Redistributions in binary form must reproduce the above copyright
  873. X *    notice, this list of conditions and the following disclaimer in the
  874. X *    documentation and/or other materials provided with the distribution.
  875. X * 3. All advertising materials mentioning features or use of this software
  876. X *    must display the following acknowledgement:
  877. X *    This product includes software developed by Michael B. Durian.
  878. X * 4. The name of the the Author may be used to endorse or promote 
  879. X *    products derived from this software without specific prior written 
  880. X *    permission.
  881. X *
  882. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  883. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  884. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  885. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  886. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  887. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  888. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  889. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  890. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  891. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  892. X * SUCH DAMAGE.
  893. X */
  894. X#ifndef MIDI_H
  895. X#define MIDI_H
  896. X/*
  897. X * MIDI MPU401 ioctls
  898. X */
  899. X#define DSPIOCTL ('m' << 8)
  900. X#define MRESET    (DSPIOCTL | 0x01)    /* no read, no write */
  901. X#define MDRAIN    (DSPIOCTL | 0x02)    /* no read, no write */
  902. X#define MFLUSH    (DSPIOCTL | 0x03)    /* no read, no write */
  903. X#define MGPLAYQ    (DSPIOCTL | 0x04)    /* read int */
  904. X#define MGRECQ    (DSPIOCTL | 0x05)    /* read int */
  905. X#define MSDIVISION    (DSPIOCTL | 0x06)    /* write int */
  906. X#define MGDIVISION    (DSPIOCTL | 0x07)    /* read int */
  907. X#define MGQAVAIL    (DSPIOCTL | 0x08)    /* read int */
  908. X/*
  909. X * I'd argue that this ioctl is only necessary because of a
  910. X * bug in the Linux kernel.  They ioctl handler processes the
  911. X * FIOASYNC ioctl and does not check the underlying driver to
  912. X * see if other actions should be performed.  The MASYNC ioctl
  913. X * command is really just FIOASYNC.
  914. X */
  915. X#define MASYNC    (DSPIOCTL | 0x09)    /* write int */
  916. X#define MTHRU        (DSPIOCTL | 0x0a)    /* write int */
  917. X#define MRECONPLAY    (DSPIOCTL | 0x0b)    /* write int */
  918. X
  919. X
  920. X
  921. X#ifdef __KERNEL__
  922. X/*
  923. X * midi port offsets
  924. X */
  925. X#define    MIDI_DATA            0
  926. X#define    MIDI_STATUS            1
  927. X#define    MIDI_COMMAND            1
  928. X
  929. X
  930. X/*
  931. X * midi data transfer status bits
  932. X */
  933. X#define    MIDI_RDY_RCV            (1 << 6)
  934. X#define    MIDI_DATA_AVL            (1 << 7)
  935. X
  936. X/*
  937. X * midi status flags
  938. X */
  939. X#define MIDI_UNAVAILABLE    (1 << 0) /* not in uart mode */
  940. X#define MIDI_READING        (1 << 1) /* open for reading */
  941. X#define MIDI_WRITING        (1 << 2) /* open for writing */
  942. X#define MIDI_CALLBACK_ISSUED    (1 << 3) /* waiting for a timer to expire */
  943. X#define MIDI_RD_BLOCK        (1 << 4) /* read will block */
  944. X#define MIDI_WR_BLOCK        (1 << 5) /* write will block */
  945. X#define MIDI_WR_ABORT        (1 << 6) /* write should abort */
  946. X#define MIDI_OPEN        (1 << 7) /* device is open */
  947. X#define MIDI_FLUSH_SLEEP    (1 << 8) /* blocking on flush */
  948. X#define MIDI_RD_SLEEP        (1 << 9) /* blocking on read */
  949. X#define MIDI_WR_SLEEP        (1 << 10) /* blocking on write */
  950. X#define MIDI_BUFFER_SLEEP    (1 << 11) /* blocking on buffer */
  951. X#define MIDI_NEED_ACK        (1 << 12) /* command needs and ack */
  952. X#define MIDI_ASYNC        (1 << 13) /* send sigios */
  953. X#define MIDI_SENDIO        (1 << 14) /* a sigio should be send at low h2o */
  954. X#define MIDI_NONBLOCK        (1 << 15) /* non blocking mode */
  955. X#define MIDI_SELOUT        (1 << 16) /* wait for a select output */
  956. X#define MIDI_SELIN        (1 << 17) /* wait for a select input */
  957. X#define MIDI_THRU        (1 << 18) /* copy in port to out port? */
  958. X#define MIDI_RECONPLAY        (1 << 19) /* start record timer on play */
  959. X
  960. X/*
  961. X * These are the various input data states
  962. X */
  963. Xtypedef enum {START, NEEDDATA1, NEEDDATA2, SYSEX, SYSTEM1, SYSTEM2} InputState;
  964. X
  965. X/*
  966. X * midi command values
  967. X */
  968. X#define MIDI_RESET            0xff
  969. X#define MIDI_UART            0x3f
  970. X#define MIDI_ACK            0xfe
  971. X#define MIDI_TRIES            20000
  972. X
  973. X/*
  974. X * most events are short, so we use the static array,
  975. X * but occationally we get a long event (sysex) and
  976. X * we dynamically allocate that
  977. X */
  978. X#define STYNAMIC_SIZE 4
  979. X#define STYNAMIC_ALLOC 256
  980. X
  981. Xstruct stynamic {
  982. X    short    allocated;
  983. X    short    len;
  984. X    u_char    datas[4];
  985. X    u_char    *datad;
  986. X};
  987. X
  988. X/*
  989. X * data from the board that hasn't formed a complete event yet
  990. X */
  991. Xstruct partial_event {
  992. X    struct    stynamic event;        /* the data */
  993. X    u_long    jiffs;            /* try out using jiffies */
  994. X    long    tempo;            /* tempo setting when event arrived */
  995. X    InputState    state;        /* what we are expecting next */
  996. X    u_char    rs;            /* the midi running state */
  997. X};
  998. X
  999. X/*
  1000. X * the internal representation of an event
  1001. X */
  1002. Xtypedef enum {NORMAL, TEMPO, TIMESIG, SYSX} EventType;
  1003. X
  1004. Xstruct event {
  1005. X    u_long    time;        /* time until event in kernel clicks */
  1006. X        long    tempo;        /*
  1007. X                 * not used in play events, but contains
  1008. X                 * the tempo setting current when the
  1009. X                 * incoming event arrived.  Used for
  1010. X                 * convert kernel ticks to smf ticks
  1011. X                 */
  1012. X    EventType    type;
  1013. X    struct    stynamic data;
  1014. X};
  1015. X
  1016. X/*
  1017. X * A event queue, used for both incoming and outgoing
  1018. X */
  1019. X#define MIDI_Q_SIZE 150
  1020. X#define MIDI_LOW_WATER 40
  1021. X
  1022. Xstruct event_queue {
  1023. X    int    count;
  1024. X    struct    event events[MIDI_Q_SIZE];
  1025. X    struct    event *end;
  1026. X    struct    event *head;
  1027. X    struct    event *tail;
  1028. X};
  1029. X
  1030. Xstruct midi_softc {      /* Driver status information */
  1031. X    /*
  1032. X     * various wait queues - why can't linux use addresses
  1033. X     * like everybody else
  1034. X     */
  1035. X    struct    wait_queue *flush_waitq;
  1036. X    struct    wait_queue *read_waitq;
  1037. X    struct    wait_queue *write_waitq;
  1038. X    struct    wait_queue *selin_waitq;
  1039. X    struct    wait_queue *selout_waitq;
  1040. X    struct    wait_queue *forever_waitq;
  1041. X    /* who's running us */
  1042. X    struct    task_struct *owner;
  1043. X    /* midi specific stuff */
  1044. X    struct    event_queue *rqueue;
  1045. X    struct    event_queue *wqueue;
  1046. X    struct    stynamic rpartial;
  1047. X    struct    stynamic wpartial;
  1048. X    struct    partial_event partial_event;
  1049. X    u_long    prev_incoming;    /* try using jiffies */
  1050. X    struct    timer_list timer;
  1051. X    volatile    long status;
  1052. X     long long    premainder;
  1053. X     long long    rremainder;
  1054. X     long    ptempo;            /* usec / beat */
  1055. X     long    rtempo;            /* usec / beat */
  1056. X    long    prev_rtempo;
  1057. X    int    pgid;
  1058. X    int    addr;
  1059. X    int    intr;
  1060. X    int    division;
  1061. X    int    wpartialpos;
  1062. X    long    write_noop_time;
  1063. X    short    noteon[0x80];        /*
  1064. X                     * each element is a different pitch
  1065. X                     * each bit is a different channel
  1066. X                     */
  1067. X    u_char    readrs;
  1068. X    u_char    writers;
  1069. X    u_char    noteonrs;
  1070. X};
  1071. X
  1072. Xstruct midi_config {
  1073. X    int    addr;
  1074. X    int    intr;
  1075. X};
  1076. X
  1077. X/* for mem.c */
  1078. Xextern long midiinit(long);
  1079. X
  1080. X#endif
  1081. X#endif
  1082. END_OF_FILE
  1083.   if test 6775 -ne `wc -c <'tclmidi-2.0/drivers/LINUX/midi.h'`; then
  1084.     echo shar: \"'tclmidi-2.0/drivers/LINUX/midi.h'\" unpacked with wrong size!
  1085.   fi
  1086.   # end of 'tclmidi-2.0/drivers/LINUX/midi.h'
  1087. fi
  1088. if test -f 'tclmidi-2.0/drivers/SVR4/midi.h' -a "${1}" != "-c" ; then 
  1089.   echo shar: Will not clobber existing file \"'tclmidi-2.0/drivers/SVR4/midi.h'\"
  1090. else
  1091.   echo shar: Extracting \"'tclmidi-2.0/drivers/SVR4/midi.h'\" \(5896 characters\)
  1092.   sed "s/^X//" >'tclmidi-2.0/drivers/SVR4/midi.h' <<'END_OF_FILE'
  1093. X/*-
  1094. X * Copyright (c) 1993, 1994 Michael B. Durian.  All rights reserved.
  1095. X *
  1096. X * Redistribution and use in source and binary forms, with or without
  1097. X * modification, are permitted provided that the following conditions
  1098. X * are met:
  1099. X * 1. Redistributions of source code must retain the above copyright
  1100. X *    notice, this list of conditions and the following disclaimer.
  1101. X * 2. Redistributions in binary form must reproduce the above copyright
  1102. X *    notice, this list of conditions and the following disclaimer in the
  1103. X *    documentation and/or other materials provided with the distribution.
  1104. X * 3. All advertising materials mentioning features or use of this software
  1105. X *    must display the following acknowledgement:
  1106. X *    This product includes software developed by Michael B. Durian.
  1107. X * 4. The name of the the Author may be used to endorse or promote 
  1108. X *    products derived from this software without specific prior written 
  1109. X *    permission.
  1110. X *
  1111. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  1112. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  1113. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  1114. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  1115. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  1116. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  1117. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  1118. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  1119. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  1120. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  1121. X * SUCH DAMAGE.
  1122. X */
  1123. X/*
  1124. X * MIDI MPU401 ioctls
  1125. X */
  1126. X#define DSPIOCTL ('m' << 8)
  1127. X#define MRESET    (DSPIOCTL | 0x01)    /* no read, no write */
  1128. X#define MDRAIN    (DSPIOCTL | 0x02)    /* no read, no write */
  1129. X#define MFLUSH    (DSPIOCTL | 0x03)    /* no read, no write */
  1130. X#define MGPLAYQ    (DSPIOCTL | 0x04)    /* read int */
  1131. X#define MGRECQ    (DSPIOCTL | 0x05)    /* read int */
  1132. X#define MSDIVISION    (DSPIOCTL | 0x06)    /* write int */
  1133. X#define MGDIVISION    (DSPIOCTL | 0x07)    /* read int */
  1134. X#define MGQAVAIL    (DSPIOCTL | 0x08)    /* read int */
  1135. X#define MASYNC    (DSPIOCTL | 0x09)    /* write int */
  1136. X#define MTHRU    (DSPIOCTL | 0x0a)    /* write int */
  1137. X#define MRECONPLAY    (DSPIOCTL | 0x0b)    /* write int */
  1138. X
  1139. X
  1140. X
  1141. X#ifdef INKERNEL
  1142. X/*
  1143. X * midi port offsets
  1144. X */
  1145. X#define    MIDI_DATA            0
  1146. X#define    MIDI_STATUS            1
  1147. X#define    MIDI_COMMAND            1
  1148. X
  1149. X
  1150. X/*
  1151. X * midi data transfer status bits
  1152. X */
  1153. X#define    MIDI_RDY_RCV            (1 << 6)
  1154. X#define    MIDI_DATA_AVL            (1 << 7)
  1155. X
  1156. X/*
  1157. X * midi status flags
  1158. X */
  1159. X#define MIDI_UNAVAILABLE    (1 << 0) /* not in uart mode */
  1160. X#define MIDI_READING        (1 << 1) /* open for reading */
  1161. X#define MIDI_WRITING        (1 << 2) /* open for writing */
  1162. X#define MIDI_CALLBACK_ISSUED    (1 << 3) /* waiting for a timer to expire */
  1163. X#define MIDI_RD_BLOCK        (1 << 4) /* read will block */
  1164. X#define MIDI_WR_BLOCK        (1 << 5) /* write will block */
  1165. X#define MIDI_WR_ABORT        (1 << 6) /* write should abort */
  1166. X#define MIDI_OPEN        (1 << 7) /* device is open */
  1167. X#define MIDI_FLUSH_SLEEP    (1 << 8) /* blocking on flush */
  1168. X#define MIDI_RD_SLEEP        (1 << 9) /* blocking on read */
  1169. X#define MIDI_WR_SLEEP        (1 << 10) /* blocking on write */
  1170. X#define MIDI_BUFFER_SLEEP    (1 << 11) /* blocking on buffer */
  1171. X#define MIDI_NEED_ACK        (1 << 12) /* command needs and ack */
  1172. X#define MIDI_ASYNC        (1 << 13) /* send sigios */
  1173. X#define MIDI_SENDIO        (1 << 14) /* a sigio should be send at low h2o */
  1174. X#define MIDI_NONBLOCK        (1 << 15) /* non blocking mode */
  1175. X#define MIDI_THRU        (1 << 16) /* copy in port to out port? */
  1176. X#define MIDI_RECONPLAY        (1 << 17) /* clear record timer on play? */
  1177. X
  1178. X/*
  1179. X * These are the various input data states
  1180. X */
  1181. Xtypedef enum {START, NEEDDATA1, NEEDDATA2, SYSEX, SYSTEM1, SYSTEM2} InputState;
  1182. X
  1183. X/*
  1184. X * midi command values
  1185. X */
  1186. X#define MIDI_RESET            0xff
  1187. X#define MIDI_UART            0x3f
  1188. X#define MIDI_ACK            0xfe
  1189. X#define MIDI_TRIES            5000
  1190. X
  1191. X/*
  1192. X * most events are short, so we use the static array,
  1193. X * but occationally we get a long event (sysex) and
  1194. X * we dynamically allocate that
  1195. X */
  1196. X#define STYNAMIC_SIZE 4
  1197. X#define STYNAMIC_ALLOC 256
  1198. X
  1199. Xstruct stynamic {
  1200. X    short    allocated;
  1201. X      short    len;
  1202. X    u_char    datas[4];
  1203. X    u_char    *datad;
  1204. X};
  1205. X
  1206. X/*
  1207. X * data from the board that hasn't formed a complete event yet
  1208. X */
  1209. Xstruct partial_event {
  1210. X    struct    stynamic event;        /* the data */
  1211. X    clock_t    time;            /* when the event occured */
  1212. X    long    tempo;            /* tempo setting when event arrived */
  1213. X    InputState    state;        /* what we are expecting next */
  1214. X    u_char    rs;            /* the midi running state */
  1215. X};
  1216. X
  1217. X/*
  1218. X * the internal representation of an event
  1219. X */
  1220. Xtypedef enum {NORMAL, TEMPO, TIMESIG, SYSX} EventType;
  1221. X
  1222. Xstruct event {
  1223. X    u_long    time;        /* time until event in smf clicks */
  1224. X    long    tempo;        /*
  1225. X                 * not used in play events, but contains
  1226. X                 * the tempo setting current when the
  1227. X                 * incoming event arrived.  Used for
  1228. X                 * convert kernel ticks to smf ticks
  1229. X                 */
  1230. X
  1231. X    EventType    type;
  1232. X    struct    stynamic data;
  1233. X};
  1234. X
  1235. X/*
  1236. X * A event queue, used for both incoming and outgoing
  1237. X */
  1238. X#define MIDI_Q_SIZE 150
  1239. X#define MIDI_LOW_WATER 40
  1240. X
  1241. Xstruct event_queue {
  1242. X    int    count;
  1243. X    struct    event events[MIDI_Q_SIZE];
  1244. X    struct    event *end;
  1245. X    struct    event *head;
  1246. X    struct    event *tail;
  1247. X};
  1248. X
  1249. Xstruct midi_softc {      /* Driver status information */
  1250. X    struct    pollhead pollhead;
  1251. X    proc_t    *owner;
  1252. X    /* midi specific stuff */
  1253. X    struct    event_queue *rqueue;
  1254. X    struct    event_queue *wqueue;
  1255. X    struct    stynamic rpartial;
  1256. X    struct    stynamic wpartial;
  1257. X    struct    partial_event partial_event;
  1258. X    clock_t    prev_incoming;
  1259. X    volatile    long status;
  1260. X      long long    premainder;
  1261. X      long long    rremainder;
  1262. X      long    ptempo;            /* usec / beat */
  1263. X      long    rtempo;            /* usec / beat */
  1264. X     long    prev_rtempo;
  1265. X    int    pgid;
  1266. X    int    addr;
  1267. X    int    intr;
  1268. X    int    division;
  1269. X    int    timeout_id;
  1270. X    int    wpartialpos;
  1271. X    long    write_noop_time;
  1272. X    short    noteon[0x80];        /*
  1273. X                     * each element is a different pitch
  1274. X                     * each bit is a different channel
  1275. X                     */
  1276. X    u_char    readrs;
  1277. X    u_char    writers;
  1278. X    u_char    noteonrs;
  1279. X};
  1280. X#endif
  1281. END_OF_FILE
  1282.   if test 5896 -ne `wc -c <'tclmidi-2.0/drivers/SVR4/midi.h'`; then
  1283.     echo shar: \"'tclmidi-2.0/drivers/SVR4/midi.h'\" unpacked with wrong size!
  1284.   fi
  1285.   # end of 'tclmidi-2.0/drivers/SVR4/midi.h'
  1286. fi
  1287. if test -f 'tclmidi-2.0/events/EventUtil.C' -a "${1}" != "-c" ; then 
  1288.   echo shar: Will not clobber existing file \"'tclmidi-2.0/events/EventUtil.C'\"
  1289. else
  1290.   echo shar: Extracting \"'tclmidi-2.0/events/EventUtil.C'\" \(7082 characters\)
  1291.   sed "s/^X//" >'tclmidi-2.0/events/EventUtil.C' <<'END_OF_FILE'
  1292. X/*-
  1293. X * Copyright (c) 1993, 1994 Michael B. Durian.  All rights reserved.
  1294. X *
  1295. X * Redistribution and use in source and binary forms, with or without
  1296. X * modification, are permitted provided that the following conditions
  1297. X * are met:
  1298. X * 1. Redistributions of source code must retain the above copyright
  1299. X *    notice, this list of conditions and the following disclaimer.
  1300. X * 2. Redistributions in binary form must reproduce the above copyright
  1301. X *    notice, this list of conditions and the following disclaimer in the
  1302. X *    documentation and/or other materials provided with the distribution.
  1303. X * 3. All advertising materials mentioning features or use of this software
  1304. X *    must display the following acknowledgement:
  1305. X *    This product includes software developed by Michael B. Durian.
  1306. X * 4. The name of the the Author may be used to endorse or promote 
  1307. X *    products derived from this software without specific prior written 
  1308. X *    permission.
  1309. X *
  1310. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  1311. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  1312. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  1313. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  1314. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  1315. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  1316. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  1317. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  1318. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  1319. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  1320. X * SUCH DAMAGE.
  1321. X */
  1322. X#include "EventUtil.h"
  1323. X#include "AllEvents.h"
  1324. X
  1325. XEvent *
  1326. XReadEventFromSMFTrack(SMFTrack &track, long &last_t, const char *&errstr)
  1327. X{
  1328. X    long t;
  1329. X    Event *event;
  1330. X    const unsigned char *ptr;
  1331. X    unsigned char state;
  1332. X
  1333. X    errstr = 0;
  1334. X    event = 0;
  1335. X    if ((t = track.GetVarValue()) == -1)
  1336. X        return(0);
  1337. X
  1338. X    t += last_t;
  1339. X    last_t = t;
  1340. X
  1341. X    // try to determine event type
  1342. X    if ((ptr = track.PeekByte()) == 0) {
  1343. X        errstr = "Incomplete event";
  1344. X        return (0);
  1345. X    }
  1346. X
  1347. X    if (*ptr & 0x80) {
  1348. X        // It's a new state - go ahead a get it
  1349. X        state = *track.GetByte();
  1350. X        // and change running state
  1351. X        track.SetRunningState(state);
  1352. X    } else {
  1353. X        // we're using the running state
  1354. X        state = track.GetRunningState();
  1355. X        if (!(state & 0x80)) {
  1356. X            errstr = "Making use of invalid running state";
  1357. X            return (0);
  1358. X        }
  1359. X    }
  1360. X
  1361. X    if (state == 0xf0) {
  1362. X        // reset running state
  1363. X        track.SetRunningState(0);
  1364. X        event = new SystemExclusiveEvent(0);
  1365. X        if (event == 0) {    
  1366. X            errstr = "Out of memory";
  1367. X            return (0);
  1368. X        }
  1369. X    } else if (state == 0xf7) {
  1370. X        // reset running state
  1371. X        track.SetRunningState(0);
  1372. X        event = new SystemExclusiveEvent(1);
  1373. X        if (event == 0) {
  1374. X            errstr = "Out of memory";
  1375. X            return (0);
  1376. X        }
  1377. X    } else if (state == 0xff) {
  1378. X        // reset running state
  1379. X        track.SetRunningState(0);
  1380. X        // meta event - determined by next byte
  1381. X        if ((ptr = track.GetByte()) == 0) {
  1382. X            errstr = "Incomplete Meta event";
  1383. X            return (0);
  1384. X        }
  1385. X        switch (*ptr) {
  1386. X        case 0x00:
  1387. X            event = new MetaSequenceNumberEvent();
  1388. X            break;
  1389. X        case 0x01: case 0x08: case 0x09: case 0x0a:
  1390. X        case 0x0b: case 0x0c: case 0x0d: case 0x0e:
  1391. X        case 0x0f:
  1392. X            event = new MetaTextEvent();
  1393. X            break;
  1394. X        case 0x02:
  1395. X            event = new MetaCopyrightEvent();
  1396. X            break;
  1397. X        case 0x03:
  1398. X            event = new MetaSequenceNameEvent();
  1399. X            break;
  1400. X        case 0x04:
  1401. X            event = new MetaInstrumentNameEvent();
  1402. X            break;
  1403. X        case 0x05:
  1404. X            event = new MetaLyricEvent();
  1405. X            break;
  1406. X        case 0x06:
  1407. X            event = new MetaMarkerEvent();
  1408. X            break;
  1409. X        case 0x07:
  1410. X            event = new MetaCueEvent();
  1411. X            break;
  1412. X        case 0x20:
  1413. X            event = new MetaChannelPrefixEvent();
  1414. X            break;
  1415. X        case 0x21:
  1416. X            event = new MetaPortNumberEvent();
  1417. X            break;
  1418. X        case 0x2f:
  1419. X            event = new MetaEndOfTrackEvent();
  1420. X            break;
  1421. X        case 0x51:
  1422. X            event = new MetaTempoEvent();
  1423. X            break;
  1424. X        case 0x54:
  1425. X            event = new MetaSMPTEEvent();
  1426. X            break;
  1427. X        case 0x58:
  1428. X            event = new MetaTimeEvent();
  1429. X            break;
  1430. X        case 0x59:
  1431. X            event = new MetaKeyEvent();
  1432. X            break;
  1433. X        case 0x7f:
  1434. X            event = new
  1435. X                MetaSequencerSpecificEvent();
  1436. X            break;
  1437. X        default:
  1438. X            event = new MetaUnknownEvent(*ptr);
  1439. X            break;
  1440. X        }
  1441. X        if (event == 0) {
  1442. X            errstr = "Out of memory";
  1443. X            return (0);
  1444. X        }
  1445. X    } else {
  1446. X        switch (state & 0xf0) {
  1447. X        case 0x80:
  1448. X            event = new NoteOffEvent();
  1449. X            break;
  1450. X        case 0x90:
  1451. X            event = new NoteOnEvent();
  1452. X            break;
  1453. X        case 0xa0:
  1454. X            event = new KeyPressureEvent();
  1455. X            break;
  1456. X        case 0xb0:
  1457. X            event = new ParameterEvent();
  1458. X            break;
  1459. X        case 0xc0:
  1460. X            event = new ProgramEvent();
  1461. X            break;
  1462. X        case 0xd0:
  1463. X            event = new ChannelPressureEvent();
  1464. X            break;
  1465. X        case 0xe0:
  1466. X            event = new PitchWheelEvent();
  1467. X            break;
  1468. X        }
  1469. X        if (event == 0) {
  1470. X            errstr = "Out of memory";
  1471. X            return (0);
  1472. X        }
  1473. X        ((NormalEvent *)event)->SetChannel(state & 0x0f);
  1474. X    }
  1475. X
  1476. X    // Now event points to the correct event
  1477. X    // Set the time
  1478. X    event->SetTime(t);
  1479. X    // Now read the event
  1480. X    if ((errstr = event->SMFRead(track)) == 0)
  1481. X        return (event);
  1482. X    else {
  1483. X        delete event;
  1484. X        return (0);
  1485. X    }
  1486. X}
  1487. X
  1488. Xint
  1489. XWriteEventToSMFTrack(SMFTrack &track, long &last_t, const Event *event,
  1490. X    const char *&errstr)
  1491. X{
  1492. X    EventType type;
  1493. X    long t;
  1494. X
  1495. X    errstr = 0;
  1496. X    t = event->GetTime() - last_t;
  1497. X    last_t = event->GetTime();
  1498. X
  1499. X    if (!track.PutFixValue(t)) {
  1500. X        errstr = "Out of memory";
  1501. X        return (0);
  1502. X    }
  1503. X
  1504. X    type = event->GetType();
  1505. X    if (type == SYSTEMEXCLUSIVE) {
  1506. X        if (((SystemExclusiveEvent *)event)->GetContinued() == 1) {
  1507. X            if (!track.PutByte(0xf7)) {
  1508. X                errstr = "Out of memory";
  1509. X                return (0);
  1510. X            }
  1511. X        } else {
  1512. X            if (!track.PutByte(0xf0)) {
  1513. X                errstr = "Out of memory";
  1514. X                return (0);
  1515. X            }
  1516. X        }
  1517. X        // clear running state
  1518. X        track.SetRunningState(0);
  1519. X    } else if (type >= NOTEOFF && type <= PITCHWHEEL) {
  1520. X        unsigned char state;
  1521. X
  1522. X        state = 0x80 + (type - NOTEOFF) * 0x10 +
  1523. X            ((NormalEvent *)event)->GetChannel();
  1524. X
  1525. X        if (state != track.GetRunningState()) {
  1526. X            if (!track.PutByte(state)) {
  1527. X                errstr = "Out of memory";
  1528. X                return (0);
  1529. X            }
  1530. X            track.SetRunningState(state);
  1531. X        }
  1532. X    } else {
  1533. X        // meta events
  1534. X        unsigned char metatype;
  1535. X
  1536. X        if (!track.PutByte(0xff)) {
  1537. X            errstr = "Out of memory";
  1538. X            return (0);
  1539. X        }
  1540. X        if (type >= METATEXT && type <= METACUE)
  1541. X            metatype = 0x01 + (type - METATEXT);
  1542. X        else {
  1543. X            switch (type) {
  1544. X            case METASEQUENCENUMBER:
  1545. X                metatype = 0x00;
  1546. X                break;
  1547. X            case METACHANNELPREFIX:
  1548. X                metatype = 0x20;
  1549. X                break;
  1550. X            case METAPORTNUMBER:
  1551. X                metatype = 0x21;
  1552. X                break;
  1553. X            case METAENDOFTRACK:
  1554. X                metatype = 0x2f;
  1555. X                break;
  1556. X            case METATEMPO:
  1557. X                metatype = 0x51;
  1558. X                break;
  1559. X            case METASMPTE:
  1560. X                metatype = 0x54;
  1561. X                break;
  1562. X            case METATIME:
  1563. X                metatype = 0x58;
  1564. X                break;
  1565. X            case METAKEY:
  1566. X                metatype = 0x59;
  1567. X                break;
  1568. X            case METASEQUENCERSPECIFIC:
  1569. X                metatype = 0x7f;
  1570. X                break;
  1571. X            case METAUNKNOWN:
  1572. X                metatype =
  1573. X                    ((MetaUnknownEvent *)event)->GetMetaType();
  1574. X                break;
  1575. X            default:
  1576. X                /* shut up warning */
  1577. X                metatype = 0x00;
  1578. X                break;
  1579. X            }
  1580. X        }
  1581. X        if (!track.PutByte(metatype)) {
  1582. X            errstr = "Out of memory";
  1583. X            return (0);
  1584. X        }
  1585. X        // clear running state
  1586. X        track.SetRunningState(0);
  1587. X    }
  1588. X
  1589. X    if ((errstr = event->SMFWrite(track)) == 0)
  1590. X        return (1);
  1591. X    else
  1592. X        return (0);
  1593. X}
  1594. END_OF_FILE
  1595.   if test 7082 -ne `wc -c <'tclmidi-2.0/events/EventUtil.C'`; then
  1596.     echo shar: \"'tclmidi-2.0/events/EventUtil.C'\" unpacked with wrong size!
  1597.   fi
  1598.   # end of 'tclmidi-2.0/events/EventUtil.C'
  1599. fi
  1600. if test -f 'tclmidi-2.0/events/MetaSeqName.C' -a "${1}" != "-c" ; then 
  1601.   echo shar: Will not clobber existing file \"'tclmidi-2.0/events/MetaSeqName.C'\"
  1602. else
  1603.   echo shar: Extracting \"'tclmidi-2.0/events/MetaSeqName.C'\" \(2416 characters\)
  1604.   sed "s/^X//" >'tclmidi-2.0/events/MetaSeqName.C' <<'END_OF_FILE'
  1605. X/*-
  1606. X * Copyright (c) 1993, 1994 Michael B. Durian.  All rights reserved.
  1607. X *
  1608. X * Redistribution and use in source and binary forms, with or without
  1609. X * modification, are permitted provided that the following conditions
  1610. X * are met:
  1611. X * 1. Redistributions of source code must retain the above copyright
  1612. X *    notice, this list of conditions and the following disclaimer.
  1613. X * 2. Redistributions in binary form must reproduce the above copyright
  1614. X *    notice, this list of conditions and the following disclaimer in the
  1615. X *    documentation and/or other materials provided with the distribution.
  1616. X * 3. All advertising materials mentioning features or use of this software
  1617. X *    must display the following acknowledgement:
  1618. X *    This product includes software developed by Michael B. Durian.
  1619. X * 4. The name of the the Author may be used to endorse or promote 
  1620. X *    products derived from this software without specific prior written 
  1621. X *    permission.
  1622. X *
  1623. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  1624. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  1625. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  1626. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  1627. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  1628. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  1629. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  1630. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  1631. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  1632. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  1633. X * SUCH DAMAGE.
  1634. X */
  1635. X#include "MetaSeqName.h"
  1636. X
  1637. XMetaSequenceNameEvent::MetaSequenceNameEvent()
  1638. X{
  1639. X}
  1640. X
  1641. XMetaSequenceNameEvent::MetaSequenceNameEvent(unsigned long t, const char *str) :
  1642. X    MetaTextEvent(t, str)
  1643. X{
  1644. X}
  1645. X
  1646. XMetaSequenceNameEvent::MetaSequenceNameEvent(const MetaSequenceNameEvent &e) :
  1647. X    MetaTextEvent(e)
  1648. X{
  1649. X}
  1650. X
  1651. XMetaSequenceNameEvent::~MetaSequenceNameEvent()
  1652. X{
  1653. X}
  1654. X
  1655. XMetaSequenceNameEvent &
  1656. XMetaSequenceNameEvent::operator=(const MetaSequenceNameEvent &e)
  1657. X{
  1658. X
  1659. X    (MetaTextEvent)*this = (MetaTextEvent)e;
  1660. X    return (*this);
  1661. X}
  1662. X
  1663. Xchar *
  1664. XMetaSequenceNameEvent::GetEventStr(void) const
  1665. X{
  1666. X
  1667. X    return (MetaTextEvent::GetEventStr());
  1668. X}
  1669. X
  1670. Xostream &
  1671. Xoperator<<(ostream &os, const MetaSequenceNameEvent &e)
  1672. X{
  1673. X    char *str;
  1674. X
  1675. X    os << (str = e.GetEventStr());
  1676. X    delete str;
  1677. X    return (os);
  1678. X}
  1679. END_OF_FILE
  1680.   if test 2416 -ne `wc -c <'tclmidi-2.0/events/MetaSeqName.C'`; then
  1681.     echo shar: \"'tclmidi-2.0/events/MetaSeqName.C'\" unpacked with wrong size!
  1682.   fi
  1683.   # end of 'tclmidi-2.0/events/MetaSeqName.C'
  1684. fi
  1685. if test -f 'tclmidi-2.0/smf/SMFTrack.C' -a "${1}" != "-c" ; then 
  1686.   echo shar: Will not clobber existing file \"'tclmidi-2.0/smf/SMFTrack.C'\"
  1687. else
  1688.   echo shar: Extracting \"'tclmidi-2.0/smf/SMFTrack.C'\" \(6784 characters\)
  1689.   sed "s/^X//" >'tclmidi-2.0/smf/SMFTrack.C' <<'END_OF_FILE'
  1690. X/*-
  1691. X * Copyright (c) 1993, 1994 Michael B. Durian.  All rights reserved.
  1692. X *
  1693. X * Redistribution and use in source and binary forms, with or without
  1694. X * modification, are permitted provided that the following conditions
  1695. X * are met:
  1696. X * 1. Redistributions of source code must retain the above copyright
  1697. X *    notice, this list of conditions and the following disclaimer.
  1698. X * 2. Redistributions in binary form must reproduce the above copyright
  1699. X *    notice, this list of conditions and the following disclaimer in the
  1700. X *    documentation and/or other materials provided with the distribution.
  1701. X * 3. All advertising materials mentioning features or use of this software
  1702. X *    must display the following acknowledgement:
  1703. X *    This product includes software developed by Michael B. Durian.
  1704. X * 4. The name of the the Author may be used to endorse or promote 
  1705. X *    products derived from this software without specific prior written 
  1706. X *    permission.
  1707. X *
  1708. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  1709. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  1710. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  1711. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  1712. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  1713. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  1714. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  1715. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  1716. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  1717. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  1718. X * SUCH DAMAGE.
  1719. X */
  1720. X#include <assert.h>
  1721. X#include <string.h>
  1722. X#include "SMFTrack.h"
  1723. X#include "SMFUtils.h"
  1724. X#include <iomanip.h>
  1725. X
  1726. XSMFTrack::SMFTrack() : allocated(0L), length(0L), run_state(0), start(0),
  1727. X    pos(0), end(0), static_buf(0)
  1728. X{
  1729. X}
  1730. X
  1731. XSMFTrack::SMFTrack(unsigned char *data, long len) : length(len), run_state(0),
  1732. X    static_buf(0)
  1733. X{
  1734. X
  1735. X    allocated = (len / StreamBlockSize + 1) * StreamBlockSize;
  1736. X    start = new unsigned char[allocated];
  1737. X    assert (start != 0);
  1738. X    pos = start;
  1739. X    memcpy(start, data, len);
  1740. X    end = &start[len];
  1741. X}
  1742. X
  1743. XSMFTrack::SMFTrack(const SMFTrack &t) : length(t.length),
  1744. X    run_state(t.run_state), allocated(t.allocated), static_buf(t.static_buf)
  1745. X{
  1746. X
  1747. X    if (t.static_buf)
  1748. X        start = t.start;
  1749. X    else {
  1750. X        start = new unsigned char[allocated];
  1751. X        assert (start != 0);
  1752. X        memcpy(start, t.start, length);
  1753. X    }
  1754. X    pos = start + (t.pos - t.start);
  1755. X    end = start + (t.end - t.start);
  1756. X}
  1757. X
  1758. XSMFTrack::~SMFTrack()
  1759. X{
  1760. X
  1761. X    if (start != 0 && !static_buf)
  1762. X        delete start;
  1763. X}
  1764. X
  1765. X/*
  1766. X * SGI's C++ compiler can't handle inline function with
  1767. X * ifs in them, thus these are outlined
  1768. X */
  1769. Xconst unsigned char *
  1770. XSMFTrack::GetByte(void)
  1771. X{
  1772. X
  1773. X    if (pos == end)
  1774. X        return (0);
  1775. X    else
  1776. X        return (pos++);
  1777. X}
  1778. X
  1779. Xconst unsigned char *
  1780. XSMFTrack::PeekByte(void) const
  1781. X{
  1782. X
  1783. X    if (pos == end)
  1784. X        return (0);
  1785. X    else
  1786. X        return (pos);
  1787. X}
  1788. X
  1789. Xvoid
  1790. XSMFTrack::StaticBuffer(unsigned char *buf, long len, int init)
  1791. X{
  1792. X
  1793. X    if (!static_buf)
  1794. X        delete start;
  1795. X    start = buf;
  1796. X    allocated = len;
  1797. X    pos = start;
  1798. X    if (init) {
  1799. X        length = len;
  1800. X        end = &start[length];
  1801. X    } else {
  1802. X        length = 0;
  1803. X        end = start;
  1804. X    }
  1805. X    static_buf = 1;
  1806. X}
  1807. X
  1808. Xvoid
  1809. XSMFTrack::DynamicBuffer(void)
  1810. X{
  1811. X
  1812. X    start = 0;
  1813. X    length = 0;
  1814. X    pos = 0;
  1815. X    end = 0;
  1816. X    allocated = 0;
  1817. X    static_buf = 0;
  1818. X}
  1819. X
  1820. Xconst unsigned char *
  1821. XSMFTrack::GetData(long len)
  1822. X{
  1823. X    unsigned char *retptr;
  1824. X
  1825. X    if (pos + len > end)
  1826. X        return (0);
  1827. X    else {
  1828. X        retptr = pos;
  1829. X        pos += len;
  1830. X        return (retptr);
  1831. X    }
  1832. X}
  1833. X
  1834. Xlong
  1835. XSMFTrack::GetVarValue(void)
  1836. X{
  1837. X    long fix;
  1838. X    unsigned char *init_pos;
  1839. X
  1840. X    fix = 0;
  1841. X    init_pos = pos;
  1842. X    if (pos == end)
  1843. X        return (-1);
  1844. X    if (*pos & 0x80)
  1845. X        do {
  1846. X            if (pos == end) {
  1847. X                pos = init_pos;
  1848. X                return (-1);
  1849. X            }
  1850. X            fix = (fix << 7) + (*pos &0x7f);
  1851. X        } while (*pos++ & 0x80);
  1852. X    else
  1853. X        fix = *pos++;
  1854. X    return (fix);
  1855. X}
  1856. X
  1857. Xint
  1858. XSMFTrack::PutByte(unsigned char b)
  1859. X{
  1860. X
  1861. X    if (length + 1 > allocated) {
  1862. X        if (!IncreaseSize(1))
  1863. X            return (0);
  1864. X    }
  1865. X    *end++ = b;
  1866. X    length++;
  1867. X    return (1);
  1868. X}
  1869. X
  1870. Xint
  1871. XSMFTrack::PutData(unsigned char *data, long len)
  1872. X{
  1873. X
  1874. X    if (length + len > allocated) {
  1875. X        if (static_buf)
  1876. X            return (0);
  1877. X        else {
  1878. X            if (!IncreaseSize(len))
  1879. X                return (0);
  1880. X        }
  1881. X    }
  1882. X    memcpy(end, data, len);
  1883. X    end += len;
  1884. X    length += len;
  1885. X    return (1);
  1886. X}
  1887. X
  1888. Xint
  1889. XSMFTrack::PutFixValue(long val)
  1890. X{
  1891. X    unsigned char buf[4];
  1892. X    unsigned char *bptr;
  1893. X
  1894. X    buf[0] = buf[1] = buf[2] = buf[3] = 0;
  1895. X    bptr = buf;
  1896. X    *bptr++ = val & 0x7f;
  1897. X    while ((val >>= 7) > 0) {
  1898. X        *bptr |= 0x80;
  1899. X        *bptr++ += (val & 0x7f);
  1900. X    }
  1901. X    do {
  1902. X        if (!PutByte(*--bptr))
  1903. X            return (0);
  1904. X    } while (bptr != buf);
  1905. X    return (1);
  1906. X}
  1907. X
  1908. XSMFTrack &
  1909. XSMFTrack::operator=(const SMFTrack &t)
  1910. X{
  1911. X
  1912. X    if (start != 0 && !static_buf)
  1913. X        delete start;
  1914. X
  1915. X    allocated = t.allocated;
  1916. X    length = t.length;
  1917. X    run_state = t.run_state;
  1918. X    static_buf = t.static_buf;
  1919. X    if (t.static_buf)
  1920. X        start = t.start;
  1921. X    else {
  1922. X        start = new unsigned char[allocated];
  1923. X        assert (start != 0);
  1924. X        memcpy(start, t.start, length);
  1925. X    }
  1926. X    pos = start + (t.pos - t.start);
  1927. X    end = start + (t.end - t.start);
  1928. X    return (*this);
  1929. X}
  1930. X
  1931. Xvoid
  1932. XSMFTrack::Empty(void)
  1933. X{
  1934. X
  1935. X    if (start != 0 && !static_buf)
  1936. X        delete start;
  1937. X    allocated = 0;
  1938. X    length = 0;
  1939. X    start = 0;
  1940. X    pos = 0;
  1941. X    end = 0;
  1942. X    run_state = 0;
  1943. X}
  1944. X
  1945. Xint
  1946. XSMFTrack::Read(int fd)
  1947. X{
  1948. X    char id[4];
  1949. X
  1950. X    Empty();
  1951. X    if (MRead(fd, id, 4) != 4)
  1952. X        return (0);
  1953. X    if (strncmp(id, "MTrk", 4) != 0)
  1954. X        return (0);
  1955. X    if (MRead(fd, (char *)&length, 4) != 4)
  1956. X        return (0);
  1957. X    length = mtohl(length);
  1958. X    if (!static_buf)
  1959. X        if (!IncreaseSize(length))
  1960. X            return (0);
  1961. X    if (MRead(fd, (char *)start, length) != length)
  1962. X        return (0);
  1963. X    pos = start;
  1964. X    end = &start[length];
  1965. X    return (1);
  1966. X}
  1967. X
  1968. Xint
  1969. XSMFTrack::Write(int fd) const
  1970. X{
  1971. X    long mlength;
  1972. X
  1973. X    if (MWrite(fd, "MTrk", 4) != 4)
  1974. X        return (0);
  1975. X    mlength = htoml(length);
  1976. X    if (MWrite(fd, (char *)&mlength, 4) != 4)
  1977. X        return (0);
  1978. X    if (MWrite(fd, (char *)start, length) != length)
  1979. X        return (0);
  1980. X    return (1);
  1981. X}
  1982. X
  1983. Xint
  1984. XSMFTrack::IncreaseSize(long len)
  1985. X{
  1986. X    unsigned char *new_start;
  1987. X
  1988. X    if (static_buf)
  1989. X        return (0);
  1990. X    allocated += (len / StreamBlockSize + 1) * StreamBlockSize;
  1991. X    new_start = new unsigned char [allocated];
  1992. X    if (new_start == 0)
  1993. X        return (0);
  1994. X    if (start == 0) {
  1995. X        pos = new_start;
  1996. X        end = new_start;
  1997. X    } else {
  1998. X        memcpy(new_start, start, length);
  1999. X        pos = new_start + (pos - start);
  2000. X        end = new_start + (end - start);
  2001. X        delete start;
  2002. X    }
  2003. X    start = new_start;
  2004. X    return (1);
  2005. X}
  2006. X
  2007. Xostream &
  2008. Xoperator<<(ostream &os, const SMFTrack &t)
  2009. X{
  2010. X    long i, prev_flags;
  2011. X    int prev_width;
  2012. X    unsigned char *ptr;
  2013. X
  2014. X    os << "Length: " << t.length << "Running State: " << (int)t.run_state
  2015. X        << "\n";
  2016. X    prev_flags = os.setf(ios::showbase | ios::hex | ios::internal);
  2017. X    prev_width = os.width();
  2018. X
  2019. X    ptr = t.pos;
  2020. X    while (ptr != t.end) {
  2021. X        for (i = 0; i < 16 && ptr != t.end; i++)
  2022. X            os << hex << setw(4) << setfill('0')
  2023. X                << (int)*ptr++ << " ";
  2024. X        os << "\n";
  2025. X    }
  2026. X    os.flags(prev_flags);
  2027. X    os.width(prev_width);
  2028. X    return (os);
  2029. X}
  2030. END_OF_FILE
  2031.   if test 6784 -ne `wc -c <'tclmidi-2.0/smf/SMFTrack.C'`; then
  2032.     echo shar: \"'tclmidi-2.0/smf/SMFTrack.C'\" unpacked with wrong size!
  2033.   fi
  2034.   # end of 'tclmidi-2.0/smf/SMFTrack.C'
  2035. fi
  2036. if test -f 'tclmidi-2.0/tclmEvent.h' -a "${1}" != "-c" ; then 
  2037.   echo shar: Will not clobber existing file \"'tclmidi-2.0/tclmEvent.h'\"
  2038. else
  2039.   echo shar: Extracting \"'tclmidi-2.0/tclmEvent.h'\" \(5860 characters\)
  2040.   sed "s/^X//" >'tclmidi-2.0/tclmEvent.h' <<'END_OF_FILE'
  2041. X/*-
  2042. X * Copyright (c) 1993, 1994 Michael B. Durian.  All rights reserved.
  2043. X *
  2044. X * Redistribution and use in source and binary forms, with or without
  2045. X * modification, are permitted provided that the following conditions
  2046. X * are met:
  2047. X * 1. Redistributions of source code must retain the above copyright
  2048. X *    notice, this list of conditions and the following disclaimer.
  2049. X * 2. Redistributions in binary form must reproduce the above copyright
  2050. X *    notice, this list of conditions and the following disclaimer in the
  2051. X *    documentation and/or other materials provided with the distribution.
  2052. X * 3. All advertising materials mentioning features or use of this software
  2053. X *    must display the following acknowledgement:
  2054. X *    This product includes software developed by Michael B. Durian.
  2055. X * 4. The name of the the Author may be used to endorse or promote 
  2056. X *    products derived from this software without specific prior written 
  2057. X *    permission.
  2058. X *
  2059. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  2060. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  2061. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  2062. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  2063. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  2064. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  2065. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  2066. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  2067. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  2068. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  2069. X * SUCH DAMAGE.
  2070. X */
  2071. X#ifndef TCLMEVENT_H
  2072. X#define TCLMEVENT_H
  2073. X
  2074. X#include "AllEvents.h"
  2075. X
  2076. Xextern void Tclm_PrintEvent(ostream &buf, Event *e);
  2077. Xextern char *Tclm_PrintNoteOff(NoteOffEvent *e);
  2078. Xextern char *Tclm_PrintNoteOn(NoteOnEvent *e);
  2079. Xextern char *Tclm_PrintNote(NoteOnEvent *e);
  2080. Xextern char *Tclm_PrintKeyPressure(KeyPressureEvent *e);
  2081. Xextern char *Tclm_PrintParameter(ParameterEvent *e);
  2082. Xextern char *Tclm_PrintProgram(ProgramEvent *e);
  2083. Xextern char *Tclm_PrintChannelPressure(ChannelPressureEvent *e);
  2084. Xextern char *Tclm_PrintPitchWheel(PitchWheelEvent *e);
  2085. Xextern char *Tclm_PrintSystemExclusive(SystemExclusiveEvent *e);
  2086. Xextern char *Tclm_PrintMetaSequenceNumber(MetaSequenceNumberEvent *e);
  2087. Xextern char *Tclm_PrintMetaText(MetaTextEvent *e);
  2088. Xextern char *Tclm_PrintMetaCopyright(MetaCopyrightEvent *e);
  2089. Xextern char *Tclm_PrintMetaSequenceName(MetaSequenceNameEvent *e);
  2090. Xextern char *Tclm_PrintMetaInstrumentName(MetaInstrumentNameEvent *e);
  2091. Xextern char *Tclm_PrintMetaLyric(MetaLyricEvent *e);
  2092. Xextern char *Tclm_PrintMetaMarker(MetaMarkerEvent *e);
  2093. Xextern char *Tclm_PrintMetaCue(MetaCueEvent *e);
  2094. Xextern char *Tclm_PrintMetaChannelPrefix(MetaChannelPrefixEvent *e);
  2095. Xextern char *Tclm_PrintMetaPortNumber(MetaPortNumberEvent *e);
  2096. Xextern char *Tclm_PrintMetaEndOfTrack(MetaEndOfTrackEvent *e);
  2097. Xextern char *Tclm_PrintMetaTempo(MetaTempoEvent *e);
  2098. Xextern char *Tclm_PrintMetaSMPTE(MetaSMPTEEvent *e);
  2099. Xextern char *Tclm_PrintMetaTime(MetaTimeEvent *e);
  2100. Xextern char *Tclm_PrintMetaKey(MetaKeyEvent *e);
  2101. Xextern char *Tclm_PrintMetaSequencerSpecific(MetaSequencerSpecificEvent *e);
  2102. Xextern char *Tclm_PrintMetaUnknown(MetaUnknownEvent *e);
  2103. Xextern Event *Tclm_ParseEvent(Tcl_Interp *interp, char *str);
  2104. Xextern Event *Tclm_ParseNoteOff(Tcl_Interp *interp, long time, int argc,
  2105. X    char *argv[]);
  2106. Xextern Event *Tclm_ParseNoteOn(Tcl_Interp *interp, long time, int argc,
  2107. X    char *argv[]);
  2108. Xextern Event *Tclm_ParseNote(Tcl_Interp *interp, long time, int argc,
  2109. X    char *argv[]);
  2110. Xextern Event *Tclm_ParseKeyPressure(Tcl_Interp *interp, long time, int argc,
  2111. X    char *argv[]);
  2112. Xextern Event *Tclm_ParseParameter(Tcl_Interp *interp, long time, int argc,
  2113. X    char *argv[]);
  2114. Xextern Event *Tclm_ParseProgram(Tcl_Interp *interp, long time, int argc,
  2115. X    char *argv[]);
  2116. Xextern Event *Tclm_ParseChannelPressure(Tcl_Interp *interp, long time, int argc,
  2117. X    char *argv[]);
  2118. Xextern Event *Tclm_ParsePitchWheel(Tcl_Interp *interp, long time, int argc,
  2119. X    char *argv[]);
  2120. Xextern Event *Tclm_ParseSystemExclusive(Tcl_Interp *interp, long time, int argc,
  2121. X    char *argv[]);
  2122. Xextern Event *Tclm_ParseMetaSequenceNumber(Tcl_Interp *interp, long time,
  2123. X    int argc, char *argv[]);
  2124. Xextern Event *Tclm_ParseMetaText(Tcl_Interp *interp, long time, int argc,
  2125. X    char *argv[]);
  2126. Xextern Event *Tclm_ParseMetaCopyright(Tcl_Interp *interp, long time, int argc,
  2127. X    char *argv[]);
  2128. Xextern Event *Tclm_ParseMetaSequenceName(Tcl_Interp *interp, long time,
  2129. X    int argc, char *argv[]);
  2130. Xextern Event *Tclm_ParseMetaInstrumentName(Tcl_Interp *interp, long time,
  2131. X    int argc, char *argv[]);
  2132. Xextern Event *Tclm_ParseMetaLyric(Tcl_Interp *interp, long time, int argc,
  2133. X    char *argv[]);
  2134. Xextern Event *Tclm_ParseMetaMarker(Tcl_Interp *interp, long time, int argc,
  2135. X    char *argv[]);
  2136. Xextern Event *Tclm_ParseMetaCue(Tcl_Interp *interp, long time, int argc,
  2137. X    char *argv[]);
  2138. Xextern Event *Tclm_ParseMetaChannelPrefix(Tcl_Interp *interp, long time,
  2139. X    int argc, char *argv[]);
  2140. Xextern Event *Tclm_ParseMetaPortNumber(Tcl_Interp *interp, long time, int argc,
  2141. X    char *argv[]);
  2142. Xextern Event *Tclm_ParseMetaEndOfTrack(Tcl_Interp *interp, long time, int argc,
  2143. X    char *argv[]);
  2144. Xextern Event *Tclm_ParseMetaTempo(Tcl_Interp *interp, long time, int argc,
  2145. X    char *argv[]);
  2146. Xextern Event *Tclm_ParseMetaSMPTE(Tcl_Interp *interp, long time, int argc,
  2147. X    char *argv[]);
  2148. Xextern Event *Tclm_ParseMetaTime(Tcl_Interp *interp, long time, int argc,
  2149. X    char *argv[]);
  2150. Xextern Event *Tclm_ParseMetaKey(Tcl_Interp *interp, long time, int argc,
  2151. X    char *argv[]);
  2152. Xextern Event *Tclm_ParseMetaSequencerSpecific(Tcl_Interp *interp, long time,
  2153. X    int argc, char *argv[]);
  2154. Xextern Event *Tclm_ParseMetaUnknown(Tcl_Interp *interp, long time, int argc,
  2155. X    char *argv[]);
  2156. X#endif
  2157. END_OF_FILE
  2158.   if test 5860 -ne `wc -c <'tclmidi-2.0/tclmEvent.h'`; then
  2159.     echo shar: \"'tclmidi-2.0/tclmEvent.h'\" unpacked with wrong size!
  2160.   fi
  2161.   # end of 'tclmidi-2.0/tclmEvent.h'
  2162. fi
  2163. echo shar: End of archive 7 \(of 14\).
  2164. cp /dev/null ark7isdone
  2165. MISSING=""
  2166. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  2167.     if test ! -f ark${I}isdone ; then
  2168.     MISSING="${MISSING} ${I}"
  2169.     fi
  2170. done
  2171. if test "${MISSING}" = "" ; then
  2172.     echo You have unpacked all 14 archives.
  2173.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2174. else
  2175.     echo You still must unpack the following archives:
  2176.     echo "        " ${MISSING}
  2177. fi
  2178. exit 0
  2179. exit 0 # Just in case...
  2180.