home *** CD-ROM | disk | FTP | other *** search
| Text File | 1993-01-12 | 27.6 KB | 1,025 lines |
- Newsgroups: comp.lang.tcl
- Path: sparky!uunet!paladin.american.edu!howland.reston.ans.net!zaphod.mps.ohio-state.edu!magnus.acs.ohio-state.edu!usenet.ins.cwru.edu!agate!boulder!csn!cherokee!durian
- From: durian@advtech.uswest.com (Mike Durian)
- Subject: tclm0.1 - tcl with MIDI extensions (7/7)
- Message-ID: <1993Jan12.203139.20129@advtech.uswest.com>
- Sender: news@advtech.uswest.com (Radio Free Boulder)
- Nntp-Posting-Host: mongo.advtech.uswest.com
- Organization: U S WEST Advanced Technologies
- Date: Tue, 12 Jan 1993 20:31:39 GMT
- Lines: 1013
-
- # This is a shell archive. Save it in a file, remove anything before
- # this line, and then unpack it by entering "sh file". Note, it may
- # create directories; files and directories will be owned by you and
- # have default permissions.
- #
- # This archive contains:
- #
- # tclm0.1/minfo
- # tclm0.1/mlib/mplayutil.c
- #
- echo x - tclm0.1/minfo
- sed 's/^X//' >tclm0.1/minfo << 'END-of-tclm0.1/minfo'
- X#!/usr/local/bin/tclm -f
- X#
- X# Copyright (c) 1993 Michael B. Durian. All rights reserved.
- X#
- X# Redistribution and use in source and binary forms, with or without
- X# modification, are permitted provided that the following conditions
- X# are met:
- X# 1. Redistributions of source code must retain the above copyright
- X# notice, this list of conditions and the following disclaimer.
- X# 2. Redistributions in binary form must reproduce the above copyright
- X# notice, this list of conditions and the following disclaimer in the
- X# documentation and/or other materials provided with the distribution.
- X# 3. All advertising materials mentioning features or use of this software
- X# must display the following acknowledgement:
- X# This product includes software developed by Michael B. Durian.
- X# 4. The name of the the Author may be used to endorse or promote
- X# products derived from this software without specific prior written
- X# permission.
- X#
- X# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- X# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- X# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- X# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- X# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- X# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- X# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- X# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- X# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- X# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- X# SUCH DAMAGE.
- X#
- X
- X# get filename arg
- Xif {[string compare [lindex $argv 0] "-f"] == 0} {
- X set midi_file_name [lindex $argv 2]
- X} else {
- X set midi_file_name [lindex $argv 0]
- X}
- X
- X# info on the different types of events
- Xset NORMAL 0xff
- Xset SYSEX 0xf0
- Xset EVENT(NORMAL) 0xff
- Xset EVENT(SYSEX) 0xf0
- Xset EVENT(METASEQNUM) 0x00
- Xset EVENT(METATEXT) 0x01
- Xset EVENT(METACPY) 0x02
- Xset EVENT(METASEQNAME) 0x03
- Xset EVENT(METAINSTNAME) 0x04
- Xset EVENT(METALYRIC) 0x05
- Xset EVENT(METAMARKER) 0x06
- Xset EVENT(METACUE) 0x07
- Xset EVENT(METACHANPREFIX) 0x20
- Xset EVENT(METAEOT) 0x2f
- Xset EVENT(METATEMPO) 0x51
- Xset EVENT(METASMPTE) 0x54
- Xset EVENT(METATIME) 0x58
- Xset EVENT(METAKEY) 0x59
- Xset EVENT(METASEQSPEC) 0x7f
- X
- X# clear running state
- Xset rstate 0
- X
- X# the different keys
- Xset key {"C flat" "G flat" "D flat" "A flat" "E flat" "B flat" "F" "C" "G" \
- X "D" "A" "E" "B" "F sharp" "C sharp"}
- Xset key_class {"major" "minor"}
- X
- X#
- X# takes bytes that are in the ascii range and makes a string out of them
- X#
- Xproc make_string {bytes} {
- X
- X foreach byte $bytes {
- X set char [format "%c" $byte]
- X append str $char
- X }
- X return $str
- X}
- X
- X#
- X# etype identifies an event a formats it so it is human readable
- X#
- Xproc etype {event} {
- X global EVENT
- X global rstate
- X
- X # look at the first byte
- X set identifier [lindex $event 0]
- X # if it has the high bit set then it is a new running state
- X # otherwise it uses the previous running state.
- X # if the later is the case we prepend the last running state
- X # so the event looks whole
- X if {[expr {$identifier & 0x80}]} {
- X set rstate $identifier
- X } else {
- X set event [linsert $event 0 $rstate]
- X set identifier $rstate
- X }
- X case $identifier in \
- X 0xff {
- X # meta events
- X set meta_type [lindex $event 1]
- X case $meta_type in \
- X $EVENT(METATEXT) {
- X set str [make_string [lrange $event 3 end]]
- X return "METATEXT $str"
- X } $EVENT(METASEQNUM) {
- X set seq_num [expr {[expr {[lindex $event 4] << 8]} + \
- X [lindex $event 5]}]
- X return "METASEQNUM $seq_num"
- X } $EVENT(METACPY) {
- X set str [make_string [lrange $event 3 end]]
- X return "METACPY $str"
- X } $EVENT(METASEQNAME) {
- X set str [make_string [lrange $event 3 end]]
- X return "METASEQNAME $str"
- X } $EVENT(METAINSTNAME) {
- X set str [make_string [lrange $event 3 end]]
- X return "METAINSTNAME $str"
- X } $EVENT(METALYRIC) {
- X set str [make_string [lrange $event 3 end]]
- X return "METALYRIC $str"
- X } $EVENT(METAMARKER) {
- X set str [make_string [lrange $event 3 end]]
- X return "METAMARKER $str"
- X } $EVENT(METACUE) {
- X set str [make_string [lrange $event 3 end]]
- X return "METACUE $str"
- X } $EVENT(METACHANPREFIX) {
- X return "METACHANPREFIX [lrange $event 3 end]"
- X } $EVENT(METAEOT) {
- X return "METAEOT"
- X } $EVENT(METATEMPO) {
- X set e3 [lindex $event 3]
- X set se3 [expr {$e3 * 0x010000}]
- X set e4 [lindex $event 4]
- X set se4 [expr {$e4 * 0x0100}]
- X set e5 [lindex $event 5]
- X set usec [expr {$se3 + $se4 + $e5}]
- X set bpm [expr {60000000 / $usec}]
- X return "METATEMPO $usec usec/beat $bpm beats/min"
- X } $EVENT(METASMPTE) {
- X set hr [format "%d" [lindex $event 3]]
- X set min [format "%d" [lindex $event 4]]
- X set sec [format "%d" [lindex $event 5]]
- X set fr [format "%d" [lindex $event 6]]
- X set ffr [format "%d" [lindex $event 7]]
- X return [concat "METASMPTE Hour $hr, Min. $min, " \
- X "Sec. $sec, Frame $fr, Frac. Frame $ffr"]
- X } $EVENT(METATIME) {
- X set num [lindex $event 3]
- X set dnum [format "%d" $num]
- X set denom [lindex $event 4]
- X set den 1
- X for {set i 0} {$i < $denom} {incr i} {
- X set den [expr {$den * 2}]
- X }
- X set cpmb [lindex $event 5]
- X set dcpmb [format "%d" $cpmb]
- X set _32 [lindex $event 6]
- X set d_32 [format "%d" $_32]
- X return [concat "METATIME $dnum/$den, $dcpmb clocks " \
- X "/ met. beat, $d_32 32nd notes " \
- X "/ 1/4 note"]
- X } $EVENT(METAKEY) {
- X global key
- X global key_class
- X set ind [expr {[lindex $event 3] + 7}]
- X set keyname [lindex $key $ind]
- X set class [lindex $key_class [lindex $event 4]]
- X return "METAKEY $keyname $class"
- X } default {
- X return "UNKNOWN META"
- X }
- X } 0xf0 {
- X # system exclusive event
- X return "SYSEX"
- X } 0x8? {
- X # note off event
- X set chan [expr {$identifier - 0x80}]
- X set pitch [lindex $event 1]
- X set vel [lindex $event 2]
- X return "NOTEOFF channel $chan pitch $pitch velocity $vel"
- X } 0x9? {
- X # note on event
- X set chan [expr {$identifier - 0x90}]
- X set pitch [lindex $event 1]
- X set vel [lindex $event 2]
- X return "NOTEON channel $chan pitch $pitch velocity $vel"
- X } 0xa? {
- X # key pressure event
- X set chan [expr {$identifier - 0xa0}]
- X set pitch [lindex $event 1]
- X set pres [lindex $event 2]
- X return "KEY PRESSURE channel $chan pitch $pitch pressure $pres"
- X } 0xb? {
- X # parameter event
- X set chan [expr {$identifier - 0xb0}]
- X set param [lindex $event 1]
- X set setting [lindex $event 2]
- X return [concat "PARAMETER channel $chan parameter $param " \
- X "setting $setting"]
- X } 0xc? {
- X # program change event
- X set chan [expr {$identifier - 0xc0}]
- X set prog [lindex $event 1]
- X return "PROGRAM channel $chan program $prog"
- X } 0xd? {
- X # channel pressure event
- X set chan [expr {$identifier - 0xd0}]
- X set pres [lindex $event 1]
- X return "CHANNEL PRESSURE channel $chan pressure $pres"
- X } 0xe? {
- X # pitch wheel event
- X set chan [expr {$identifier - 0xe0}]
- X set lo7 [lindex $event 1]
- X set hi7 [lindex $event 2]
- X set wheel [expr {[expr {$lo7 & 0x7f}] | \
- X [expr {[expr {$hi7 << 7}] & 0x3f80}]}]
- X return "PITCH WHEEL channel $chan val $wheel"
- X } default {
- X # anything that fell through the cracks
- X return "DEFAULT $identifier"
- X }
- X}
- X
- Xif {[string length $midi_file_name] == 0} {
- X # if no filename is specified use stdin
- X set midi_file stdin
- X set midi_file_name stdin
- X} else {
- X # check to see if the specified file exists and open it
- X if {![file exists $midi_file_name]} then {
- X puts stderr "Bad file name: $midi_file_name"
- X exit 1
- X } else {
- X set midi_file [open $midi_file_name]
- X }
- X}
- X
- X# read the midi file
- X# print out error if there is one
- Xif {[catch {midiread $midi_file} mfile]} {
- X puts stderr $mfile
- X exit 1
- X}
- Xputs stdout [format "%-16s = %s" "file name" $midi_file_name]
- Xputs stdout [format "%-16s = %s" "format" [midiconfig $mfile format]]
- Xputs stdout [format "%-16s = %s" "division" [midiconfig $mfile division]]
- Xset num_trks [midiconfig $mfile tracks]
- Xputs stdout [format "%-16s = %s" "number of tracks" $num_trks]
- X
- X# print out all the tracks
- Xfor {set track 0} {$track < $num_trks} {incr track} {
- X puts stdout "\nTrack $track"
- X set pos 0
- X while {1} {
- X # get an event
- X set event [midiget $mfile $track]
- X # get the timing part of the event
- X set timing [miditiming $event]
- X # convert timing to fixed length notation
- X set fix [midivartofix $timing]
- X # determine offset from start of track
- X set pos [expr {$fix + $pos}]
- X # get part of event that is not timing
- X set rest [lrange $event [llength $timing] end]
- X # determine the event type
- X set event_type [etype $rest]
- X # print it out
- X set out [format "%6d: %s" $pos $event_type]
- X puts stdout $out
- X # break if it is the end of the file
- X if {[string compare $event_type METAEOT] == 0} break
- X }
- X}
- END-of-tclm0.1/minfo
- echo x - tclm0.1/mlib/mplayutil.c
- sed 's/^X//' >tclm0.1/mlib/mplayutil.c << 'END-of-tclm0.1/mlib/mplayutil.c'
- X/* mplayutil.c,v 1.3 1993/01/12 19:23:42 durian Exp */
- X/*
- X * Copyright (c) 1993 Michael B. Durian. All rights reserved.
- X *
- X * Redistribution and use in source and binary forms, with or without
- X * modification, are permitted provided that the following conditions
- X * are met:
- X * 1. Redistributions of source code must retain the above copyright
- X * notice, this list of conditions and the following disclaimer.
- X * 2. Redistributions in binary form must reproduce the above copyright
- X * notice, this list of conditions and the following disclaimer in the
- X * documentation and/or other materials provided with the distribution.
- X * 3. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by Michael B. Durian.
- X * 4. The name of the the Author may be used to endorse or promote
- X * products derived from this software without specific prior written
- X * permission.
- X *
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- X * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- X * SUCH DAMAGE.
- X */
- X#ifdef MPU
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <unistd.h>
- X#include <sys/file.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <sys/ioctl.h>
- X#include <i386/isa/midiioctl.h>
- X#include "mutil.h"
- X#include "mpu401.h"
- X#include "mplayutil.h"
- X
- X#define MAX_TRACKS 8
- X
- X/* global */
- Xdouble TempoRatio = 1.0; /* this changes when clocks_per_met change */
- Xint StopRecording;
- Xint Verbose;
- Xint Tempo = 120;
- Xchar Key[15][10] = {"C flat", "G flat", "D flat", "A flat", "E flat",
- X "B flat", "F", "C", "G", "D", "A", "E", "B", "F sharp", "C sharp"};
- X
- Xint
- Xplay_tracks(tracks, devs, num, t_scalar, repeat)
- X TCHUNK *tracks;
- X int *devs;
- X int num;
- X int t_scalar;
- X int repeat;
- X{
- X
- X return (record_tracks(tracks, devs, num, NULL, -1, t_scalar, repeat));
- X}
- X
- Xint
- Xrecord_tracks(p_tracks, p_devs, p_num, r_track, r_dev, t_scalar, repeat)
- X TCHUNK *p_tracks;
- X int *p_devs;
- X int p_num;
- X TCHUNK *r_track;
- X int r_dev;
- X int t_scalar;
- X int repeat;
- X{
- X struct timeval mwait;
- X fd_set w_select;
- X fd_set r_select;
- X int click_fraction[16];
- X int i;
- X#ifdef MIDI_DEBUG
- X int j;
- X#endif
- X int num_active;
- X int select_return;
- X int something_open;
- X int *track_active;
- X
- X num_active = p_num;
- X if (p_num) {
- X if ((track_active = (int *) malloc(sizeof(int) * p_num))
- X == NULL)
- X return (0);
- X for (i = 0; i < p_num; i++)
- X track_active[i] = 1;
- X }
- X
- X for (i = 0; i < 16; i++)
- X click_fraction[i] = 0;
- X something_open = 1;
- X StopRecording = 0;
- X do {
- X while (something_open && !StopRecording) {
- X /* select on open play tracks */
- X FD_ZERO(&w_select);
- X for (i = 0; i < p_num; i++)
- X if (track_active[i])
- X FD_SET(p_devs[i], &w_select);
- X FD_ZERO(&r_select);
- X if (r_dev != -1)
- X FD_SET(r_dev, &r_select);
- X mwait.tv_sec = 0;
- X mwait.tv_usec = 100000;
- X if ((select_return = select(getdtablesize(), &r_select,
- X &w_select, NULL, &mwait)) == -1) {
- X if (errno == EINTR)
- X break;
- X else {
- X sprintf(MidiError,
- X "Error in select: %s",
- X sys_errlist[errno]);
- X return (0);
- X }
- X }
- X if (select_return == 0)
- X continue;
- X
- X /* write event to non-blocked one */
- X for (i = 0; i < p_num && !StopRecording; i++) {
- X if (!track_active[i] || !FD_ISSET(p_devs[i],
- X &w_select))
- X continue;
- X
- X something_open = process_play_event(i,
- X &p_tracks[i], p_devs[i], &track_active[i],
- X &num_active, t_scalar);
- X if (!track_active[i] && repeat) {
- X rewind_track(&p_tracks[i]);
- X track_active[i] = 1;
- X num_active++;
- X something_open = 1;
- X }
- X }
- X if (r_dev != -1 && FD_ISSET(r_dev, &r_select)) {
- X
- X if (!process_record_event(r_dev, r_track))
- X return (0);
- X }
- X }
- X } while (repeat && !StopRecording);
- X
- X if (!StopRecording) {
- X for (i = 0; i < p_num; i++)
- X if (ioctl(p_devs[i], MFLUSHQ, NULL) == -1) {
- X sprintf(MidiError,
- X "Error flushing queue for track %d", i);
- X }
- X } else {
- X /* flush any delays stuck in board2smf */
- X/*
- X flush_event(r_track);
- X*/
- X }
- X if (p_num)
- X free(track_active);
- X return (1);
- X}
- X
- Xint
- Xprocess_play_event(track_num, p_track, p_dev, track_active, num_active,
- X t_scalar)
- X int track_num;
- X TCHUNK *p_track;
- X int p_dev;
- X int *track_active;
- X int *num_active;
- X int t_scalar;
- X{
- X EVENT_TYPE event_type;
- X static int need_event[16] =
- X {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
- X int event_size;
- X#ifdef MIDI_DEBUG
- X int j;
- X#endif
- X int smf_size;
- X int something_open;
- X int valid_event;
- X unsigned char smf_event[2048];
- X unsigned char event[2048];
- X
- X something_open = 1;
- X valid_event = 0;
- X do {
- X if (!need_event[track_num])
- X event_size = smf2board(track_num, NULL, smf_size,
- X event, t_scalar, &need_event[track_num],
- X &event_type);
- X else {
- X smf_size = get_smf_event(p_track, smf_event,
- X &event_type);
- X if (smf_size == -1) {
- X sprintf(MidiError, "Error reading event");
- X return (0);
- X } else if (smf_size == 0) {
- X *track_active = 0;
- X valid_event = 1;
- X if (--(*num_active) == 0)
- X something_open = 0;
- X break;
- X }
- X event_size = smf2board(track_num, smf_event, smf_size,
- X event, t_scalar, &need_event[track_num],
- X &event_type);
- X }
- X
- X#ifdef MIDI_DEBUG
- X printf("track %d: ", track_num);
- X for (j = 0; j < event_size; j++)
- X printf("0x%02x ", event[j]);
- X printf("\n");
- X fflush(stdout);
- X#endif
- X switch(send_event(p_dev, event, event_size,
- X event_type, track_num == 0)) {
- X case SEND_ERROR:
- X return (0);
- X case SEND_VALID:
- X valid_event = 1;
- X break;
- X case SEND_INVALID:
- X valid_event = 0;
- X break;
- X case SEND_DONE:
- X *track_active = 0;
- X valid_event = 1;
- X if (--(*num_active) == 0)
- X something_open = 0;
- X break;
- X }
- X } while (!valid_event && !StopRecording);
- X return(something_open);
- X}
- X
- Xint
- Xprocess_record_event(dev, r_track)
- X int dev;
- X TCHUNK *r_track;
- X{
- X int event_size;
- X int events_delta;
- X int events_pos;
- X int events_size;
- X#ifdef MIDI_DEBUG
- X int i;
- X#endif
- X int smf_size;
- X unsigned char events[256];
- X unsigned char event_data[256];
- X unsigned char smf_event[256];
- X unsigned char *events_ptr;
- X
- X if ((events_size = read(dev, events, 256)) == -1) {
- X perror("");
- X sprintf(MidiError, "Couldn't read from MIDI board");
- X return (0);
- X }
- X#ifdef MIDI_DEBUG
- X printf("\n");
- X printf("board:");
- X for (i = 0; i < events_size; i++)
- X printf(" 0x%02x", events[i]);
- X printf("\n");
- X#endif
- X events_ptr = events;
- X events_pos = 0;
- X do {
- X if((events_delta = get_board_event(events_ptr, events_size,
- X event_data, &event_size)) == -1) {
- X sprintf(MidiError, "Couldn't get board event "
- X "from stream");
- X return (0);
- X }
- X events_ptr += events_delta;
- X events_pos += events_delta;
- X#ifdef MIDI_DEBUG
- X printf("single event:");
- X for (i = 0; i < event_size; i++)
- X printf(" 0x%02x", event_data[i]);
- X printf("\n");
- X#endif
- X
- X board2smf(event_data, event_size, smf_event, &smf_size);
- X#ifdef MIDI_DEBUG
- X printf("smf:");
- X for (i = 0; i < smf_size; i++)
- X printf(" 0x%02x", smf_event[i]);
- X printf("\n");
- X#endif
- X if (smf_size > 0)
- X if (!put_smf_event(r_track, smf_event, smf_size)) {
- X sprintf(MidiError, "Couldn't put event "
- X "in record track");
- X return (0);
- X }
- X } while (events_pos < events_size);
- X return(1);
- X}
- X
- Xvoid
- Xflush_event(r_track)
- X TCHUNK *r_track;
- X{
- X int smf_size;
- X unsigned char flush_event[] = {0x00, 0xf8};
- X unsigned char smf_event[256];
- X
- X board2smf(flush_event, sizeof(flush_event), smf_event, &smf_size);
- X
- X if (!put_smf_event(r_track, smf_event, smf_size)) {
- X sprintf(MidiError, "Couldn't put flush event");
- X }
- X}
- X
- Xvoid
- Xstop_recording()
- X{
- X StopRecording = 1;
- X}
- X
- X
- XSEND_VAL
- Xsend_event(dev, event, event_size, event_type, conductor)
- X int dev;
- X unsigned char *event;
- X int event_size;
- X EVENT_TYPE event_type;
- X int conductor;
- X{
- X SEND_VAL return_val;
- X static int clocks_per_beat = 24;
- X int num_written;
- X short seq_num;
- X unsigned char time_event[10];
- X
- X switch (event_type) {
- X case NORMAL:
- X if ((num_written = write(dev, event, event_size)) == -1) {
- X sprintf(MidiError, "Couldn't write to MIDI board: %s",
- X sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X break;
- X case METASEQNUM:
- X seq_num = event[4] << 8 + event[5];
- X if (Verbose)
- X printf("Sequence number %d\n", seq_num);
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METATEXT:
- X event[event_size] = '\0';
- X if (Verbose)
- X printf("METATEXT: %s\n", &event[4]);
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METACPY:
- X event[event_size] = '\0';
- X if (Verbose)
- X printf("METACPY: %s\n", &event[4]);
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METASEQNAME:
- X event[event_size] = '\0';
- X if (Verbose)
- X printf("METASEQNAME: %s\n", &event[4]);
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METAINSTNAME:
- X event[event_size] = '\0';
- X if (Verbose)
- X printf("METAINSTNAME: %s\n", &event[4]);
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METALYRIC:
- X event[event_size] = '\0';
- X if (Verbose)
- X printf("METALYRIC: %s\n", &event[4]);
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METAMARKER:
- X event[event_size] = '\0';
- X if (Verbose)
- X printf("METAMARKER: %s\n", &event[4]);
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METACUE:
- X event[event_size] = '\0';
- X if (Verbose)
- X printf("METACUE: %s\n", &event[4]);
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METACHANPREFIX:
- X /* I have no data on how this is formatted */
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METAEOT:
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board:", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_DONE;
- X break;
- X case METATEMPO:
- X /* only do this for the conductor track - pos 0 */
- X if (conductor) {
- X /* just the byte meaningful to the board */
- X event[1] = (unsigned char) (MSETBASETMP & 0xff);
- X /* convert usec / beat to beats / min */
- X event[2] = TempoRatio * (60 * 1000000) /
- X (event[4] * 0x010000 + event[5] * 0x0100 +
- X event[6]);
- X Tempo = event[2];
- X if (Verbose)
- X printf("METATEMPO: Beats Per Minute: %d\n",
- X event[2]);
- X if (write(dev, event, 3) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X } else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METASMPTE:
- X /* Not sure on this one */
- X if (Verbose) {
- X printf("METASMPTE: Hour %d Minute %d Second %d "
- X "Frame %d Fractional Frame %d\n",
- X event[4], event[5], event[6], event[7],
- X event[8]);
- X }
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METATIME:
- X if (conductor) {
- X if (Verbose)
- X printf("METATIME: %d / %d "
- X "Clocks per met beat = %d\n",
- X event[4], event[5], event[6]);
- X time_event[0] = event[0];
- X time_event[1] = (unsigned char) (MSETBPM & 0xff);
- X /* bpm = numerator of time sig */
- X time_event[2] = event[4];
- X /* no time delay */
- X time_event[3] = 0;
- X time_event[4] = (unsigned char) (MSETMETFRQ & 0xff);
- X /* met freq = byte seven in time sig */
- X time_event[5] = event[6];
- X /*
- X * if the clocks per met changes we should adjust
- X * the tempo accordingly - at least until I figure
- X * out a better way of doing this.
- X */
- X /* new clock_per_bear over old */
- X TempoRatio = (double)event[6] / clocks_per_beat;
- X Tempo = Tempo * TempoRatio;
- X time_event[6] = 0;
- X time_event[7] = (unsigned char) (MSETBASETMP & 0xff);
- X time_event[8] = Tempo;
- X if (write(dev, time_event, 9) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X clocks_per_beat = event[6];
- X return_val = SEND_VALID;
- X } else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X case METAKEY:
- X if (Verbose)
- X printf("METAKEY: %s %s\n", Key[(signed char)event[4]
- X + 7], event[5] ? "minor" : "major");
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X default:
- X if (event[0] == 0)
- X return_val = SEND_INVALID;
- X else {
- X event[1] = MIDI_NOOP;
- X if (write(dev, event, 2) == -1) {
- X sprintf(MidiError, "Couldn't write to "
- X "MIDI board: %s", sys_errlist[errno]);
- X return_val = SEND_ERROR;
- X break;
- X }
- X return_val = SEND_VALID;
- X }
- X break;
- X }
- X
- X return (return_val);
- X}
- X
- Xint
- Xopen_midi_devices(hchunk, spec_tracks, num, devs, active_mask)
- X HCHUNK *hchunk;
- X TRKS *spec_tracks;
- X int *num;
- X int *devs;
- X unsigned char *active_mask;
- X{
- X int cond_on;
- X int dev_counter;
- X int i;
- X int j;
- X char dev_name[100];
- X
- X cond_on = 0;
- X j = 0;
- X if (hchunk->format == 0) {
- X if ((devs[j++] = open("/dev/midicond", O_WRONLY | O_NONBLOCK,
- X 0)) == -1) {
- X sprintf(MidiError, "Coudln't open conductor track: %s",
- X sys_errlist[errno]);
- X return (-1);
- X }
- X cond_on = 1;
- X }
- X
- X for (i = 0; i < spec_tracks->num_tracks && !cond_on; i++)
- X if (spec_tracks->tracks[i] == 0) {
- X if ((devs[j++] = open("/dev/midicond", O_WRONLY |
- X O_NONBLOCK, 0)) == -1) {
- X sprintf(MidiError,
- X "Coudln't open conductor track: %s",
- X sys_errlist[errno]);
- X return (-1);
- X }
- X cond_on = 1;
- X }
- X
- X dev_counter = 0;
- X *active_mask = 0;
- X for (i = j; i < *num; i++) {
- X if (dev_counter == MAX_TRACKS) {
- X sprintf(MidiError, "Too many play tracks (%d). "
- X "Only using first %d", *num - cond_on, MAX_TRACKS);
- X *num = MAX_TRACKS + cond_on;
- X break;
- X }
- X
- X sprintf(dev_name, "/dev/midi%d", dev_counter);
- X if ((devs[j++] = open(dev_name, O_WRONLY | O_NONBLOCK, 0))
- X == -1) {
- X sprintf(MidiError, "Coudln't open midi track %d: %s",
- X dev_counter, sys_errlist[errno]);
- X return (-1);
- X }
- X *active_mask |= (unsigned char)(1 << dev_counter++);
- X }
- X
- X return (cond_on);
- X}
- X
- Xvoid
- Xset_midi_verbose(v)
- X int v;
- X{
- X Verbose = v;
- X}
- X#endif
- END-of-tclm0.1/mlib/mplayutil.c
- exit
-
-