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

  1. From: durian@boogie.com (Mike Durian)
  2. Newsgroups: comp.sources.misc
  3. Subject: v43i112:  tclmidi - A language for manipulating MIDI files, v2.0, Part04/14
  4. Date: 21 Jul 1994 19:26:26 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <30n3ni$733@sparky.sterling.com>
  9. X-Md4-Signature: bb696fc3a4659398b68bd179ded8ce22
  10.  
  11. Submitted-by: durian@boogie.com (Mike Durian)
  12. Posting-number: Volume 43, Issue 112
  13. Archive-name: tclmidi/part04
  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/contrib/mmerge tclmidi-2.0/tclmCmd.C
  22. #   tclmidi-2.0/tclmEvent.C tclmidi-2.0/tclmPlay.C
  23. # Wrapped by kent@sparky on Thu Jul 21 19:05:14 1994
  24. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 4 (of 14)."'
  27. if test -f 'tclmidi-2.0/contrib/mmerge' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'tclmidi-2.0/contrib/mmerge'\"
  29. else
  30.   echo shar: Extracting \"'tclmidi-2.0/contrib/mmerge'\" \(700 characters\)
  31.   sed "s/^X//" >'tclmidi-2.0/contrib/mmerge' <<'END_OF_FILE'
  32. X#!/usr/local/bin/tclmidi
  33. X
  34. Xif {$argc} {
  35. X    puts {Usage: mmerge < type1.mid > type0.mid}
  36. X    exit 1
  37. X}
  38. X
  39. Xset imf [midiread stdin]
  40. Xset config [midiconfig $imf]
  41. X
  42. Xif {[lindex [lindex $config 0] 1] != 1} {
  43. X    puts stderr {Input must be type 1}
  44. X    exit -1
  45. X}
  46. X
  47. Xset division [lindex $config 1]
  48. Xset omf [midimake]
  49. Xmidiconfig $omf "format 0" $division "tracks 1"
  50. Xset tracks [lindex [lindex $config 2] 1]
  51. X
  52. Xfor {set i 0} {$i < $tracks} {incr i} {
  53. X    midirewind $imf
  54. X    set lastevent [midiget $imf $i prev]
  55. X    if {[lindex $lastevent 1] == "MetaEndOfTrack"} {
  56. X        mididelete $imf $i $lastevent
  57. X    }
  58. X    midimerge "$omf 0" "$imf $i"
  59. X}
  60. X
  61. Xmidiput $omf 0 "[miditrack $omf 0 end] MetaEndOfTrack"
  62. Xmidiwrite stdout $omf
  63. Xmidifree $imf
  64. Xmidifree $omf
  65. END_OF_FILE
  66.   if test 700 -ne `wc -c <'tclmidi-2.0/contrib/mmerge'`; then
  67.     echo shar: \"'tclmidi-2.0/contrib/mmerge'\" unpacked with wrong size!
  68.   fi
  69.   chmod +x 'tclmidi-2.0/contrib/mmerge'
  70.   # end of 'tclmidi-2.0/contrib/mmerge'
  71. fi
  72. if test -f 'tclmidi-2.0/tclmCmd.C' -a "${1}" != "-c" ; then 
  73.   echo shar: Will not clobber existing file \"'tclmidi-2.0/tclmCmd.C'\"
  74. else
  75.   echo shar: Extracting \"'tclmidi-2.0/tclmCmd.C'\" \(22271 characters\)
  76.   sed "s/^X//" >'tclmidi-2.0/tclmCmd.C' <<'END_OF_FILE'
  77. X/*-
  78. X * Copyright (c) 1993, 1994 Michael B. Durian.  All rights reserved.
  79. X *
  80. X * Redistribution and use in source and binary forms, with or without
  81. X * modification, are permitted provided that the following conditions
  82. X * are met:
  83. X * 1. Redistributions of source code must retain the above copyright
  84. X *    notice, this list of conditions and the following disclaimer.
  85. X * 2. Redistributions in binary form must reproduce the above copyright
  86. X *    notice, this list of conditions and the following disclaimer in the
  87. X *    documentation and/or other materials provided with the distribution.
  88. X * 3. All advertising materials mentioning features or use of this software
  89. X *    must display the following acknowledgement:
  90. X *    This product includes software developed by Michael B. Durian.
  91. X * 4. The name of the the Author may be used to endorse or promote 
  92. X *    products derived from this software without specific prior written 
  93. X *    permission.
  94. X *
  95. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  96. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  97. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  98. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  99. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  100. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  101. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  102. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  103. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  104. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  105. X * SUCH DAMAGE.
  106. X */
  107. Xextern "C" {
  108. X#include <tcl.h>
  109. X}
  110. X#include <stdlib.h>
  111. X#include <string.h>
  112. X#include <iostream.h>
  113. X#include "tclmidi.h"
  114. X#include "TclmInterp.h"
  115. X#include "Song.h"
  116. X#include "tclmEvent.h"
  117. X#include "patchlevel.h"
  118. X
  119. Xstatic int Tclm_MidiMake(ClientData client_data, Tcl_Interp *interp, int argc,
  120. X    char *argv[]);
  121. Xstatic int Tclm_MidiFree(ClientData client_data, Tcl_Interp *interp, int argc,
  122. X    char *argv[]);
  123. Xstatic int Tclm_MidiRead(ClientData client_data, Tcl_Interp *interp, int argc,
  124. X    char *argv[]);
  125. Xstatic int Tclm_MidiWrite(ClientData client_data, Tcl_Interp *interp, int argc,
  126. X    char *argv[]);
  127. Xstatic int Tclm_MidiConfig(ClientData client_data, Tcl_Interp *interp, int argc,
  128. X    char *argv[]);
  129. Xstatic int Tclm_MidiRewind(ClientData client_data, Tcl_Interp *interp, int argc,
  130. X    char *argv[]);
  131. Xstatic int Tclm_MidiGet(ClientData client_data, Tcl_Interp *interp, int argc,
  132. X    char *argv[]);
  133. Xstatic int Tclm_MidiPut(ClientData client_data, Tcl_Interp *interp, int argc,
  134. X    char *argv[]);
  135. Xstatic int Tclm_MidiDelete(ClientData client_data, Tcl_Interp *interp, int argc,
  136. X    char *argv[]);
  137. Xstatic int Tclm_MidiMerge(ClientData client_data, Tcl_Interp *interp, int argc,
  138. X    char *argv[]);
  139. Xstatic int Tclm_MidiSplit(ClientData client_data, Tcl_Interp *interp, int argc,
  140. X    char *argv[]);
  141. Xstatic int Tclm_MidiCopy(ClientData client_data, Tcl_Interp *interp, int argc,
  142. X    char *argv[]);
  143. Xstatic int Tclm_MidiVersion(ClientData client_data, Tcl_Interp *interp,
  144. X    int argc, char *argv[]);
  145. Xstatic int Tclm_MidiTrack(ClientData client_data, Tcl_Interp *interp,
  146. X    int argc, char *argv[]);
  147. Xstatic int Tclm_GetTrack(TclmInterp *tclm_interp, Tcl_Interp *interp,
  148. X    const char *str, Song **song, int *track);
  149. X
  150. Xint
  151. XTclm_Init(Tcl_Interp *interp)
  152. X{
  153. X    TclmInterp *ti;
  154. X
  155. X    ti = new TclmInterp;
  156. X    if (ti == 0) {
  157. X        Tcl_SetResult(interp, "Out of memory in Tclm_Init",
  158. X            TCL_STATIC);
  159. X        return (TCL_ERROR);
  160. X    }
  161. X    Tcl_CreateCommand(interp, "midimake", Tclm_MidiMake, ti, 0);
  162. X    Tcl_CreateCommand(interp, "midifree", Tclm_MidiFree, ti, 0);
  163. X    Tcl_CreateCommand(interp, "midiread", Tclm_MidiRead, ti, 0);
  164. X    Tcl_CreateCommand(interp, "midiwrite", Tclm_MidiWrite, ti, 0);
  165. X    Tcl_CreateCommand(interp, "midiconfig", Tclm_MidiConfig, ti, 0);
  166. X    Tcl_CreateCommand(interp, "midirewind", Tclm_MidiRewind, ti, 0);
  167. X    Tcl_CreateCommand(interp, "midiget", Tclm_MidiGet, ti, 0);
  168. X    Tcl_CreateCommand(interp, "midiput", Tclm_MidiPut, ti, 0);
  169. X    Tcl_CreateCommand(interp, "mididelete", Tclm_MidiDelete, ti, 0);
  170. X    Tcl_CreateCommand(interp, "midimerge", Tclm_MidiMerge, ti, 0);
  171. X    Tcl_CreateCommand(interp, "midisplit", Tclm_MidiSplit, ti, 0);
  172. X    Tcl_CreateCommand(interp, "midimove", Tclm_MidiCopy, ti, 0);
  173. X    Tcl_CreateCommand(interp, "midicopy", Tclm_MidiCopy, ti, 0);
  174. X    Tcl_CreateCommand(interp, "midiversion", Tclm_MidiVersion, ti, 0);
  175. X    Tcl_CreateCommand(interp, "miditrack", Tclm_MidiTrack, ti, 0);
  176. X
  177. X    return (Tclm_PlayInit(interp, ti));
  178. X}
  179. X
  180. Xint
  181. XTclm_MidiMake(ClientData client_data, Tcl_Interp *interp, int argc,
  182. X    char *argv[])
  183. X{
  184. X    TclmInterp *tclm_interp;
  185. X    Song *s;
  186. X    char *key;
  187. X
  188. X    if (argc != 1) {
  189. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  190. X            argv[0], "\"", 0);
  191. X        return (TCL_ERROR);
  192. X    }
  193. X    tclm_interp = (TclmInterp *)client_data;
  194. X
  195. X    s = new Song;
  196. X    key = tclm_interp->AddSong(s);
  197. X    Tcl_SetResult(interp, key, TCL_VOLATILE);
  198. X    delete key;
  199. X    return (TCL_OK);
  200. X}
  201. X
  202. Xint
  203. XTclm_MidiFree(ClientData client_data, Tcl_Interp *interp, int argc,
  204. X    char *argv[])
  205. X{
  206. X    TclmInterp *tclm_interp;
  207. X
  208. X    if (argc != 2) {
  209. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  210. X            argv[0], " MidiID\"", 0);
  211. X        return (TCL_ERROR);
  212. X    }
  213. X    tclm_interp = (TclmInterp *)client_data;
  214. X
  215. X    if (!tclm_interp->DeleteSong(argv[1])) {
  216. X        Tcl_AppendResult(interp, "Bad key ", argv[1], 0);
  217. X        return (TCL_ERROR);
  218. X    }
  219. X    return (TCL_OK);
  220. X}
  221. X
  222. Xint
  223. XTclm_MidiRead(ClientData client_data, Tcl_Interp *interp, int argc,
  224. X    char *argv[])
  225. X{
  226. X    FILE *file;
  227. X    TclmInterp *tclm_interp;
  228. X    Song *song;
  229. X    char *key;
  230. X
  231. X    if (argc != 2) {
  232. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  233. X            argv[0], " FileID\"", 0);
  234. X        return (TCL_ERROR);
  235. X    }
  236. X    tclm_interp = (TclmInterp *)client_data;
  237. X
  238. X    song = new Song;
  239. X
  240. X    if (Tcl_GetOpenFile(interp, argv[1], 0, 1, &file) != TCL_OK)
  241. X        return (TCL_ERROR);
  242. X    if (!song->SMFRead(fileno(file))) {
  243. X        Tcl_AppendResult(interp, "coudln't read MIDI file ", argv[1],
  244. X            ": ", song->GetError(), 0);
  245. X        delete song;
  246. X        return (TCL_ERROR);
  247. X    }
  248. X    key = tclm_interp->AddSong(song);
  249. X    Tcl_SetResult(interp, key, TCL_VOLATILE);
  250. X    delete key;
  251. X    return (TCL_OK);
  252. X}
  253. X
  254. Xint
  255. XTclm_MidiWrite(ClientData client_data, Tcl_Interp *interp, int argc,
  256. X    char *argv[])
  257. X{
  258. X    TclmInterp *tclm_interp;
  259. X    Song *song;
  260. X    FILE *file;
  261. X
  262. X    if (argc != 3) {
  263. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  264. X            argv[0], " FileID MidiID\"", 0);
  265. X        return (TCL_ERROR);
  266. X    }
  267. X    tclm_interp = (TclmInterp *)client_data;
  268. X
  269. X    if ((song = tclm_interp->GetSong(argv[2])) == 0) {
  270. X        Tcl_AppendResult(interp, "bad key ", argv[2], 0);
  271. X        return (TCL_ERROR);
  272. X    }
  273. X
  274. X    if (Tcl_GetOpenFile(interp, argv[1], 1, 1, &file) != TCL_OK)
  275. X        return (TCL_ERROR);
  276. X    if (!song->SMFWrite(fileno(file))) {
  277. X        Tcl_AppendResult(interp, "couldn't write ", argv[2],
  278. X            ": ", song->GetError(), 0);
  279. X        delete song;
  280. X        return (TCL_ERROR);
  281. X    }
  282. X    return (TCL_OK);
  283. X}
  284. X
  285. Xint
  286. XTclm_MidiConfig(ClientData client_data, Tcl_Interp *interp, int argc,
  287. X    char *argv[])
  288. X{
  289. X    ostrstream *buf;
  290. X    TclmInterp *tclm_interp;
  291. X    Song *song;
  292. X    char *str, **sub_argv;
  293. X    int i, sub_argc, value;
  294. X
  295. X    if (argc < 2) {
  296. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  297. X            argv[0], " MidiID ?{format|division|tracks ?value?} ...?\"",
  298. X            0);
  299. X        return (TCL_ERROR);
  300. X    }
  301. X    tclm_interp = (TclmInterp *)client_data;
  302. X
  303. X    if ((song = tclm_interp->GetSong(argv[1])) == 0) {
  304. X        Tcl_AppendResult(interp, "bad key ", argv[1], 0);
  305. X        return (TCL_ERROR);
  306. X    }
  307. X
  308. X    if (argc == 2) {
  309. X        // make list of all values
  310. X        buf = new ostrstream;
  311. X        *buf << "format " << song->GetFormat() << ends;
  312. X        str = buf->str();
  313. X        Tcl_AppendElement(interp, str);
  314. X        delete str;
  315. X        delete buf;
  316. X        buf = new ostrstream;
  317. X        *buf << "division " << song->GetDivision() << ends;
  318. X        str = buf->str();
  319. X        Tcl_AppendElement(interp, str);
  320. X        delete str;
  321. X        delete buf;
  322. X        buf = new ostrstream;
  323. X        *buf << "tracks " << song->GetNumTracks() << ends;
  324. X        str = buf->str();
  325. X        Tcl_AppendElement(interp, str);
  326. X        delete str;
  327. X        delete buf;
  328. X        return (TCL_OK);
  329. X    }
  330. X    for (i = 2; i < argc; i++) {
  331. X        // loop through each arg and either set or return values
  332. X        if (Tcl_SplitList(interp, argv[i], &sub_argc, &sub_argv)
  333. X            != TCL_OK)
  334. X            return (TCL_ERROR);
  335. X        switch (sub_argc) {
  336. X        case 1:
  337. X            // return the value
  338. X            buf = new ostrstream;
  339. X            if (strcmp(sub_argv[0], "format") == 0) {
  340. X                *buf << "format " << song->GetFormat() << ends;
  341. X            } else if (strcmp(sub_argv[0], "division") == 0) {
  342. X                *buf << "division " << song->GetDivision()
  343. X                    << ends;
  344. X            } else if (strcmp(sub_argv[0], "tracks") == 0) {
  345. X                *buf << "tracks " << song->GetNumTracks()
  346. X                    << ends;
  347. X            } else {
  348. X                Tcl_AppendResult(interp, "bad parameter ",
  349. X                    sub_argv[0], 0);
  350. X                delete buf;
  351. X                return (TCL_ERROR);
  352. X            }
  353. X            str = buf->str();
  354. X            Tcl_AppendElement(interp, str);
  355. X            delete str;
  356. X            delete buf;
  357. X            break;
  358. X        case 2:
  359. X            // set the value
  360. X            if (Tcl_GetInt(interp, sub_argv[1], &value) != TCL_OK)
  361. X                return (TCL_ERROR);
  362. X            if (strcmp(sub_argv[0], "format") == 0) {
  363. X                song->SetFormat(value);
  364. X            } else if (strcmp(sub_argv[0], "division") == 0) {
  365. X                song->SetDivision(value);
  366. X            } else if (strcmp(sub_argv[0], "tracks") == 0) {
  367. X                song->SetNumTracks(value);
  368. X            } else {
  369. X                Tcl_AppendResult(interp, "bad parameter ",
  370. X                    sub_argv[0], 0);
  371. X                return (TCL_ERROR);
  372. X            }
  373. X            break;
  374. X        default:
  375. X            Tcl_SetResult(interp, "wrong # args: should be "
  376. X                "{format|division|tracks ?value?}", TCL_STATIC);
  377. X            return (TCL_ERROR);
  378. X            break;
  379. X        }
  380. X        free(sub_argv);
  381. X    }
  382. X    return (TCL_OK);
  383. X}
  384. X
  385. Xint
  386. XTclm_MidiRewind(ClientData client_data, Tcl_Interp *interp, int argc,
  387. X    char *argv[])
  388. X{
  389. X    TclmInterp *tclm_interp;
  390. X    Song *song;
  391. X    int track;
  392. X
  393. X    if (argc != 3 && argc != 2) {
  394. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  395. X            argv[0], " MidiID ?track?\"", 0);
  396. X        return (TCL_ERROR);
  397. X    }
  398. X    tclm_interp = (TclmInterp *)client_data;
  399. X
  400. X    if ((song = tclm_interp->GetSong(argv[1])) == 0) {
  401. X        Tcl_AppendResult(interp, "bad key ", argv[1], 0);
  402. X        return (TCL_ERROR);
  403. X    }
  404. X
  405. X    if (argc == 2)
  406. X        song->RewindEvents();
  407. X    else {
  408. X        if (Tcl_GetInt(interp, argv[2], &track) != TCL_OK)
  409. X            return (TCL_ERROR);
  410. X        song->RewindEvents(track);
  411. X    }
  412. X    return (TCL_OK);
  413. X}
  414. X
  415. Xint
  416. XTclm_MidiGet(ClientData client_data, Tcl_Interp *interp, int argc,
  417. X    char *argv[])
  418. X{
  419. X    ostrstream *buf;
  420. X    long time;
  421. X    int printable, track;
  422. X    TclmInterp *tclm_interp;
  423. X    Song *song;
  424. X    Event *e, *events;
  425. X    char *str;
  426. X
  427. X    if (argc != 4) {
  428. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  429. X            argv[0], " MidiID track time|next|prev\"", 0);
  430. X        return (TCL_ERROR);
  431. X    }
  432. X    tclm_interp = (TclmInterp *)client_data;
  433. X
  434. X    if ((song = tclm_interp->GetSong(argv[1])) == 0) {
  435. X        Tcl_AppendResult(interp, "bad key ", argv[1], 0);
  436. X        return (TCL_ERROR);
  437. X    }
  438. X
  439. X    if (Tcl_GetInt(interp, argv[2], &track) != TCL_OK)
  440. X        return (TCL_ERROR);
  441. X
  442. X    if (strcmp(argv[3], "next") == 0) {
  443. X        printable = 0;
  444. X        while (!printable) {
  445. X            if ((e = song->NextEvent(track)) == 0) {
  446. X                Tcl_SetResult(interp, "EOT", TCL_STATIC);
  447. X                printable = 1;
  448. X            } else {
  449. X                buf = new ostrstream;
  450. X                Tclm_PrintEvent(*buf, e);
  451. X                str = buf->str();
  452. X                if (str != 0 && str[0] != '\0') {
  453. X                    Tcl_SetResult(interp, str,
  454. X                        TCL_VOLATILE);
  455. X                    printable = 1;
  456. X                }
  457. X                delete str;
  458. X                delete buf;
  459. X            }
  460. X        }
  461. X    } else if (strcmp(argv[3], "prev") == 0) {
  462. X        printable = 0;
  463. X        while (!printable) {
  464. X            if ((e = song->PrevEvent(track)) == 0) {
  465. X                Tcl_SetResult(interp, "EOT", TCL_STATIC);
  466. X                printable = 1;
  467. X            } else {
  468. X                buf = new ostrstream;
  469. X                Tclm_PrintEvent(*buf, e);
  470. X                str = buf->str();
  471. X                if (str != 0 && str[0] != '\0') {
  472. X                    Tcl_SetResult(interp, str,
  473. X                        TCL_VOLATILE);
  474. X                    printable = 1;
  475. X                }
  476. X                delete str;
  477. X                delete buf;
  478. X            }
  479. X        }
  480. X    } else {
  481. X        if (Tcl_GetLong(interp, argv[3], &time) != TCL_OK)
  482. X            return (TCL_ERROR);
  483. X        if ((events = song->GetEvents((short)track, time)) == 0)
  484. X            Tcl_SetResult(interp, "NoEvent", TCL_STATIC);
  485. X        else {
  486. X            for (e = events; e != 0; e = e->GetNextEvent()) {
  487. X                buf = new ostrstream;
  488. X                Tclm_PrintEvent(*buf, e);
  489. X                str = buf->str();
  490. X                if (str != 0 && str[0] != '\0')
  491. X                    Tcl_AppendElement(interp, str);
  492. X                delete str;
  493. X                delete buf;
  494. X            }
  495. X        }
  496. X    }
  497. X    return (TCL_OK);
  498. X}
  499. X
  500. Xint
  501. XTclm_MidiPut(ClientData client_data, Tcl_Interp *interp, int argc,
  502. X    char *argv[])
  503. X{
  504. X    TclmInterp *tclm_interp;
  505. X    Song *song;
  506. X    NoteEvent *np, *new_e2;
  507. X    Event *event, *new_e1;
  508. X    int track;
  509. X
  510. X    if (argc != 4) {
  511. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  512. X            argv[0], " MidiID track event\"", 0);
  513. X        return (TCL_ERROR);
  514. X    }
  515. X    tclm_interp = (TclmInterp *)client_data;
  516. X
  517. X    if ((song = tclm_interp->GetSong(argv[1])) == 0) {
  518. X        Tcl_AppendResult(interp, "bad key ", argv[1], 0);
  519. X        return (TCL_ERROR);
  520. X    }
  521. X
  522. X    if (Tcl_GetInt(interp, argv[2], &track) != TCL_OK)
  523. X        return (TCL_ERROR);
  524. X
  525. X    if (track >= song->GetNumTracks() || track < 0) {
  526. X        ostrstream buf;
  527. X        char *bstr;
  528. X
  529. X        buf << "bad track value " << track << " (only " <<
  530. X            (int)song->GetNumTracks() << " tracks in song)" << ends;
  531. X        bstr = buf.str();
  532. X        Tcl_SetResult(interp, bstr, TCL_VOLATILE);
  533. X        delete bstr;
  534. X        return (TCL_ERROR);
  535. X    }
  536. X
  537. X    if ((event = Tclm_ParseEvent(interp, argv[3])) == 0) {
  538. X        if (strlen(interp->result) == 0)
  539. X            Tcl_SetResult(interp, "No more memory", TCL_STATIC);
  540. X        return (TCL_ERROR);
  541. X    }
  542. X    new_e1 = song->PutEvent(track, *event);
  543. X    if (new_e1 == 0) {
  544. X        Tcl_SetResult(interp, "Couldn't put event", TCL_STATIC);
  545. X        return (TCL_ERROR);
  546. X    }
  547. X    // check to see if it has a note off too
  548. X    if (event->GetType() == NOTEON &&
  549. X        (np = ((NoteEvent *)event)->GetNotePair()) != 0) {
  550. X        new_e2 = (NoteEvent *)song->PutEvent(track, *np);
  551. X        if (new_e2 == 0) {
  552. X            Tcl_SetResult(interp, "Couldn't put event",
  553. X                TCL_STATIC);
  554. X            return (TCL_ERROR);
  555. X        }
  556. X        ((NoteEvent *)new_e1)->SetNotePair(new_e2);
  557. X        new_e2->SetNotePair((NoteEvent *)new_e1);
  558. X        delete np;
  559. X    }
  560. X    delete event;
  561. X
  562. X    return (TCL_OK);
  563. X}
  564. X
  565. Xint
  566. XTclm_MidiDelete(ClientData client_data, Tcl_Interp *interp, int argc,
  567. X    char *argv[])
  568. X{
  569. X    TclmInterp *tclm_interp;
  570. X    Song *song;
  571. X    Event *event, *note_off;
  572. X    int track;
  573. X
  574. X    if (argc != 4 && argc != 6) {
  575. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  576. X            argv[0], " MidiID track {event | range starttime "
  577. X            "endtime}\"", 0);
  578. X        return (TCL_ERROR);
  579. X    }
  580. X    tclm_interp = (TclmInterp *)client_data;
  581. X
  582. X    if ((song = tclm_interp->GetSong(argv[1])) == 0) {
  583. X        Tcl_AppendResult(interp, "bad key ", argv[1], 0);
  584. X        return (TCL_ERROR);
  585. X    }
  586. X
  587. X    if (Tcl_GetInt(interp, argv[2], &track) != TCL_OK)
  588. X        return (TCL_ERROR);
  589. X
  590. X    if (track >= song->GetNumTracks() || track < 0) {
  591. X        ostrstream buf;
  592. X        char *bstr;
  593. X
  594. X        buf << "bad track value " << track << " (only " <<
  595. X            (int)song->GetNumTracks() << " tracks in song)" << ends;
  596. X        bstr = buf.str();
  597. X        Tcl_SetResult(interp, bstr, TCL_VOLATILE);
  598. X        delete bstr;
  599. X        return (TCL_ERROR);
  600. X    }
  601. X
  602. X    if (strcmp(argv[3], "range") == 0) {
  603. X        unsigned long start, end;
  604. X
  605. X        if (Tcl_GetLong(interp, argv[4], (long *)&start) != TCL_OK)
  606. X            return (TCL_ERROR);
  607. X        if (Tcl_GetLong(interp, argv[5], (long *)&end) != TCL_OK)
  608. X            return (TCL_ERROR);
  609. X        if (!song->DeleteRange(track, start, end)) {
  610. X            Tcl_SetResult(interp, "couldn't delete range",
  611. X                TCL_STATIC);
  612. X            return (TCL_ERROR);
  613. X        }
  614. X        Tcl_SetResult(interp, "1", TCL_STATIC);
  615. X        return (TCL_OK);
  616. X    }
  617. X
  618. X    if ((event = Tclm_ParseEvent(interp, argv[3])) == 0) {
  619. X        if (strlen(interp->result) == 0)
  620. X            Tcl_SetResult(interp, "No more memory", TCL_STATIC);
  621. X        return (TCL_ERROR);
  622. X    }
  623. X    if (!song->DeleteEvent(track, *event)) {
  624. X        Tcl_SetResult(interp, "0", TCL_STATIC);
  625. X        if (event->GetType() == NOTEON &&
  626. X           ((NoteEvent *)event)->GetNotePair() != 0)
  627. X            delete ((NoteEvent *)event)->GetNotePair();
  628. X        delete event;
  629. X        return (TCL_OK);
  630. X    }
  631. X    // delete matching note off if applicable
  632. X    if (event->GetType() == NOTEON &&
  633. X        (note_off = ((NoteEvent *)event)->GetNotePair()) != 0) {
  634. X        if (!song->DeleteEvent(track, *note_off)) {
  635. X            Tcl_SetResult(interp, "Couldn't delete note off "
  636. X                "half of pair", TCL_STATIC);
  637. X            delete event;
  638. X            delete note_off;
  639. X            return (TCL_ERROR);
  640. X        }
  641. X        delete note_off;
  642. X    }
  643. X    delete event;
  644. X    Tcl_SetResult(interp, "1", TCL_STATIC);
  645. X    return (TCL_OK);
  646. X}
  647. X
  648. Xint
  649. XTclm_MidiMerge(ClientData client_data, Tcl_Interp *interp, int argc,
  650. X    char *argv[])
  651. X{
  652. X    TclmInterp *tclm_interp;
  653. X    Song *dest_song, *src_song;
  654. X    int dest_track, i, src_track;
  655. X
  656. X    if (argc < 3) {
  657. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  658. X            argv[0], " {destMidiID destTrack} {srcMidiID srcTrack} "
  659. X            "?{srcMidiID srcTrack} ...?\"", 0);
  660. X        return (TCL_ERROR);
  661. X    }
  662. X    tclm_interp = (TclmInterp *)client_data;
  663. X
  664. X    if (Tclm_GetTrack(tclm_interp, interp, argv[1], &dest_song,
  665. X        &dest_track) != TCL_OK)
  666. X        return (TCL_ERROR);
  667. X
  668. X    for (i = 2; i < argc; i++) {
  669. X        if (Tclm_GetTrack(tclm_interp, interp, argv[i], &src_song,
  670. X            &src_track) != TCL_OK)
  671. X            return (TCL_ERROR);
  672. X        if (!dest_song->Merge(dest_track, *src_song, src_track)) {
  673. X            Tcl_AppendResult(interp, "couldn't merge ",
  674. X                argv[i], " to ", argv[1], 0);
  675. X            return (TCL_ERROR);
  676. X        }
  677. X    }
  678. X    return (TCL_OK);
  679. X}
  680. X
  681. Xint
  682. XTclm_MidiSplit(ClientData client_data, Tcl_Interp *interp, int argc,
  683. X    char *argv[])
  684. X{
  685. X    TclmInterp *tclm_interp;
  686. X    Song *src_song, *meta_song, *normal_song;
  687. X    int src_track, meta_track, normal_track;
  688. X
  689. X    if (argc != 4) {
  690. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  691. X            argv[0], " {srcMidiID srcTrack} {metaMidiID metaTrack} "
  692. X            "{otherMidiID otherTrack}\"", 0);
  693. X        return (TCL_ERROR);
  694. X    }
  695. X    tclm_interp = (TclmInterp *)client_data;
  696. X
  697. X    if (Tclm_GetTrack(tclm_interp, interp, argv[1], &src_song, &src_track)
  698. X        != TCL_OK)
  699. X        return (TCL_ERROR);
  700. X    if (Tclm_GetTrack(tclm_interp, interp, argv[2], &meta_song, &meta_track)
  701. X        != TCL_OK)
  702. X        return (TCL_ERROR);
  703. X    if (Tclm_GetTrack(tclm_interp, interp, argv[3], &normal_song,
  704. X        &normal_track) != TCL_OK)
  705. X        return (TCL_ERROR);
  706. X
  707. X    if (!src_song->Split(src_track, *meta_song, meta_track, *normal_song,
  708. X        normal_track)) {
  709. X        Tcl_AppendResult(interp, "Couldn't split track ", argv[1], 0);
  710. X        return (TCL_ERROR);
  711. X    }
  712. X    return (TCL_OK);
  713. X}
  714. X
  715. X
  716. Xint
  717. XTclm_MidiCopy(ClientData client_data, Tcl_Interp *interp, int argc,
  718. X    char *argv[])
  719. X{
  720. X    TclmInterp *tclm_interp;
  721. X    EventTree *tmp_track;
  722. X    Song *src_song, *dest_song;
  723. X    double scalar;
  724. X    unsigned long dstart, sstart, send;
  725. X    int src_track, dest_track;
  726. X
  727. X    if (argc != 6) {
  728. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  729. X            argv[0], " {destMidiID destTrack} destStartTime "
  730. X            "{srcMidiID srcTrack} srcStartTime srcEndTime\"", 0);
  731. X        return (TCL_ERROR);
  732. X    }
  733. X    tclm_interp = (TclmInterp *)client_data;
  734. X
  735. X    if (Tclm_GetTrack(tclm_interp, interp, argv[1], &dest_song, &dest_track)
  736. X        != TCL_OK)
  737. X        return (TCL_ERROR);
  738. X    if (Tcl_GetLong(interp, argv[2], (long *)&dstart) != TCL_OK)
  739. X        return (TCL_ERROR);
  740. X    if (Tclm_GetTrack(tclm_interp, interp, argv[3], &src_song, &src_track)
  741. X        != TCL_OK)
  742. X        return (TCL_ERROR);
  743. X    if (Tcl_GetLong(interp, argv[4], (long *)&sstart) != TCL_OK)
  744. X        return (TCL_ERROR);
  745. X    if (Tcl_GetLong(interp, argv[5], (long *)&send) != TCL_OK)
  746. X        return (TCL_ERROR);
  747. X
  748. X    scalar = (double)dest_song->GetDivision() / src_song->GetDivision();
  749. X
  750. X    tmp_track = src_song->GetRange(src_track, sstart, send);
  751. X    if (tmp_track == 0) {
  752. X        Tcl_AppendResult(interp, "Couldn't get range from: ", argv[3],
  753. X            " to ", argv[4], 0);
  754. X        return (TCL_ERROR);
  755. X    }
  756. X    if (strcmp(argv[0], "midimove") == 0) {
  757. X        if (!src_song->DeleteRange(src_track, sstart, send)) {
  758. X            Tcl_AppendResult(interp, "Couldn't remove events "
  759. X                "from source track", 0);
  760. X            return (TCL_ERROR);
  761. X        }
  762. X    }
  763. X    if (!dest_song->Add(dest_track, *tmp_track, dstart, scalar)) {
  764. X        Tcl_AppendResult(interp, "Couldn't add range", 0);
  765. X        return (TCL_ERROR);
  766. X    }
  767. X    delete tmp_track;
  768. X    return (TCL_OK);
  769. X}
  770. X
  771. Xint
  772. XTclm_MidiVersion(ClientData client_data, Tcl_Interp *interp, int argc,
  773. X    char *argv[])
  774. X{
  775. X
  776. X    if (argc != 1) {
  777. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  778. X            argv[0], "\"", 0);
  779. X        return (TCL_ERROR);
  780. X    }
  781. X    Tcl_SetResult(interp, (char *)TCLMIDI_VERSION, TCL_STATIC);
  782. X    return (TCL_OK);
  783. X}
  784. X
  785. Xint
  786. XTclm_MidiTrack(ClientData client_data, Tcl_Interp *interp, int argc,
  787. X    char *argv[])
  788. X{
  789. X    TclmInterp *tclm_interp;
  790. X    Song *song;
  791. X    int track;
  792. X
  793. X    if (argc != 4) {
  794. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  795. X            argv[0], " MidiID track {start|end}\"", 0);
  796. X        return (TCL_ERROR);
  797. X    }
  798. X    tclm_interp = (TclmInterp *)client_data;
  799. X
  800. X    if ((song = tclm_interp->GetSong(argv[1])) == 0) {
  801. X        Tcl_AppendResult(interp, "bad key ", argv[1], 0);
  802. X        return (TCL_ERROR);
  803. X    }
  804. X
  805. X    if (Tcl_GetInt(interp, argv[2], &track) != TCL_OK)
  806. X        return (TCL_ERROR);
  807. X
  808. X    if (track >= song->GetNumTracks() || track < 0) {
  809. X        ostrstream buf;
  810. X        char *bstr;
  811. X
  812. X        buf << "bad track value " << track << " (only " <<
  813. X            (int)song->GetNumTracks() << " tracks in song)" << ends;
  814. X        bstr = buf.str();
  815. X        Tcl_SetResult(interp, bstr, TCL_VOLATILE);
  816. X        delete bstr;
  817. X        return (TCL_ERROR);
  818. X    }
  819. X
  820. X    if (strcmp(argv[3], "start") == 0) {
  821. X        ostrstream buf;
  822. X        char *bstr;
  823. X
  824. X        buf << song->GetTrack(track).GetStartTime() << ends;
  825. X        bstr = buf.str();
  826. X        Tcl_SetResult(interp, bstr, TCL_VOLATILE);
  827. X        delete bstr;
  828. X        return (TCL_OK);
  829. X    } else if (strcmp(argv[3], "end") == 0) {
  830. X        ostrstream buf;
  831. X        char *bstr;
  832. X
  833. X        buf << song->GetTrack(track).GetEndTime() << ends;
  834. X        bstr = buf.str();
  835. X        Tcl_SetResult(interp, bstr, TCL_VOLATILE);
  836. X        delete bstr;
  837. X        return (TCL_OK);
  838. X    } else {
  839. X        Tcl_AppendResult(interp, "bad ", argv[0], " command \"",
  840. X            argv[3], "\"", 0);
  841. X        return (TCL_ERROR);
  842. X    }
  843. X}
  844. X
  845. Xint
  846. XTclm_GetTrack(TclmInterp *tclm_interp, Tcl_Interp *interp, const char *str,
  847. X    Song **song, int *track)
  848. X{
  849. X    char **sub_argv;
  850. X    int sub_argc;
  851. X
  852. X    if (Tcl_SplitList(interp, (char *)str, &sub_argc, &sub_argv) != TCL_OK)
  853. X        return (TCL_ERROR);
  854. X    if (sub_argc != 2) {
  855. X        Tcl_SetResult(interp, "bad track designation: "
  856. X            "should be \"{MidiID Track}\"", TCL_STATIC);
  857. X        free(sub_argv);
  858. X        return (TCL_ERROR);
  859. X    }
  860. X    if ((*song = tclm_interp->GetSong(sub_argv[0])) == 0) {
  861. X        Tcl_AppendResult(interp, "bad MidiID ", str, 0);
  862. X        free(sub_argv);
  863. X        return (TCL_ERROR);
  864. X    }
  865. X    if (Tcl_GetInt(interp, sub_argv[1], track) != TCL_OK) {
  866. X        Tcl_AppendResult(interp, "bad track ", str, 0);
  867. X        free(sub_argv);
  868. X        return (TCL_ERROR);
  869. X    }
  870. X    if (*track < 0 || *track >= (*song)->GetNumTracks()) {
  871. X        ostrstream buf;
  872. X        char *s;
  873. X
  874. X        buf << "Bad track value " << str << " (only "
  875. X            << (*song)->GetNumTracks() << " tracks in song)" << ends;
  876. X        s = buf.str();
  877. X        Tcl_SetResult(interp, s, TCL_VOLATILE);
  878. X        delete s;
  879. X        free(sub_argv);
  880. X        return (TCL_ERROR);
  881. X    }
  882. X    free(sub_argv);
  883. X    return (TCL_OK);
  884. X}
  885. END_OF_FILE
  886.   if test 22271 -ne `wc -c <'tclmidi-2.0/tclmCmd.C'`; then
  887.     echo shar: \"'tclmidi-2.0/tclmCmd.C'\" unpacked with wrong size!
  888.   fi
  889.   # end of 'tclmidi-2.0/tclmCmd.C'
  890. fi
  891. if test -f 'tclmidi-2.0/tclmEvent.C' -a "${1}" != "-c" ; then 
  892.   echo shar: Will not clobber existing file \"'tclmidi-2.0/tclmEvent.C'\"
  893. else
  894.   echo shar: Extracting \"'tclmidi-2.0/tclmEvent.C'\" \(25530 characters\)
  895.   sed "s/^X//" >'tclmidi-2.0/tclmEvent.C' <<'END_OF_FILE'
  896. X/*-
  897. X * Copyright (c) 1993, 1994 Michael B. Durian.  All rights reserved.
  898. X *
  899. X * Redistribution and use in source and binary forms, with or without
  900. X * modification, are permitted provided that the following conditions
  901. X * are met:
  902. X * 1. Redistributions of source code must retain the above copyright
  903. X *    notice, this list of conditions and the following disclaimer.
  904. X * 2. Redistributions in binary form must reproduce the above copyright
  905. X *    notice, this list of conditions and the following disclaimer in the
  906. X *    documentation and/or other materials provided with the distribution.
  907. X * 3. All advertising materials mentioning features or use of this software
  908. X *    must display the following acknowledgement:
  909. X *    This product includes software developed by Michael B. Durian.
  910. X * 4. The name of the the Author may be used to endorse or promote 
  911. X *    products derived from this software without specific prior written 
  912. X *    permission.
  913. X *
  914. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  915. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  916. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  917. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  918. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  919. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  920. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  921. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  922. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  923. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  924. X * SUCH DAMAGE.
  925. X */
  926. Xextern "C" {
  927. X#include <tcl.h>
  928. X}
  929. X#include <strstream.h>
  930. X#include <ctype.h>
  931. X#include <string.h>
  932. X#include <stdlib.h>
  933. X
  934. X#include "tclmidi.h"
  935. X#include "tclmEvent.h"
  936. X
  937. Xvoid
  938. XTclm_PrintEvent(ostream &buf, Event *e)
  939. X{
  940. X    char *str;
  941. X
  942. X    switch (e->GetType()) {
  943. X    case NOTEOFF:
  944. X        if (((NoteEvent *)e)->GetNotePair() != 0) {
  945. X            buf << ends;
  946. X            return;
  947. X        }
  948. X        str = Tclm_PrintNoteOff((NoteOffEvent *)e);
  949. X        break;
  950. X    case NOTEON:
  951. X        if (((NoteEvent *)e)->GetNotePair() == 0)
  952. X            str = Tclm_PrintNoteOn((NoteOnEvent *)e);
  953. X        else {
  954. X            if (((NoteEvent *)e)->GetVelocity() == 0) {
  955. X                buf << ends;
  956. X                return;
  957. X            }
  958. X            str = Tclm_PrintNote((NoteOnEvent *)e);
  959. X        }
  960. X        break;
  961. X    case KEYPRESSURE:
  962. X        str = Tclm_PrintKeyPressure((KeyPressureEvent *)e);
  963. X        break;
  964. X    case PARAMETER:
  965. X        str = Tclm_PrintParameter((ParameterEvent *)e);
  966. X        break;
  967. X    case PROGRAM:
  968. X        str = Tclm_PrintProgram((ProgramEvent *)e);
  969. X        break;
  970. X    case CHANNELPRESSURE:
  971. X        str = Tclm_PrintChannelPressure((ChannelPressureEvent *)e);
  972. X        break;
  973. X    case PITCHWHEEL:
  974. X        str = Tclm_PrintPitchWheel((PitchWheelEvent *)e);
  975. X        break;
  976. X    case SYSTEMEXCLUSIVE:
  977. X        str = Tclm_PrintSystemExclusive((SystemExclusiveEvent *)e);
  978. X        break;
  979. X    case METASEQUENCENUMBER:
  980. X        str = Tclm_PrintMetaSequenceNumber(
  981. X            (MetaSequenceNumberEvent *)e);
  982. X        break;
  983. X    case METATEXT:
  984. X        str = Tclm_PrintMetaText((MetaTextEvent *)e);
  985. X        break;
  986. X    case METACOPYRIGHT:
  987. X        str = Tclm_PrintMetaCopyright((MetaCopyrightEvent *)e);
  988. X        break;
  989. X    case METASEQUENCENAME:
  990. X        str = Tclm_PrintMetaSequenceName((MetaSequenceNameEvent *)e);
  991. X        break;
  992. X    case METAINSTRUMENTNAME:
  993. X        str = Tclm_PrintMetaInstrumentName(
  994. X            (MetaInstrumentNameEvent *)e);
  995. X        break;
  996. X    case METALYRIC:
  997. X        str = Tclm_PrintMetaLyric((MetaLyricEvent *)e);
  998. X        break;
  999. X    case METAMARKER:
  1000. X        str = Tclm_PrintMetaMarker((MetaMarkerEvent *)e);
  1001. X        break;
  1002. X    case METACUE:
  1003. X        str = Tclm_PrintMetaCue((MetaCueEvent *)e);
  1004. X        break;
  1005. X    case METACHANNELPREFIX:
  1006. X        str = Tclm_PrintMetaChannelPrefix((MetaChannelPrefixEvent *)e);
  1007. X        break;
  1008. X    case METAPORTNUMBER:
  1009. X        str = Tclm_PrintMetaPortNumber((MetaPortNumberEvent *)e);
  1010. X        break;
  1011. X    case METAENDOFTRACK:
  1012. X        str = Tclm_PrintMetaEndOfTrack((MetaEndOfTrackEvent *)e);
  1013. X        break;
  1014. X    case METATEMPO:
  1015. X        str = Tclm_PrintMetaTempo((MetaTempoEvent *)e);
  1016. X        break;
  1017. X    case METASMPTE:
  1018. X        str = Tclm_PrintMetaSMPTE((MetaSMPTEEvent *)e);
  1019. X        break;
  1020. X    case METATIME:
  1021. X        str = Tclm_PrintMetaTime((MetaTimeEvent *)e);
  1022. X        break;
  1023. X    case METAKEY:
  1024. X        str = Tclm_PrintMetaKey((MetaKeyEvent *)e);
  1025. X        break;
  1026. X    case METASEQUENCERSPECIFIC:
  1027. X        str = Tclm_PrintMetaSequencerSpecific(
  1028. X            (MetaSequencerSpecificEvent *)e);
  1029. X        break;
  1030. X    case METAUNKNOWN:
  1031. X        str = Tclm_PrintMetaUnknown((MetaUnknownEvent *)e);
  1032. X        break;
  1033. X    default:
  1034. X        str = 0;
  1035. X        break;
  1036. X    }
  1037. X    buf << e->GetTime() << " " << str << ends;
  1038. X    delete str;
  1039. X}
  1040. X
  1041. Xchar *
  1042. XTclm_PrintNoteOff(NoteOffEvent *e)
  1043. X{
  1044. X    ostrstream buf;
  1045. X
  1046. X    buf << "NoteOff " << (int)e->GetChannel() << " " << (int)e->GetPitch()
  1047. X        << " " << (int)e->GetVelocity() << ends;
  1048. X    return (buf.str());
  1049. X}
  1050. X
  1051. Xchar *
  1052. XTclm_PrintNoteOn(NoteOnEvent *e)
  1053. X{
  1054. X    ostrstream buf;
  1055. X
  1056. X    buf << "NoteOn " << (int)e->GetChannel() << " " << (int)e->GetPitch()
  1057. X        << " " << (int)e->GetVelocity() << ends;
  1058. X    return (buf.str());
  1059. X}
  1060. X
  1061. Xchar *
  1062. XTclm_PrintNote(NoteOnEvent *e)
  1063. X{
  1064. X    ostrstream buf;
  1065. X
  1066. X    buf << "Note " << (int)e->GetChannel() << " " << (int)e->GetPitch()
  1067. X        << " " << (int)e->GetVelocity() << " " <<
  1068. X        (e->GetNotePair()->GetTime() - e->GetTime()) << ends;
  1069. X    return (buf.str());
  1070. X}
  1071. X
  1072. Xchar *
  1073. XTclm_PrintKeyPressure(KeyPressureEvent *e)
  1074. X{
  1075. X    ostrstream buf;
  1076. X
  1077. X    buf << "KeyPressure " << (int)e->GetChannel() << " "
  1078. X        << (int)e->GetPitch() << " " << (int)e->GetPressure() << ends;
  1079. X    return (buf.str());
  1080. X}
  1081. X
  1082. Xchar *
  1083. XTclm_PrintParameter(ParameterEvent *e)
  1084. X{
  1085. X    ostrstream buf;
  1086. X
  1087. X    buf << "Parameter " << (int)e->GetChannel() << " "
  1088. X        << (int)e->GetParameter() << " " << (int)e->GetValue() << ends;
  1089. X    return (buf.str());
  1090. X}
  1091. X
  1092. Xchar *
  1093. XTclm_PrintProgram(ProgramEvent *e)
  1094. X{
  1095. X    ostrstream buf;
  1096. X
  1097. X    buf << "Program " << (int)e->GetChannel() << " "
  1098. X        << (int)e->GetValue() << ends;
  1099. X    return (buf.str());
  1100. X}
  1101. X
  1102. Xchar *
  1103. XTclm_PrintChannelPressure(ChannelPressureEvent *e)
  1104. X{
  1105. X    ostrstream buf;
  1106. X
  1107. X    buf << "ChannelPressure " << (int)e->GetChannel() << " "
  1108. X        << (int)e->GetPressure() << ends;
  1109. X    return (buf.str());
  1110. X}
  1111. X
  1112. Xchar *
  1113. XTclm_PrintPitchWheel(PitchWheelEvent *e)
  1114. X{
  1115. X    ostrstream buf;
  1116. X
  1117. X    buf << "PitchWheel " << (int)e->GetChannel() << " " <<
  1118. X        e->GetValue() << ends;
  1119. X    return (buf.str());
  1120. X}
  1121. X
  1122. Xchar *
  1123. XTclm_PrintSystemExclusive(SystemExclusiveEvent *e)
  1124. X{
  1125. X    ostrstream buf;
  1126. X
  1127. X    buf << "SystemExclusive ";
  1128. X    if (e->GetContinued() == 1)
  1129. X        buf << "continued ";
  1130. X    buf << "{";
  1131. X    Tclm_PrintData(buf, e->GetData(), e->GetLength());
  1132. X    buf << "}" << ends;
  1133. X    return (buf.str());
  1134. X}
  1135. X
  1136. Xchar *
  1137. XTclm_PrintMetaSequenceNumber(MetaSequenceNumberEvent *e)
  1138. X{
  1139. X    ostrstream buf;
  1140. X
  1141. X    buf << "MetaSequenceNumber " << e->GetNumber() << ends;
  1142. X    return (buf.str());
  1143. X}
  1144. X
  1145. Xchar *
  1146. XTclm_PrintMetaText(MetaTextEvent *e)
  1147. X{
  1148. X    ostrstream buf;
  1149. X
  1150. X    buf << "MetaText \"" << e->GetString() << "\"" << ends;
  1151. X    return (buf.str());
  1152. X}
  1153. X
  1154. Xchar *
  1155. XTclm_PrintMetaCopyright(MetaCopyrightEvent *e)
  1156. X{
  1157. X    ostrstream buf;
  1158. X
  1159. X    buf << "MetaCopyright \"" << e->GetString() << "\"" << ends;
  1160. X    return (buf.str());
  1161. X}
  1162. X
  1163. Xchar *
  1164. XTclm_PrintMetaSequenceName(MetaSequenceNameEvent *e)
  1165. X{
  1166. X    ostrstream buf;
  1167. X
  1168. X    buf << "MetaSequenceName \"" << e->GetString() << "\"" << ends;
  1169. X    return (buf.str());
  1170. X}
  1171. X
  1172. Xchar *
  1173. XTclm_PrintMetaInstrumentName(MetaInstrumentNameEvent *e)
  1174. X{
  1175. X    ostrstream buf;
  1176. X
  1177. X    buf << "MetaInstrumentName \"" << e->GetString() << "\"" << ends;
  1178. X    return (buf.str());
  1179. X}
  1180. X
  1181. Xchar *
  1182. XTclm_PrintMetaLyric(MetaLyricEvent *e)
  1183. X{
  1184. X    ostrstream buf;
  1185. X
  1186. X    buf << "MetaLyric \"" << e->GetString() << "\"" << ends;
  1187. X    return (buf.str());
  1188. X}
  1189. X
  1190. Xchar *
  1191. XTclm_PrintMetaMarker(MetaMarkerEvent *e)
  1192. X{
  1193. X    ostrstream buf;
  1194. X
  1195. X    buf << "MetaMarker \"" << e->GetString() << "\"" << ends;
  1196. X    return (buf.str());
  1197. X}
  1198. X
  1199. Xchar *
  1200. XTclm_PrintMetaCue(MetaCueEvent *e)
  1201. X{
  1202. X    ostrstream buf;
  1203. X
  1204. X    buf << "MetaCue \"" << e->GetString() << "\"" << ends;
  1205. X    return (buf.str());
  1206. X}
  1207. X
  1208. Xchar *
  1209. XTclm_PrintMetaChannelPrefix(MetaChannelPrefixEvent *e)
  1210. X{
  1211. X    ostrstream buf;
  1212. X
  1213. X    buf << "MetaChannelPrefix {";
  1214. X    Tclm_PrintData(buf, e->GetData(), e->GetLength());
  1215. X    buf << "}" << ends;
  1216. X    return (buf.str());
  1217. X}
  1218. X
  1219. Xchar *
  1220. XTclm_PrintMetaPortNumber(MetaPortNumberEvent *e)
  1221. X{
  1222. X    ostrstream buf;
  1223. X
  1224. X    buf << "MetaPortNumber " << (int)e->GetPort() << ends;
  1225. X    return (buf.str());
  1226. X}
  1227. X
  1228. Xchar *
  1229. XTclm_PrintMetaEndOfTrack(MetaEndOfTrackEvent *e)
  1230. X{
  1231. X    ostrstream buf;
  1232. X
  1233. X    buf << "MetaEndOfTrack" << ends;
  1234. X    return (buf.str());
  1235. X}
  1236. X
  1237. Xchar *
  1238. XTclm_PrintMetaTempo(MetaTempoEvent *e)
  1239. X{
  1240. X    ostrstream buf;
  1241. X
  1242. X    buf << "MetaTempo " << e->GetTempo() << ends;
  1243. X    return (buf.str());
  1244. X}
  1245. X
  1246. Xchar *
  1247. XTclm_PrintMetaSMPTE(MetaSMPTEEvent *e)
  1248. X{
  1249. X    ostrstream buf;
  1250. X
  1251. X    buf << "MetaSMPTE " << (int)e->GetHour() << " " << (int)e->GetMinute()
  1252. X        << " " << (int)e->GetSecond() << " " << (int)e->GetFrame()
  1253. X        << " " << (int)e->GetFractionalFrame() << ends;
  1254. X    return (buf.str());
  1255. X}
  1256. X
  1257. Xchar *
  1258. XTclm_PrintMetaTime(MetaTimeEvent *e)
  1259. X{
  1260. X    ostrstream buf;
  1261. X
  1262. X    buf << "MetaTime " << (int)e->GetNumerator()
  1263. X        << " " << (int)e->GetDenominator()
  1264. X        << " " << (int)e->GetClocksPerBeat()
  1265. X        << " " << (int)e->Get32ndNotesPerQuarterNote() << ends;
  1266. X    return (buf.str());
  1267. X}
  1268. X
  1269. Xchar *
  1270. XTclm_PrintMetaKey(MetaKeyEvent *e)
  1271. X{
  1272. X    ostrstream buf;
  1273. X
  1274. X    buf << "MetaKey \"" << e->GetKeyStr() << "\" " << e->GetModeStr()
  1275. X        << ends;
  1276. X    return (buf.str());
  1277. X}
  1278. X
  1279. Xchar *
  1280. XTclm_PrintMetaSequencerSpecific(MetaSequencerSpecificEvent *e)
  1281. X{
  1282. X    ostrstream buf;
  1283. X
  1284. X    buf << "MetaSequencerSpecific {";
  1285. X    Tclm_PrintData(buf, e->GetData(), e->GetLength());
  1286. X    buf << "}" << ends;
  1287. X    return (buf.str());
  1288. X}
  1289. X
  1290. Xchar *
  1291. XTclm_PrintMetaUnknown(MetaUnknownEvent *e)
  1292. X{
  1293. X    ostrstream buf;
  1294. X
  1295. X    buf << "MetaUnknown " << (int)e->GetMetaType() << " {";
  1296. X    Tclm_PrintData(buf, e->GetData(), e->GetLength());
  1297. X    buf << "}" << ends;
  1298. X    return (buf.str());
  1299. X}
  1300. X
  1301. XEvent *
  1302. XTclm_ParseEvent(Tcl_Interp *interp, char *str)
  1303. X{
  1304. X    Event *event;
  1305. X    Event *(*pfunc)(Tcl_Interp *, long, int, char **);
  1306. X    char **argv, **aptr;;
  1307. X    char *name;
  1308. X    long time;
  1309. X    int argc, i, length;
  1310. X
  1311. X    if (Tcl_SplitList(interp, str, &argc, &argv) != TCL_OK)
  1312. X        return (0);
  1313. X    aptr = argv;
  1314. X
  1315. X    if (Tcl_GetLong(interp, argv[0], &time) != TCL_OK)
  1316. X        return (0);
  1317. X
  1318. X    length = strlen(argv[1]);
  1319. X    name = new char[length + 1];
  1320. X    for (i = 0; i < length; i++)
  1321. X        name[i] = tolower(argv[1][i]);
  1322. X    name[i] = '\0';
  1323. X
  1324. X    argv++;
  1325. X    argc--;
  1326. X    
  1327. X    pfunc = 0;
  1328. X    switch (name[0]) {
  1329. X    case 'c':
  1330. X        if (strncmp(name, "channelpressure", length) == 0)
  1331. X            pfunc = Tclm_ParseChannelPressure;
  1332. X        break;
  1333. X    case 'k':
  1334. X        if (strncmp(name, "keypressure", length) == 0)
  1335. X            pfunc = Tclm_ParseKeyPressure;
  1336. X        break;
  1337. X    case 'm':
  1338. X        // meta events
  1339. X        switch (name[4]) {
  1340. X        case 'c':
  1341. X            if (strncmp(name, "metachannelprefix", length) == 0)
  1342. X                pfunc = Tclm_ParseMetaChannelPrefix;
  1343. X            else if (strncmp(name, "metacopyright", length) == 0)
  1344. X                pfunc = Tclm_ParseMetaCopyright;
  1345. X            else if (strncmp(name, "metacue", length) == 0)
  1346. X                pfunc = Tclm_ParseMetaCue;
  1347. X            break;
  1348. X        case 'e':
  1349. X            if (strncmp(name, "metaendoftrack", length) == 0)
  1350. X                pfunc = Tclm_ParseMetaEndOfTrack;
  1351. X            break;
  1352. X        case 'i':
  1353. X            if (strncmp(name, "metainstrumentname", length) == 0)
  1354. X                pfunc = Tclm_ParseMetaInstrumentName;
  1355. X            break;
  1356. X        case 'k':
  1357. X            if (strncmp(name, "metakey", length) == 0)
  1358. X                pfunc = Tclm_ParseMetaKey;
  1359. X            break;
  1360. X        case 'l':
  1361. X            if (strncmp(name, "metalyric", length) == 0)
  1362. X                pfunc = Tclm_ParseMetaLyric;
  1363. X            break;
  1364. X        case 'm':
  1365. X            if (strncmp(name, "metamarker", length) == 0)
  1366. X                pfunc = Tclm_ParseMetaMarker;
  1367. X            break;
  1368. X        case 'p':
  1369. X            if (strncmp(name, "metaportnumber", length) == 0)
  1370. X                pfunc = Tclm_ParseMetaPortNumber;
  1371. X            break;
  1372. X        case 's':
  1373. X            if (strncmp(name, "metasequencename", length) == 0)
  1374. X                pfunc = Tclm_ParseMetaSequenceName;
  1375. X            else if (strncmp(name, "metasequencenumber", length)
  1376. X                == 0)
  1377. X                pfunc = Tclm_ParseMetaSequenceNumber;
  1378. X            else if (strncmp(name, "metasequencerspecific", length)
  1379. X                == 0)
  1380. X                pfunc = Tclm_ParseMetaSequencerSpecific;
  1381. X            else if (strncmp(name, "metasmpte", length) == 0)
  1382. X                pfunc = Tclm_ParseMetaSMPTE;
  1383. X            break;
  1384. X        case 't':
  1385. X            if (strncmp(name, "metatempo", length) == 0)
  1386. X                pfunc = Tclm_ParseMetaTempo;
  1387. X            else if (strncmp(name, "metatext", length) == 0)
  1388. X                pfunc = Tclm_ParseMetaText;
  1389. X            else if (strncmp(name, "metatime", length) == 0)
  1390. X                pfunc = Tclm_ParseMetaTime;
  1391. X            break;
  1392. X        case 'u':
  1393. X            if (strncmp(name, "metaunknown", length) == 0)
  1394. X                pfunc = Tclm_ParseMetaUnknown;
  1395. X            break;
  1396. X        }
  1397. X        break;
  1398. X    case 'n':
  1399. X        if (strncmp(name, "note", length) == 0)
  1400. X            pfunc = Tclm_ParseNote;
  1401. X        else if (strncmp(name, "noteoff", length) == 0)
  1402. X            pfunc = Tclm_ParseNoteOff;
  1403. X        else if (strncmp(name, "noteon", length) == 0)
  1404. X            pfunc = Tclm_ParseNoteOn;
  1405. X        break;
  1406. X    case 'p':
  1407. X        if (strncmp(name, "parameter", length) == 0)
  1408. X            pfunc = Tclm_ParseParameter;
  1409. X        else if (strncmp(name, "pitchwheel", length) == 0)
  1410. X            pfunc = Tclm_ParsePitchWheel;
  1411. X        else if (strncmp(name, "program", length) == 0)
  1412. X            pfunc = Tclm_ParseProgram;
  1413. X        break;
  1414. X    case 's':
  1415. X        if (strncmp(name, "systemexclusive", length) == 0)
  1416. X            pfunc = Tclm_ParseSystemExclusive;
  1417. X        break;
  1418. X    }
  1419. X
  1420. X    if (pfunc == 0) {
  1421. X        Tcl_AppendResult(interp, "bad event type ", argv[0], 0);
  1422. X        free(aptr);
  1423. X        delete name;
  1424. X        return (0);
  1425. X    }
  1426. X    event = pfunc(interp, time, argc, argv);
  1427. X    free(aptr);
  1428. X    delete name;
  1429. X    return (event);
  1430. X}
  1431. X
  1432. XEvent *
  1433. XTclm_ParseNoteOff(Tcl_Interp *interp, long time, int argc, char *argv[])
  1434. X{
  1435. X    unsigned char channel, pitch, velocity;
  1436. X
  1437. X    if (argc != 3 && argc != 4) {
  1438. X        Tcl_SetResult(interp, "bad event: should be \"time NoteOff "
  1439. X            "channel pitch ?velocity?\"", TCL_STATIC);
  1440. X        return (0);
  1441. X    }
  1442. X
  1443. X    if (!Tclm_ParseDataByte(interp, argv[1], &channel))
  1444. X        return (0);
  1445. X    if (!Tclm_ParseDataByte(interp, argv[2], &pitch))
  1446. X        return (0);
  1447. X    if (argc == 3)
  1448. X        velocity = 0;
  1449. X    else if (!Tclm_ParseDataByte(interp, argv[3], &velocity))
  1450. X        return (0);
  1451. X
  1452. X    return (new NoteOffEvent(time, channel, pitch, velocity));
  1453. X}
  1454. X
  1455. XEvent *
  1456. XTclm_ParseNoteOn(Tcl_Interp *interp, long time, int argc, char *argv[])
  1457. X{
  1458. X    unsigned char channel, pitch, velocity;
  1459. X
  1460. X    if (argc != 4) {
  1461. X        Tcl_SetResult(interp, "bad event: should be \"time NoteOn "
  1462. X            "channel pitch velocity\"", TCL_STATIC);
  1463. X        return (0);
  1464. X    }
  1465. X
  1466. X    if (!Tclm_ParseDataByte(interp, argv[1], &channel))
  1467. X        return (0);
  1468. X    if (!Tclm_ParseDataByte(interp, argv[2], &pitch))
  1469. X        return (0);
  1470. X    if (!Tclm_ParseDataByte(interp, argv[3], &velocity))
  1471. X        return (0);
  1472. X
  1473. X    return (new NoteOnEvent(time, channel, pitch, velocity));
  1474. X}
  1475. X
  1476. XEvent *
  1477. XTclm_ParseNote(Tcl_Interp *interp, long time, int argc, char *argv[])
  1478. X{
  1479. X    NoteOnEvent *event;
  1480. X    NoteOffEvent *off;
  1481. X    long duration;
  1482. X    unsigned char channel, pitch, velocity;
  1483. X
  1484. X    if (argc != 5) {
  1485. X        Tcl_SetResult(interp, "bad event: should be \"time Note "
  1486. X            "channel pitch velocity duration\"", TCL_STATIC);
  1487. X        return (0);
  1488. X    }
  1489. X
  1490. X    if (!Tclm_ParseDataByte(interp, argv[1], &channel))
  1491. X        return (0);
  1492. X    if (!Tclm_ParseDataByte(interp, argv[2], &pitch))
  1493. X        return (0);
  1494. X    if (!Tclm_ParseDataByte(interp, argv[3], &velocity))
  1495. X        return (0);
  1496. X    if (Tcl_GetLong(interp, argv[4], &duration) != TCL_OK)
  1497. X        return (0);
  1498. X
  1499. X    event = new NoteOnEvent();
  1500. X    event->SetTime(time);
  1501. X    event->SetChannel(channel);
  1502. X    event->SetPitch(pitch);
  1503. X    event->SetVelocity(velocity);
  1504. X
  1505. X    off = new NoteOffEvent();
  1506. X    off->SetTime(time + duration);
  1507. X    off->SetChannel(channel);
  1508. X    off->SetPitch(pitch);
  1509. X    event->SetNotePair(off);
  1510. X    off->SetNotePair(event);
  1511. X
  1512. X    return (event);
  1513. X}
  1514. X
  1515. XEvent *
  1516. XTclm_ParseKeyPressure(Tcl_Interp *interp, long time, int argc, char *argv[])
  1517. X{
  1518. X    unsigned char channel, pitch, pressure;
  1519. X
  1520. X    if (argc != 4) {
  1521. X        Tcl_SetResult(interp, "bad event: should be "
  1522. X            "\"time KeyPressure channel pitch pressure\"", TCL_STATIC);
  1523. X        return (0);
  1524. X    }
  1525. X
  1526. X    if (!Tclm_ParseDataByte(interp, argv[1], &channel))
  1527. X        return (0);
  1528. X    if (!Tclm_ParseDataByte(interp, argv[2], &pitch))
  1529. X        return (0);
  1530. X    if (!Tclm_ParseDataByte(interp, argv[3], &pressure))
  1531. X        return (0);
  1532. X
  1533. X    return (new KeyPressureEvent(time, channel, pitch, pressure));
  1534. X}
  1535. X
  1536. XEvent *
  1537. XTclm_ParseParameter(Tcl_Interp *interp, long time, int argc, char *argv[])
  1538. X{
  1539. X    unsigned char channel, parameter, value;
  1540. X
  1541. X    if (argc != 4) {
  1542. X        Tcl_SetResult(interp, "bad event: should be \"time Parameter "
  1543. X            "channel parameter value\"", TCL_STATIC);
  1544. X        return (0);
  1545. X    }
  1546. X
  1547. X    if (!Tclm_ParseDataByte(interp, argv[1], &channel))
  1548. X        return (0);
  1549. X    if (!Tclm_ParseDataByte(interp, argv[2], ¶meter))
  1550. X        return (0);
  1551. X    if (!Tclm_ParseDataByte(interp, argv[3], &value))
  1552. X        return (0);
  1553. X
  1554. X    return (new ParameterEvent(time, channel, parameter, value));
  1555. X}
  1556. X
  1557. XEvent *
  1558. XTclm_ParseProgram(Tcl_Interp *interp, long time, int argc, char *argv[])
  1559. X{
  1560. X    unsigned char channel, value;
  1561. X
  1562. X    if (argc != 3) {
  1563. X        Tcl_SetResult(interp, "bad event: should be \"time Program "
  1564. X            "channel value\"", TCL_STATIC);
  1565. X        return (0);
  1566. X    }
  1567. X
  1568. X    if (!Tclm_ParseDataByte(interp, argv[1], &channel))
  1569. X        return (0);
  1570. X    if (!Tclm_ParseDataByte(interp, argv[2], &value))
  1571. X        return (0);
  1572. X
  1573. X    return (new ProgramEvent(time, channel, value));
  1574. X}
  1575. X
  1576. XEvent *
  1577. XTclm_ParseChannelPressure(Tcl_Interp *interp, long time, int argc, char *argv[])
  1578. X{
  1579. X    unsigned char channel, pressure;
  1580. X
  1581. X    if (argc != 3) {
  1582. X        Tcl_SetResult(interp, "bad event: should be "
  1583. X            "\"time ChannelPressure channel pressure\"", TCL_STATIC);
  1584. X        return (0);
  1585. X    }
  1586. X
  1587. X    if (!Tclm_ParseDataByte(interp, argv[1], &channel))
  1588. X        return (0);
  1589. X    if (!Tclm_ParseDataByte(interp, argv[2], &pressure))
  1590. X        return (0);
  1591. X
  1592. X    return (new ChannelPressureEvent(time, channel, pressure));
  1593. X}
  1594. X
  1595. XEvent *
  1596. XTclm_ParsePitchWheel(Tcl_Interp *interp, long time, int argc, char *argv[])
  1597. X{
  1598. X    unsigned char channel;
  1599. X    int value;
  1600. X
  1601. X    if (argc != 3) {
  1602. X        Tcl_SetResult(interp, "bad event: should be \"time PitchWheel "
  1603. X            "channel value\"", TCL_STATIC);
  1604. X        return (0);
  1605. X    }
  1606. X
  1607. X    if (!Tclm_ParseDataByte(interp, argv[1], &channel))
  1608. X        return (0);
  1609. X    if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK)
  1610. X        return (0);
  1611. X
  1612. X    return (new PitchWheelEvent(time, channel, value));
  1613. X}
  1614. X
  1615. XEvent *
  1616. XTclm_ParseSystemExclusive(Tcl_Interp *interp, long time, int argc, char *argv[])
  1617. X{
  1618. X    char **str;
  1619. X    SystemExclusiveEvent *event;
  1620. X    unsigned char *data;
  1621. X    int i, len, val;
  1622. X
  1623. X    if ((argc != 2 && argc != 3) || (argc == 3 && strncmp(argv[1], "cont",
  1624. X        4) != 0)) {
  1625. X        Tcl_SetResult(interp, "bad event: should be "
  1626. X            "\"time SystemExclusive ?continued? {data ?data ...?}\"",
  1627. X            TCL_STATIC);
  1628. X        return (0);
  1629. X    }
  1630. X
  1631. X    if (argc == 2) {
  1632. X        if (Tcl_SplitList(interp, argv[1], &len, &str) != TCL_OK)
  1633. X            return (0);
  1634. X    } else {
  1635. X        if (Tcl_SplitList(interp, argv[2], &len, &str) != TCL_OK)
  1636. X            return (0);
  1637. X    }
  1638. X
  1639. X    data = new unsigned char[len];
  1640. X    if (data == 0)
  1641. X        return (0);
  1642. X
  1643. X    for (i = 0; i < len; i++) {
  1644. X        if (Tcl_GetInt(interp, str[i], &val) != TCL_OK)
  1645. X            return (0);
  1646. X        data[i] = val;
  1647. X    }
  1648. X
  1649. X    free(str);
  1650. X    event = new SystemExclusiveEvent(time, data, len);
  1651. X    if (argc == 3)
  1652. X        event->SetContinued(1);
  1653. X    delete data;
  1654. X
  1655. X    return (event);
  1656. X}
  1657. X
  1658. XEvent *
  1659. XTclm_ParseMetaSequenceNumber(Tcl_Interp *interp, long time, int argc,
  1660. X    char *argv[])
  1661. X{
  1662. X    int num;
  1663. X
  1664. X    if (argc != 2) {
  1665. X        Tcl_SetResult(interp, "bad event: should be "
  1666. X            "\"time MetaSequenceNumber number\"", TCL_STATIC);
  1667. X        return (0);
  1668. X    }
  1669. X
  1670. X    if (Tcl_GetInt(interp, argv[1], &num) != TCL_OK)
  1671. X        return (0);
  1672. X
  1673. X    return (new MetaSequenceNumberEvent(time, num));
  1674. X}
  1675. X
  1676. XEvent *
  1677. XTclm_ParseMetaText(Tcl_Interp *interp, long time, int argc, char *argv[])
  1678. X{
  1679. X
  1680. X    if (argc != 2) {
  1681. X        Tcl_SetResult(interp, "bad event: should be \"time MetaText "
  1682. X            "string\"", TCL_STATIC);
  1683. X        return (0);
  1684. X    }
  1685. X
  1686. X    return (new MetaTextEvent(time, argv[1]));
  1687. X}
  1688. X
  1689. XEvent *
  1690. XTclm_ParseMetaCopyright(Tcl_Interp *interp, long time, int argc, char *argv[])
  1691. X{
  1692. X
  1693. X    if (argc != 2) {
  1694. X        Tcl_SetResult(interp, "bad event: should be "
  1695. X            "\"time MetaCopyright string\"", TCL_STATIC);
  1696. X        return (0);
  1697. X    }
  1698. X
  1699. X    return (new MetaCopyrightEvent(time, argv[1]));
  1700. X}
  1701. X
  1702. XEvent *
  1703. XTclm_ParseMetaSequenceName(Tcl_Interp *interp, long time, int argc,
  1704. X    char *argv[])
  1705. X{
  1706. X
  1707. X    if (argc != 2) {
  1708. X        Tcl_SetResult(interp, "bad event: should be "
  1709. X            "\"time MetaSequenceName string\"", TCL_STATIC);
  1710. X        return (0);
  1711. X    }
  1712. X
  1713. X    return (new MetaSequenceNameEvent(time, argv[1]));
  1714. X}
  1715. X
  1716. XEvent *
  1717. XTclm_ParseMetaInstrumentName(Tcl_Interp *interp, long time, int argc,
  1718. X    char *argv[])
  1719. X{
  1720. X
  1721. X    if (argc != 2) {
  1722. X        Tcl_SetResult(interp, "bad event: should be "
  1723. X            "\"time MetaInstrumentName string\"", TCL_STATIC);
  1724. X        return (0);
  1725. X    }
  1726. X
  1727. X    return (new MetaInstrumentNameEvent(time, argv[1]));
  1728. X}
  1729. X
  1730. XEvent *
  1731. XTclm_ParseMetaLyric(Tcl_Interp *interp, long time, int argc, char *argv[])
  1732. X{
  1733. X
  1734. X    if (argc != 2) {
  1735. X        Tcl_SetResult(interp, "bad event: should be \"time MetaLyric "
  1736. X            "string\"", TCL_STATIC);
  1737. X        return (0);
  1738. X    }
  1739. X
  1740. X    return (new MetaLyricEvent(time, argv[1]));
  1741. X}
  1742. X
  1743. XEvent *
  1744. XTclm_ParseMetaMarker(Tcl_Interp *interp, long time, int argc, char *argv[])
  1745. X{
  1746. X
  1747. X    if (argc != 2) {
  1748. X        Tcl_SetResult(interp, "bad event: should be \"time MetaMarker "
  1749. X            "string\"", TCL_STATIC);
  1750. X        return (0);
  1751. X    }
  1752. X
  1753. X    return (new MetaMarkerEvent(time, argv[1]));
  1754. X}
  1755. X
  1756. XEvent *
  1757. XTclm_ParseMetaCue(Tcl_Interp *interp, long time, int argc, char *argv[])
  1758. X{
  1759. X
  1760. X    if (argc != 2) {
  1761. X        Tcl_SetResult(interp, "bad event: should be \"time MetaCue "
  1762. X            "string\"", TCL_STATIC);
  1763. X        return (0);
  1764. X    }
  1765. X
  1766. X    return (new MetaCueEvent(time, argv[1]));
  1767. X}
  1768. X
  1769. XEvent *
  1770. XTclm_ParseMetaChannelPrefix(Tcl_Interp *interp, long time, int argc,
  1771. X    char *argv[])
  1772. X{
  1773. X    char **str;
  1774. X    MetaChannelPrefixEvent *event;
  1775. X    unsigned char *data;
  1776. X    int i, len, val;
  1777. X
  1778. X    if (argc != 2) {
  1779. X        Tcl_SetResult(interp, "bad event: should be "
  1780. X            "\"time MetaChannelPrefix {data ?data ...?}\"", TCL_STATIC);
  1781. X        return (0);
  1782. X    }
  1783. X
  1784. X    if (Tcl_SplitList(interp, argv[1], &len, &str) != TCL_OK)
  1785. X        return (0);
  1786. X
  1787. X    data = new unsigned char[len];
  1788. X    if (data == 0)
  1789. X        return (0);
  1790. X
  1791. X    for (i = 0; i < len; i++) {
  1792. X        if (Tcl_GetInt(interp, str[i], &val) != TCL_OK)
  1793. X            return (0);
  1794. X        data[i] = val;
  1795. X    }
  1796. X
  1797. X    free(str);
  1798. X    event = new MetaChannelPrefixEvent(time, data, len);
  1799. X    delete data;
  1800. X
  1801. X    return (event);
  1802. X}
  1803. X
  1804. XEvent *
  1805. XTclm_ParseMetaPortNumber(Tcl_Interp *interp, long time, int argc, char *argv[])
  1806. X{
  1807. X    int port;
  1808. X
  1809. X    if (argc != 2) {
  1810. X        Tcl_SetResult(interp, "bad event: should be "
  1811. X            "\"time MetaPortNumber port\"", TCL_STATIC);
  1812. X        return (0);
  1813. X    }
  1814. X
  1815. X    if (Tcl_GetInt(interp, argv[1], &port) != TCL_OK)
  1816. X        return (0);
  1817. X
  1818. X    return (new MetaPortNumberEvent(time, port));
  1819. X}
  1820. X
  1821. XEvent *
  1822. XTclm_ParseMetaEndOfTrack(Tcl_Interp *interp, long time, int argc, char *argv[])
  1823. X{
  1824. X
  1825. X    if (argc != 1) {
  1826. X        Tcl_SetResult(interp, "bad event: should be "
  1827. X            "\"time MetaEndOfTrack\"", TCL_STATIC);
  1828. X        return (0);
  1829. X    }
  1830. X
  1831. X    return (new MetaEndOfTrackEvent(time));
  1832. X}
  1833. X
  1834. XEvent *
  1835. XTclm_ParseMetaTempo(Tcl_Interp *interp, long time, int argc, char *argv[])
  1836. X{
  1837. X    int tempo;
  1838. X
  1839. X    if (argc != 2) {
  1840. X        Tcl_SetResult(interp, "bad event: should be \"time MetaTempo "
  1841. X            "tempo\"", TCL_STATIC);
  1842. X        return (0);
  1843. X    }
  1844. X
  1845. X    if (Tcl_GetInt(interp, argv[1], &tempo) != TCL_OK)
  1846. X        return (0);
  1847. X
  1848. X    return (new MetaTempoEvent(time, tempo));
  1849. X}
  1850. X
  1851. XEvent *
  1852. XTclm_ParseMetaSMPTE(Tcl_Interp *interp, long time, int argc, char *argv[])
  1853. X{
  1854. X    int hour, minute, second, frame, fractional_frame;
  1855. X
  1856. X    if (argc != 6) {
  1857. X        Tcl_SetResult(interp, "bad event: should be \"time MetaSMPTE "
  1858. X            "hour minute second frame fractional_frame\"", TCL_STATIC);
  1859. X        return (0);
  1860. X    }
  1861. X
  1862. X    if (Tcl_GetInt(interp, argv[1], &hour) != TCL_OK)
  1863. X        return (0);
  1864. X    if (Tcl_GetInt(interp, argv[2], &minute) != TCL_OK)
  1865. X        return (0);
  1866. X    if (Tcl_GetInt(interp, argv[3], &second) != TCL_OK)
  1867. X        return (0);
  1868. X    if (Tcl_GetInt(interp, argv[4], &frame) != TCL_OK)
  1869. X        return (0);
  1870. X    if (Tcl_GetInt(interp, argv[5], &fractional_frame) != TCL_OK)
  1871. X        return (0);
  1872. X
  1873. X    return (new MetaSMPTEEvent(time, hour, minute, second, frame,
  1874. X        fractional_frame));
  1875. X}
  1876. X
  1877. XEvent *
  1878. XTclm_ParseMetaTime(Tcl_Interp *interp, long time, int argc, char *argv[])
  1879. X{
  1880. X    int numerator, denominator, clocks, thirty_seconds;
  1881. X
  1882. X    if (argc != 5) {
  1883. X        Tcl_SetResult(interp, "bad event: should be \"time MetaTime "
  1884. X            "numerator denominator clocks/beat 32nds/quarter\"",
  1885. X            TCL_STATIC);
  1886. X        return (0);
  1887. X    }
  1888. X
  1889. X    if (Tcl_GetInt(interp, argv[1], &numerator) != TCL_OK)
  1890. X        return (0);
  1891. X    if (Tcl_GetInt(interp, argv[2], &denominator) != TCL_OK)
  1892. X        return (0);
  1893. X    if (Tcl_GetInt(interp, argv[3], &clocks) != TCL_OK)
  1894. X        return (0);
  1895. X    if (Tcl_GetInt(interp, argv[4], &thirty_seconds) != TCL_OK)
  1896. X        return (0);
  1897. X
  1898. X    return (new MetaTimeEvent(time, numerator, denominator, clocks,
  1899. X        thirty_seconds));
  1900. X}
  1901. X
  1902. XEvent *
  1903. XTclm_ParseMetaKey(Tcl_Interp *interp, long time, int argc, char *argv[])
  1904. X{
  1905. X    Key key;
  1906. X    Mode mode;
  1907. X    int match;
  1908. X
  1909. X    if (argc != 3) {
  1910. X        Tcl_SetResult(interp, "bad event: should be \"time MetaKey "
  1911. X            "key mode\"", TCL_STATIC);
  1912. X        return (0);
  1913. X    }
  1914. X
  1915. X    key = StrToKey(argv[1], &match);
  1916. X    if (!match) {
  1917. X        Tcl_AppendResult(interp, "bad key: ", argv[1], 0);
  1918. X        return (0);
  1919. X    }
  1920. X    mode = StrToMode(argv[2], &match);
  1921. X    if (!match) {
  1922. X        Tcl_AppendResult(interp, "bad mode: ", argv[2], 0);
  1923. X        return (0);
  1924. X    }
  1925. X
  1926. X    return (new MetaKeyEvent(time, key, mode));
  1927. X}
  1928. X
  1929. XEvent *
  1930. XTclm_ParseMetaSequencerSpecific(Tcl_Interp *interp, long time, int argc,
  1931. X    char *argv[])
  1932. X{
  1933. X    char **str;
  1934. X    MetaSequencerSpecificEvent *event;
  1935. X    unsigned char *data;
  1936. X    int i, len, val;
  1937. X
  1938. X    if (argc != 2) {
  1939. X        Tcl_SetResult(interp, "bad event: should be "
  1940. X            "\"time MetaSequencerSpecific {data ?data ...?}\"",
  1941. X            TCL_STATIC);
  1942. X        return (0);
  1943. X    }
  1944. X
  1945. X    if (Tcl_SplitList(interp, argv[1], &len, &str) != TCL_OK)
  1946. X        return (0);
  1947. X
  1948. X    data = new unsigned char[len];
  1949. X    if (data == 0)
  1950. X        return (0);
  1951. X
  1952. X    for (i = 0; i < len; i++) {
  1953. X        if (Tcl_GetInt(interp, str[i], &val) != TCL_OK)
  1954. X            return (0);
  1955. X        data[i] = val;
  1956. X    }
  1957. X
  1958. X    free(str);
  1959. X    event = new MetaSequencerSpecificEvent(time, data, len);
  1960. X    delete data;
  1961. X
  1962. X    return (event);
  1963. X}
  1964. X
  1965. XEvent *
  1966. XTclm_ParseMetaUnknown(Tcl_Interp *interp, long time, int argc, char *argv[])
  1967. X{
  1968. X    char **str;
  1969. X    MetaUnknownEvent *event;
  1970. X    unsigned char *data;
  1971. X    int i, len, type, val;
  1972. X
  1973. X    if (argc != 3) {
  1974. X        Tcl_SetResult(interp, "bad event: should be \"time MetaUnknown "
  1975. X            "type {data ?data ...?}\"", TCL_STATIC);
  1976. X        return (0);
  1977. X    }
  1978. X
  1979. X    if (Tcl_GetInt(interp, argv[1], &type) != TCL_OK)
  1980. X        return (0);
  1981. X
  1982. X    if (Tcl_SplitList(interp, argv[2], &len, &str) != TCL_OK)
  1983. X        return (0);
  1984. X
  1985. X    data = new unsigned char[len];
  1986. X    if (data == 0)
  1987. X        return (0);
  1988. X
  1989. X    for (i = 0; i < len; i++) {
  1990. X        if (Tcl_GetInt(interp, str[i], &val) != TCL_OK)
  1991. X            return (0);
  1992. X        data[i] = val;
  1993. X    }
  1994. X
  1995. X    free(str);
  1996. X    event = new MetaUnknownEvent(time, data, len, type);
  1997. X    delete data;
  1998. X
  1999. X    return (event);
  2000. X}
  2001. END_OF_FILE
  2002.   if test 25530 -ne `wc -c <'tclmidi-2.0/tclmEvent.C'`; then
  2003.     echo shar: \"'tclmidi-2.0/tclmEvent.C'\" unpacked with wrong size!
  2004.   fi
  2005.   # end of 'tclmidi-2.0/tclmEvent.C'
  2006. fi
  2007. if test -f 'tclmidi-2.0/tclmPlay.C' -a "${1}" != "-c" ; then 
  2008.   echo shar: Will not clobber existing file \"'tclmidi-2.0/tclmPlay.C'\"
  2009. else
  2010.   echo shar: Extracting \"'tclmidi-2.0/tclmPlay.C'\" \(8922 characters\)
  2011.   sed "s/^X//" >'tclmidi-2.0/tclmPlay.C' <<'END_OF_FILE'
  2012. X/*-
  2013. X * Copyright (c) 1993, 1994 Michael B. Durian.  All rights reserved.
  2014. X *
  2015. X * Redistribution and use in source and binary forms, with or without
  2016. X * modification, are permitted provided that the following conditions
  2017. X * are met:
  2018. X * 1. Redistributions of source code must retain the above copyright
  2019. X *    notice, this list of conditions and the following disclaimer.
  2020. X * 2. Redistributions in binary form must reproduce the above copyright
  2021. X *    notice, this list of conditions and the following disclaimer in the
  2022. X *    documentation and/or other materials provided with the distribution.
  2023. X * 3. All advertising materials mentioning features or use of this software
  2024. X *    must display the following acknowledgement:
  2025. X *    This product includes software developed by Michael B. Durian.
  2026. X * 4. The name of the the Author may be used to endorse or promote 
  2027. X *    products derived from this software without specific prior written 
  2028. X *    permission.
  2029. X *
  2030. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  2031. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  2032. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  2033. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  2034. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  2035. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  2036. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  2037. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  2038. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  2039. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  2040. X * SUCH DAMAGE.
  2041. X */
  2042. Xextern "C" {
  2043. X#include <tcl.h>
  2044. X}
  2045. X#include <stdlib.h>
  2046. X#include <iostream.h>
  2047. X#include <string.h>
  2048. X#include "tclmidi.h"
  2049. X#include "TclmInterp.h"
  2050. X#include "Song.h"
  2051. X#ifdef USE_MPU401
  2052. X#include "MPU401.h"
  2053. X#endif
  2054. X#ifdef USE_MPU401COPY
  2055. X#include "MPU401Copy.h"
  2056. X#endif
  2057. X
  2058. Xstatic int Tclm_MidiPlay(ClientData client_data, Tcl_Interp *interp, int argc,
  2059. X    char *argv[]);
  2060. Xstatic int Tclm_MidiRecord(ClientData client_data, Tcl_Interp *interp, int argc,
  2061. X    char *argv[]);
  2062. Xstatic int Tclm_MidiStop(ClientData client_data, Tcl_Interp *interp, int argc,
  2063. X    char *argv[]);
  2064. Xstatic int Tclm_MidiWait(ClientData client_data, Tcl_Interp *interp, int argc,
  2065. X    char *argv[]);
  2066. Xstatic int Tclm_MidiDevice(ClientData client_data, Tcl_Interp *interp, int argc,
  2067. X    char *argv[]);
  2068. X
  2069. Xint
  2070. XTclm_PlayInit(Tcl_Interp *interp, TclmInterp *tclm_interp)
  2071. X{
  2072. X
  2073. X#if defined(USE_MPU401)
  2074. X    tclm_interp->SetMidiDevice(new MPU401("/dev/midi0"));
  2075. X#elif defined(USE_MPU401COPY)
  2076. X    tclm_interp->SetMidiDevice(new MPU401Copy("/dev/midi0"));
  2077. X#else
  2078. X    tclm_interp->SetMidiDevice(0);
  2079. X#endif
  2080. X
  2081. X    Tcl_CreateCommand(interp, "midiplay", Tclm_MidiPlay, tclm_interp, 0);
  2082. X    Tcl_CreateCommand(interp, "midirecord", Tclm_MidiRecord,
  2083. X        tclm_interp, 0);
  2084. X    Tcl_CreateCommand(interp, "midistop", Tclm_MidiStop, tclm_interp, 0);
  2085. X    Tcl_CreateCommand(interp, "midiwait", Tclm_MidiWait, tclm_interp, 0);
  2086. X    Tcl_CreateCommand(interp, "mididevice", Tclm_MidiDevice,
  2087. X        tclm_interp, 0);
  2088. X    return (TCL_OK);
  2089. X}
  2090. X
  2091. Xint
  2092. XTclm_MidiPlay(ClientData client_data, Tcl_Interp *interp, int argc,
  2093. X    char *argv[])
  2094. X{
  2095. X    TclmInterp *tclm_interp;
  2096. X    Song *song;
  2097. X    MidiDevice *dev;
  2098. X    int repeat;
  2099. X
  2100. X    if (argc != 2 && argc != 3) {
  2101. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  2102. X            argv[0], " MidiID ?repeat?\"", 0);
  2103. X        return (TCL_ERROR);
  2104. X    }
  2105. X    tclm_interp = (TclmInterp *)client_data;
  2106. X
  2107. X    dev = tclm_interp->GetMidiDevice();
  2108. X    if (dev == 0) {
  2109. X        Tcl_SetResult(interp, "0", TCL_STATIC);
  2110. X        return (TCL_OK);
  2111. X    }
  2112. X
  2113. X    if ((song = tclm_interp->GetSong(argv[1])) == 0) {
  2114. X        Tcl_AppendResult(interp, "bad key ", argv[1], 0);
  2115. X        return (TCL_ERROR);
  2116. X    }
  2117. X
  2118. X    repeat = 0;
  2119. X    if (argc == 3 && strlen(argv[2]) != 0) {
  2120. X        if (strcmp(argv[2], "repeat") == 0)
  2121. X            repeat = 1;
  2122. X        else {
  2123. X            Tcl_AppendResult(interp, "bad repeat option: should "
  2124. X                "be \"", argv[0], " MidiID ?repeat?\"", 0);
  2125. X            return (TCL_ERROR);
  2126. X        }
  2127. X    }
  2128. X
  2129. X    if (!dev->Play(song, repeat)) {
  2130. X        Tcl_AppendResult(interp, "couldn't play song \n",
  2131. X            dev->GetError(), 0);
  2132. X        return (TCL_ERROR);
  2133. X    }
  2134. X    Tcl_SetResult(interp, "1", TCL_STATIC);
  2135. X    return (TCL_OK);
  2136. X}
  2137. X
  2138. Xint
  2139. XTclm_MidiRecord(ClientData client_data, Tcl_Interp *interp, int argc,
  2140. X    char *argv[])
  2141. X{
  2142. X    TclmInterp *tclm_interp;
  2143. X    Song *rsong, *psong;
  2144. X    MidiDevice *dev;
  2145. X    int repeat;
  2146. X
  2147. X    if (argc < 2 || argc > 4) {
  2148. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  2149. X            argv[0], " RecMidiID ?PlayMidiID ?repeat??\"", 0);
  2150. X        return (TCL_ERROR);
  2151. X    }
  2152. X    tclm_interp = (TclmInterp *)client_data;
  2153. X
  2154. X    dev = tclm_interp->GetMidiDevice();
  2155. X    if (dev == 0) {
  2156. X        Tcl_SetResult(interp, "0", TCL_STATIC);
  2157. X        return (TCL_OK);
  2158. X    }
  2159. X
  2160. X    if ((rsong = tclm_interp->GetSong(argv[1])) == 0) {
  2161. X        Tcl_AppendResult(interp, "bad key ", argv[1], 0);
  2162. X        return (TCL_ERROR);
  2163. X    }
  2164. X
  2165. X    psong = 0;
  2166. X    repeat = 0;
  2167. X    if (argc > 2) {
  2168. X        if ((psong = tclm_interp->GetSong(argv[2])) == 0) {
  2169. X            Tcl_AppendResult(interp, "bad key ", argv[2], 0);
  2170. X            return (TCL_ERROR);
  2171. X        }
  2172. X
  2173. X        if (argc == 4 && strlen(argv[3]) != 0) {
  2174. X            if (strcmp(argv[3], "repeat") == 0)
  2175. X                repeat = 1;
  2176. X            else {
  2177. X                Tcl_AppendResult(interp, "bad repeat flag: ",
  2178. X                    argv[3], 0);
  2179. X                return (TCL_ERROR);
  2180. X            }
  2181. X        }
  2182. X    }
  2183. X
  2184. X    if (!dev->Record(rsong, psong, repeat)) {
  2185. X        Tcl_AppendResult(interp, "Couldn't record song\n",
  2186. X            dev->GetError(), 0);
  2187. X        return (TCL_ERROR);
  2188. X    }
  2189. X    Tcl_SetResult(interp, "1", TCL_STATIC);
  2190. X    return (TCL_OK);
  2191. X}
  2192. X
  2193. Xint
  2194. XTclm_MidiStop(ClientData client_data, Tcl_Interp *interp, int argc,
  2195. X    char *argv[])
  2196. X{
  2197. X    TclmInterp *tclm_interp;
  2198. X    MidiDevice *dev;
  2199. X
  2200. X    if (argc != 1) {
  2201. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  2202. X            argv[0], "\"", 0);
  2203. X        return (TCL_ERROR);
  2204. X    }
  2205. X    tclm_interp = (TclmInterp *)client_data;
  2206. X
  2207. X    dev = tclm_interp->GetMidiDevice();
  2208. X    if (dev == 0) {
  2209. X        Tcl_SetResult(interp, "0", TCL_STATIC);
  2210. X        return (TCL_OK);
  2211. X    }
  2212. X
  2213. X    if (!dev->Stop()) {
  2214. X        Tcl_AppendResult(interp, "Couldn't stop playing/recording\n",
  2215. X            dev->GetError(), 0);
  2216. X        return (TCL_ERROR);
  2217. X    }
  2218. X    Tcl_SetResult(interp, "1", TCL_STATIC);
  2219. X    return (TCL_OK);
  2220. X}
  2221. X
  2222. Xint
  2223. XTclm_MidiWait(ClientData client_data, Tcl_Interp *interp, int argc,
  2224. X    char *argv[])
  2225. X{
  2226. X    TclmInterp *tclm_interp;
  2227. X    MidiDevice *dev;
  2228. X
  2229. X    if (argc != 1) {
  2230. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  2231. X            argv[0], 0);
  2232. X        return (TCL_ERROR);
  2233. X    }
  2234. X    tclm_interp = (TclmInterp *)client_data;
  2235. X    dev = tclm_interp->GetMidiDevice();
  2236. X    if (dev == 0) {
  2237. X        Tcl_SetResult(interp, "0", TCL_STATIC);
  2238. X        return (TCL_OK);
  2239. X    }
  2240. X    if (!dev->Wait()) {
  2241. X        Tcl_AppendResult(interp, "Couldn't wait for playing/recording "
  2242. X            "to stop\n", dev->GetError(), 0);
  2243. X        return (TCL_ERROR);
  2244. X    }
  2245. X    Tcl_SetResult(interp, "1", TCL_STATIC);
  2246. X    return (TCL_OK);
  2247. X}
  2248. X
  2249. Xint
  2250. XTclm_MidiDevice(ClientData client_data, Tcl_Interp *interp, int argc,
  2251. X    char *argv[])
  2252. X{
  2253. X    TclmInterp *tclm_interp;
  2254. X    MidiDevice *dev;
  2255. X    ostrstream *buf;
  2256. X    char *str, **sub_argv;
  2257. X    int i, sub_argc, value;
  2258. X
  2259. X    if (argc < 1) {
  2260. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  2261. X            argv[0], " ?{name|midithru ?value?} ...?\"", 0);
  2262. X        return (TCL_ERROR);
  2263. X    }
  2264. X    tclm_interp = (TclmInterp *)client_data;
  2265. X    dev = tclm_interp->GetMidiDevice();
  2266. X    if (dev == 0) {
  2267. X        Tcl_SetResult(interp, "0", TCL_STATIC);
  2268. X        return (TCL_OK);
  2269. X    }
  2270. X
  2271. X    if (argc == 1) {
  2272. X        // make list of all values
  2273. X        buf = new ostrstream;
  2274. X        *buf << "name \"" << dev->GetName() << "\"" << ends;
  2275. X        str = buf->str();
  2276. X        Tcl_AppendElement(interp, str);
  2277. X        delete str;
  2278. X        delete buf;
  2279. X        buf = new ostrstream;
  2280. X        *buf << "midithru " << (dev->GetMidiThru() ? "on" : "off")
  2281. X            << ends;
  2282. X        str = buf->str();
  2283. X        Tcl_AppendElement(interp, str);
  2284. X        delete str;
  2285. X        delete buf;
  2286. X        return (TCL_OK);
  2287. X    }
  2288. X    for (i = 1; i < argc; i++) {
  2289. X        // loop through each arg and either set or return values
  2290. X        if (Tcl_SplitList(interp, argv[i], &sub_argc, &sub_argv)
  2291. X            != TCL_OK)
  2292. X            return (TCL_ERROR);
  2293. X        switch (sub_argc) {
  2294. X        case 1:
  2295. X            // return the value
  2296. X            buf = new ostrstream;
  2297. X            if (strcmp(sub_argv[0], "name") == 0) {
  2298. X                *buf << "name \"" << dev->GetName() <<
  2299. X                    "\"" << ends;
  2300. X            } else if (strcmp(sub_argv[0], "midithru") == 0) {
  2301. X                *buf << "midithru " <<
  2302. X                    (dev->GetMidiThru() ? "on" : "off")
  2303. X                    << ends;
  2304. X            } else {
  2305. X                Tcl_AppendResult(interp, "bad parameter ",
  2306. X                    sub_argv[0], 0);
  2307. X                delete buf;
  2308. X                return (TCL_ERROR);
  2309. X            }
  2310. X            str = buf->str();
  2311. X            Tcl_AppendElement(interp, str);
  2312. X            delete str;
  2313. X            delete buf;
  2314. X            break;
  2315. X        case 2:
  2316. X            // set the value
  2317. X            if (strcmp(sub_argv[0], "name") == 0) {
  2318. X                dev->SetName(sub_argv[1]);
  2319. X            } else if (strcmp(sub_argv[0], "midithru") == 0) {
  2320. X                if (Tcl_GetBoolean(interp, sub_argv[1], &value)
  2321. X                    != TCL_OK)
  2322. X                    return (TCL_ERROR);
  2323. X                dev->SetMidiThru(value);
  2324. X            } else {
  2325. X                Tcl_AppendResult(interp, "bad parameter ",
  2326. X                    sub_argv[0], 0);
  2327. X                return (TCL_ERROR);
  2328. X            }
  2329. X            break;
  2330. X        default:
  2331. X            Tcl_SetResult(interp, "wrong # args: should be "
  2332. X                "{name|midithru ?value?}", TCL_STATIC);
  2333. X            return (TCL_ERROR);
  2334. X            break;
  2335. X        }
  2336. X        free(sub_argv);
  2337. X    }
  2338. X    return (TCL_OK);
  2339. X}
  2340. END_OF_FILE
  2341.   if test 8922 -ne `wc -c <'tclmidi-2.0/tclmPlay.C'`; then
  2342.     echo shar: \"'tclmidi-2.0/tclmPlay.C'\" unpacked with wrong size!
  2343.   fi
  2344.   # end of 'tclmidi-2.0/tclmPlay.C'
  2345. fi
  2346. echo shar: End of archive 4 \(of 14\).
  2347. cp /dev/null ark4isdone
  2348. MISSING=""
  2349. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  2350.     if test ! -f ark${I}isdone ; then
  2351.     MISSING="${MISSING} ${I}"
  2352.     fi
  2353. done
  2354. if test "${MISSING}" = "" ; then
  2355.     echo You have unpacked all 14 archives.
  2356.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2357. else
  2358.     echo You still must unpack the following archives:
  2359.     echo "        " ${MISSING}
  2360. fi
  2361. exit 0
  2362. exit 0 # Just in case...
  2363.