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

  1. From: durian@boogie.com (Mike Durian)
  2. Newsgroups: comp.sources.misc
  3. Subject: v43i111:  tclmidi - A language for manipulating MIDI files, v2.0, Part03/14
  4. Date: 21 Jul 1994 19:26:14 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <30n3n6$723@sparky.sterling.com>
  9. X-Md4-Signature: 5bd81fb02b7ba888918fdfd2db8e01b7
  10.  
  11. Submitted-by: durian@boogie.com (Mike Durian)
  12. Posting-number: Volume 43, Issue 111
  13. Archive-name: tclmidi/part03
  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/drivers/LINUX/Makefile
  22. #   tclmidi-2.0/drivers/SVR4/midi.c tclmidi-2.0/rb/rb.c
  23. # Wrapped by kent@sparky on Thu Jul 21 19:05:13 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 3 (of 14)."'
  27. if test -f 'tclmidi-2.0/drivers/LINUX/Makefile' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'tclmidi-2.0/drivers/LINUX/Makefile'\"
  29. else
  30.   echo shar: Extracting \"'tclmidi-2.0/drivers/LINUX/Makefile'\" \(301 characters\)
  31.   sed "s/^X//" >'tclmidi-2.0/drivers/LINUX/Makefile' <<'END_OF_FILE'
  32. XEXTRAFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486
  33. XCFLAGS = -DLOADABLE -D__KERNEL__ -DLINUX $(EXTRAFLAGS)
  34. X
  35. Xmidimodule.o: release.h midi.o midiconf.o quad.o
  36. X    ld -r -o midimodule.o midi.o midiconf.o quad.o
  37. X
  38. Xrelease.h:
  39. X    @echo char kernel_version[] = \"`uname -r`\"\; > release.h
  40. END_OF_FILE
  41.   if test 301 -ne `wc -c <'tclmidi-2.0/drivers/LINUX/Makefile'`; then
  42.     echo shar: \"'tclmidi-2.0/drivers/LINUX/Makefile'\" unpacked with wrong size!
  43.   fi
  44.   # end of 'tclmidi-2.0/drivers/LINUX/Makefile'
  45. fi
  46. if test -f 'tclmidi-2.0/drivers/SVR4/midi.c' -a "${1}" != "-c" ; then 
  47.   echo shar: Will not clobber existing file \"'tclmidi-2.0/drivers/SVR4/midi.c'\"
  48. else
  49.   echo shar: Extracting \"'tclmidi-2.0/drivers/SVR4/midi.c'\" \(42554 characters\)
  50.   sed "s/^X//" >'tclmidi-2.0/drivers/SVR4/midi.c' <<'END_OF_FILE'
  51. X/*-
  52. X * Copyright (c) 1993, 1994 Michael B. Durian.  All rights reserved.
  53. X *
  54. X * Redistribution and use in source and binary forms, with or without
  55. X * modification, are permitted provided that the following conditions
  56. X * are met:
  57. X * 1. Redistributions of source code must retain the above copyright
  58. X *    notice, this list of conditions and the following disclaimer.
  59. X * 2. Redistributions in binary form must reproduce the above copyright
  60. X *    notice, this list of conditions and the following disclaimer in the
  61. X *    documentation and/or other materials provided with the distribution.
  62. X * 3. All advertising materials mentioning features or use of this software
  63. X *    must display the following acknowledgement:
  64. X *    This product includes software developed by Michael B. Durian.
  65. X * 4. The name of the the Author may be used to endorse or promote 
  66. X *    products derived from this software without specific prior written 
  67. X *    permission.
  68. X *
  69. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 
  70. X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  71. X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  72. X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  73. X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  74. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  75. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  76. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  77. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  78. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  79. X * SUCH DAMAGE.
  80. X */
  81. X
  82. X#define INKERNEL 1
  83. X#define _KERNEL 1
  84. X
  85. X#include <sys/sysmacros.h>
  86. X#include <sys/types.h>
  87. X#include <sys/param.h>
  88. X#include <sys/file.h>
  89. X#include <sys/dir.h>
  90. X#include <sys/signal.h>
  91. X#include <sys/user.h>
  92. X#include <sys/systm.h>
  93. X#include <sys/errno.h>
  94. X#include <sys/open.h>
  95. X#include <sys/uio.h>
  96. X#include <sys/cred.h>
  97. X#include <sys/ddi.h>
  98. X#include <sys/poll.h>
  99. X#include <sys/kmem.h>
  100. X#include <sys/filio.h>
  101. X#include <sys/termios.h>
  102. X
  103. X#include "midi.h"
  104. X
  105. Xextern struct midi_softc midi_sc[];
  106. Xextern int midi_addrs[];
  107. Xextern int midi_intrs[];
  108. Xextern int NumMidi;
  109. X
  110. X#if defined(__STDC__) || defined(__cplusplus)
  111. X#define __P(protos)    protos
  112. X#else
  113. X#define __P(protos)    ()
  114. X#endif
  115. X
  116. X/* I've been burned too many times by different byte ordering */
  117. X#define OUTB(x, y) outb((x), (y))
  118. X#define INB(x) inb((x))
  119. X
  120. Xvoid midiinit __P(());
  121. Xint midiopen __P((dev_t *dev, int flag, int otyp, cred_t *cred_p));
  122. Xint midiclose __P((dev_t dev, int flag, int otyp, cred_t *cred_p));
  123. Xint midiread __P((dev_t dev, uio_t *uio_p, cred_t *cred_p));
  124. Xint midiwrite __P((dev_t dev, uio_t *uio_p, cred_t *cred_p));
  125. Xint midiioctl __P((dev_t dev, int cmd, int arg, int mode, cred_t *cred_p,
  126. X    int *rval_p));
  127. Xint midipoll __P((dev_t dev, int /* short */ events, int anyyet,
  128. X    short *reventsp, struct pollhead **phpp));
  129. Xint midiintr __P((int ivec));
  130. X
  131. Xstatic void midi_copy_event __P((struct event *, struct event *));
  132. Xstatic void midi_initq __P((struct event_queue *));
  133. Xstatic int midi_deq __P((struct event_queue *, struct event **));
  134. Xstatic int midi_peekq __P((struct event_queue *, struct event **));
  135. Xstatic int midi_enq __P((struct event_queue *, struct event *));
  136. Xstatic int midi_reset __P((struct midi_softc *));
  137. Xstatic int midi_wait_rdy_rcv __P((struct midi_softc *softc));
  138. Xstatic int midi_send_command __P((struct midi_softc *softc,
  139. X    /* u_char */ int comm));
  140. Xstatic int midi_uart __P((struct midi_softc *));
  141. Xstatic int midi_event2smf __P((struct midi_softc *, struct event *,
  142. X    struct stynamic *));
  143. Xstatic int midi_next_byte __P((struct midi_softc *, struct uio *));
  144. Xstatic int midi_uio2event __P((struct midi_softc *, struct uio *,
  145. X    struct event *));
  146. Xstatic int midi_fix2var __P((u_long, u_char *));
  147. Xstatic int midi_var2fix __P((u_char *, u_long *));
  148. Xstatic u_long midi_smf2kernel_tick __P((struct midi_softc *, long));
  149. Xstatic u_long midi_kernel2smf_tick __P((struct midi_softc *, long, long));
  150. Xstatic void midi_timeout __P((caddr_t arg));
  151. Xstatic void midi_add_complete_event __P((struct midi_softc *));
  152. Xstatic void midi_schedule_timeout __P((struct midi_softc *));
  153. Xstatic void midi_write_event __P((struct midi_softc *, struct event *));
  154. Xstatic void midi_reset_devices __P((struct midi_softc *));
  155. Xstatic void stynamic_add_byte __P((struct stynamic *, int /* u_char */));
  156. Xstatic void stynamic_add_bytes __P((struct stynamic *, u_char *, int));
  157. Xstatic u_char stynamic_get_byte __P((struct stynamic *, int));
  158. Xstatic void stynamic_copy __P((struct stynamic *, void *, int));
  159. Xstatic void stynamic_copy_from __P((struct stynamic *, int, void *, int));
  160. Xstatic void stynamic_append __P((struct stynamic *, struct stynamic *));
  161. Xstatic void stynamic_release __P((struct stynamic *));
  162. Xstatic void stynamic_shift __P((struct stynamic *, int));
  163. Xstatic void stynamic_init __P((struct stynamic *));
  164. Xstatic void stynamic_print __P((struct stynamic *));
  165. Xstatic int midi_killable __P((proc_t *owner, int pid));
  166. X
  167. Xvoid
  168. Xmidiinit()
  169. X{
  170. X    struct midi_softc *softc;
  171. X    int i;
  172. X
  173. X    for (i = 0; i < NumMidi; i++) {
  174. X        softc = &midi_sc[i];
  175. X        softc->addr = midi_addrs[i];
  176. X        softc->intr = midi_intrs[i];
  177. X        softc->status = MIDI_RD_BLOCK;
  178. X        if (!midi_reset(softc))
  179. X            if (!midi_reset(softc)) {
  180. X                printf("Couldn't reset MPU401\n");
  181. X                softc->status |= MIDI_UNAVAILABLE;
  182. X                continue;
  183. X            }
  184. X        if (!midi_uart(softc)) {
  185. X            printf("Couldn't put MPU401 into UART mode!\n");
  186. X            softc->status |= MIDI_UNAVAILABLE;
  187. X            continue;
  188. X        }
  189. X
  190. X        /* allocate memory for event queues */
  191. X        if ((softc->rqueue = kmem_alloc(sizeof(struct event_queue),
  192. X            KM_NOSLEEP)) == NULL) {
  193. X            printf("No memory for rqueue\n");
  194. X            softc->status |= MIDI_UNAVAILABLE;
  195. X            continue;
  196. X        }
  197. X        if ((softc->wqueue = kmem_alloc(sizeof(struct event_queue),
  198. X            KM_NOSLEEP)) == NULL) {
  199. X            printf("No memory for wqueue\n");
  200. X            softc->status |= MIDI_UNAVAILABLE;
  201. X            kmem_free(softc->rqueue, sizeof(struct event_queue));
  202. X        }
  203. X        /* zero read/write queue to clear stynamic structures */
  204. X        bzero(softc->rqueue, sizeof(struct event_queue));
  205. X        bzero(softc->wqueue, sizeof(struct event_queue));
  206. X        stynamic_init(&softc->rpartial);
  207. X        stynamic_init(&softc->wpartial);
  208. X        softc->wpartialpos = 0;
  209. X    }
  210. X}
  211. X
  212. Xint
  213. Xmidiopen(dev, flag, otyp, cred_p)
  214. X    dev_t *dev;
  215. X    int flag, otyp;
  216. X    cred_t *cred_p;
  217. X{
  218. X    register struct midi_softc *softc;
  219. X    register int unit;
  220. X    unit = minor(*dev);
  221. X    if (unit >= NumMidi)
  222. X        return (ENXIO);
  223. X    softc = &midi_sc[unit];
  224. X    if (softc->status & MIDI_UNAVAILABLE)
  225. X        return (EIO);
  226. X    
  227. X    if (softc->status & MIDI_OPEN)
  228. X        return (EBUSY);
  229. X    else
  230. X        softc->status = MIDI_OPEN;
  231. X
  232. X    /*
  233. X     * reads will block until something appears
  234. X     */
  235. X    softc->status |= MIDI_RD_BLOCK;
  236. X
  237. X    /* initialize the queues */
  238. X    midi_initq(softc->rqueue);
  239. X    midi_initq(softc->wqueue);
  240. X
  241. X    softc->partial_event.event.len = 0;
  242. X    softc->partial_event.event.datad = NULL;
  243. X
  244. X    /* make sure we are in UART mode */
  245. X    if (!midi_fullreset(softc)) {
  246. X        printf("Couldn't put MPU401 into UART mode!\n");
  247. X        softc->status |= MIDI_UNAVAILABLE;
  248. X        kmem_free(softc->rqueue, sizeof(struct event_queue));
  249. X        kmem_free(softc->wqueue, sizeof(struct event_queue));
  250. X        return (EIO);
  251. X    }
  252. X
  253. X    softc->pgid = u.u_procp->p_pid;
  254. X    softc->owner = u.u_procp;
  255. X
  256. X    /* are we going to read, write or both? */
  257. X    if (flag & FREAD)
  258. X        softc->status |= MIDI_READING;
  259. X    else
  260. X        softc->status &= ~MIDI_READING;
  261. X    if (flag & FWRITE)
  262. X        softc->status |= MIDI_WRITING;
  263. X    else
  264. X        softc->status &= ~MIDI_WRITING;
  265. X    if (flag & FNONBLOCK)
  266. X        softc->status |= MIDI_NONBLOCK;
  267. X    else
  268. X        softc->status &= ~MIDI_NONBLOCK;
  269. X
  270. X    return (0);
  271. X}
  272. X
  273. Xint
  274. Xmidiclose(dev, flag, otyp, cred_p)
  275. X    dev_t dev;
  276. X    int flag, otyp;
  277. X    cred_t *cred_p;
  278. X{
  279. X    register struct midi_softc *softc;
  280. X    register int error, unit;
  281. X
  282. X    unit = minor(dev);
  283. X    softc = &midi_sc[unit];
  284. X
  285. X    /*
  286. X     * we're not going to finish closing until everything has
  287. X     * been played.
  288. X     */
  289. X    error = 0;
  290. X    if (softc->status & MIDI_WRITING) {
  291. X        /* same as MFLUSHQ ioctl */
  292. X        if (softc->wqueue->count != 0) {
  293. X            softc->status |= MIDI_FLUSH_SLEEP;
  294. X            do {
  295. X                if (error = sleep((caddr_t)&softc->status,
  296. X                    PWAIT | PCATCH))
  297. X                    softc->status &= ~MIDI_FLUSH_SLEEP;
  298. X            } while (softc->status & MIDI_FLUSH_SLEEP);
  299. X        }
  300. X    }
  301. X
  302. X    /* turn off any notes that might be stuck on */
  303. X    midi_reset_devices(softc);
  304. X    midi_fullreset(softc);
  305. X
  306. X    softc->status &= ~MIDI_OPEN;
  307. X    return (error);
  308. X}
  309. X
  310. Xint
  311. Xmidiread(dev, uio, cred_p)
  312. X    dev_t dev;
  313. X    uio_t *uio;
  314. X    cred_t *cred_p;
  315. X{
  316. X    struct event *event;
  317. X    register struct midi_softc *softc;
  318. X    int error, in, num_to_move, unit;
  319. X
  320. X    unit = minor(dev);
  321. X    softc = &midi_sc[unit];
  322. X
  323. X    if (softc->rqueue->count == 0 && softc->rpartial.len == 0) {
  324. X        if (softc->status & MIDI_NONBLOCK)
  325. X            return (EWOULDBLOCK);
  326. X        else {
  327. X            softc->status |= MIDI_RD_SLEEP;
  328. X            do {
  329. X                if (error = sleep((caddr_t)softc->rqueue,
  330. X                    PWAIT | PCATCH))
  331. X                    return (error);
  332. X            } while (softc->status & MIDI_RD_SLEEP);
  333. X            /* XXX maybe check for abort here */
  334. X        }
  335. X    }
  336. X    while (uio->uio_resid) {
  337. X        /*
  338. X         * dequeue an event if partial is empty
  339. X         */
  340. X        if (softc->rpartial.len == 0) {
  341. X            if (!midi_deq(softc->rqueue, &event)) {
  342. X                softc->status |= MIDI_RD_BLOCK;
  343. X                return (0);
  344. X            }
  345. X            midi_event2smf(softc, event, &softc->rpartial);
  346. X            styanmic_release(&event->data);
  347. X        }
  348. X        /* read out as much of rpartial as possible */
  349. X        num_to_move = MIN(softc->rpartial.len, uio->uio_resid);
  350. X        if (softc->rpartial.len <= STYNAMIC_SIZE) {
  351. X            if (uiomove(softc->rpartial.datas, num_to_move,
  352. X                UIO_READ, uio) == -1)
  353. X            return (-1);
  354. X        } else {
  355. X            if (uiomove(softc->rpartial.datad, num_to_move,
  356. X                UIO_READ, uio) == -1)
  357. X            return (-1);
  358. X        }
  359. X        stynamic_shift(&softc->rpartial, num_to_move);
  360. X    }
  361. X    return (0);
  362. X}
  363. X
  364. Xint
  365. Xmidiwrite(dev, uio, cred_p)
  366. X    dev_t dev;
  367. X    uio_t *uio;
  368. X    cred_t *cred_p;
  369. X{
  370. X    register struct midi_softc *softc;
  371. X    struct event event;
  372. X    int convert, error, unit, iovec, empty_queue;
  373. X
  374. X    unit = minor(dev);
  375. X    softc = &midi_sc[unit];
  376. X
  377. X    if (softc->wqueue->count == 0)
  378. X        empty_queue = 1;
  379. X    else
  380. X        empty_queue = 0;
  381. X
  382. X    /* check to see if we'll block */
  383. X    if (softc->status & MIDI_WR_BLOCK) {
  384. X        if (softc->status & MIDI_NONBLOCK)
  385. X            return (EWOULDBLOCK);
  386. X        else {
  387. X            softc->status |= MIDI_WR_SLEEP;
  388. X            do {
  389. X                if (error = sleep((caddr_t)softc->wqueue,
  390. X                    PWAIT | PCATCH))
  391. X                    return (error);
  392. X            } while (softc->status & MIDI_WR_SLEEP);
  393. X        }
  394. X    }
  395. X    /* if returns from sleep and should abort because of DRAIN */
  396. X    if (softc->status & MIDI_WR_ABORT) {
  397. X        softc->status &= ~MIDI_WR_ABORT;
  398. X        return (0);
  399. X    }
  400. X
  401. X    stynamic_init(&event.data);
  402. X    while (uio->uio_resid) {
  403. X        /* block if queue is full */
  404. X        if (softc->wqueue->count == MIDI_Q_SIZE) {
  405. X            softc->status |= MIDI_WR_BLOCK;
  406. X            if (empty_queue) {
  407. X                midi_schedule_timeout(softc);
  408. X                empty_queue = 0;
  409. X            }
  410. X            if (softc->status & MIDI_NONBLOCK)
  411. X                return (0);
  412. X            else {
  413. X                softc->status |= MIDI_WR_SLEEP;
  414. X                do {
  415. X                    if (error = sleep(softc->wqueue,
  416. X                        PWAIT | PCATCH))
  417. X                        return (error);
  418. X                } while (softc->status & MIDI_WR_SLEEP);
  419. X            }
  420. X        }
  421. X
  422. X        /*
  423. X         * 1) get a complete event off queue
  424. X         * 2) convert it from SMF to board format
  425. X         * 3) deal with it
  426. X         */
  427. X        convert = midi_uio2event(softc, uio, &event);
  428. X        switch (convert) {
  429. X        case 0:
  430. X            break;
  431. X        case -1:
  432. X            /* not a complete event - we'll get it next time */
  433. X            if (empty_queue)
  434. X                midi_schedule_timeout(softc);
  435. X            return (0);
  436. X        case -2:
  437. X            /* it was a noop event */
  438. X            break;
  439. X        default:
  440. X            return (convert);
  441. X        }
  442. X        if (convert == -2)
  443. X            continue;
  444. X
  445. X        if (midi_enq(softc->wqueue, &event) == -1)
  446. X            return (EIO);
  447. X        stynamic_release(&event.data);
  448. X        /* set flag so next time we cross LOW water we will SIGIO */
  449. X        if (softc->wqueue->count >= MIDI_LOW_WATER)
  450. X            softc->status |= MIDI_SENDIO;
  451. X    }
  452. X
  453. X    if (empty_queue)
  454. X        midi_schedule_timeout(softc);
  455. X
  456. X    return (0);
  457. X}
  458. X
  459. X/*
  460. X * XXXINTR
  461. X * I don't know what ivec is.  I'm really hoping it is something
  462. X * useful like the unit number.
  463. X * If it is the interrupt number, then we can loop through all the
  464. X * midi_sc comparing ivec against softc->intr until we find the right
  465. X * one.  No biggie, I just don't know which way it works.
  466. X * For for I'll assume by default that it is the interrupt number.
  467. X */
  468. Xint
  469. Xmidiintr(ivec)
  470. X    int ivec;
  471. X{
  472. X    register struct midi_softc *softc;
  473. X    register u_char code;
  474. X    register struct partial_event *pe;
  475. X
  476. X#if 1
  477. X    int i;
  478. X
  479. X    for (i = 0; i < NumMidi && midi_sc[i].intr != ivec; i++);
  480. X    if (i == NumMidi) {
  481. X        printf("midi: ivec(%d) is not a valid MPU401 intr number\n");
  482. X        return;
  483. X    }
  484. X    softc = &midi_sc[i];
  485. X#else
  486. X    softc = &midi_sc[ivec];
  487. X#endif
  488. X
  489. X    code = INB(softc->addr + MIDI_DATA);
  490. X    if (code == 0xfe && (softc->status & MIDI_NEED_ACK)) {
  491. X        softc->status &= ~MIDI_NEED_ACK;
  492. X        return (1);
  493. X    }
  494. X    /* throw away data if no one has the device open */
  495. X    if (!(softc->status & MIDI_READING))
  496. X        return (1);
  497. X
  498. X    /* pass input data to out port if necessary */
  499. X    if (softc->status & MIDI_THRU) {
  500. X        if (!midi_wait_rdy_rcv(softc))
  501. X            printf("Couldn't pass data thru\n");
  502. X        else
  503. X            OUTB(softc->addr + MIDI_DATA, code);
  504. X    }
  505. X    pe = &softc->partial_event;
  506. X
  507. X    /* check for realtime events */
  508. X    if ((code & 0xf8) == 0xf8) {
  509. X        switch (code) {
  510. X        case 0xfa:    /* start */
  511. X            /* reset prev_incoming */
  512. X            softc->prev_incoming = lbolt;
  513. X            break;
  514. X        case 0xff:    /* reset */
  515. X            /*
  516. X             * I don't really want to do a full reset
  517. X             * I'll just clear any event in progress
  518. X             */
  519. X            stynamic_release(&pe->event);
  520. X            pe->state = START;
  521. X            break;
  522. X        case 0xf8:    /* timing clock */
  523. X        case 0xf9:    /* undefined */
  524. X        case 0xfb:    /* continue */
  525. X        case 0xfc:    /* stop */
  526. X        case 0xfd:    /* undefined */
  527. X        case 0xfe:    /* active sensing */
  528. X            break;
  529. X        }
  530. X        return (1);
  531. X    }
  532. XINTR_SWITCH:
  533. X    switch (pe->state) {
  534. X    case START:
  535. X        /* record when the time when the event started */
  536. X        pe->time = lbolt;
  537. X        pe->tempo = softc->rtempo;
  538. X        /* start collecting the input */
  539. X        stynamic_release(&pe->event);
  540. X        /* decide what state is next */
  541. X        if (!(code & 0x80)) {
  542. X            stynamic_add_byte(&pe->event, code);
  543. X            switch (pe->rs) {
  544. X            case 0x80:
  545. X            case 0x90:
  546. X            case 0xa0:
  547. X            case 0xb0:
  548. X            case 0xe0:
  549. X                /*
  550. X                 * code is the first data byte, but
  551. X                 * we still need to get the second
  552. X                 */
  553. X                pe->state = NEEDDATA2;
  554. X                break;
  555. X            case 0xc0:
  556. X            case 0xd0:
  557. X                /* code is the only data byte */
  558. X                pe->state = START;
  559. X                midi_add_complete_event(softc);
  560. X                break;
  561. X            default:
  562. X                break;
  563. X            }
  564. X        } else {
  565. X            switch (code & 0xf0) {
  566. X            case 0x80:
  567. X            case 0x90:
  568. X            case 0xa0:
  569. X            case 0xb0:
  570. X            case 0xe0:
  571. X                pe->rs = code & 0xf0;
  572. X                stynamic_add_byte(&pe->event, code);
  573. X                pe->state = NEEDDATA1;
  574. X                break;
  575. X            case 0xc0:
  576. X            case 0xd0:
  577. X                pe->rs = code & 0xf0;
  578. X                stynamic_add_byte(&pe->event, code);
  579. X                pe->state = NEEDDATA2;
  580. X                break;
  581. X            default:
  582. X                switch (code) {
  583. X                case 0xf0: /* sysex */
  584. X                    stynamic_add_byte(&pe->event, code);
  585. X                    pe->state = SYSEX;
  586. X                    break;
  587. X                case 0xf1: /* undefined */
  588. X                case 0xf4: /* undefined */
  589. X                case 0xf5: /* undefined */
  590. X                case 0xf6: /* tune request */
  591. X                case 0xf7: /* EOX (terminator) */
  592. X                    /* ignore these */
  593. X                    break;
  594. X                case 0xf2: /* song position */
  595. X                    pe->state = SYSTEM2;
  596. X                    break;
  597. X                case 0xf3: /* song select */
  598. X                    pe->state = SYSTEM1;
  599. X                    break;
  600. X                }
  601. X                break;
  602. X            }
  603. X        }
  604. X        break;
  605. X    case NEEDDATA1:
  606. X        stynamic_add_byte(&pe->event, code);
  607. X        pe->state = NEEDDATA2;
  608. X        break;
  609. X    case NEEDDATA2:
  610. X        stynamic_add_byte(&pe->event, code);
  611. X        pe->state = START;
  612. X        midi_add_complete_event(softc);
  613. X        break;
  614. X    case SYSEX:
  615. X        /* any non-data byte ends sysex */
  616. X        if (!(code & 0x80))
  617. X            stynamic_add_byte(&pe->event, code);
  618. X        else {
  619. X            stynamic_add_byte(&pe->event, 0xf7);
  620. X            midi_add_complete_event(softc);
  621. X            pe->state = START;
  622. X            if (code != 0xf7)
  623. X                goto INTR_SWITCH;
  624. X        }
  625. X        break;
  626. X    case SYSTEM1:
  627. X        /* throw away one data byte of a system message */
  628. X        pe->state = START;
  629. X        break;
  630. X    case SYSTEM2:
  631. X        /* throw away two data bytes of a system message */
  632. X        pe->state = SYSTEM1;
  633. X        break;
  634. X    }
  635. X    return (1);
  636. X}
  637. X
  638. Xint
  639. Xmidiioctl(dev, cmd, arg, mode, cred_p, rval_p)
  640. X    dev_t dev;
  641. X    int cmd, arg, mode;
  642. X    cred_t *cred_p;
  643. X    int *rval_p;
  644. X{
  645. X    struct event *event;
  646. X    struct midi_softc *softc;
  647. X    register int error, unit;
  648. X    int i, ret, val;
  649. X
  650. X    unit = minor(dev);
  651. X    softc = &midi_sc[unit];
  652. X
  653. X    switch (cmd) {
  654. X    case FIOASYNC:
  655. X    case MASYNC:
  656. X        /*
  657. X         * Linux doesn't properly process the FIOASYNC
  658. X         * ioctl entry point, thus we have two.  For
  659. X         * compatibility purposes, I'm duplicating it
  660. X         * here too.
  661. X         */
  662. X
  663. X        copyin((caddr_t)arg, (caddr_t)&val, sizeof(int));
  664. X        if (!val)
  665. X            softc->status &= ~MIDI_ASYNC;
  666. X        else {
  667. X            struct proc *p;
  668. X
  669. X            softc->status |= MIDI_ASYNC;
  670. X            if (softc->wqueue->count < MIDI_LOW_WATER
  671. X                && softc->status & MIDI_WRITING) {
  672. X                if (softc->pgid < 0)
  673. X                    signal(-softc->pgid, SIGIO);
  674. X                else if ((p = prfind(softc->pgid)) != 0)
  675. X                    psignal(p, SIGIO);
  676. X            }
  677. X        }
  678. X        break;
  679. X    case TIOCSPGRP:
  680. X        /*
  681. X         * XXXSIGNAL we need to check to be sure we can kill the
  682. X         * the process we are being told to kill
  683. X         */
  684. X        copyin((caddr_t)arg, (caddr_t)&val, sizeof(int));
  685. X        if ((ret = midi_killable(softc->owner, val) != 0)) != 0)
  686. X            return (ret);
  687. X        softc->pgid = val;
  688. X        break;
  689. X    case TIOCGPGRP:
  690. X        copyout((caddr_t)&softc->pgid, (caddr_t)arg, sizeof(int));
  691. X        break;
  692. X    case MRESET:
  693. X        if (!midi_fullreset(softc))
  694. X            return (EIO);
  695. X        break;
  696. X    case MSDIVISION:
  697. X        copyin((caddr_t)arg, (caddr_t)&val, sizeof(int));
  698. X          /* must recalculate play remainder */
  699. X          softc->premainder = softc->premainder * val / softc->division;
  700. X          softc->division = val;
  701. X        break;
  702. X    case MGDIVISION:
  703. X        copyout((caddr_t)&softc->division, (caddr_t)arg, sizeof(int));
  704. X        break;
  705. X    case MDRAIN:
  706. X        /* dequeue all everything */
  707. X        while (midi_deq(softc->rqueue, &event))
  708. X            stynamic_release(&event->data);
  709. X        while (midi_deq(softc->wqueue, &event))
  710. X            stynamic_release(&event->data);
  711. X        /* remove any events already being timed */
  712. X        if (softc->timeout_id != -1)
  713. X            untimeout(softc->timeout_id);
  714. X        softc->status &= ~MIDI_WR_BLOCK;
  715. X        softc->status |= MIDI_RD_BLOCK;
  716. X        if (softc->status & MIDI_WR_SLEEP) {
  717. X            softc->status &= ~MIDI_WR_SLEEP;
  718. X            softc->status |= MIDI_WR_ABORT;
  719. X            wakeup((caddr_t)softc->wqueue);
  720. X        }
  721. X        midi_reset_devices(softc);
  722. X        break;
  723. X    case MFLUSH:
  724. X        if (softc->wqueue->count != 0) {
  725. X            softc->status |= MIDI_FLUSH_SLEEP;
  726. X            do {
  727. X                if (error = sleep((caddr_t)&softc->status,
  728. X                    PWAIT | PCATCH))
  729. X                    return (error);
  730. X            } while (softc->status & MIDI_FLUSH_SLEEP);
  731. X        }
  732. X        break;
  733. X    case MGPLAYQ:
  734. X        copyout((caddr_t)&softc->wqueue->count, (caddr_t)arg,
  735. X            sizeof(int));
  736. X        break;
  737. X    case MGRECQ:
  738. X        copyout((caddr_t)&softc->rqueue->count, (caddr_t)arg,
  739. X            sizeof(int));
  740. X        break;
  741. X    case MGQAVAIL:
  742. X        val = MIDI_Q_SIZE - softc->wqueue->count;
  743. X        copyout((caddr_t)&val, (caddr_t)arg, sizeof(int));
  744. X        break;
  745. X    case MTHRU:
  746. X        copyin((caddr_t)arg, (caddr_t)&val, sizeof(int));
  747. X        if (val)
  748. X            softc->status |= MIDI_THRU;
  749. X        else
  750. X            softc->status &= ~MIDI_THRU;
  751. X        break;
  752. X    case MRECONPLAY:
  753. X        copyin((caddr_t)arg, (caddr_t)&val, sizeof(int));
  754. X        if (val)
  755. X            softc->status |= MIDI_RECONPLAY;
  756. X        else
  757. X            softc->status &= ~MIDI_RECONPLAY;
  758. X        break;
  759. X    default:
  760. X        return (ENOTTY);
  761. X    }
  762. X    return (0);
  763. X}
  764. X
  765. X/*
  766. X * XXXPOLL
  767. X * I don't know how this is supposed to work.  The SVR4/386
  768. X * DDI/DKI reference manual doesn't explain it well enough for me.
  769. X */
  770. Xint
  771. Xmidipoll(dev, events, anyyet, reventsp, phpp)
  772. X    dev_t dev;
  773. X    short events;
  774. X    int anyyet;
  775. X    short *reventsp;
  776. X    struct pollhead **phpp;
  777. X{
  778. X    register struct midi_softc *softc;
  779. X    int unit;
  780. X
  781. X    unit = minor(dev);
  782. X    softc = &midi_sc[unit];
  783. X
  784. X    *reventsp = 0;
  785. X    if (events & POLLIN && !(softc->status & MIDI_RD_BLOCK))
  786. X        *reventsp |= POLLIN;
  787. X    if (events & POLLOUT && !(softc->status & MIDI_WR_BLOCK))
  788. X        *reventsp |= POLLOUT;
  789. X    if (*reventsp == 0)
  790. X        if (!anyyet)
  791. X            *phpp = &softc->pollhead;
  792. X    return (0);
  793. X}
  794. X
  795. Xint
  796. Xmidi_fullreset(softc)
  797. X    struct midi_softc *softc;
  798. X{
  799. X    u_char pitch;
  800. X    struct event *event;
  801. X
  802. X    /* dequeue all everything */
  803. X    while (midi_deq(softc->rqueue, &event))
  804. X        stynamic_release(&event->data);
  805. X    while (midi_deq(softc->wqueue, &event))
  806. X        stynamic_release(&event->data);
  807. X    /* remove any events already being timed */
  808. X    if (softc->timeout_id != -1)
  809. X        untimeout(softc->timeout_id);
  810. X    softc->timeout_id = -1;
  811. X    /* mark start time */
  812. X    softc->prev_incoming = lbolt;
  813. X    /* reset fractional count */
  814. X    softc->premainder = 0;
  815. X    softc->rremainder = 0;
  816. X    /* initialize some variables */
  817. X    /* this is 120 bpm when a quarter note == 1 beat */
  818. X    softc->ptempo = 500000;
  819. X    softc->rtempo = 500000;
  820. X    softc->prev_rtempo = 500000;
  821. X
  822. X    /* clear noteon */
  823. X    for (pitch = 0; pitch <= 0x7f; pitch++)
  824. X        softc->noteon[pitch] = 0;
  825. X    softc->noteonrs = 0;
  826. X
  827. X    /* clear running play state */
  828. X    softc->writers = 0;
  829. X
  830. X    /* reset partial event stuff */
  831. X    stynamic_release(&softc->partial_event.event);
  832. X    softc->partial_event.state = START;
  833. X    stynamic_release(&softc->rpartial);
  834. X    stynamic_release(&softc->wpartial);
  835. X    softc->wpartialpos = 0;
  836. X
  837. X    /* defaults to 120 clocks per beat */
  838. X    softc->division = 120;
  839. X    /* reset and enter uart mode */
  840. X    return (midi_uart(softc));
  841. X}
  842. X
  843. Xint
  844. Xmidi_wait_rdy_rcv(softc)
  845. X    struct midi_softc *softc;
  846. X{
  847. X    int flag;
  848. X    register int i;
  849. X
  850. X    for (i = 0; i < MIDI_TRIES; i++) {
  851. X        flag = INB(softc->addr + MIDI_STATUS) & MIDI_RDY_RCV;
  852. X        if (flag == 0)
  853. X            break;
  854. X    }
  855. X    if (i == MIDI_TRIES)
  856. X        return (0);
  857. X    return(1);
  858. X}
  859. X
  860. Xint
  861. Xmidi_send_command(softc, comm)
  862. X    struct midi_softc *softc;
  863. X    u_char comm;
  864. X{
  865. X    int flag;
  866. X    register int i, s;
  867. X    unsigned char ack;
  868. X
  869. X    /* writing command and setting flag must be atomic */
  870. X    s = spltty();
  871. X    OUTB(softc->addr + MIDI_COMMAND, comm);
  872. X    softc->status |= MIDI_NEED_ACK;
  873. X    splx(s);
  874. X
  875. X    /* time out after MIDI_TRIES times */
  876. X    for (i = 0; i < MIDI_TRIES; i++) {
  877. X        /* did we pick up the ack via midiintr? */
  878. X        if (!(softc->status & MIDI_NEED_ACK))
  879. X            break;
  880. X        /* can we read a data byte? */
  881. X        flag = INB(softc->addr + MIDI_STATUS) & MIDI_DATA_AVL;
  882. X        if (flag == 0)
  883. X            break;
  884. X    }
  885. X    if (i == MIDI_TRIES)
  886. X        return (0);
  887. X
  888. X    if (softc->status & MIDI_NEED_ACK) {
  889. X        ack = INB(softc->addr + MIDI_DATA);
  890. X        if (ack != MIDI_ACK)
  891. X            return (0);
  892. X    }
  893. X    softc->status &= ~MIDI_NEED_ACK;
  894. X    return (1);
  895. X}
  896. X
  897. Xint
  898. Xmidi_reset(softc)
  899. X    struct midi_softc *softc;
  900. X{
  901. X
  902. X    if (!midi_wait_rdy_rcv(softc))
  903. X        return (0);
  904. X
  905. X    if (!midi_send_command(softc, MIDI_RESET))
  906. X        return (0);
  907. X
  908. X    return (1);
  909. X}
  910. X
  911. Xint
  912. Xmidi_uart(softc)
  913. X    struct midi_softc *softc;
  914. X{
  915. X
  916. X    /*
  917. X     * first reset.  We can't issue the UART command when already
  918. X     * in UART mode.
  919. X     */
  920. X    (void)midi_reset(softc);
  921. X
  922. X    if (!midi_wait_rdy_rcv(softc))
  923. X        return (0);
  924. X
  925. X    if (!midi_send_command(softc, MIDI_UART))
  926. X        return (0);
  927. X    return (1);
  928. X}
  929. X
  930. Xint
  931. Xmidi_event2smf(softc, event, smf)
  932. X    struct midi_softc *softc;
  933. X    struct event *event;
  934. X    struct stynamic *smf;
  935. X{
  936. X    long tempo, smf_ticks;
  937. X    int tmp_len;
  938. X    u_char tmp_buf[4];
  939. X
  940. X    /* convert from kernel ticks to SMF ticks */
  941. X    smf_ticks = midi_kernel2smf_tick(softc, event->tempo, event->time);
  942. X    tmp_len = midi_fix2var(smf_ticks, tmp_buf);
  943. X    stynamic_add_bytes(smf, tmp_buf, tmp_len);
  944. X
  945. X    switch (event->type) {
  946. X    case NORMAL:
  947. X        stynamic_append(smf, &event->data);
  948. X        break;
  949. X    case TEMPO:
  950. X        /* this case just won't occur */
  951. X        stynamic_copy(&event->data, (void *)&tempo, sizeof(tempo));
  952. X        stynamic_add_byte(smf, 0xff);
  953. X        stynamic_add_byte(smf, 0x51);
  954. X        stynamic_add_byte(smf, 0x03);
  955. X        stynamic_add_byte(smf, (tempo & 0xff0000) >> 16);
  956. X        stynamic_add_byte(smf, (tempo & 0xff00) >> 8);
  957. X        stynamic_add_byte(smf, tempo & 0xff00);
  958. X        break;
  959. X    case SYSX:
  960. X        stynamic_add_byte(smf, 0xf0);
  961. X        /* skip over the leading 0xf0 */
  962. X        stynamic_shift(&event->data, 1);
  963. X        tmp_len = midi_fix2var(event->data.len, tmp_buf);
  964. X        stynamic_add_bytes(smf, tmp_buf, tmp_len);
  965. X        styanmic_append(smf, &event->data);
  966. X        break;
  967. X    }
  968. X    return (1);
  969. X}
  970. X
  971. Xint
  972. Xmidi_next_byte(softc, uio)
  973. X    struct midi_softc *softc;
  974. X    struct uio *uio;
  975. X{
  976. X    int byte;
  977. X
  978. X    /* if we're not at the end of a partial event, read from it */
  979. X    if (softc->wpartialpos < softc->wpartial.len) {
  980. X        byte = stynamic_get_byte(&softc->wpartial,
  981. X            softc->wpartialpos++);
  982. X        return (byte);
  983. X    } else {
  984. X        /* read from uio and copy uio onto partial event */
  985. X        if ((byte = uwritec(uio)) == -1) {
  986. X            /*
  987. X             * reset partialpos so next time through
  988. X             * we'll read from the partial event if
  989. X             * it is non-zero in length
  990. X             */
  991. X            softc->wpartialpos = 0;
  992. X            return (-1);
  993. X        }
  994. X        stynamic_add_byte(&softc->wpartial, byte);
  995. X        softc->wpartialpos = softc->wpartial.len;
  996. X        return (byte);
  997. X    }
  998. X}
  999. X
  1000. Xint
  1001. Xmidi_uio2event(softc, uio, event)
  1002. X    struct midi_softc *softc;
  1003. X    struct uio *uio;
  1004. X    struct event *event;
  1005. X{
  1006. X    u_long smf_ticks, ulen;
  1007. X    long tempo;
  1008. X    int byte, error, extra_byte, i, len, num_data_bytes;
  1009. X    int rs_change;
  1010. X    u_char meta_type, tmp_buf[256];
  1011. X
  1012. X    /* copy in timing portion */
  1013. X    len = 0;
  1014. X    do {
  1015. X        if ((byte = midi_next_byte(softc, uio)) == -1) {
  1016. X            stynamic_release(&event->data);
  1017. X            return (-1);
  1018. X        }
  1019. X        tmp_buf[len++] = byte;
  1020. X    } while (byte & 0x80);
  1021. X
  1022. X    /* compute time in smf ticks */
  1023. X    midi_var2fix(tmp_buf, &smf_ticks);
  1024. X    smf_ticks += softc->write_noop_time;
  1025. X    softc->write_noop_time = 0;
  1026. X
  1027. X    /* now convert from smf to kernel */
  1028. X    event->time = midi_smf2kernel_tick(softc, smf_ticks);
  1029. X
  1030. X    /* get first byte of event data */
  1031. X    if ((byte = midi_next_byte(softc, uio)) == -1) {
  1032. X        stynamic_release(&event->data);
  1033. X        return (-1);
  1034. X    }
  1035. X    switch (byte) {
  1036. X    case 0xf0:
  1037. X        /* basic sysex type */
  1038. X        event->type = SYSX;
  1039. X        len = 0;
  1040. X        do {
  1041. X            if ((byte = midi_next_byte(softc, uio)) == -1) {
  1042. X                stynamic_release(&event->data);
  1043. X                return (-1);
  1044. X            }
  1045. X            tmp_buf[len++] = byte;
  1046. X        } while (byte & 0x80);
  1047. X        midi_var2fix(tmp_buf, &ulen);
  1048. X        stynamic_add_byte(&event->data, 0xf0);
  1049. X        for (; ulen > 0; ulen--) {
  1050. X            if ((byte = midi_next_byte(softc, uio)) == -1) {
  1051. X                stynamic_release(&event->data);
  1052. X                return (-1);
  1053. X            }
  1054. X            stynamic_add_byte(&event->data, byte);
  1055. X        }
  1056. X        break;
  1057. X    case 0xf7:
  1058. X        /* continued sysex type */
  1059. X        event->type = SYSX;
  1060. X        len = 0;
  1061. X        do {
  1062. X            if ((byte = midi_next_byte(softc, uio)) == -1) {
  1063. X                stynamic_release(&event->data);
  1064. X                return (-1);
  1065. X            }
  1066. X            tmp_buf[len++] = byte;
  1067. X        } while (byte & 0x80);
  1068. X        midi_var2fix(smf, &ulen);
  1069. X        for (; ulen > 0; ulen--) {
  1070. X            if ((byte = midi_next_byte(softc, uio)) == -1) {
  1071. X                stynamic_release(&event->data);
  1072. X                return (-1);
  1073. X            }
  1074. X            stynamic_add_byte(&event->data, byte);
  1075. X        }
  1076. X        if (error = uiomove(event->data, event->length, UIO_WRITE,
  1077. X            uio))
  1078. X            return (error);
  1079. X        break;
  1080. X    case 0xff:
  1081. X        /* meta events */
  1082. X        if ((byte = midi_next_byte(softc, uio)) == -1) {
  1083. X            stynamic_release(&event->data);
  1084. X            return (-1);
  1085. X        }
  1086. X        meta_type = byte;
  1087. X        /* get length of meta data */
  1088. X        len = 0;
  1089. X        do {
  1090. X            if ((byte = midi_next_byte(softc, uio)) == -1) {
  1091. X                stynamic_release(&event->data);
  1092. X                return (-1);
  1093. X            }
  1094. X            tmp_buf[len++] = byte;
  1095. X        } while (byte & 0x80);
  1096. X        midi_var2fix(tmp_buf, &ulen);
  1097. X        /* read it in  - meta events are not over 256 in size */
  1098. X        for (i = 0; i < ulen; i++) {
  1099. X            if ((byte = midi_next_byte(softc, uio)) == -1) {
  1100. X                stynamic_release(&event->data);
  1101. X                return (-1);
  1102. X            }
  1103. X        }
  1104. X        switch (meta_type) {
  1105. X        default:
  1106. X            /*
  1107. X             * we'll skip these events, but we need to
  1108. X             * save the timing info
  1109. X             */
  1110. X            softc->write_noop_time = smf_ticks;
  1111. X            stynamic_release(&softc->wpartial);
  1112. X            softc->wpartialpos = 0;
  1113. X            return (-2);
  1114. X        case 0x51:
  1115. X            /* tempo event */
  1116. X            event->type = TEMPO;
  1117. X            tempo = 0;
  1118. X            for (i = 0; i < 3; i++) {
  1119. X                tempo = tempo << 8;
  1120. X                tempo |= tmp_buf[i];
  1121. X            }
  1122. X            stynamic_add_bytes(&event->data, (u_char *)&tempo,
  1123. X                sizeof(tempo));
  1124. X            /*
  1125. X             * change ptempo now, rtempo will change when
  1126. X             * the event's time comes up
  1127. X             */
  1128. X            softc->ptempo = tempo;
  1129. X            break;
  1130. X        }
  1131. X        break;
  1132. X    default:
  1133. X        if ((byte & 0xf0) == 0x80) {
  1134. X            u_char rs_chan, rs_type;
  1135. X
  1136. X            /* check note off events separately */
  1137. X            tmp_buf[0] = byte;
  1138. X            if ((byte = midi_next_byte(softc, uio)) == -1) {
  1139. X                stynamic_release(&event->data);
  1140. X                return (-1);
  1141. X            }
  1142. X            tmp_buf[1] = byte;
  1143. X            if ((byte = midi_next_byte(softc, uio)) == -1) {
  1144. X                stynamic_release(&event->data);
  1145. X                return (-1);
  1146. X            }
  1147. X            tmp_buf[2] = byte;
  1148. X            len = 3;
  1149. X            /*
  1150. X             * check to see if we can collapse and use
  1151. X             * running state
  1152. X             */
  1153. X            rs_type = softc->writers & 0xf0;
  1154. X            rs_chan = softc->writers & 0x0f;
  1155. X            /*
  1156. X             * collapse to running state if time is 0
  1157. X             * and the running state is the same
  1158. X             * or the running state is note on for the
  1159. X             * same channel and the note off velocity is
  1160. X             * zero.
  1161. X             */
  1162. X            if (event->time == 0 && (softc->writers == tmp_buf[0]
  1163. X                || (tmp_buf[2] == 0 && rs_type == 0x90
  1164. X                && rs_chan == (tmp_buf[0] & 0x0f)))) {
  1165. X                tmp_buf[0] = tmp_buf[1];
  1166. X                tmp_buf[1] = tmp_buf[2];
  1167. X                len = 2;
  1168. X            } else {
  1169. X                softc->writers = tmp_buf[0];
  1170. X            }
  1171. X        } else {
  1172. X            extra_byte = 0;
  1173. X            rs_change = 0;
  1174. X            if ((byte & 0x80) && (byte != softc->writers)) {
  1175. X                softc->writers = byte;
  1176. X                rs_change = 1;
  1177. X            }
  1178. X            len = 0;
  1179. X            if (event->time != 0 || rs_change) {
  1180. X                /*
  1181. X                 * stick in a mode byte if time is non-zero
  1182. X                 * This is so we don't confuse hardware that
  1183. X                 * is turned on while we're playing
  1184. X                 * also add it if the running state changes
  1185. X                 */
  1186. X                tmp_buf[0] = softc->writers;
  1187. X                len = 1;
  1188. X            }
  1189. X            if (byte & 0x80)
  1190. X                extra_byte = 1;
  1191. X            else {
  1192. X                tmp_buf[len] = byte;
  1193. X                len++;
  1194. X            }
  1195. X
  1196. X            switch (softc->writers & 0xf0) {
  1197. X            case 0x80:
  1198. X            case 0x90:
  1199. X            case 0xa0:
  1200. X            case 0xb0:
  1201. X            case 0xe0:
  1202. X                num_data_bytes = 1;
  1203. X                break;
  1204. X            default:
  1205. X                num_data_bytes = 0;
  1206. X            }
  1207. X            for (i = 0; i < num_data_bytes + extra_byte; i++) {
  1208. X                if ((byte = midi_next_byte(softc, uio)) == -1) {
  1209. X                    stynamic_release(&event->data);
  1210. X                    return (-1);
  1211. X                }
  1212. X                tmp_buf[len++] = byte;
  1213. X            }
  1214. X        }
  1215. X        event->type = NORMAL;
  1216. X        stynamic_add_bytes(&event->data, tmp_buf, len);
  1217. X    }
  1218. X    stynamic_release(&softc->wpartial);
  1219. X    softc->wpartialpos = 0;
  1220. X    return (0);
  1221. X}
  1222. X
  1223. Xint
  1224. Xmidi_fix2var(fix, var)
  1225. X    u_long fix;
  1226. X    u_char *var;
  1227. X{
  1228. X    int i;
  1229. X    unsigned char buf[4], *bptr;
  1230. X
  1231. X    buf[0] = buf[1] = buf[2] = buf[3] = 0;
  1232. X    bptr = buf;
  1233. X    *bptr++ = fix & 0x7f;
  1234. X    while ((fix >>= 7) > 0) {
  1235. X        *bptr |= 0x80;
  1236. X        *bptr++ += (fix & 0x7f);
  1237. X        }
  1238. X
  1239. X    i = 0;
  1240. X    do {
  1241. X        *var++ = *--bptr;
  1242. X        i++;
  1243. X    } while (bptr != buf);
  1244. X
  1245. X    return (i);
  1246. X}
  1247. X
  1248. Xint
  1249. Xmidi_var2fix(var, fix)
  1250. X    u_char *var;
  1251. X    u_long *fix;
  1252. X{
  1253. X    int delta;
  1254. X
  1255. X    *fix = 0;
  1256. X    delta = 0;
  1257. X    do {
  1258. X        *fix = (*fix << 7) + (*var & 0x7f);
  1259. X        delta++;
  1260. X    } while (*var++ & 0x80);
  1261. X
  1262. X    return (delta);
  1263. X}
  1264. X
  1265. Xu_long
  1266. Xmidi_smf2kernel_tick(softc, smf)
  1267. X    struct midi_softc *softc;
  1268. X    long smf;
  1269. X{
  1270. X      long long denominator, numerator;
  1271. X      u_long kernel;
  1272. X   
  1273. X     numerator = (long long)softc->ptempo * Hz * smf + softc->premainder;
  1274. X      denominator = 1000000 * (long long)softc->division;
  1275. X      kernel = numerator / denominator;
  1276. X      softc->premainder = numerator % denominator;
  1277. X       return (kernel);
  1278. X}
  1279. X
  1280. Xu_long
  1281. Xmidi_kernel2smf_tick(softc, tempo, kernel)
  1282. X    struct midi_softc *softc;
  1283. X    long tempo, kernel;
  1284. X{
  1285. X      long long numerator, denominator;
  1286. X      u_long smf;
  1287. X   
  1288. X      if (softc->prev_rtempo != tempo) {
  1289. X          /*
  1290. X           * also update the rremainder to reflect tempo
  1291. X           * change
  1292. X           */
  1293. X          softc->rremainder = softc->rremainder * tempo
  1294. X              / softc->prev_rtempo;
  1295. X          softc->prev_rtempo = tempo;
  1296. X      }
  1297. X     numerator = (long long)softc->division * 1000000 * kernel
  1298. X         + softc->rremainder;
  1299. X      denominator = (long long)tempo * Hz;
  1300. X      smf = numerator / denominator;
  1301. X      softc->rremainder = numerator % denominator;
  1302. X       return (smf);
  1303. X}
  1304. X
  1305. Xvoid
  1306. Xmidi_add_complete_event(softc)
  1307. X    struct midi_softc *softc;
  1308. X{
  1309. X    struct timeval t;
  1310. X    struct timeval curr;
  1311. X    struct event event;
  1312. X    struct partial_event *pe;
  1313. X    long ticks;
  1314. X
  1315. X    stynamic_init(&event.data);
  1316. X    pe = &softc->partial_event;
  1317. X    /* calculate delta time */
  1318. X    ticks = softc->prev_incoming - pe->time;
  1319. X    if (ticks < 0) {
  1320. X        ticks = 0;
  1321. X        pe->time = softc->prev_incoming;
  1322. X    }
  1323. X    event.time = ticks;
  1324. X    event.tempo = pe->tempo;
  1325. X    switch (stynamic_get_byte(&pe->event, 0)) {
  1326. X    case 0xf0:
  1327. X        /* sysex */
  1328. X        event.type = SYSX;
  1329. X        break;
  1330. X    default:
  1331. X        event.type = NORMAL;
  1332. X        break;
  1333. X    }
  1334. X    stynamic_append(&event.data, &softc->partial_event.event);
  1335. X    /* enqueue new event */
  1336. X    midi_enq(softc->rqueue, &event);
  1337. X    stynamic_release(&event.data);
  1338. X    /* readjust previous event time */
  1339. X    softc->prev_incoming = pe->time;
  1340. X
  1341. X    softc->status &= ~MIDI_RD_BLOCK;
  1342. X    if (softc->status & MIDI_RD_SLEEP) {
  1343. X        softc->status &= ~MIDI_RD_SLEEP;
  1344. X        wakeup((caddr_t)softc->rqueue);
  1345. X    }
  1346. X    if (softc->status & MIDI_ASYNC) {
  1347. X        struct proc *p;
  1348. X
  1349. X        if (softc->pgid < 0)
  1350. X            signal(-softc->pgid, SIGIO);
  1351. X        else if ((p = prfind(softc->pgid)) != 0)
  1352. X            psignal(p, SIGIO);
  1353. X    }
  1354. X
  1355. X    /* notify poll that there is data to be read */
  1356. X    /*
  1357. X     * XXXPOLL - do I only want to do this is a poll is in
  1358. X     * progress and anyyet is 0?  Then I'll need to set
  1359. X     * a status flag, and how do I know when to unset it after
  1360. X     * the poll times out (ala select).
  1361. X     */
  1362. X    pollwakeup(&softc->pollhead, POLLIN);
  1363. X
  1364. X    return;
  1365. X}
  1366. X
  1367. Xvoid
  1368. Xmidi_schedule_timeout(softc)
  1369. X    struct midi_softc *softc;
  1370. X{
  1371. X    struct event *event;
  1372. X
  1373. X    if (!midi_peekq(softc->wqueue, &event))
  1374. X        return;
  1375. X    softc->timeout_id = timeout(midi_timeout, (caddr_t)softc,
  1376. X        event->time);
  1377. X
  1378. X    /* clear record timer? */
  1379. X    if (softc->status & MIDI_RECONPLAY) {
  1380. X        softc->prev_incoming = lbolt;
  1381. X        /* clear flag */
  1382. X        softc->status &= ~MIDI_RECONPLAY;
  1383. X    }
  1384. X}
  1385. X
  1386. Xvoid
  1387. Xmidi_timeout(arg)
  1388. X    caddr_t arg;
  1389. X{
  1390. X    struct event *event;
  1391. X    struct midi_softc *softc = (struct midi_softc *)arg;
  1392. X    int i;
  1393. X
  1394. X    /* send first event since we know it is ready */
  1395. X    midi_deq(softc->wqueue, &event);
  1396. X    midi_write_event(softc, event);
  1397. X    stynamic_release(&event->data);
  1398. X
  1399. X    /* process all events that also occur at this time (event->time == 0) */
  1400. X    for(;;) {
  1401. X        if (!midi_peekq(softc->wqueue, &event))
  1402. X            return;
  1403. X        if (event->time != 0)
  1404. X            break;    
  1405. X        midi_deq(softc->wqueue, NULL);
  1406. X        midi_write_event(softc, event);
  1407. X        stynamic_release(&event->data);
  1408. X    }
  1409. X
  1410. X    /* setup timeout for next event */
  1411. X    midi_schedule_timeout(softc);
  1412. X}
  1413. X
  1414. Xvoid
  1415. Xmidi_write_event(softc, event)
  1416. X    struct midi_softc *softc;
  1417. X    struct event *event;
  1418. X{
  1419. X    int i, j;
  1420. X    u_char bytes[4], channel, command, *dataptr;
  1421. X
  1422. X    switch (event->type) {
  1423. X    case TEMPO:
  1424. X        stynamic_copy(&event->data, &softc->rtempo,
  1425. X            sizeof(softc->rtempo));
  1426. X        break;
  1427. X    case NORMAL:
  1428. X        /*
  1429. X         * fourth byte might not be valid, but who cares,
  1430. X         * we're only reading and in the kernel.  We'll
  1431. X         * ignore it if it isn't.
  1432. X         */
  1433. X        stynamic_copy(&event->data, &bytes, 4);
  1434. X        if (!(bytes[0] & 0x80))
  1435. X            dataptr = &bytes[0];
  1436. X        else {
  1437. X            softc->noteonrs = bytes[0];
  1438. X            dataptr = &bytes[1];
  1439. X        }
  1440. X        command = softc->noteonrs & 0xf0;
  1441. X        channel = softc->noteonrs & 0x0f;
  1442. X        if (command == 0x90) {
  1443. X            /*
  1444. X             * set of clear appropriate bit in noteon
  1445. X             * array depending on velocity value
  1446. X             */
  1447. X            if (dataptr[1] != 0)
  1448. X                softc->noteon[dataptr[0]] |= 1 << channel;
  1449. X            else
  1450. X                softc->noteon[dataptr[0]] &= ~(1 << channel);
  1451. X        }
  1452. X        if (command == 0x80)
  1453. X            /* clear bit */
  1454. X            softc->noteon[dataptr[0]] &= ~(1 << channel);
  1455. X        /* FALLTHRU */
  1456. X    default:
  1457. X        for (i = 0; i < event->data.len; i++) {
  1458. X            if (!midi_wait_rdy_rcv(softc))
  1459. X                break;
  1460. X            OUTB(softc->addr + MIDI_DATA,
  1461. X                stynamic_get_byte(&event->data, i));
  1462. X        }
  1463. X        break;
  1464. X    }
  1465. X    if (softc->wqueue->count < MIDI_LOW_WATER) {
  1466. X        softc->status &= ~MIDI_WR_BLOCK;
  1467. X        if (softc->status & MIDI_WR_SLEEP) {
  1468. X            softc->status &= ~MIDI_WR_SLEEP;
  1469. X            wakeup((caddr_t)softc->wqueue);
  1470. X        }
  1471. X        if (softc->status & MIDI_ASYNC &&
  1472. X            (softc->status & MIDI_SENDIO || softc->wqueue->count
  1473. X            == 0)) {
  1474. X            struct proc *p;
  1475. X
  1476. X            if (softc->pgid < 0)
  1477. X                signal(-softc->pgid, SIGIO);
  1478. X            else if ((p = prfind(softc->pgid)) != 0)
  1479. X                psignal(p, SIGIO);
  1480. X        }
  1481. X        softc->status &= ~MIDI_SENDIO;
  1482. X        /* notify poll that writes will succeed */
  1483. X        /*
  1484. X         * XXXPOLL - do I only want to do this is a poll is in
  1485. X         * progress and anyyet is 0?  Then I'll need to set
  1486. X         * a status flag, and how do I know when to unset it after
  1487. X         * the poll times out (ala select).
  1488. X         */
  1489. X        pollwakeup(&softc->pollhead, POLLOUT);
  1490. X    }
  1491. X    if (softc->status & MIDI_FLUSH_SLEEP && softc->wqueue->count == 0) {
  1492. X        softc->status &= ~MIDI_FLUSH_SLEEP;
  1493. X        wakeup((caddr_t)&softc->status);
  1494. X    }
  1495. X}
  1496. X
  1497. X
  1498. X/*
  1499. X * try to reset the midi devices as best we can
  1500. X */
  1501. Xvoid
  1502. Xmidi_reset_devices(softc)
  1503. X    struct midi_softc *softc;
  1504. X{
  1505. X    int i;
  1506. X    u_char channel, pitch;
  1507. X
  1508. X    /* manual note off calls - turn off any note that is on */
  1509. X    for (pitch = 0; pitch <= 0x7f; pitch++) {
  1510. X        for (channel = 0; channel <= 0x0f; channel++) {
  1511. X            if ((softc->noteon[pitch] >> (int)channel) & 0x01) {
  1512. X                if (!midi_wait_rdy_rcv(softc))
  1513. X                    break;
  1514. X                OUTB(softc->addr + MIDI_DATA, channel | 0x90);
  1515. X
  1516. X                if (!midi_wait_rdy_rcv(softc))
  1517. X                    break;
  1518. X                OUTB(softc->addr + MIDI_DATA, pitch);
  1519. X
  1520. X                if (!midi_wait_rdy_rcv(softc))
  1521. X                    break;
  1522. X                OUTB(softc->addr + MIDI_DATA, 0);
  1523. X            }
  1524. X        }
  1525. X        softc->noteon[pitch] = 0;
  1526. X    }
  1527. X    for (channel = 0; channel <= 0x0f; channel++) {
  1528. X        /*
  1529. X         * send paramter event for all notes off for redundancy
  1530. X         * some older synths don't support this
  1531. X         */
  1532. X        if (!midi_wait_rdy_rcv(softc))
  1533. X            break;
  1534. X        OUTB(softc->addr + MIDI_DATA, channel | 0xb0);
  1535. X        if (!midi_wait_rdy_rcv(softc))
  1536. X            break;
  1537. X        OUTB(softc->addr + MIDI_DATA, 0x7b);
  1538. X        if (!midi_wait_rdy_rcv(softc))
  1539. X            break;
  1540. X        OUTB(softc->addr + MIDI_DATA, 0);
  1541. X
  1542. X        /* modulation controller to zero */
  1543. X        if (!midi_wait_rdy_rcv(softc))
  1544. X            break;
  1545. X        OUTB(softc->addr + MIDI_DATA, 0x01);
  1546. X        if (!midi_wait_rdy_rcv(softc))
  1547. X            break;
  1548. X        OUTB(softc->addr + MIDI_DATA, 0);
  1549. X
  1550. X        /* reset all controllers */
  1551. X        if (!midi_wait_rdy_rcv(softc))
  1552. X            break;
  1553. X        OUTB(softc->addr + MIDI_DATA, 0x79);
  1554. X        if (!midi_wait_rdy_rcv(softc))
  1555. X            break;
  1556. X        OUTB(softc->addr + MIDI_DATA, 0);
  1557. X
  1558. X        /* lift sustain pedal */
  1559. X        if (!midi_wait_rdy_rcv(softc))
  1560. X            break;
  1561. X        OUTB(softc->addr + MIDI_DATA, 0x40);
  1562. X        if (!midi_wait_rdy_rcv(softc))
  1563. X            break;
  1564. X        OUTB(softc->addr + MIDI_DATA, 0);
  1565. X
  1566. X        /* center pitch wheel */
  1567. X        if (!midi_wait_rdy_rcv(softc))
  1568. X            break;
  1569. X        OUTB(softc->addr + MIDI_DATA, 0xe0 | channel);
  1570. X        if (!midi_wait_rdy_rcv(softc))
  1571. X            break;
  1572. X        OUTB(softc->addr + MIDI_DATA, 0);
  1573. X        if (!midi_wait_rdy_rcv(softc))
  1574. X            break;
  1575. X        OUTB(softc->addr + MIDI_DATA, 0x40);
  1576. X    }
  1577. X    softc->noteonrs = 0;
  1578. X}
  1579. X
  1580. Xvoid
  1581. Xmidi_initq(eq)
  1582. X    struct event_queue *eq;
  1583. X{
  1584. X
  1585. X    eq->count = 0;
  1586. X    eq->end = &eq->events[MIDI_Q_SIZE - 1];
  1587. X    eq->head = eq->events;
  1588. X    eq->tail = eq->events;
  1589. X    /* zero events to clear stynamic stuctures */
  1590. X    bzero(eq->events, MIDI_Q_SIZE * sizeof(struct event));
  1591. X}
  1592. X
  1593. Xvoid
  1594. Xmidi_copy_event(e1, e2)
  1595. X    struct event *e1, *e2;
  1596. X{
  1597. X    short i;
  1598. X
  1599. X    e1->time = e2->time;
  1600. X    e1->type = e2->type;
  1601. X    e1->tempo = e2->tempo;
  1602. X    stynamic_release(&e1->data);
  1603. X    stynamic_append(&e1->data, &e2->data);
  1604. X}
  1605. X
  1606. Xint
  1607. Xmidi_deq(eq, event)
  1608. X    struct event_queue *eq;
  1609. X    struct event **event;
  1610. X{
  1611. X    int s;
  1612. X
  1613. X    s = spltty();
  1614. X    if (eq->count == 0) {
  1615. X        splx(s);
  1616. X        return (0);
  1617. X    }
  1618. X    if (event == NULL)
  1619. X        eq->head++;
  1620. X    else
  1621. X        *event = eq->head++;
  1622. X    if (eq->head > eq->end)
  1623. X        eq->head = eq->events;
  1624. X    eq->count--;
  1625. X    splx(s);
  1626. X    return (1);
  1627. X}
  1628. X
  1629. Xint
  1630. Xmidi_peekq(eq, event)
  1631. X    struct event_queue *eq;
  1632. X    struct event **event;
  1633. X{
  1634. X    int s;
  1635. X
  1636. X    s = spltty();
  1637. X    if (eq->count == 0) {
  1638. X        splx(s);
  1639. X        return (0);
  1640. X    }
  1641. X    *event = eq->head;
  1642. X    splx(s);
  1643. X    return (1);
  1644. X}
  1645. X
  1646. Xint
  1647. Xmidi_enq(eq, event)
  1648. X    struct event_queue *eq;
  1649. X    struct event *event;
  1650. X{
  1651. X    int s;
  1652. X
  1653. X    s = spltty();
  1654. X    if (eq->count == MIDI_Q_SIZE) {
  1655. X        splx(s);
  1656. X        return (0);
  1657. X    }
  1658. X    midi_copy_event(eq->tail++, event);
  1659. X    if (eq->tail > eq->end)
  1660. X        eq->tail = eq->events;
  1661. X    eq->count++;
  1662. X    splx(s);
  1663. X    return (1);
  1664. X}
  1665. X
  1666. Xvoid
  1667. Xstynamic_add_byte(sty, byte)
  1668. X    struct stynamic *sty;
  1669. X    u_char byte;
  1670. X{
  1671. X    int s;
  1672. X    u_char *new_ptr;
  1673. X
  1674. X    s = spltty();
  1675. X    if (sty->len < STYNAMIC_SIZE)
  1676. X        sty->datas[sty->len++] = byte;
  1677. X    else {
  1678. X        if (sty->len < sty->allocated) {
  1679. X            sty->datad[sty->len++] = byte;
  1680. X        } else {
  1681. X            new_ptr = kmem_alloc(sty->allocated + STYNAMIC_ALLOC,
  1682. X                KM_NOSLEEP);
  1683. X            if (new_ptr == NULL) {
  1684. X                printf("midi: out of memory\n");
  1685. X                return;
  1686. X            }
  1687. X            if (sty->allocated == 0)
  1688. X                bcopy(sty->datas, new_ptr, sty->len);
  1689. X            else {
  1690. X                bcopy(sty->datad, new_ptr, sty->len);
  1691. X                kmem_free(sty->datad, sty->allocated);
  1692. X            }
  1693. X            sty->datad = new_ptr;
  1694. X            sty->datad[sty->len++] = byte;
  1695. X            sty->allocated += STYNAMIC_ALLOC;
  1696. X        }
  1697. X    }
  1698. X    splx(s);
  1699. X}
  1700. X
  1701. Xvoid
  1702. Xstynamic_add_bytes(sty, bytes, num)
  1703. X    struct stynamic *sty;
  1704. X    u_char *bytes;
  1705. X    int num;
  1706. X{
  1707. X    int s, size_inc;
  1708. X    u_char *new_ptr;
  1709. X
  1710. X    s = spltty();
  1711. X    if (sty->len + num <= STYNAMIC_SIZE) {
  1712. X        bcopy(bytes, &sty->datas[sty->len], num);
  1713. X        sty->len += num;
  1714. X    } else {
  1715. X        if (sty->len + num <= sty->allocated) {
  1716. X            bcopy(bytes, &sty->datad[sty->len], num);
  1717. X            sty->len += num;
  1718. X        } else {
  1719. X            size_inc = (num / STYNAMIC_ALLOC + 1) * STYNAMIC_ALLOC;
  1720. X            new_ptr = kmem_alloc(sty->allocated + size_inc,
  1721. X                KM_NOSLEEP);
  1722. X            if (sty->allocated == 0)
  1723. X                bcopy(sty->datas, new_ptr, sty->len);
  1724. X            else {
  1725. X                bcopy(sty->datad, new_ptr, sty->len);
  1726. X                kmem_free(sty->datad, sty->allocated);
  1727. X            }
  1728. X            sty->datad = new_ptr;
  1729. X            bcopy(bytes, &sty->datad[sty->len], num);
  1730. X            sty->allocated += size_inc;
  1731. X            sty->len += num;
  1732. X        }
  1733. X    }
  1734. X    splx(s);
  1735. X}
  1736. X
  1737. Xu_char
  1738. Xstynamic_get_byte(sty, index)
  1739. X    struct stynamic *sty;
  1740. X    int index;
  1741. X{
  1742. X    int s;
  1743. X
  1744. X    s = spltty();
  1745. X    if (sty->len <= 4)
  1746. X        return (sty->datas[index]);
  1747. X    else
  1748. X        return (sty->datad[index]);
  1749. X    splx(s);
  1750. X}
  1751. X
  1752. Xvoid
  1753. Xstynamic_copy(sty, dest, len)
  1754. X    struct stynamic *sty;
  1755. X    void *dest;
  1756. X    int len;
  1757. X{
  1758. X    int s;
  1759. X
  1760. X    s = spltty();
  1761. X    if (sty->len <= 4)
  1762. X        bcopy(sty->datas, dest, len);
  1763. X    else
  1764. X        bcopy(sty->datad, dest, len);
  1765. X    splx(s);
  1766. X}
  1767. X
  1768. Xvoid
  1769. Xstynamic_append(dest, src)
  1770. X    struct stynamic *dest;
  1771. X    struct stynamic *src;
  1772. X{
  1773. X
  1774. X    if (src->len <= 4)
  1775. X        stynamic_add_bytes(dest, src->datas, src->len);
  1776. X    else
  1777. X        stynamic_add_bytes(dest, src->datad, src->len);
  1778. X}
  1779. X
  1780. Xvoid
  1781. Xstynamic_copy_from(sty, index, dest, len)
  1782. X    struct stynamic *sty;
  1783. X    int index, len;
  1784. X    void *dest;
  1785. X{
  1786. X    int s;
  1787. X
  1788. X    s = spltty();
  1789. X    if (sty->len <= 4)
  1790. X        bcopy(&sty->datas[index], dest, len);
  1791. X    else
  1792. X        bcopy(&sty->datad[index], dest, len);
  1793. X    splx(s);
  1794. X}
  1795. X
  1796. X
  1797. Xvoid
  1798. Xstynamic_release(sty)
  1799. X    struct stynamic *sty;
  1800. X{
  1801. X    int s;
  1802. X
  1803. X    s = spltty();
  1804. X    if (sty->len > STYNAMIC_SIZE)
  1805. X        kmem_free(sty->datad, sty->allocated);
  1806. X    sty->len = 0;
  1807. X    sty->allocated = 0;
  1808. X    sty->datad = NULL;
  1809. X    bzero(sty->datas, STYNAMIC_SIZE);
  1810. X    splx(s);
  1811. X}
  1812. X
  1813. Xvoid
  1814. Xstynamic_shift(sty, num)
  1815. X    struct stynamic *sty;
  1816. X    int num;
  1817. X{
  1818. X    int rem, s;
  1819. X    u_char *ptr;
  1820. X
  1821. X    if (sty->len <= num) {
  1822. X        stynamic_release(sty);
  1823. X        return;
  1824. X    }
  1825. X    s = spltty();
  1826. X    if (sty->len > STYNAMIC_SIZE)
  1827. X        ptr = &sty->datad[num];
  1828. X    else
  1829. X        ptr = &sty->datas[num];
  1830. X    rem = sty->len - num;
  1831. X    if (rem > STYNAMIC_SIZE)
  1832. X        bcopy(ptr, sty->datad, rem);
  1833. X    else {
  1834. X        bcopy(ptr, sty->datas, rem);
  1835. X        if (sty->datad != NULL) {
  1836. X            kmem_free(sty->datad, sty->allocated);
  1837. X            sty->datad = NULL;
  1838. X            sty->allocated = 0;
  1839. X        }
  1840. X    }
  1841. X    splx(s);
  1842. X    sty->len = rem;
  1843. X}
  1844. X
  1845. Xvoid
  1846. Xstynamic_init(sty)
  1847. X    struct stynamic *sty;
  1848. X{
  1849. X    int s;
  1850. X
  1851. X    s = spltty();
  1852. X    sty->len = 0;
  1853. X    sty->allocated = 0;
  1854. X    sty->datad = NULL;
  1855. X    bzero(sty->datas, STYNAMIC_SIZE);
  1856. X    splx(s);
  1857. X}
  1858. X
  1859. Xvoid
  1860. Xstynamic_print(sty)
  1861. X    struct stynamic *sty;
  1862. X{
  1863. X
  1864. X    printf("\t\tlen = %d\n", sty->len);
  1865. X    printf("\t\tallocated = %d\n", sty->allocated);
  1866. X    printf("\t\tdatad = 0x%x\n", sty->datad);
  1867. X}
  1868. X
  1869. X/*
  1870. X * XXXSIGNAL
  1871. X * I have no idea how to verify that a process is killable under
  1872. X * SVR4.  We need to check both individual processes and process
  1873. X * groups.  My drivers don't even cope with broadcast kills, so
  1874. X * don't worry about that one.
  1875. X * See the BSD and LINUX versions for ideas on how to verify this.
  1876. X */
  1877. Xint
  1878. Xmidi_killable(owner, pid)
  1879. X    proc_t *owner;
  1880. X    int pid;
  1881. X{
  1882. X
  1883. X    if (pid == 0)
  1884. X        return (0);
  1885. X    if (pid == -1)
  1886. X        return (EPERM);
  1887. X    return (0);
  1888. X}
  1889. END_OF_FILE
  1890.   if test 42554 -ne `wc -c <'tclmidi-2.0/drivers/SVR4/midi.c'`; then
  1891.     echo shar: \"'tclmidi-2.0/drivers/SVR4/midi.c'\" unpacked with wrong size!
  1892.   fi
  1893.   # end of 'tclmidi-2.0/drivers/SVR4/midi.c'
  1894. fi
  1895. if test -f 'tclmidi-2.0/rb/rb.c' -a "${1}" != "-c" ; then 
  1896.   echo shar: Will not clobber existing file \"'tclmidi-2.0/rb/rb.c'\"
  1897. else
  1898.   echo shar: Extracting \"'tclmidi-2.0/rb/rb.c'\" \(13684 characters\)
  1899.   sed "s/^X//" >'tclmidi-2.0/rb/rb.c' <<'END_OF_FILE'
  1900. X#include <stdio.h>
  1901. X#include <stdlib.h>
  1902. X#include <string.h>
  1903. X#include "rb.h"
  1904. X#include "list.h"
  1905. X
  1906. X#define isred(n) (n->s.red)
  1907. X#define isblack(n) (!isred(n))
  1908. X#define isleft(n) (n->s.left)
  1909. X#define isright(n) (!isleft(n))
  1910. X#define isint(n) (n->s.internal)
  1911. X#define isext(n) (!isint(n))
  1912. X#define ishead(n) (n->s.head)
  1913. X#define isroot(n) (n->s.root)
  1914. X#define setred(n) n->s.red = 1
  1915. X#define setblack(n) n->s.red = 0
  1916. X#define setleft(n) n->s.left = 1
  1917. X#define setright(n) n->s.left = 0
  1918. X#define sethead(n) n->s.head = 1
  1919. X#define setroot(n) n->s.root = 1
  1920. X#define setint(n) n->s.internal = 1
  1921. X#define setext(n) n->s.internal = 0
  1922. X#define setnormal(n) { n->s.root = 0; n ->s.head = 0; }
  1923. X#define sibling(n) ((isleft(n)) ? n->p.parent->c.child.right \
  1924. X                                : n->p.parent->c.child.left)
  1925. X
  1926. X#define mk_new_ext(new, kkkey, vvval) {\
  1927. X    new = (Rb_node) malloc(sizeof(struct rb_node));\
  1928. X    new->v.val = vvval;\
  1929. X    new->k.key = kkkey;\
  1930. X    setext(new);\
  1931. X    setblack(new);\
  1932. X    setnormal(new);\
  1933. X}
  1934. X
  1935. Xvoid
  1936. Xmk_new_int(l, r, p, il)
  1937. X    Rb_node l, r, p;
  1938. X    int il;
  1939. X{
  1940. X    Rb_node new;
  1941. X
  1942. X    new = (Rb_node) malloc(sizeof(struct rb_node));
  1943. X    setint(new);
  1944. X    setred(new);
  1945. X    setnormal(new);
  1946. X    new->c.child.left = l;
  1947. X    new->c.child.right = r;
  1948. X    new->p.parent = p;
  1949. X    new->k.lext = l;
  1950. X    new->v.rext = r;
  1951. X    l->p.parent = new;
  1952. X    r->p.parent = new;
  1953. X    setleft(l);
  1954. X    setright(r);
  1955. X    if (ishead(p)) {
  1956. X        p->p.root = new;
  1957. X        setroot(new);
  1958. X    } else if (il) {
  1959. X        setleft(new);
  1960. X        p->c.child.left = new;
  1961. X    } else {
  1962. X        setright(new);
  1963. X        p->c.child.right = new;
  1964. X    }
  1965. X    recolor(new);
  1966. X}
  1967. X
  1968. X
  1969. XRb_node 
  1970. Xlprev(n)
  1971. X    Rb_node n;
  1972. X{
  1973. X    if (ishead(n))
  1974. X        return (n);
  1975. X    while (!isroot(n)) {
  1976. X        if (isright(n))
  1977. X            return (n->p.parent);
  1978. X        n = n->p.parent;
  1979. X    }
  1980. X    return (n->p.parent);
  1981. X}
  1982. X
  1983. XRb_node 
  1984. Xrprev(n)
  1985. X    Rb_node n;
  1986. X{
  1987. X    if (ishead(n))
  1988. X        return (n);
  1989. X    while (!isroot(n)) {
  1990. X        if (isleft(n))
  1991. X            return (n->p.parent);
  1992. X        n = n->p.parent;
  1993. X    }
  1994. X    return (n->p.parent);
  1995. X}
  1996. X
  1997. XRb_node 
  1998. Xmake_rb()
  1999. X{
  2000. X    Rb_node head;
  2001. X
  2002. X    if ((head = (Rb_node)malloc(sizeof(struct rb_node))) == NULL)
  2003. X        return (NULL);
  2004. X    head->c.list.flink = head;
  2005. X    head->c.list.blink = head;
  2006. X    head->p.root = head;
  2007. X    head->k.key = "";
  2008. X    head->v.val = NULL;
  2009. X    sethead(head);
  2010. X    return (head);
  2011. X}
  2012. X
  2013. XRb_node 
  2014. Xrb_find_key_n(n, key, fnd)
  2015. X    Rb_node n;
  2016. X    char *key;
  2017. X    int *fnd;
  2018. X{
  2019. X    int cmp;
  2020. X
  2021. X    *fnd = 0;
  2022. X    if (!ishead(n)) {
  2023. X        fprintf(stderr, "rb_find_key_n called on non-head 0x%x\n",
  2024. X            (int)n);
  2025. X        exit(1);
  2026. X    }
  2027. X    if (n->p.root == n)
  2028. X        return (n);
  2029. X    cmp = strcmp(key, n->c.list.blink->k.key);
  2030. X    if (cmp == 0) {
  2031. X        *fnd = 1;
  2032. X        return (n->c.list.blink);
  2033. X    }
  2034. X    if (cmp > 0)
  2035. X        return (n);
  2036. X    else
  2037. X        n = n->p.root;
  2038. X    while (1) {
  2039. X        if (isext(n))
  2040. X            return (n);
  2041. X        cmp = strcmp(key, n->k.lext->k.key);
  2042. X        if (cmp == 0) {
  2043. X            *fnd = 1;
  2044. X            return (n->k.lext);
  2045. X        }
  2046. X        if (cmp < 0)
  2047. X            n = n->c.child.left;
  2048. X        else
  2049. X            n = n->c.child.right;
  2050. X    }
  2051. X}
  2052. X
  2053. XRb_node 
  2054. Xrb_find_key(n, key)
  2055. X    Rb_node n;
  2056. X    char *key;
  2057. X{
  2058. X    int fnd;
  2059. X
  2060. X    return (rb_find_key_n(n, key, &fnd));
  2061. X}
  2062. X
  2063. XRb_node 
  2064. Xrb_find_ikey_n(n, ikey, fnd)
  2065. X    Rb_node n;
  2066. X    int ikey;
  2067. X    int *fnd;
  2068. X{
  2069. X    *fnd = 0;
  2070. X    if (!ishead(n)) {
  2071. X        fprintf(stderr, "rb_find_ikey_n called on non-head 0x%x\n",
  2072. X            (int)n);
  2073. X        exit(1);
  2074. X    }
  2075. X    if (n->p.root == n)
  2076. X        return (n);
  2077. X    if (ikey == n->c.list.blink->k.ikey) {
  2078. X        *fnd = 1;
  2079. X        return (n->c.list.blink);
  2080. X    }
  2081. X    if (ikey > n->c.list.blink->k.ikey)
  2082. X        return (n);
  2083. X    else
  2084. X        n = n->p.root;
  2085. X    while (1) {
  2086. X        if (isext(n))
  2087. X            return (n);
  2088. X        if (ikey == n->k.lext->k.ikey) {
  2089. X            *fnd = 1;
  2090. X            return (n->k.lext);
  2091. X        }
  2092. X        n = (ikey < n->k.lext->k.ikey) ? n->c.child.left :
  2093. X            n->c.child.right;
  2094. X    }
  2095. X}
  2096. X
  2097. XRb_node 
  2098. Xrb_find_ukey_n(n, ukey, fnd)
  2099. X    register Rb_node n;
  2100. X    unsigned long ukey;
  2101. X    int *fnd;
  2102. X{
  2103. X
  2104. X    *fnd = 0;
  2105. X    if (!ishead(n)) {
  2106. X        fprintf(stderr, "rb_find_ukey_n called on non-head 0x%x\n",
  2107. X            (int)n);
  2108. X        exit(1);
  2109. X    }
  2110. X    if (n->p.root == n)
  2111. X        return (n);
  2112. X    if (ukey == n->c.list.blink->k.ukey) {
  2113. X        *fnd = 1;
  2114. X        return (n->c.list.blink);
  2115. X    }
  2116. X    if (ukey > n->c.list.blink->k.ukey)
  2117. X        return (n);
  2118. X    else
  2119. X        n = n->p.root;
  2120. X    while (1) {
  2121. X        if (isext(n))
  2122. X            return (n);
  2123. X        if (ukey == n->k.lext->k.ukey) {
  2124. X            *fnd = 1;
  2125. X            return (n->k.lext);
  2126. X        }
  2127. X        n = (ukey < n->k.lext->k.ukey) ? n->c.child.left :
  2128. X            n->c.child.right;
  2129. X    }
  2130. X}
  2131. X
  2132. XRb_node 
  2133. Xrb_find_ikey(n, ikey)
  2134. X    Rb_node n;
  2135. X    int ikey;
  2136. X{
  2137. X    int fnd;
  2138. X
  2139. X    return (rb_find_ikey_n(n, ikey, &fnd));
  2140. X}
  2141. X
  2142. XRb_node 
  2143. Xrb_find_ukey(n, ukey)
  2144. X    Rb_node n;
  2145. X    unsigned long ukey;
  2146. X{
  2147. X    int fnd;
  2148. X
  2149. X    return (rb_find_ukey_n(n, ukey, &fnd));
  2150. X}
  2151. X
  2152. XRb_node 
  2153. Xrb_find_gkey_n(n, key, fxn, fnd)
  2154. X    Rb_node n;
  2155. X    char *key;
  2156. X    int (*fxn)();
  2157. X    int *fnd;
  2158. X{
  2159. X    int cmp;
  2160. X
  2161. X    *fnd = 0;
  2162. X    if (!ishead(n)) {
  2163. X        fprintf(stderr, "rb_find_key_n called on non-head 0x%x\n",
  2164. X            (int)n);
  2165. X        exit(1);
  2166. X    }
  2167. X    if (n->p.root == n)
  2168. X        return (n);
  2169. X    cmp = (*fxn)(key, n->c.list.blink->k.key);
  2170. X    if (cmp == 0) {
  2171. X        *fnd = 1;
  2172. X        return (n->c.list.blink);
  2173. X    }
  2174. X    if (cmp > 0)
  2175. X        return (n);
  2176. X    else
  2177. X        n = n->p.root;
  2178. X    while (1) {
  2179. X        if (isext(n))
  2180. X            return (n);
  2181. X        cmp = (*fxn)(key, n->k.lext->k.key);
  2182. X        if (cmp == 0) {
  2183. X            *fnd = 1;
  2184. X            return (n->k.lext);
  2185. X        }
  2186. X        if (cmp < 0)
  2187. X            n = n->c.child.left;
  2188. X        else
  2189. X            n = n->c.child.right;
  2190. X    }
  2191. X}
  2192. X
  2193. XRb_node 
  2194. Xrb_find_gkey(n, key, fxn)
  2195. X    Rb_node n;
  2196. X    char *key;
  2197. X    int (*fxn)();
  2198. X{
  2199. X    int fnd;
  2200. X
  2201. X    return (rb_find_gkey_n(n, key, fxn, &fnd));
  2202. X}
  2203. XRb_node 
  2204. Xrb_insert_b(n, key, val)
  2205. X    Rb_node n;
  2206. X    char *key;
  2207. X    char *val;
  2208. X{
  2209. X    Rb_node newleft, newright, newnode, p;
  2210. X
  2211. X    if (ishead(n)) {
  2212. X        if (n->p.root == n) {
  2213. X            /* Tree is empty */
  2214. X            mk_new_ext(newnode, key, val);
  2215. X            insert((List)newnode, (List)n);
  2216. X            n->p.root = newnode;
  2217. X            newnode->p.parent = n;
  2218. X            setroot(newnode);
  2219. X            return (newnode);
  2220. X        } else {
  2221. X            mk_new_ext(newright, key, val);
  2222. X            insert((List)newright, (List)n);
  2223. X            newleft = newright->c.list.blink;
  2224. X            setnormal(newleft);
  2225. X            mk_new_int(newleft, newright, newleft->p.parent, isleft(newleft));
  2226. X            p = rprev(newright);
  2227. X            if (!ishead(p))
  2228. X                p->k.lext = newright;
  2229. X            return (newright);
  2230. X        }
  2231. X    } else {
  2232. X        mk_new_ext(newleft, key, val);
  2233. X        insert((List)newleft, (List)n);
  2234. X        setnormal(n);
  2235. X        mk_new_int(newleft, n, n->p.parent, isleft(n));
  2236. X        p = lprev(newleft);
  2237. X        if (!ishead(p))
  2238. X            p->v.rext = newleft;
  2239. X        return (newleft);
  2240. X    }
  2241. X}
  2242. X
  2243. Xvoid
  2244. Xrecolor(n)
  2245. X    Rb_node n;
  2246. X{
  2247. X    Rb_node p, gp, s;
  2248. X    int done = 0;
  2249. X
  2250. X    while (!done) {
  2251. X        if (isroot(n)) {
  2252. X            setblack(n);
  2253. X            return;
  2254. X        }
  2255. X        p = n->p.parent;
  2256. X
  2257. X        if (isblack(p))
  2258. X            return;
  2259. X
  2260. X        if (isroot(p)) {
  2261. X            setblack(p);
  2262. X            return;
  2263. X        }
  2264. X        gp = p->p.parent;
  2265. X        s = sibling(p);
  2266. X        if (isred(s)) {
  2267. X            setblack(p);
  2268. X            setred(gp);
  2269. X            setblack(s);
  2270. X            n = gp;
  2271. X        } else {
  2272. X            done = 1;
  2273. X        }
  2274. X    }
  2275. X    /* p's sibling is black, p is red, gp is black */
  2276. X
  2277. X    if ((isleft(n) == 0) == (isleft(p) == 0)) {
  2278. X        single_rotate(gp, isleft(n));
  2279. X        setblack(p);
  2280. X        setred(gp);
  2281. X    } else {
  2282. X        single_rotate(p, isleft(n));
  2283. X        single_rotate(gp, isleft(n));
  2284. X        setblack(n);
  2285. X        setred(gp);
  2286. X    }
  2287. X}
  2288. X
  2289. Xvoid
  2290. Xsingle_rotate(y, l)
  2291. X    Rb_node y;
  2292. X    int l;
  2293. X{
  2294. X    int rl, ir;
  2295. X    Rb_node x, yp;
  2296. X
  2297. X    /* quiet warning */
  2298. X    rl = 0;
  2299. X    ir = isroot(y);
  2300. X    yp = y->p.parent;
  2301. X    if (!ir) {
  2302. X        rl = isleft(y);
  2303. X    }
  2304. X    if (l) {
  2305. X        x = y->c.child.left;
  2306. X        y->c.child.left = x->c.child.right;
  2307. X        setleft(y->c.child.left);
  2308. X        y->c.child.left->p.parent = y;
  2309. X        x->c.child.right = y;
  2310. X        setright(y);
  2311. X    } else {
  2312. X        x = y->c.child.right;
  2313. X        y->c.child.right = x->c.child.left;
  2314. X        setright(y->c.child.right);
  2315. X        y->c.child.right->p.parent = y;
  2316. X        x->c.child.left = y;
  2317. X        setleft(y);
  2318. X    }
  2319. X
  2320. X    x->p.parent = yp;
  2321. X    y->p.parent = x;
  2322. X    if (ir) {
  2323. X        yp->p.root = x;
  2324. X        setnormal(y);
  2325. X        setroot(x);
  2326. X    } else {
  2327. X        if (rl) {
  2328. X            yp->c.child.left = x;
  2329. X            setleft(x);
  2330. X        } else {
  2331. X            yp->c.child.right = x;
  2332. X            setright(x);
  2333. X        }
  2334. X    }
  2335. X}
  2336. X
  2337. Xvoid
  2338. Xrb_delete_node(n)
  2339. X    Rb_node n;
  2340. X{
  2341. X    Rb_node s, p, gp;
  2342. X    char ir;
  2343. X
  2344. X    if (isint(n)) {
  2345. X        fprintf(stderr, "Cannot delete an internal node: 0x%x\n",
  2346. X            (int)n);
  2347. X        exit(1);
  2348. X    }
  2349. X    if (ishead(n)) {
  2350. X        fprintf(stderr, "Cannot delete the head of an rb_tree: 0x%x\n",
  2351. X            (int)n);
  2352. X        exit(1);
  2353. X    }
  2354. X    delete_item((List)n);    /* Delete it from the list */
  2355. X    p = n->p.parent;    /* The only node */
  2356. X    if (isroot(n)) {
  2357. X        p->p.root = p;
  2358. X        free(n);
  2359. X        return;
  2360. X    }
  2361. X    s = sibling(n);        /* The only node after deletion */
  2362. X    if (isroot(p)) {
  2363. X        s->p.parent = p->p.parent;
  2364. X        s->p.parent->p.root = s;
  2365. X        setroot(s);
  2366. X        free(p);
  2367. X        free(n);
  2368. X        return;
  2369. X    }
  2370. X    gp = p->p.parent;    /* Set parent to sibling */
  2371. X    s->p.parent = gp;
  2372. X    if (isleft(p)) {
  2373. X        gp->c.child.left = s;
  2374. X        setleft(s);
  2375. X    } else {
  2376. X        gp->c.child.right = s;
  2377. X        setright(s);
  2378. X    }
  2379. X    ir = isred(p);
  2380. X    free(p);
  2381. X    free(n);
  2382. X
  2383. X    if (isext(s)) {        /* Update proper rext and lext values */
  2384. X        p = lprev(s);
  2385. X        if (!ishead(p))
  2386. X            p->v.rext = s;
  2387. X        p = rprev(s);
  2388. X        if (!ishead(p))
  2389. X            p->k.lext = s;
  2390. X    } else if (isblack(s)) {
  2391. X        fprintf(stderr, "DELETION PROB -- sib is black, internal\n");
  2392. X        exit(1);
  2393. X    } else {
  2394. X        p = lprev(s);
  2395. X        if (!ishead(p))
  2396. X            p->v.rext = s->c.child.left;
  2397. X        p = rprev(s);
  2398. X        if (!ishead(p))
  2399. X            p->k.lext = s->c.child.right;
  2400. X        setblack(s);
  2401. X        return;
  2402. X    }
  2403. X
  2404. X    if (ir)
  2405. X        return;
  2406. X
  2407. X    /* Recolor */
  2408. X
  2409. X    n = s;
  2410. X    p = n->p.parent;
  2411. X    s = sibling(n);
  2412. X    while (isblack(p) && isblack(s) && isint(s) &&
  2413. X           isblack(s->c.child.left) && isblack(s->c.child.right)) {
  2414. X        setred(s);
  2415. X        n = p;
  2416. X        if (isroot(n))
  2417. X            return;
  2418. X        p = n->p.parent;
  2419. X        s = sibling(n);
  2420. X    }
  2421. X
  2422. X    if (isblack(p) && isred(s)) {    /* Rotation 2.3b */
  2423. X        single_rotate(p, isright(n));
  2424. X        setred(p);
  2425. X        setblack(s);
  2426. X        s = sibling(n);
  2427. X    }
  2428. X    {
  2429. X        Rb_node x, z;
  2430. X        char il;
  2431. X
  2432. X        if (isext(s)) {
  2433. X            fprintf(stderr,
  2434. X                "DELETION ERROR: sibling not internal\n");
  2435. X            exit(1);
  2436. X        }
  2437. X        il = isleft(n);
  2438. X        x = il ? s->c.child.left : s->c.child.right;
  2439. X        z = sibling(x);
  2440. X
  2441. X        if (isred(z)) {    /* Rotation 2.3f */
  2442. X            single_rotate(p, !il);
  2443. X            setblack(z);
  2444. X            if (isred(p))
  2445. X                setred(s);
  2446. X            else
  2447. X                setblack(s);
  2448. X            setblack(p);
  2449. X        } else if (isblack(x)) {
  2450. X            /* Recoloring only (2.3c) */
  2451. X            if (isred(s) || isblack(p)) {
  2452. X                fprintf(stderr,
  2453. X                    "DELETION ERROR: 2.3c not quite right\n");
  2454. X                exit(1);
  2455. X            }
  2456. X            setblack(p);
  2457. X            setred(s);
  2458. X            return;
  2459. X        } else if (isred(p)) {
  2460. X            /* 2.3d */
  2461. X            single_rotate(s, il);
  2462. X            single_rotate(p, !il);
  2463. X            setblack(x);
  2464. X            setred(s);
  2465. X            return;
  2466. X        } else {
  2467. X            /* 2.3e */
  2468. X            single_rotate(s, il);
  2469. X            single_rotate(p, !il);
  2470. X            setblack(x);
  2471. X            return;
  2472. X        }
  2473. X    }
  2474. X}
  2475. X
  2476. Xvoid
  2477. Xrb_print_tree(t, level)
  2478. X    Rb_node t;
  2479. X    int level;
  2480. X{
  2481. X    int i;
  2482. X
  2483. X    if (ishead(t) && t->p.parent == t) {
  2484. X        printf("tree 0x%x is empty\n",
  2485. X            (int)t);
  2486. X    } else if (ishead(t)) {
  2487. X        printf("Head: 0x%x.  Root = 0x%x\n", (int)t, (int)t->p.root);
  2488. X        rb_print_tree(t->p.root, 0);
  2489. X    } else {
  2490. X        if (isext(t)) {
  2491. X            for (i = 0; i < level; i++)
  2492. X                putchar(' ');
  2493. X            printf("Ext node 0x%x: %c,%c: p=0x%x, k=%s\n", (int)t,
  2494. X                isred(t) ? 'R' : 'B', isleft(t) ? 'l' : 'r',
  2495. X                (int)t->p.parent, t->k.key);
  2496. X        } else {
  2497. X            rb_print_tree(t->c.child.left, level + 2);
  2498. X            rb_print_tree(t->c.child.right, level + 2);
  2499. X            for (i = 0; i < level; i++)
  2500. X                putchar(' ');
  2501. X            printf("Int node 0x%x: %c,%c: l=0x%x, r=0x%x, p=0x%x, lr=(%s,%s)\n",
  2502. X                (int)t, isred(t) ? 'R' : 'B', isleft(t) ? 'l' : 'r',
  2503. X                (int)t->c.child.left, (int)t->c.child.right,
  2504. X                (int)t->p.parent, t->k.lext->k.key,
  2505. X                t->v.rext->k.key);
  2506. X        }
  2507. X    }
  2508. X}
  2509. X
  2510. Xvoid
  2511. Xrb_iprint_tree(t, level)
  2512. X    Rb_node t;
  2513. X    int level;
  2514. X{
  2515. X    int i;
  2516. X
  2517. X    if (ishead(t) && t->p.parent == t) {
  2518. X        printf("tree 0x%x is empty\n", (int)t);
  2519. X    } else if (ishead(t)) {
  2520. X        printf("Head: 0x%x.  Root = 0x%x, < = 0x%x, > = 0x%x\n",
  2521. X            (int)t, (int)t->p.root, (int)t->c.list.blink,
  2522. X            (int)t->c.list.flink);
  2523. X        rb_iprint_tree(t->p.root, 0);
  2524. X    } else {
  2525. X        if (isext(t)) {
  2526. X            for (i = 0; i < level; i++)
  2527. X                putchar(' ');
  2528. X            printf("Ext node 0x%x: %c,%c: p=0x%x, <=0x%x, >=0x%x k=%d\n",
  2529. X                (int)t, isred(t) ? 'R' : 'B', isleft(t) ? 'l' : 'r',
  2530. X                (int)t->p.parent, (int)t->c.list.blink,
  2531. X                (int)t->c.list.flink, t->k.ikey);
  2532. X        } else {
  2533. X            rb_iprint_tree(t->c.child.left, level + 2);
  2534. X            rb_iprint_tree(t->c.child.right, level + 2);
  2535. X            for (i = 0; i < level; i++)
  2536. X                putchar(' ');
  2537. X            printf("Int node 0x%x: %c,%c: l=0x%x, r=0x%x, p=0x%x, lr=(%d,%d)\n",
  2538. X                (int)t, isred(t) ? 'R' : 'B', isleft(t) ? 'l' : 'r',
  2539. X                (int)t->c.child.left, (int)t->c.child.right,
  2540. X                (int)t->p.parent, t->k.lext->k.ikey,
  2541. X                t->v.rext->k.ikey);
  2542. X        }
  2543. X    }
  2544. X}
  2545. X
  2546. Xvoid
  2547. Xrb_uprint_tree(t, level)
  2548. X    Rb_node         t;
  2549. X    int             level;
  2550. X{
  2551. X    int             i;
  2552. X    if (ishead(t) && t->p.parent == t) {
  2553. X        printf("tree 0x%x is empty\n", (int)t);
  2554. X    } else if (ishead(t)) {
  2555. X        printf("Head: 0x%x.  Root = 0x%x, < = 0x%x, > = 0x%x\n",
  2556. X            (int)t, (int)t->p.root, (int)t->c.list.blink,
  2557. X            (int)t->c.list.flink);
  2558. X        rb_uprint_tree(t->p.root, 0);
  2559. X    } else {
  2560. X        if (isext(t)) {
  2561. X            for (i = 0; i < level; i++)
  2562. X                putchar(' ');
  2563. X            printf("Ext node 0x%x: %c,%c: p=0x%x, <=0x%x, >=0x%x k=%lu\n",
  2564. X                (int)t, isred(t) ? 'R' : 'B', isleft(t) ? 'l' : 'r',
  2565. X                (int)t->p.parent, (int)t->c.list.blink,
  2566. X                (int)t->c.list.flink, t->k.ukey);
  2567. X        } else {
  2568. X            rb_uprint_tree(t->c.child.left, level + 2);
  2569. X            rb_uprint_tree(t->c.child.right, level + 2);
  2570. X            for (i = 0; i < level; i++)
  2571. X                putchar(' ');
  2572. X            printf("Int node 0x%x: %c,%c: l=0x%x, r=0x%x, p=0x%x, lr=(%lu,%lu)\n",
  2573. X                (int)t, isred(t) ? 'R' : 'B', isleft(t) ? 'l' : 'r',
  2574. X                (int)t->c.child.left, (int)t->c.child.right,
  2575. X                (int)t->p.parent, t->k.lext->k.ukey,
  2576. X                t->v.rext->k.ukey);
  2577. X        }
  2578. X    }
  2579. X}
  2580. X
  2581. Xint
  2582. Xrb_nblack(n)
  2583. X    Rb_node(n);
  2584. X{
  2585. X    int nb;
  2586. X
  2587. X    if (ishead(n) || isint(n)) {
  2588. X        fprintf(stderr,
  2589. X            "ERROR: rb_nblack called on a non-external node 0x%x\n",
  2590. X            (int)n);
  2591. X        exit(1);
  2592. X    }
  2593. X    nb = 0;
  2594. X    while (!ishead(n)) {
  2595. X        if (isblack(n))
  2596. X            nb++;
  2597. X        n = n->p.parent;
  2598. X    }
  2599. X    return (nb);
  2600. X}
  2601. X
  2602. Xint
  2603. Xrb_plength(n)
  2604. X    Rb_node(n);
  2605. X{
  2606. X    int pl;
  2607. X
  2608. X    if (ishead(n) || isint(n)) {
  2609. X        fprintf(stderr,
  2610. X            "ERROR: rb_plength called on a non-external node 0x%x\n",
  2611. X            (int)n);
  2612. X        exit(1);
  2613. X    }
  2614. X    pl = 0;
  2615. X    while (!ishead(n)) {
  2616. X        pl++;
  2617. X        n = n->p.parent;
  2618. X    }
  2619. X    return (pl);
  2620. X}
  2621. X
  2622. Xvoid
  2623. Xrb_free_tree(n)
  2624. X    Rb_node(n);
  2625. X{
  2626. X
  2627. X    if (!ishead(n)) {
  2628. X        fprintf(stderr,
  2629. X            "ERROR: Rb_free_tree called on a non-head node\n");
  2630. X        exit(1);
  2631. X    }
  2632. X    while (rb_first(n) != nil(n)) {
  2633. X        rb_delete_node(rb_first(n));
  2634. X    }
  2635. X    free(n);
  2636. X}
  2637. X
  2638. Xchar *
  2639. Xrb_val(n)
  2640. X    Rb_node(n);
  2641. X{
  2642. X    return (n->v.val);
  2643. X}
  2644. END_OF_FILE
  2645.   if test 13684 -ne `wc -c <'tclmidi-2.0/rb/rb.c'`; then
  2646.     echo shar: \"'tclmidi-2.0/rb/rb.c'\" unpacked with wrong size!
  2647.   fi
  2648.   # end of 'tclmidi-2.0/rb/rb.c'
  2649. fi
  2650. echo shar: End of archive 3 \(of 14\).
  2651. cp /dev/null ark3isdone
  2652. MISSING=""
  2653. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  2654.     if test ! -f ark${I}isdone ; then
  2655.     MISSING="${MISSING} ${I}"
  2656.     fi
  2657. done
  2658. if test "${MISSING}" = "" ; then
  2659.     echo You have unpacked all 14 archives.
  2660.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2661. else
  2662.     echo You still must unpack the following archives:
  2663.     echo "        " ${MISSING}
  2664. fi
  2665. exit 0
  2666. exit 0 # Just in case...
  2667.