diff options
Diffstat (limited to 'tutorials/sndkit/ossmplay/ossmplay.c')
-rw-r--r-- | tutorials/sndkit/ossmplay/ossmplay.c | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/tutorials/sndkit/ossmplay/ossmplay.c b/tutorials/sndkit/ossmplay/ossmplay.c new file mode 100644 index 0000000..0325922 --- /dev/null +++ b/tutorials/sndkit/ossmplay/ossmplay.c @@ -0,0 +1,233 @@ +#define DEB(stmt) /* stmt */ /* For debug printing */ +#define DEB2(stmt) /* stmt */ /* For debug printing */ +#define DEB3(stmt) stmt /* For debug printing */ +#define DEB_ALWAYS(stmt) stmt /* Interesting things */ + +#define _INCLUDE_POSIX_SOURCE 1 +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <sys/errno.h> +#include "../../../include/soundcard.h" + +extern int errno; + +#include "mlib.h" + +SEQ_DEFINEBUF (1024); + +int seqfd; +mlib_track *tracks[1024]; +int ntrks = 0; +int dev = 0; + +void +player () +{ + int i, track; + int prev_time = 0; + + int ptrs[1024] = { 0 }; + unsigned char *ptr; + unsigned char *event; + int time, n = 0; + +#if 0 + for (track = 0; track < ntrks; track++) + for (i = 0; i < 128; i++) + { + if (tracks[track]->pgm_map[i] != -1) + { + n++; + SEQ_LOAD_GMINSTR (dev, i); + } + tracks[track]->pgm_map[i] = i; + + if (n == 0) /* No program changes. Assume pgm# 0 */ + SEQ_LOAD_GMINSTR (dev, 0); + + if (tracks[track]->drum_map[i] != -1) + SEQ_LOAD_GMDRUM (dev, i); + tracks[track]->drum_map[i] = i; + } + + if (n == 0) /* No program changes detected */ + SEQ_LOAD_GMINSTR (dev, 0); /* Acoustic piano */ + +#endif + + SEQ_START_TIMER (); + while (1) + { + int best = -1, best_time = 0x7fffffff; + + for (i = 0; i < ntrks; i++) + if (ptrs[i] < tracks[i]->len) + { + ptr = &(tracks[i]->events[ptrs[i] * 12]); + event = &ptr[4]; + time = *(int *) ptr; + + if (time < best_time) + { + best = i; + best_time = time; + } + } + + if (best == -1) + return; + + ptr = &(tracks[best]->events[ptrs[best] * 12]); + event = &ptr[4]; + time = *(int *) ptr; + ptrs[best]++; + + if (event[0] < 128) + { + } + else + { + int j; + + if (time > prev_time) + { + SEQ_WAIT_TIME (time); + prev_time = time; + } + + if (event[0] == EV_SYSEX) + { + event[1] = dev; + } + + if ((event[0] & 0xf0) == 0x90) + { + event[1] = dev; + + if (event[0] == EV_CHN_COMMON && event[2] == MIDI_PGM_CHANGE) + { + event[4] = tracks[best]->pgm_map[event[4]]; + } + } + + _SEQ_NEEDBUF (8); + memcpy (&_seqbuf[_seqbufptr], event, 8); + _SEQ_ADVBUF (8); + + } + } +} + +int +main (int argc, char *argv[]) +{ + mlib_desc *mdesc; + int was_last; + int tmp, argp = 1; + oss_longname_t song_name; + char *p, *s, *devname="/dev/midi00";; + extern void OSS_set_timebase(int tb); + + if (argc < 2) + { + fprintf (stderr, "Usage: %s midifile\n", argv[0]); + exit (-1); + } + + if (argc==3) + { + devname=argv[1]; + argp++; + } + + + if ((seqfd = open (devname, O_WRONLY, 0)) == -1) + { + perror (devname); + exit (-1); + } + dev=0; + +#ifdef OSSLIB + OSS_init (seqfd, 1024); +#endif + + if ((mdesc = mlib_open (argv[argp])) == NULL) + { + fprintf (stderr, "Can't open MIDI file %s: %s\n", + argv[argp], mlib_errmsg ()); + exit (-1); + } + ioctl(seqfd, SNDCTL_SETSONG, argv[argp]); + +/* + * Extract the file name part of the argument + */ + + p=s=argv[argp]; + while (*s) + { + if (*s=='/') + p=s+1; + s++; + } + + memset(song_name, 0, sizeof(song_name)); + strcpy(song_name, p); + +#if 1 + tmp=MIDI_MODE_TIMED; + if (ioctl(seqfd, SNDCTL_MIDI_SETMODE, &tmp)==-1) + { + perror("SNDCTL_MIDI_SETMODE"); + exit(-1); + } +#endif + + tmp = mdesc->hdr.division; +printf("Timebase %d\n", tmp); + OSS_set_timebase(tmp); + if (ioctl(seqfd, SNDCTL_MIDI_TIMEBASE, &tmp)==-1) + { + perror("SNDCTL_MIDI_TIMEBASE"); + exit(-1); + } + + ntrks = 0; + + while ((tracks[ntrks] = mlib_loadtrack (mdesc, &was_last)) != NULL) + { + int i; + + DEB2 (printf ("Loaded track %03d: len = %d events, flags = %08x\n", + mdesc->curr_trk, tracks[ntrks]->len, + tracks[ntrks]->flags)); + ntrks++; + } + + if (!was_last) + { + fprintf (stderr, "%s: %s\n", argv[argp], mlib_errmsg ()); + exit (-1); + } + + tmp = (int) mdesc->timesig; + printf("Timesig %08x\n", tmp); + +/* + * Set the current song name (OSS 4.0 feature). + */ + ioctl(seqfd, SNDCTL_SETSONG, song_name); + player (); + SEQ_DELTA_TIME (mdesc->hdr.division * 8); + SEQ_PGM_CHANGE(0, 0, 0); + SEQ_DUMPBUF (); + + mlib_close (mdesc); + close (seqfd); + exit (0); +} |