home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / lang / tcl / 2354 < prev    next >
Encoding:
Internet Message Format  |  1993-01-12  |  26.7 KB

  1. Path: sparky!uunet!olivea!spool.mu.edu!agate!boulder!csn!cherokee!durian
  2. From: durian@advtech.uswest.com (Mike Durian)
  3. Newsgroups: comp.lang.tcl
  4. Subject: tclm0.1 - tcl with MIDI extensions (2/7)
  5. Message-ID: <1993Jan12.202750.19780@advtech.uswest.com>
  6. Date: 12 Jan 93 20:27:50 GMT
  7. Sender: news@advtech.uswest.com (Radio Free Boulder)
  8. Organization: U S WEST Advanced Technologies
  9. Lines: 886
  10. Nntp-Posting-Host: mongo.advtech.uswest.com
  11.  
  12. # This is a shell archive.  Save it in a file, remove anything before
  13. # this line, and then unpack it by entering "sh file".  Note, it may
  14. # create directories; files and directories will be owned by you and
  15. # have default permissions.
  16. #
  17. # This archive contains:
  18. #
  19. #    tclm0.1/Makefile
  20. #    tclm0.1/bsdi.patch
  21. #    tclm0.1/main.c
  22. #    tclm0.1/tclm.h
  23. #    tclm0.1/tclmMPU.c
  24. #    tclm0.1/tclmMPU.h
  25. #
  26. echo x - tclm0.1/Makefile
  27. sed 's/^X//' >tclm0.1/Makefile << 'END-of-tclm0.1/Makefile'
  28. X# set TCLSRCDIR to the location of the tcl source
  29. XTCLSRCDIR = /u/durian/src/tk3.0/tcl
  30. X
  31. X# add -DMPU to defines if you wish to compile in the ability to
  32. X# play standard MIDI files.  This will only work on BSD/386
  33. X# (BSDI) machines equipped with a MPU401 compatible MIDI card.
  34. X# DEFS =
  35. XDEFS = -DMPU
  36. X
  37. X# set RANLIB to ranlib if your system has it - otherwise set it to
  38. X# true
  39. X# RANLIB = true
  40. XRANLIB = ranlib
  41. X
  42. X# set BINDIR to the directory in which you want the executables
  43. X# to reside
  44. XBINDIR = /usr/local/bin
  45. X
  46. X# tclm library stuff
  47. XAR = libtclm.a
  48. XSRCS = tclmCmd.c tclmMPU.c
  49. XOBJS = tclmCmd.o tclmMPU.o
  50. X
  51. X# stuff for a tclm executable
  52. XTCLMSRC = main.c
  53. XTCLMOBJ = main.o
  54. XTCLMEXEC = tclm
  55. X
  56. X# some sample scripts
  57. XTCLMSCRIPTS = mplay minfo
  58. X
  59. X# where the MIDI library routines are located
  60. XMIDILIBDIR = ./mlib
  61. XMIDIAR = $(MIDILIBDIR)/libmutil.a
  62. X
  63. X# flags and libraries
  64. XLIBS = -ltcl -ltclm -lmutil
  65. XLDFLAGS = -L$(TCLSRCDIR) -L$(MIDILIBDIR) -L. $(LIBS)
  66. XCFLAGS = $(DEFS) -O -I$(TCLSRCDIR) -I$(MIDILIBDIR)
  67. XCC = cc
  68. X
  69. X
  70. X$(TCLMEXEC):    $(MIDIAR) $(AR) $(TCLMOBJ)
  71. X    $(CC) -o $(TCLMEXEC) $(TCLMOBJ) $(LDFLAGS)
  72. X
  73. X$(AR):    $(OBJS)
  74. X    rm -f $(AR)
  75. X    ar cr $(AR) $(OBJS)
  76. X    $(RANLIB) $(AR)
  77. X
  78. X$(MIDIAR): FORCE
  79. X    cd $(MIDILIBDIR); $(MAKE) DEFS=$(DEFS) RANLIB=$(RANLIB)
  80. X
  81. Xinstall:    $(TCLMEXEC) $(TCLMSCRIPTS)
  82. X    chmod 755 $(TCLMSCRIPTS)
  83. X    cp $(TCLMEXEC) $(TCLMSCRIPTS) $(BINDIR)
  84. X
  85. Xclean:
  86. X    rm -f $(TCLMEXEC) $(AR) $(OBJS) $(TCLMOBJ)
  87. X    cd $(MIDILIBDIR); $(MAKE) clean
  88. X
  89. XFORCE:
  90. END-of-tclm0.1/Makefile
  91. echo x - tclm0.1/bsdi.patch
  92. sed 's/^X//' >tclm0.1/bsdi.patch << 'END-of-tclm0.1/bsdi.patch'
  93. X*** tcl/tclEnv.c    Fri Nov 20 09:41:26 1992
  94. X--- ../tk3.0.new/tcl/tclEnv.c    Tue Jan  5 19:10:58 1993
  95. X***************
  96. X*** 57,65 ****
  97. X                  int flags));
  98. X  static int        FindVariable _ANSI_ARGS_((CONST char *name,
  99. X                  int *lengthPtr));
  100. X! void            setenv _ANSI_ARGS_((CONST char *name,
  101. X                  CONST char *value));
  102. X! void            unsetenv _ANSI_ARGS_((CONST char *name));
  103. X  
  104. X  /*
  105. X   *----------------------------------------------------------------------
  106. X--- 57,65 ----
  107. X                  int flags));
  108. X  static int        FindVariable _ANSI_ARGS_((CONST char *name,
  109. X                  int *lengthPtr));
  110. X! void            Setenv _ANSI_ARGS_((CONST char *name,
  111. X                  CONST char *value));
  112. X! void            Unsetenv _ANSI_ARGS_((CONST char *name));
  113. X  
  114. X  /*
  115. X   *----------------------------------------------------------------------
  116. X***************
  117. X*** 183,189 ****
  118. X  /*
  119. X   *----------------------------------------------------------------------
  120. X   *
  121. X!  * setenv --
  122. X   *
  123. X   *    Set an environment variable, replacing an existing value
  124. X   *    or creating a new variable if there doesn't exist a variable
  125. X--- 183,189 ----
  126. X  /*
  127. X   *----------------------------------------------------------------------
  128. X   *
  129. X!  * Setenv --
  130. X   *
  131. X   *    Set an environment variable, replacing an existing value
  132. X   *    or creating a new variable if there doesn't exist a variable
  133. X***************
  134. X*** 200,206 ****
  135. X   */
  136. X  
  137. X  void
  138. X! setenv(name, value)
  139. X      CONST char *name;        /* Name of variable whose value is to be
  140. X                   * set. */
  141. X      CONST char *value;        /* New value for variable. */
  142. X--- 200,206 ----
  143. X   */
  144. X  
  145. X  void
  146. X! Setenv(name, value)
  147. X      CONST char *name;        /* Name of variable whose value is to be
  148. X                   * set. */
  149. X      CONST char *value;        /* New value for variable. */
  150. X***************
  151. X*** 275,281 ****
  152. X  /*
  153. X   *----------------------------------------------------------------------
  154. X   *
  155. X!  * unsetenv --
  156. X   *
  157. X   *    Remove an environment variable, updating the "env" arrays
  158. X   *    in all interpreters managed by us.
  159. X--- 275,281 ----
  160. X  /*
  161. X   *----------------------------------------------------------------------
  162. X   *
  163. X!  * Unsetenv --
  164. X   *
  165. X   *    Remove an environment variable, updating the "env" arrays
  166. X   *    in all interpreters managed by us.
  167. X***************
  168. X*** 290,296 ****
  169. X   */
  170. X  
  171. X  void
  172. X! unsetenv(name)
  173. X      CONST char *name;            /* Name of variable to remove. */
  174. X  {
  175. X      int index, dummy;
  176. X--- 290,296 ----
  177. X   */
  178. X  
  179. X  void
  180. X! Unsetenv(name)
  181. X      CONST char *name;            /* Name of variable to remove. */
  182. X  {
  183. X      int index, dummy;
  184. X***************
  185. X*** 392,406 ****
  186. X      }
  187. X  
  188. X      /*
  189. X!      * If a value is being set, call setenv to do all of the work.
  190. X       */
  191. X  
  192. X      if (flags & TCL_TRACE_WRITES) {
  193. X!     setenv(name2, Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY));
  194. X      }
  195. X  
  196. X      if (flags & TCL_TRACE_UNSETS) {
  197. X!     unsetenv(name2);
  198. X      }
  199. X      return NULL;
  200. X  }
  201. X--- 392,406 ----
  202. X      }
  203. X  
  204. X      /*
  205. X!      * If a value is being set, call Setenv to do all of the work.
  206. X       */
  207. X  
  208. X      if (flags & TCL_TRACE_WRITES) {
  209. X!     Setenv(name2, Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY));
  210. X      }
  211. X  
  212. X      if (flags & TCL_TRACE_UNSETS) {
  213. X!     Unsetenv(name2);
  214. X      }
  215. X      return NULL;
  216. X  }
  217. X*** tcl/tclUnix.h    Fri Aug 21 16:59:18 1992
  218. X--- ../tk3.0.new/tcl/tclUnix.h    Tue Jan  5 19:07:10 1993
  219. X***************
  220. X*** 294,300 ****
  221. X--- 294,303 ----
  222. X  extern int    execvp       _ANSI_ARGS_((CONST char *name, char **argv));
  223. X  extern void    _exit        _ANSI_ARGS_((int status));
  224. X  extern pid_t    fork       _ANSI_ARGS_((void));
  225. X+ /*
  226. X  extern long    fseek       _ANSI_ARGS_((FILE *stream, long offset, int base));
  227. X+ */
  228. X+ extern int    fseek       _ANSI_ARGS_((FILE *stream, long offset, int base));
  229. X  extern uid_t    geteuid       _ANSI_ARGS_((void));
  230. X  extern pid_t    getpid       _ANSI_ARGS_((void));
  231. X  extern char *    getcwd        _ANSI_ARGS_((char *buffer, int size));
  232. END-of-tclm0.1/bsdi.patch
  233. echo x - tclm0.1/main.c
  234. sed 's/^X//' >tclm0.1/main.c << 'END-of-tclm0.1/main.c'
  235. X/* main.c,v 1.3 1993/01/12 19:23:02 durian Exp */
  236. X/*
  237. X * Copyright (c) 1993 Michael B. Durian.  All rights reserved.
  238. X *
  239. X * Redistribution and use in source and binary forms, with or without
  240. X * modification, are permitted provided that the following conditions
  241. X * are met:
  242. X * 1. Redistributions of source code must retain the above copyright
  243. X *    notice, this list of conditions and the following disclaimer.
  244. X * 2. Redistributions in binary form must reproduce the above copyright
  245. X *    notice, this list of conditions and the following disclaimer in the
  246. X *    documentation and/or other materials provided with the distribution.
  247. X * 3. All advertising materials mentioning features or use of this software
  248. X *    must display the following acknowledgement:
  249. X *    This product includes software developed by Michael B. Durian.
  250. X * 4. The name of the the Author may be used to endorse or promote 
  251. X *    products derived from this software without specific prior written 
  252. X *    permission.
  253. X *
  254. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  255. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  256. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  257. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  258. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  259. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  260. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  261. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  262. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  263. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  264. X * SUCH DAMAGE.
  265. X */
  266. X#include "tclInt.h"
  267. X#include "mutil.h"
  268. X#include "tclm.h"
  269. X#include "tclmMPU.h"
  270. X
  271. X/*
  272. X * Declarations for library procedures:
  273. X */
  274. X
  275. Xextern int isatty();
  276. X
  277. XTcl_Interp *interp;
  278. XTcl_CmdBuf buffer;
  279. Xint tty;
  280. X
  281. Xvoid usage _ANSI_ARGS_(());
  282. Xextern char *optarg;
  283. X
  284. X    /* ARGSUSED */
  285. Xint
  286. Xmain(argc, argv)
  287. X    int argc;
  288. X    char **argv;
  289. X{
  290. X    static int gotPartial = 0;
  291. X    int result;
  292. X    FILE *file;
  293. X    char *args;
  294. X    char *cmd;
  295. X    int have_f;
  296. X    char buf[20];
  297. X    char line[200];
  298. X    char opt;
  299. X
  300. X    have_f = 0;
  301. X    file = stdin;
  302. X
  303. X    /*
  304. X     * we want to stop parsing args when we get a -f, so the
  305. X     * script can get the args it wants
  306. X     */
  307. X    while (!have_f && (opt = getopt(argc, argv, "f:")) != -1) {
  308. X        switch (opt) {
  309. X        case 'f':
  310. X            if ((file = fopen(optarg, "r")) == NULL) {
  311. X                fprintf(stderr, "Couldn't open %s\n", optarg);
  312. X                exit(1);
  313. X            }
  314. X            have_f = 1;
  315. X            break;
  316. X        case '?':
  317. X            usage();
  318. X            exit(1);
  319. X        }
  320. X    }
  321. X
  322. X    interp = Tcl_CreateInterp();
  323. X    args = Tcl_Merge(argc-1, argv+1);
  324. X    Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
  325. X    ckfree(args);
  326. X    sprintf(buf, "%d", argc - 1);
  327. X    Tcl_SetVar(interp, "argc", buf, TCL_GLOBAL_ONLY);
  328. X    Tclm_InitMidi(interp);
  329. X#ifdef MPU
  330. X    Tclm_InitMPU401(interp);
  331. X#endif
  332. X    buffer = Tcl_CreateCmdBuf();
  333. X    tty = isatty(0);
  334. X
  335. X    for (;;) {
  336. X        if (file == stdin && tty)
  337. X            printf("tclm: ");
  338. X
  339. X        if (fgets(line, 200, file) == NULL)
  340. X            break;
  341. X        cmd = Tcl_AssembleCmd(buffer, line);
  342. X        if (cmd == NULL) {
  343. X            gotPartial = 1;
  344. X            continue;
  345. X        }
  346. X        gotPartial = 0;
  347. X        result = Tcl_RecordAndEval(interp, cmd, 0);
  348. X        if (*interp->result != 0) {
  349. X            if (result != TCL_OK) {
  350. X                printf("%s\n", Tcl_GetVar(interp, "errorInfo",
  351. X                    0));
  352. X                if (file !=stdin || !tty)
  353. X                    break;
  354. X            } else if (file == stdin && tty) {
  355. X                printf("%s\n", interp->result);
  356. X            }
  357. X        }
  358. X    }
  359. X
  360. X    Tcl_DeleteInterp(interp);
  361. X    Tcl_DeleteCmdBuf(buffer);
  362. X    exit(0);
  363. X}
  364. X
  365. Xvoid
  366. Xusage()
  367. X{
  368. X
  369. X    (void) fprintf(stderr, "Usage: tclm [ -f filename ]\n");
  370. X}
  371. END-of-tclm0.1/main.c
  372. echo x - tclm0.1/tclm.h
  373. sed 's/^X//' >tclm0.1/tclm.h << 'END-of-tclm0.1/tclm.h'
  374. X/* tclm.h,v 1.3 1993/01/12 19:23:04 durian Exp */
  375. X/*
  376. X * Copyright (c) 1993 Michael B. Durian.  All rights reserved.
  377. X *
  378. X * Redistribution and use in source and binary forms, with or without
  379. X * modification, are permitted provided that the following conditions
  380. X * are met:
  381. X * 1. Redistributions of source code must retain the above copyright
  382. X *    notice, this list of conditions and the following disclaimer.
  383. X * 2. Redistributions in binary form must reproduce the above copyright
  384. X *    notice, this list of conditions and the following disclaimer in the
  385. X *    documentation and/or other materials provided with the distribution.
  386. X * 3. All advertising materials mentioning features or use of this software
  387. X *    must display the following acknowledgement:
  388. X *    This product includes software developed by Michael B. Durian.
  389. X * 4. The name of the the Author may be used to endorse or promote 
  390. X *    products derived from this software without specific prior written 
  391. X *    permission.
  392. X *
  393. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  394. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  395. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  396. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  397. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  398. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  399. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  400. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  401. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  402. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  403. X * SUCH DAMAGE.
  404. X */
  405. X#ifndef TCLM_H
  406. X#define TCLM_H
  407. Xtypedef struct {
  408. X    HCHUNK    hchunk;
  409. X    TCHUNK    *tchunks;
  410. X} MIDI_FILE;
  411. X
  412. X#define MAX_EVENT_SIZE 256
  413. X
  414. Xextern int Tclm_MidiConfig _ANSI_ARGS_((ClientData, Tcl_Interp *, int,
  415. X    char **));
  416. Xextern int Tclm_ConvertBytes _ANSI_ARGS_((Tcl_Interp *, char *,
  417. X    unsigned char *, int *));
  418. Xextern int Tclm_Division _ANSI_ARGS_((Tcl_Interp *, int, char **));
  419. Xextern int Tclm_MidiFixToVar _ANSI_ARGS_((ClientData, Tcl_Interp *, int,
  420. X    char **));
  421. Xextern int Tclm_Format _ANSI_ARGS_((Tcl_Interp *, int, char **));
  422. Xextern int Tclm_MidiFree _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **));
  423. Xextern int Tclm_MidiGet _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **));
  424. Xextern int Tclm_MidiPut _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **));
  425. Xextern int Tclm_GetMFile _ANSI_ARGS_((Tcl_Interp *, char *, MIDI_FILE **));
  426. Xextern void Tclm_InitMidi _ANSI_ARGS_((Tcl_Interp *));
  427. Xextern int Tclm_MidiMake _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **));
  428. Xextern int Tclm_NumTracks _ANSI_ARGS_((Tcl_Interp *, int, char **));
  429. Xextern int Tclm_MidiRead _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **));
  430. Xextern int Tclm_MidiRewind _ANSI_ARGS_((ClientData, Tcl_Interp *, int,
  431. X    char **));
  432. Xextern int Tclm_SetMFile _ANSI_ARGS_((Tcl_Interp *, char *, MIDI_FILE *));
  433. Xextern int Tclm_MidiTiming _ANSI_ARGS_((ClientData, Tcl_Interp *, int,
  434. X    char **));
  435. Xextern int Tclm_MidiVarToFix _ANSI_ARGS_((ClientData, Tcl_Interp *, int,
  436. X    char **));
  437. Xextern int Tclm_MidiWrite _ANSI_ARGS_((ClientData, Tcl_Interp *, int,
  438. X    char **));
  439. Xextern int Tclm_MidiMPU _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **));
  440. X#endif
  441. END-of-tclm0.1/tclm.h
  442. echo x - tclm0.1/tclmMPU.c
  443. sed 's/^X//' >tclm0.1/tclmMPU.c << 'END-of-tclm0.1/tclmMPU.c'
  444. X/* tclmMPU.c,v 1.3 1993/01/12 19:23:10 durian Exp */
  445. X/*
  446. X * Copyright (c) 1993 Michael B. Durian.  All rights reserved.
  447. X *
  448. X * Redistribution and use in source and binary forms, with or without
  449. X * modification, are permitted provided that the following conditions
  450. X * are met:
  451. X * 1. Redistributions of source code must retain the above copyright
  452. X *    notice, this list of conditions and the following disclaimer.
  453. X * 2. Redistributions in binary form must reproduce the above copyright
  454. X *    notice, this list of conditions and the following disclaimer in the
  455. X *    documentation and/or other materials provided with the distribution.
  456. X * 3. All advertising materials mentioning features or use of this software
  457. X *    must display the following acknowledgement:
  458. X *    This product includes software developed by Michael B. Durian.
  459. X * 4. The name of the the Author may be used to endorse or promote 
  460. X *    products derived from this software without specific prior written 
  461. X *    permission.
  462. X *
  463. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  464. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  465. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  466. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  467. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  468. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  469. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  470. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  471. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  472. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  473. X * SUCH DAMAGE.
  474. X */
  475. X#ifdef MPU
  476. X#include <signal.h>
  477. X#include <sys/ioctl.h>
  478. X#include <i386/isa/midiioctl.h>
  479. X#include "tclInt.h"
  480. X#include "tclUnix.h"
  481. X#include "mutil.h"
  482. X#include "mpu401.h"
  483. X#include "mplayutil.h"
  484. X#include "tclm.h"
  485. X#include "tclmMPU.h"
  486. X
  487. Xstatic int now_playing = 0;
  488. Xstatic int control_dev;
  489. X
  490. Xvoid
  491. XTclm_InitMPU401(interp)
  492. X    Tcl_Interp *interp;
  493. X{
  494. X
  495. X    Tcl_CreateCommand(interp, "midiplay", Tclm_MidiPlay, NULL, NULL);
  496. X    Tcl_CreateCommand(interp, "midistop", Tclm_MidiStop, NULL, NULL);
  497. X    signal(SIGCHLD, watchdog);
  498. X}
  499. X
  500. X
  501. Xint
  502. XTclm_MidiPlay(dummy, interp, argc, argv)
  503. X    ClientData dummy;
  504. X    Tcl_Interp *interp;
  505. X    int argc;
  506. X    char **argv;
  507. X{
  508. X    TRKS track_list;
  509. X    long division_ioctl;
  510. X    MIDI_FILE *mfile;
  511. X    char *mfile_name;
  512. X    int track_devs[NUM_TRKS + 1]; /* plus 1 for conductor if needed */
  513. X    int background;
  514. X    int conductor_on;
  515. X/*
  516. X    int control_dev;
  517. X*/
  518. X    int i;
  519. X    int j;
  520. X    int num_open_tracks;
  521. X    int pid;
  522. X    int repeat;
  523. X    int result;
  524. X    int tempo_scalar;
  525. X    unsigned char active_tracks;
  526. X    unsigned char rel_tempo;
  527. X    unsigned char tempo;
  528. X
  529. X    if (argc < 2) {
  530. X        Tcl_AppendResult(interp, "wrong # args: should be \"",
  531. X            argv[0], " ?options? fileId\"", (char *)NULL);
  532. X        return (TCL_ERROR);
  533. X    }
  534. X
  535. X    rel_tempo = 0x40;
  536. X    repeat = 0;
  537. X    background = 0;
  538. X    mfile_name = NULL;
  539. X    /* default tempo is 120 */
  540. X    tempo = 120;
  541. X    /* so we can check to see if it gets set explicitly */
  542. X    track_list.num_tracks = -1;
  543. X
  544. X    for (i = 1; i < argc; i++) {
  545. X        switch(argv[i][0]) {
  546. X        case 'b':
  547. X            if (strncmp(argv[i], "bg", sizeof(argv[i])) == 0 ||
  548. X                strncmp(argv[i], "background", sizeof(argv[i]))
  549. X                == 0)
  550. X                background = 1;
  551. X            else if (mfile_name == NULL)
  552. X                mfile_name = argv[i];
  553. X            else {
  554. X                Tcl_AppendResult(interp, "bad option: ",
  555. X                    argv[i], " should be \"", argv[0],
  556. X                    " ?options? ", "fileId\"", (char *)NULL);
  557. X                return (TCL_ERROR);
  558. X            }
  559. X            break;
  560. X        case 'r':
  561. X            if (strncmp(argv[i], "reltempo", strlen(argv[i]))
  562. X                == 0)
  563. X                rel_tempo = double2tempo(atof(argv[++i]));
  564. X            else if (strncmp(argv[i], "repeat", strlen(argv[i]))
  565. X                == 0)
  566. X                repeat = 1;
  567. X            else if (mfile_name == NULL)
  568. X                mfile_name = argv[i];
  569. X            else {
  570. X                Tcl_AppendResult(interp, "bad option: ",
  571. X                    argv[i], " should be \"", argv[0],
  572. X                    " ?options? ", "fileId\"", (char *)NULL);
  573. X                return (TCL_ERROR);
  574. X            }
  575. X
  576. X            break;
  577. X        case 't':
  578. X            if (strncmp(argv[i], "tracks", strlen(argv[i]))
  579. X                == 0) {
  580. X                if ((result = Tclm_ParseTracks(interp,
  581. X                    argv[i + 1], &track_list)) != TCL_OK)
  582. X                    return (result);
  583. X                i++;
  584. X            } else if (mfile_name == NULL) {
  585. X                mfile_name = argv[i];
  586. X            } else {
  587. X                Tcl_AppendResult(interp, "bad option: ",
  588. X                    argv[i], " should be \"", argv[0],
  589. X                    " ?options? ", "fileId\"", (char *)NULL);
  590. X                return (TCL_ERROR);
  591. X            }
  592. X            break;
  593. X        default:
  594. X            if (mfile_name == NULL)
  595. X                mfile_name = argv[i];
  596. X            else {
  597. X                Tcl_AppendResult(interp, "bad option: ",
  598. X                    argv[i], " should be \"", argv[0],
  599. X                    " ?options? ", "fileId\"", (char *)NULL);
  600. X                return (TCL_ERROR);
  601. X            }
  602. X        }
  603. X    }
  604. X
  605. X    if ((result = Tclm_GetMFile(interp, mfile_name, &mfile)) != TCL_OK)
  606. X        return (result);
  607. X
  608. X    /* If track list isn't set use all tracks */
  609. X    if (track_list.num_tracks == -1) {
  610. X        track_list.num_tracks = mfile->hchunk.num_trks;
  611. X        for (j = 0; j < track_list.num_tracks; j++)
  612. X            track_list.tracks[j] = j;
  613. X    }
  614. X
  615. X    /* determine tempo scalar */
  616. X    if (!adjust_division(mfile->hchunk.division, &division_ioctl,
  617. X        &tempo_scalar)) {
  618. X        Tcl_AppendResult(interp, "Bad division value.  Must be ",
  619. X            "one of 48, 72, 96, 120, 144, 168, 192 or integer ",
  620. X            "multiple thereof", (char *)NULL);
  621. X        return (TCL_ERROR);
  622. X    }
  623. X
  624. X    /* open MIDI play devices */
  625. X    num_open_tracks = track_list.num_tracks;
  626. X    if ((conductor_on = open_midi_devices(&mfile->hchunk, &track_list,
  627. X        &num_open_tracks, track_devs, &active_tracks)) == -1) {
  628. X        Tcl_AppendResult(interp, "Couldn't open MIDI devices\n",
  629. X            MidiError, (char *)NULL);
  630. X        return (TCL_ERROR);
  631. X    }
  632. X
  633. X    /* open MIDI control device */
  634. X    if ((control_dev = open("/dev/midicntl", O_RDONLY, 0)) == -1) {
  635. X        Tcl_AppendResult(interp, "Couldn't open /dev/midicntl: ",
  636. X            sys_errlist[errno], (char *)NULL);
  637. X        return (TCL_ERROR);
  638. X    }
  639. X
  640. X    /* set tempo */
  641. X    if (ioctl(control_dev, MSETBASETMP, &tempo) == -1) {
  642. X        Tcl_AppendResult(interp, "Couldn't set tempo: ",
  643. X            sys_errlist[errno], (char *)NULL);
  644. X        return (TCL_ERROR);
  645. X    }
  646. X
  647. X    /* set relative tempo */
  648. X    if (ioctl(control_dev, MSETRELTMP, &rel_tempo) == -1) {
  649. X        Tcl_AppendResult(interp, "Couldn't set relative tempo: ",
  650. X            sys_errlist[errno], (char *)NULL);
  651. X        return (TCL_ERROR);
  652. X    }
  653. X
  654. X    /* set division */
  655. X    if (ioctl(control_dev, division_ioctl, NULL) == -1) {
  656. X        Tcl_AppendResult(interp, "Couldn't set division: ",
  657. X            sys_errlist[errno], (char *)NULL);
  658. X        return (TCL_ERROR);
  659. X    }
  660. X
  661. X    /* select active tracks */
  662. X    if (ioctl(control_dev, MSELTRKS, &active_tracks) == -1) {
  663. X        Tcl_AppendResult(interp, "Couldn't select active tracks: ",
  664. X            sys_errlist[errno], (char *)NULL);
  665. X        return (TCL_ERROR);
  666. X    }
  667. X
  668. X    /* set conductor status */
  669. X    if (conductor_on) {
  670. X        if (ioctl(control_dev, MCONDON, NULL) == -1) {
  671. X            Tcl_AppendResult(interp, "Couldn't select ",
  672. X                "conductor track: ", sys_errlist[errno],
  673. X                (char *)NULL);
  674. X            return (TCL_ERROR);
  675. X        }
  676. X    } else {
  677. X        if (ioctl(control_dev, MCONDOFF, NULL) == -1) {
  678. X            Tcl_AppendResult(interp, "Couldn't unselect ",
  679. X                "conductor track: ", sys_errlist[errno],
  680. X                (char *)NULL);
  681. X            return (TCL_ERROR);
  682. X        }
  683. X    }
  684. X
  685. X    /* clear play counter */
  686. X    if (ioctl(control_dev, MCLRPC, NULL) == -1) {
  687. X        Tcl_AppendResult(interp, "Couldn't clear play counter: ",
  688. X            sys_errlist[errno], (char *)NULL);
  689. X        return (TCL_ERROR);
  690. X    }
  691. X
  692. X    /* start playing */
  693. X    if (ioctl(control_dev, MSTART, NULL) == -1) {
  694. X        Tcl_AppendResult(interp, "Couldn't start playing: ",
  695. X            sys_errlist[errno], (char *)NULL);
  696. X        return (TCL_ERROR);
  697. X    }
  698. X
  699. X
  700. X    if (!background) {
  701. X        now_playing = 1;
  702. X        if (!play_tracks(mfile->tchunks, track_devs, num_open_tracks,
  703. X            tempo_scalar, repeat)) {
  704. X            Tcl_AppendResult(interp, "Couldn't play tracks\n",
  705. X                MidiError, (char *)NULL);
  706. X            return (TCL_ERROR);
  707. X        }
  708. X        now_playing = 0;
  709. X        if (ioctl(control_dev, MSTOP, NULL) == -1) {
  710. X            Tcl_AppendResult(interp, "Couldn't stop playing: ",
  711. X                sys_errlist[errno], (char *)NULL);
  712. X            return (TCL_ERROR);
  713. X        }
  714. X
  715. X        close(control_dev);
  716. X        for (i = 0; i < num_open_tracks; i++)
  717. X            close(track_devs[i]);
  718. X        Tcl_AppendResult(interp, "0", (char *)NULL);
  719. X    } else {
  720. X        switch(pid = fork()) {
  721. X        case -1:
  722. X            Tcl_AppendResult(interp, "Couldn't fork",
  723. X                (char *)NULL);
  724. X            return (TCL_ERROR);
  725. X        case 0:
  726. X            /* child */
  727. X            now_playing = 1;
  728. X            if (!play_tracks(mfile->tchunks, track_devs,
  729. X                num_open_tracks, tempo_scalar, repeat)) {
  730. X                Tcl_AppendResult(interp,
  731. X                    "Couldn't play tracks\n", MidiError,
  732. X                    (char *)NULL);
  733. X                return (TCL_ERROR);
  734. X            }
  735. X            now_playing = 0;
  736. X            if (ioctl(control_dev, MSTOP, NULL) == -1) {
  737. X                Tcl_AppendResult(interp,
  738. X                    "Couldn't stop playing: ", MidiError,
  739. X                    (char *)NULL);
  740. X                return (TCL_ERROR);
  741. X            }
  742. X
  743. X            close(control_dev);
  744. X            for (i = 0; i < num_open_tracks; i++)
  745. X                close(track_devs[i]);
  746. X            exit(0);
  747. X        default:
  748. X            close(control_dev);
  749. X            for (i = 0; i < num_open_tracks; i++)
  750. X                close(track_devs[i]);
  751. X            sprintf(interp->result, "%d", pid);
  752. X            break;
  753. X        }
  754. X    }
  755. X
  756. X    return (TCL_OK);
  757. X}
  758. X
  759. Xvoid
  760. Xwatchdog()
  761. X{
  762. X    int wstatus;
  763. X
  764. X    while(wait3(&wstatus, WNOHANG, NULL) >= 0);
  765. X}
  766. X
  767. Xint
  768. Xcompare_ints(val1, val2)
  769. X    int *val1;
  770. X    int *val2;
  771. X{
  772. X
  773. X    if (*val1 < *val2)
  774. X        return (-1);
  775. X    else if (*val1 > *val2)
  776. X        return (1);
  777. X    else
  778. X        return (0);
  779. X}
  780. X
  781. Xint
  782. XTclm_ParseTracks(interp, list, track_list)
  783. X    Tcl_Interp *interp;
  784. X    char *list;
  785. X    TRKS *track_list;
  786. X{
  787. X    char **track_strs;
  788. X    char *chk_ptr;
  789. X    int i;
  790. X    int result;
  791. X
  792. X    if ((result = Tcl_SplitList(interp, list, &track_list->num_tracks,
  793. X        &track_strs)) != TCL_OK) {
  794. X        Tcl_AppendResult(interp, "Bad track list", (char *)NULL);
  795. X        return (result);
  796. X    }
  797. X    for (i = 0; i < track_list->num_tracks; i++) {
  798. X        track_list->tracks[i] = (int)strtol(track_strs[i],
  799. X            &chk_ptr, 0);
  800. X        if (chk_ptr == track_strs[i]) {
  801. X            Tcl_AppendResult(interp, "Bad track value ",
  802. X                track_strs[i], (char *)NULL);
  803. X            return (TCL_ERROR);
  804. X        }
  805. X    }
  806. X    qsort(track_list->tracks, track_list->num_tracks,
  807. X        sizeof(track_list->tracks[0]), (int (*)())compare_ints);
  808. X    free((char *)track_strs);
  809. X    return (TCL_OK);
  810. X}
  811. X
  812. Xint
  813. XTclm_MidiStop(dummy, interp, argc, argv)
  814. X    ClientData dummy;
  815. X    Tcl_Interp *interp;
  816. X    int argc;
  817. X    char **argv;
  818. X{
  819. X    char *chk_ptr;
  820. X    int pid;
  821. X
  822. X    /*
  823. X     * argv[0] - midistop
  824. X     * argv[1] - pid
  825. X     */
  826. X    if (argc != 2) {
  827. X        Tcl_AppendResult(interp, "wrong # args: should be\"",
  828. X            argv[0], " pid\"", (char *)NULL);
  829. X        return (TCL_ERROR);
  830. X    }
  831. X
  832. X    pid = (int)strtol(argv[1], &chk_ptr, 0);
  833. X    if (chk_ptr == argv[1] || pid <= 0) {
  834. X        Tcl_AppendResult(interp, "bad pid value: ", argv[1],
  835. X            (char *)NULL);
  836. X        return (TCL_ERROR);
  837. X    }
  838. X    if (kill(pid, SIGINT) != -1)
  839. X        Tcl_AppendResult(interp, "1", (char *)NULL);
  840. X    else {
  841. X        if (errno == ESRCH)
  842. X            Tcl_AppendResult(interp, "0", (char *)NULL);
  843. X        else {
  844. X            Tcl_AppendResult(interp, "Error killing process: ",
  845. X                sys_errlist[errno], (char *)NULL);
  846. X            return (TCL_ERROR);
  847. X        }
  848. X    }
  849. X    return (TCL_OK);
  850. X}
  851. X#endif
  852. END-of-tclm0.1/tclmMPU.c
  853. echo x - tclm0.1/tclmMPU.h
  854. sed 's/^X//' >tclm0.1/tclmMPU.h << 'END-of-tclm0.1/tclmMPU.h'
  855. X/* tclmMPU.h,v 1.3 1993/01/12 19:23:13 durian Exp */
  856. X/*
  857. X * Copyright (c) 1993 Michael B. Durian.  All rights reserved.
  858. X *
  859. X * Redistribution and use in source and binary forms, with or without
  860. X * modification, are permitted provided that the following conditions
  861. X * are met:
  862. X * 1. Redistributions of source code must retain the above copyright
  863. X *    notice, this list of conditions and the following disclaimer.
  864. X * 2. Redistributions in binary form must reproduce the above copyright
  865. X *    notice, this list of conditions and the following disclaimer in the
  866. X *    documentation and/or other materials provided with the distribution.
  867. X * 3. All advertising materials mentioning features or use of this software
  868. X *    must display the following acknowledgement:
  869. X *    This product includes software developed by Michael B. Durian.
  870. X * 4. The name of the the Author may be used to endorse or promote 
  871. X *    products derived from this software without specific prior written 
  872. X *    permission.
  873. X *
  874. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  875. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  876. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  877. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  878. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  879. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  880. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  881. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  882. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  883. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  884. X * SUCH DAMAGE.
  885. X */
  886. X#ifndef TCLMMPU_H
  887. X#define TCLMMPU_H
  888. X
  889. Xextern void Tclm_InitMPU401 _ANSI_ARGS_((Tcl_Interp *));
  890. Xextern int Tclm_MidiPlay _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **));
  891. Xextern int Tclm_MidiStop _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **));
  892. Xextern void watchdog _ANSI_ARGS_(());
  893. Xextern int compare_ints _ANSI_ARGS_((int *, int *));
  894. Xextern int Tclm_ParseTracks _ANSI_ARGS_((Tcl_Interp *, char *, TRKS *));
  895. X#endif
  896. END-of-tclm0.1/tclmMPU.h
  897. exit
  898.