0x36,
0x37,
};
+
+extern int verbose;
+
+
+// Parse and dispatch input MIDI events.
+void Cus428Midi::ProcessMidiEvents()
+{
+ snd_seq_event_t *ev;
+ unsigned char *data;
+
+ do {
+ ev = NULL;
+ snd_seq_event_input(Seq, &ev);
+ if (ev == NULL)
+ break;
+ switch (ev->type) {
+ case SND_SEQ_EVENT_SYSEX:
+ data = (unsigned char *) ev->data.ext.ptr;
+ if (data[1] == 0x7f && data[3] == 0x06) {
+ // MMC Command code is in data[4]...
+ if (verbose > 1)
+ fprintf(stderr, "MMC Command 0x%02x: ", data[4]);
+ switch (data[4]) {
+ case MMC_CMD_STOP:
+ if (verbose > 1)
+ fprintf(stderr, "STOP.\n");
+ OneState->TransportSet(T_STOP, true);
+ break;
+ case MMC_CMD_PLAY:
+ case MMC_CMD_DEFERRED_PLAY:
+ if (verbose > 1)
+ fprintf(stderr, "PLAY.\n");
+ OneState->TransportSet(T_PLAY, true);
+ break;
+ case MMC_CMD_FAST_FORWARD:
+ if (verbose > 1)
+ fprintf(stderr, "FFWD.\n");
+ OneState->TransportSet(T_F_FWD, true);
+ break;
+ case MMC_CMD_REWIND:
+ if (verbose > 1)
+ fprintf(stderr, "REW.\n");
+ OneState->TransportSet(T_REW, true);
+ break;
+ case MMC_CMD_RECORD_STROBE:
+ case MMC_CMD_RECORD_PAUSE:
+ if (verbose > 1)
+ fprintf(stderr, "RECORD ON.\n");
+ OneState->TransportSet(T_RECORD, true);
+ break;
+ case MMC_CMD_RECORD_EXIT:
+ if (verbose > 1)
+ fprintf(stderr, "RECORD OFF.\n");
+ OneState->TransportSet(T_RECORD, false);
+ break;
+ case MMC_CMD_LOCATE:
+ if (verbose > 1)
+ fprintf(stderr, "LOCATE WHEEL.\n");
+ OneState->LocateWheel(&data[7]);
+ break;
+ case MMC_CMD_MMC_RESET:
+ if (verbose > 1)
+ fprintf(stderr, "MMC RESET.\n");
+ OneState->MmcReset();
+ break;
+ default:
+ if (verbose > 1)
+ fprintf(stderr, "Not implemented.\n");
+ break;
+ }
+ } // Look for Tascam US-224/US-428(?) specific LED codes.
+ else if (data[1] == 0x4e && data[3] == 0x12) {
+ if (verbose > 1)
+ fprintf(stderr, "TASCAM Command 0x%02x.\n", data[4]);
+ // Transport LEDs.
+ switch (data[4]) {
+ case 0x01: // Transport LEDs...
+ switch(data[5]) {
+ case 0x13: // REWIND.
+ OneState->LightSet(Cus428State::eL_Rew, data[6]);
+ OneState->LightSend();
+ break;
+ case 0x14: // FFWD.
+ OneState->LightSet(Cus428State::eL_FFwd, data[6]);
+ OneState->LightSend();
+ break;
+ case 0x16: // PLAY.
+ OneState->LightSet(Cus428State::eL_Play, data[6]);
+ OneState->LightSend();
+ break;
+ case 0x17: // REC.
+ OneState->LightSet(Cus428State::eL_Record, data[6]);
+ OneState->LightSend();
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x02: // Mute LEDs
+ OneState->LightSet(Cus428State::eL_Mute0 + data[5], data[6]);
+ OneState->LightSend();
+ break;
+ case 0x03: // Select LEDs
+ OneState->LightSet(Cus428State::eL_Select0 + data[5], data[6]);
+ OneState->LightSend();
+ break;
+ case 0x04: // Record LEDs
+ OneState->LightSet(Cus428State::eL_Rec0 + data[5], data[6]);
+ OneState->LightSend();
+ break;
+ case 0x05: // Null LED
+ OneState->LightSet(Cus428State::eL_Null, data[5]);
+ OneState->LightSend();
+ break;
+ case 0x06: // Solo LED
+ OneState->LightSet(Cus428State::eL_Solo, data[5]);
+ OneState->LightSend();
+ break;
+ case 0x07: // Bank L LED
+ OneState->LightSet(Cus428State::eL_BankL, data[5]);
+ OneState->LightSend();
+ break;
+ case 0x08: // Bank R LED
+ OneState->LightSet(Cus428State::eL_BankR, data[5]);
+ OneState->LightSend();
+ break;
+ case 0x10: // Dump fader position.
+ OneState->SliderSend(data[5]);
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ snd_seq_free_event(ev);
+ }
+ while (snd_seq_event_input_pending(Seq, 0) > 0);
+}
+
+
+// Send MMC command.
+void Cus428Midi::SendMmcCommand(unsigned char MmcCmd, unsigned char *MmcData, unsigned char MmcLen)
+{
+ unsigned char SysexSize;
+ unsigned char SysexLen;
+ unsigned char *SysexData;
+
+ SysexSize = 6;
+ if (MmcLen > 0)
+ SysexSize += 1 + MmcLen;
+ SysexData = (unsigned char *) alloca(SysexSize);
+ SysexLen = 0;
+
+ SysexData[SysexLen++] = 0xf0; // Sysex header.
+ SysexData[SysexLen++] = 0x7f; // Realtime sysex.
+ SysexData[SysexLen++] = 0x7f; // All-caller-id.
+ SysexData[SysexLen++] = 0x06; // MMC command mode.
+ SysexData[SysexLen++] = MmcCmd; // MMC command code.
+ if (MmcData && MmcLen > 0) {
+ SysexData[SysexLen++] = MmcLen;
+ memcpy(&SysexData[SysexLen], MmcData, MmcLen);
+ SysexLen += MmcLen;
+ }
+ SysexData[SysexLen++] = 0xf7; // Sysex trailer.
+
+ snd_seq_ev_set_sysex(&Ev, SysexLen, SysexData);
+
+ SubMitEvent();
+}
#include "Cus428State.h"
+// MMC Command Codes.
+#define MMC_CMD_STOP 0x01
+#define MMC_CMD_PLAY 0x02
+#define MMC_CMD_DEFERRED_PLAY 0x03
+#define MMC_CMD_FAST_FORWARD 0x04
+#define MMC_CMD_REWIND 0x05
+#define MMC_CMD_RECORD_STROBE 0x06
+#define MMC_CMD_RECORD_EXIT 0x07
+#define MMC_CMD_RECORD_PAUSE 0x08
+#define MMC_CMD_PAUSE 0x09
+#define MMC_CMD_EJECT 0x0a
+#define MMC_CMD_CHASE 0x0b
+#define MMC_CMD_COMMAND_ERROR_RESET 0x0c
+#define MMC_CMD_MMC_RESET 0x0d
+#define MMC_CMD_JOG_START 0x20
+#define MMC_CMD_JOG_STOP 0x21
+#define MMC_CMD_WRITE 0x40
+#define MMC_CMD_MASKED_WRITE 0x41
+#define MMC_CMD_READ 0x42
+#define MMC_CMD_UPDATE 0x43
+#define MMC_CMD_LOCATE 0x44
+#define MMC_CMD_VARIABLE_PLAY 0x45
+#define MMC_CMD_SEARCH 0x46
+#define MMC_CMD_SHUTTLE 0x47
+#define MMC_CMD_STEP 0x48
+#define MMC_CMD_ASSIGN_SYSTEM_MASTER 0x49
+#define MMC_CMD_GENERATOR_COMMAND 0x4a
+#define MMC_CMD_MTC_COMMAND 0x4b
+#define MMC_CMD_MOVE 0x4c
+#define MMC_CMD_ADD 0x4d
+#define MMC_CMD_SUBTRACT 0x4e
+#define MMC_CMD_DROP_FRAME_ADJUST 0x4f
+#define MMC_CMD_PROCEDURE 0x50
+#define MMC_CMD_EVENT 0x51
+#define MMC_CMD_GROUP 0x52
+#define MMC_CMD_COMMAND_SEGMENT 0x53
+#define MMC_CMD_DEFERRED_VARIABLE_PLAY 0x54
+#define MMC_CMD_RECORD_STROBE_VARIABLE 0x55
+#define MMC_CMD_WAIT 0x7c
+#define MMC_CMD_RESUME 0x7f
+
+
class Cus428Midi {
public:
Cus428Midi():
snd_seq_set_client_name(Seq, "US-428");
Err = snd_seq_create_simple_port(Seq, "Controls",
SND_SEQ_PORT_CAP_READ
- //|SND_SEQ_PORT_CAP_WRITE FIXME: Next Step is to make Lights switchable
+ |SND_SEQ_PORT_CAP_WRITE
|SND_SEQ_PORT_CAP_SUBS_READ
- /*|SND_SEQ_PORT_CAP_SUBS_WRITE*/,
+ |SND_SEQ_PORT_CAP_SUBS_WRITE,
SND_SEQ_PORT_TYPE_MIDI_GENERIC);
if (Err >= 0) {
Port = Err;
return SendMidiControl(KnobParam[K - Cus428State::eK_RECORD], Down ? 0x7F : 0);
}
- private:
+ // To parse and dispatch input MIDI events.
+ void ProcessMidiEvents();
+
+ // Send MMC command.
+ void SendMmcCommand(unsigned char MmcCmd, unsigned char *MmcData = 0, unsigned char MmcLen = 0);
+
+ // Made public for friendliness.
snd_seq_t *Seq;
+
+ private:
int Port;
snd_seq_event_t Ev;
int SubMitEvent(){
extern int verbose;
-
+// Differential wheel tracking constants.
+#define W_DELTA_MAX 0xff
+#define W_DELTA_MIN (W_DELTA_MAX >> 1)
void us428_lights::init_us428_lights()
{
V.SetTo(S, New);
if (S == eFaderM || !LightIs(eL_Mute0 + S))
SendVolume(V);
- } else
- Midi.SendMidiControl(0x40 + S, ((unsigned char*)us428_ctls)[S] / 2);
-
+ }
+ else SliderSend(S);
}
+void Cus428State::SliderSend(int S)
+{
+ Midi.SendMidiControl(0x40 + S, ((unsigned char*)us428_ctls)[S] / 2);
+}
void Cus428State::KnobChangedTo(eKnobs K, bool V)
{
break;
default:
switch (K) {
+ case eK_STOP:
+ if (verbose > 1)
+ printf("Knob STOP now %i\n", V);
+ if (V) TransportToggle(T_STOP);
+ Midi.SendMidiControl(K, V);
+ break;
+ case eK_PLAY:
+ if (verbose > 1)
+ printf("Knob PLAY now %i", V);
+ if (V) TransportToggle(T_PLAY);
+ if (verbose > 1)
+ printf(" Light is %i\n", LightIs(eL_Play));
+ Midi.SendMidiControl(K, V);
+ break;
+ case eK_REW:
+ if (verbose > 1)
+ printf("Knob REW now %i", V);
+ if (V) TransportToggle(T_REW);
+ if (verbose > 1)
+ printf(" Light is %i\n", LightIs(eL_Rew));
+ Midi.SendMidiControl(K, V);
+ break;
+ case eK_FFWD:
+ if (verbose > 1)
+ printf("Knob FFWD now %i", V);
+ if (V) TransportToggle(T_F_FWD);
+ if (verbose > 1)
+ printf(" Light is %i\n", LightIs(eL_FFwd));
+ Midi.SendMidiControl(K, V);
+ break;
+ case eK_RECORD:
+ if (verbose > 1)
+ printf("Knob RECORD now %i", V);
+ if (V) TransportToggle(T_RECORD);
+ if (verbose > 1)
+ printf(" Light is %i\n", LightIs(eL_Record));
+ Midi.SendMidiControl(K, V);
+ break;
+ case eK_SET:
+ if (verbose > 1)
+ printf("Knob SET now %i", V);
+ bSetLocate = V;
+ break;
+ case eK_LOCATE_L:
+ if (verbose > 1)
+ printf("Knob LOCATE_L now %i", V);
+ if (V) {
+ if (bSetLocate)
+ aWheel_L = aWheel;
+ else {
+ aWheel = aWheel_L;
+ LocateSend();
+ }
+ }
+ break;
+ case eK_LOCATE_R:
+ if (verbose > 1)
+ printf("Knob LOCATE_R now %i", V);
+ if (V) {
+ if (bSetLocate)
+ aWheel_R = aWheel;
+ else {
+ aWheel = aWheel_R;
+ LocateSend();
+ }
+ }
+ break;
case eK_InputMonitor:
if (verbose > 1)
printf("Knob InputMonitor now %i", V);
break;
case eWheel:
Param = 0x60;
+ // Update the absolute wheel position.
+ WheelDelta((int) ((unsigned char*) us428_ctls)[W]);
+ LocateSend();
break;
}
Midi.SendMidiControl(Param, ((unsigned char*)us428_ctls)[W]);
}
+
+
+// Convert time-code (hh:mm:ss:ff:fr) into absolute wheel position.
+void Cus428State::LocateWheel ( unsigned char *tc )
+{
+#if 0
+ aWheel = (60 * 60 * 30) * (int) tc[0] // hh - hours [0..23]
+ + ( 60 * 30) * (int) tc[1] // mm - minutes [0..59]
+ + ( 30) * (int) tc[2] // ss - seconds [0..59]
+ + (int) tc[3]; // ff - frames [0..29]
+#else
+ aWheel = (60 * 60 * 3) * (int) tc[0] // hh - hours [0..23]
+ + ( 60 * 3) * (int) tc[1] // mm - minutes [0..59]
+ + ( 3) * (int) tc[2] // ss - seconds [0..59]
+ + (int) tc[3] / 10; // ff - frames [0..29]
+#endif
+}
+
+
+// Convert absolute wheel position into time-code (hh:mm:ss:ff:fr)
+void Cus428State::WheelTimecode ( unsigned char *tc )
+{
+ int W = aWheel;
+#if 0
+ tc[0] = W / (60 * 60 * 30); W -= (60 * 60 * 30) * (int) tc[0];
+ tc[1] = W / ( 60 * 30); W -= ( 60 * 30) * (int) tc[1];
+ tc[2] = W / ( 30); W -= ( 30) * (int) tc[2];
+ tc[3] = W;
+ tc[4] = 0;
+#else
+ tc[0] = W / (60 * 60 * 3); W -= (60 * 60 * 3) * (int) tc[0];
+ tc[1] = W / ( 60 * 3); W -= ( 60 * 3) * (int) tc[1];
+ tc[2] = W / ( 3); W -= ( 3) * (int) tc[2];
+ tc[3] = W * 10;
+ tc[4] = 0;
+#endif
+}
+
+
+// Get the wheel differential.
+void Cus428State::WheelDelta ( int W )
+{
+ // Compute the wheel differential.
+ int dW = W - W0;
+ if (dW > 0 && dW > +W_DELTA_MIN)
+ dW -= W_DELTA_MAX;
+ else
+ if (dW < 0 && dW < -W_DELTA_MIN)
+ dW += W_DELTA_MAX;
+
+ W0 = W;
+ aWheel += dW;
+
+ // Can't be less than zero.
+ if (aWheel < 0)
+ aWheel = 0;
+}
+
+
+// Send the MMC wheel locate command...
+void Cus428State::LocateSend ()
+{
+ unsigned char MmcData[6];
+ // Timecode's embedded on MMC command.
+ MmcData[0] = 0x01;
+ WheelTimecode(&MmcData[1]);
+ // Send the MMC locate command...
+ Midi.SendMmcCommand(MMC_CMD_LOCATE, MmcData, sizeof(MmcData));
+}
+
+
+// Toggle application transport state.
+void Cus428State::TransportToggle ( unsigned char T )
+{
+ switch (T) {
+ case T_PLAY:
+ if (uTransport & T_PLAY) {
+ uTransport = T_STOP;
+ Midi.SendMmcCommand(MMC_CMD_STOP);
+ } else {
+ uTransport &= T_RECORD;
+ uTransport |= T_PLAY;
+ Midi.SendMmcCommand(MMC_CMD_PLAY);
+ }
+ break;
+ case T_RECORD:
+ if (uTransport & T_RECORD) {
+ uTransport &= ~T_RECORD;
+ Midi.SendMmcCommand(MMC_CMD_RECORD_EXIT);
+ } else {
+ uTransport &= T_PLAY;
+ uTransport |= T_RECORD;
+ Midi.SendMmcCommand(uTransport & T_PLAY ? MMC_CMD_RECORD_STROBE : MMC_CMD_RECORD_PAUSE);
+ }
+ break;
+ default:
+ if (uTransport & T) {
+ uTransport = T_STOP;
+ } else {
+ uTransport = T;
+ }
+ if (uTransport & T_STOP)
+ Midi.SendMmcCommand(MMC_CMD_STOP);
+ if (uTransport & T_REW)
+ Midi.SendMmcCommand(MMC_CMD_REWIND);
+ if (uTransport & T_F_FWD)
+ Midi.SendMmcCommand(MMC_CMD_FAST_FORWARD);
+ break;
+ }
+
+ TransportSend();
+}
+
+
+// Set application transport state.
+void Cus428State::TransportSet ( unsigned char T, bool V )
+{
+ if (V) {
+ if (T == T_RECORD) {
+ uTransport |= T_RECORD;
+ } else {
+ uTransport = T;
+ }
+ } else {
+ if (T == T_RECORD) {
+ uTransport &= ~T_RECORD;
+ } else {
+ uTransport = T_STOP;
+ }
+ }
+
+ TransportSend();
+}
+
+// Update transport lights.
+void Cus428State::TransportSend()
+{
+ LightSet(eL_Play, (uTransport & T_PLAY));
+ LightSet(eL_Record, (uTransport & T_RECORD));
+ LightSet(eL_Rew, (uTransport & T_REW));
+ LightSet(eL_FFwd, (uTransport & T_F_FWD));
+ LightSend();
+}
+
+// Reset MMC state.
+void Cus428State::MmcReset()
+{
+ W0 = 0;
+ aWheel = aWheel_L = aWheel_R = 0;
+ bSetLocate = false;
+ uTransport = 0;
+
+ TransportSend();
+ LocateSend();
+}
+
,SelectInputMonitor(0)
,Select(0)
,us428_ctls(0)
+ ,W0(0)
+ ,aWheel(0)
+ ,aWheel_L(0)
+ ,aWheel_R(0)
+ ,bSetLocate(false)
+ ,uTransport(0)
{
init_us428_lights();
for (int v = 0; v < 5; ++v) {
void InitDevice(void);
void KnobChangedTo(eKnobs K, bool V);
void SliderChangedTo(int S, unsigned char New);
+ void SliderSend(int S);
void WheelChangedTo(E_In84 W, char Diff);
Cus428_ctls *Set_us428_ctls(Cus428_ctls *New) {
Cus428_ctls *Old = us428_ctls;
us428_ctls = New;
return Old;
}
- private:
+ // Update the LED lights state.
int LightSend();
+ // Time-code (hh:mm:ss:ff:fr) to/from absolute wheel position converters.
+ void LocateWheel(unsigned char *tc);
+ void LocateSend();
+ // Set basic application transport state.
+ void TransportToggle(unsigned char T);
+ void TransportSet(unsigned char T, bool V);
+ void TransportSend();
+ // Reset internal MMC state.
+ void MmcReset();
+ private:
void SendVolume(usX2Y_volume &V);
struct us428ctls_sharedmem* us428ctls_sharedmem;
bool StateInputMonitor() {
return LightIs(eL_InputMonitor);
}
+ // Set the wheel differential.
+ void WheelDelta(int W);
+ // Get the curent wheel timecode.
+ void WheelTimecode(unsigned char *tc);
+
usX2Y_volume_t Volume[5];
char MuteInputMonitor,
Mute,
SelectInputMonitor,
Select;
Cus428_ctls *us428_ctls;
+ // Differential wheel tracking.
+ int W0;
+ // Some way to convert wheel (absolute) position into hh:mm:ss:ff:fr
+ int aWheel;
+ // SET L/R points.
+ int aWheel_L;
+ int aWheel_R;
+ // SET knob state.
+ bool bSetLocate;
+ // Last/current transport state.
+ unsigned char uTransport;
};
extern Cus428State* OneState;
AC_INIT(us428control.cc)
-AM_INIT_AUTOMAKE(us428control, 0.4.1)
+AM_INIT_AUTOMAKE(us428control, 0.4.2)
AC_PROG_CXX
AC_PROG_INSTALL
AC_HEADER_STDC
int err;
unsigned int idx, dsps, loaded;
us428ctls_sharedmem_t *us428ctls_sharedmem;
- struct pollfd pfds;
+ struct pollfd *pfds;
+ int npfd, pollrc;
if ((err = snd_hwdep_open(&hw, DevName, O_RDWR)) < 0) {
error("cannot open hwdep %s\n", DevName);
snd_hwdep_close(hw);
return -ENODEV;
}
- snd_hwdep_poll_descriptors(hw, &pfds, 1);
- us428ctls_sharedmem = (us428ctls_sharedmem_t*)mmap(NULL, sizeof(us428ctls_sharedmem_t), PROT_READ|PROT_WRITE, MAP_SHARED, pfds.fd, 0);
+
+ Midi.CreatePorts();
+
+ npfd = snd_seq_poll_descriptors_count(Midi.Seq, POLLIN) + 1;
+ pfds = (struct pollfd *) alloca(npfd * sizeof(struct pollfd));
+ snd_hwdep_poll_descriptors(hw, &pfds[0], 1);
+ snd_seq_poll_descriptors(Midi.Seq, &pfds[1], npfd - 1, POLLIN);
+
+ us428ctls_sharedmem = (us428ctls_sharedmem_t *) mmap(NULL, sizeof(us428ctls_sharedmem_t), PROT_READ|PROT_WRITE, MAP_SHARED, pfds[0].fd, 0);
if (us428ctls_sharedmem == MAP_FAILED) {
perror("mmap failed:");
+ snd_hwdep_close(hw);
return -ENOMEM;
}
- Midi.CreatePorts();
us428ctls_sharedmem->CtlSnapShotRed = us428ctls_sharedmem->CtlSnapShotLast;
OneState = new Cus428State(us428ctls_sharedmem);
OneState->InitDevice();
- while (1) {
- int x = poll(&pfds,1,-1);
- if (verbose > 1 || pfds.revents & (POLLERR|POLLHUP))
- printf("poll returned 0x%X\n", pfds.revents);
- if (pfds.revents & (POLLERR|POLLHUP))
- return -ENXIO;
- int Last = us428ctls_sharedmem->CtlSnapShotLast;
- if (verbose > 1)
- printf("Last is %i\n", Last);
- while (us428ctls_sharedmem->CtlSnapShotRed != Last) {
- static Cus428_ctls *Red = 0;
- int Read = us428ctls_sharedmem->CtlSnapShotRed + 1;
- if (Read >= N_us428_ctl_BUFS || Read < 0)
- Read = 0;
- Cus428_ctls* PCtlSnapShot = ((Cus428_ctls*)(us428ctls_sharedmem->CtlSnapShot)) + Read;
- int DiffAt = us428ctls_sharedmem->CtlSnapShotDiffersAt[Read];
+
+ while ((pollrc = poll(pfds, npfd, 60000)) >= 0) {
+ if (pfds[0].revents) {
+ if (verbose > 1 || pfds[0].revents & (POLLERR|POLLHUP))
+ printf("poll returned 0x%X\n", pfds[0].revents);
+ if (pfds[0].revents & (POLLERR|POLLHUP))
+ return -ENXIO;
+ int Last = us428ctls_sharedmem->CtlSnapShotLast;
if (verbose > 1)
- PCtlSnapShot->dump(DiffAt);
- PCtlSnapShot->analyse(Red, DiffAt);
- Red = PCtlSnapShot;
- us428ctls_sharedmem->CtlSnapShotRed = Read;
+ printf("Last is %i\n", Last);
+ while (us428ctls_sharedmem->CtlSnapShotRed != Last) {
+ static Cus428_ctls *Red = 0;
+ int Read = us428ctls_sharedmem->CtlSnapShotRed + 1;
+ if (Read >= N_us428_ctl_BUFS || Read < 0)
+ Read = 0;
+ Cus428_ctls* PCtlSnapShot = ((Cus428_ctls*)(us428ctls_sharedmem->CtlSnapShot)) + Read;
+ int DiffAt = us428ctls_sharedmem->CtlSnapShotDiffersAt[Read];
+ if (verbose > 1)
+ PCtlSnapShot->dump(DiffAt);
+ PCtlSnapShot->analyse(Red, DiffAt);
+ Red = PCtlSnapShot;
+ us428ctls_sharedmem->CtlSnapShotRed = Read;
+ }
}
+ else if (pollrc > 0) Midi.ProcessMidiEvents();
}
+
+ return pollrc;
}
int main (int argc, char *argv[])
/* probe the all cards */
for (c = 0; c < SND_CARDS; c++) {
- verbose--;
+ // verbose--;
sprintf(name, "hw:%d", c);
if (! US428Control(name))
card = c;
public:
enum eLight{
eL_Select0 = 0,
+ eL_Rec0 = 8,
eL_Mute0 = 16,
- eL_InputMonitor = 25
+ eL_Solo = 24,
+ eL_InputMonitor = 25,
+ eL_BankL = 26,
+ eL_BankR = 27,
+ eL_Rew = 28,
+ eL_FFwd = 29,
+ eL_Play = 30,
+ eL_Record = 31,
+ eL_Null
};
bool LightIs(int L){
return Light[L / 8].Value & (1 << (L % 8));