From: Takashi Iwai Date: Wed, 28 Jul 2004 15:56:45 +0000 (+0000) Subject: Added MMC support by Rui Nuno Capela X-Git-Tag: v1.0.6~4 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=5313c941639301f73d14ac14ac1c4cac30b2cbaf;p=alsa-tools.git 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). --- 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));