From 5313c941639301f73d14ac14ac1c4cac30b2cbaf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 28 Jul 2004 15:56:45 +0000 Subject: [PATCH] Added MMC support by Rui Nuno Capela MMC support has been improved and transport LEDs is getting almost functional. Tascam control protocol sysex decoding is also complete (LEDs control mainly). --- us428control/Cus428Midi.cc | 170 +++++++++++++++++++++++ us428control/Cus428Midi.h | 56 +++++++- us428control/Cus428State.cc | 239 ++++++++++++++++++++++++++++++++- us428control/Cus428State.h | 35 ++++- us428control/configure.in | 2 +- us428control/us428control.cc | 63 +++++---- us428control/usbus428ctldefs.h | 11 +- 7 files changed, 541 insertions(+), 35 deletions(-) diff --git a/us428control/Cus428Midi.cc b/us428control/Cus428Midi.cc index 2de2391..ff25084 100644 --- a/us428control/Cus428Midi.cc +++ b/us428control/Cus428Midi.cc @@ -79,3 +79,173 @@ char Cus428Midi::KnobParam[] = { 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(); +} diff --git a/us428control/Cus428Midi.h b/us428control/Cus428Midi.h index d3b08eb..05347b0 100644 --- a/us428control/Cus428Midi.h +++ b/us428control/Cus428Midi.h @@ -19,6 +19,48 @@ #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(): @@ -30,9 +72,9 @@ class 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; @@ -55,8 +97,16 @@ class Cus428Midi { 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(){ diff --git a/us428control/Cus428State.cc b/us428control/Cus428State.cc index d6bf76b..5e1ab0d 100644 --- a/us428control/Cus428State.cc +++ b/us428control/Cus428State.cc @@ -25,7 +25,9 @@ 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() { @@ -71,11 +73,14 @@ void Cus428State::SliderChangedTo(int S, unsigned char New) 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) { @@ -103,6 +108,73 @@ 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); @@ -163,7 +235,166 @@ void Cus428State::WheelChangedTo(E_In84 W, char Diff) 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(); +} + diff --git a/us428control/Cus428State.h b/us428control/Cus428State.h index c2eb01e..93ff0c4 100644 --- a/us428control/Cus428State.h +++ b/us428control/Cus428State.h @@ -32,6 +32,12 @@ class Cus428State: public us428_lights{ ,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) { @@ -79,25 +85,52 @@ class Cus428State: public us428_lights{ 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; diff --git a/us428control/configure.in b/us428control/configure.in index 628bd20..d4da3fd 100644 --- a/us428control/configure.in +++ b/us428control/configure.in @@ -1,5 +1,5 @@ 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 diff --git a/us428control/us428control.cc b/us428control/us428control.cc index 28b856f..e826ec4 100644 --- a/us428control/us428control.cc +++ b/us428control/us428control.cc @@ -89,7 +89,8 @@ int US428Control(const char* DevName) 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); @@ -101,39 +102,51 @@ int US428Control(const char* 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[]) @@ -186,7 +199,7 @@ 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; diff --git a/us428control/usbus428ctldefs.h b/us428control/usbus428ctldefs.h index 0b65a29..d348669 100644 --- a/us428control/usbus428ctldefs.h +++ b/us428control/usbus428ctldefs.h @@ -148,8 +148,17 @@ struct us428_lights{ 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)); -- 2.47.1