From: Takashi Iwai Date: Mon, 2 Aug 2004 11:53:45 +0000 (+0000) Subject: From Rui Nuno Capela : X-Git-Tag: v1.0.6~3 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=aa16536cb3236031bbcaba8570365cf6448b4295;p=alsa-tools.git From Rui Nuno Capela : Tascam US-224/428 MMC Implementation This is my latest patch against the alsa-tools tree (as of todays CVS HEAD), regarding the us428control MMC implementation as for the Tascam US-224/428 audio/midi USB control surfaces: us428control now bumps to version 0.4.4. Interesting points are: jog wheel dialing is now alternating between spitting out some MMC-Step or MMC-Shuttle messages, depending on transport state, instead of those MMC-Locate(s) which was an early implementation mistake of mine. Controlling ardour with (my) US-224 is getting much more fun now :) However, there's still some little annoyances due to my lack of advice regarding ardour's Play/Record control behaviour: 1) Ardour doesn't seem to send out MMC-Play messages when one starts transport within it (e.g. by clicking the playback button widget). 2) Ardour doesn't seem to react against MMC-RecordPause, which I assume (probably erroneously) it would be equivalent to clicking on its record widget button. 3) Sending a MMC-RecordStrobe message to ardour has the strange effect to start playback while toggling recording off instantaneously. AFAICT these issues seems to be specific to ardour (0.9beta18.4), not to us428control which is just sending out the proper MMC messages. Or that I think. I would like to settle all this before I'm going off on holidays. Hope it's welcome and on time for the imminent alsa dot-6 release :) --- diff --git a/us428control/Cus428Midi.cc b/us428control/Cus428Midi.cc index ff25084..554c1ff 100644 --- a/us428control/Cus428Midi.cc +++ b/us428control/Cus428Midi.cc @@ -136,7 +136,7 @@ void Cus428Midi::ProcessMidiEvents() break; case MMC_CMD_LOCATE: if (verbose > 1) - fprintf(stderr, "LOCATE WHEEL.\n"); + fprintf(stderr, "LOCATE.\n"); OneState->LocateWheel(&data[7]); break; case MMC_CMD_MMC_RESET: diff --git a/us428control/Cus428State.cc b/us428control/Cus428State.cc index 5e1ab0d..5f25152 100644 --- a/us428control/Cus428State.cc +++ b/us428control/Cus428State.cc @@ -28,6 +28,8 @@ extern int verbose; // Differential wheel tracking constants. #define W_DELTA_MAX 0xff #define W_DELTA_MIN (W_DELTA_MAX >> 1) +// Shuttle speed wheel constants. +#define W_SPEED_MAX 0x3f void us428_lights::init_us428_lights() { @@ -236,48 +238,33 @@ void Cus428State::WheelChangedTo(E_In84 W, char Diff) case eWheel: Param = 0x60; // Update the absolute wheel position. - WheelDelta((int) ((unsigned char*) us428_ctls)[W]); - LocateSend(); + WheelDelta((int) ((unsigned char *) us428_ctls)[W]); break; } - Midi.SendMidiControl(Param, ((unsigned char*)us428_ctls)[W]); + 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 ) +void Cus428State::LocateTimecode ( 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 } @@ -298,6 +285,53 @@ void Cus428State::WheelDelta ( int W ) // Can't be less than zero. if (aWheel < 0) aWheel = 0; + + // Now it's whether we're running transport already... + if (aWheelSpeed) + WheelShuttle(dW); + else + WheelStep(dW); +} + +// Get the wheel step. +void Cus428State::WheelStep ( int dW ) +{ + unsigned char step; + + if (dW < 0) + step = (unsigned char) (((-dW & 0x3f) << 1) | 0x40); + else + step = (unsigned char) ((dW << 1) & 0x3f); + + Midi.SendMmcCommand(MMC_CMD_STEP, &step, sizeof(step)); +} + + +// Set the wheel shuttle speed. +void Cus428State::WheelShuttle ( int dW ) +{ + unsigned char shuttle[3]; + int V, forward; + + // Update the current absolute wheel shuttle speed. + aWheelSpeed += dW; + + // Don't make it pass some limits... + if (aWheelSpeed < -W_SPEED_MAX) aWheelSpeed = -W_SPEED_MAX; + if (aWheelSpeed > +W_SPEED_MAX) aWheelSpeed = +W_SPEED_MAX; + + // Build the MMC-Shuttle command... + V = aWheelSpeed; + forward = (V >= 0); + if (!forward) + V = -(V); + shuttle[0] = (unsigned char) ((V >> 3) & 0x07); // sh + shuttle[1] = (unsigned char) ((V & 0x07) << 4); // sm + shuttle[2] = (unsigned char) 0; // sl + if (!forward) + shuttle[0] |= (unsigned char) 0x40; + + Midi.SendMmcCommand(MMC_CMD_SHUTTLE, &shuttle[0], sizeof(shuttle)); } @@ -307,7 +341,7 @@ void Cus428State::LocateSend () unsigned char MmcData[6]; // Timecode's embedded on MMC command. MmcData[0] = 0x01; - WheelTimecode(&MmcData[1]); + LocateTimecode(&MmcData[1]); // Send the MMC locate command... Midi.SendMmcCommand(MMC_CMD_LOCATE, MmcData, sizeof(MmcData)); } @@ -376,9 +410,20 @@ void Cus428State::TransportSet ( unsigned char T, bool V ) TransportSend(); } -// Update transport lights. +// Update transport status lights. void Cus428State::TransportSend() { + // Common ground for shuttle speed set. + if (uTransport & T_PLAY) + aWheelSpeed = ((W_SPEED_MAX + 1) >> 3); + else if (uTransport & T_REW) + aWheelSpeed = -(W_SPEED_MAX + 1); + else if (uTransport & T_F_FWD) + aWheelSpeed = +(W_SPEED_MAX + 1); + else + aWheelSpeed = 0; + + // Lightning feedback :) LightSet(eL_Play, (uTransport & T_PLAY)); LightSet(eL_Record, (uTransport & T_RECORD)); LightSet(eL_Rew, (uTransport & T_REW)); @@ -391,6 +436,7 @@ void Cus428State::MmcReset() { W0 = 0; aWheel = aWheel_L = aWheel_R = 0; + aWheelSpeed = 0; bSetLocate = false; uTransport = 0; diff --git a/us428control/Cus428State.h b/us428control/Cus428State.h index 93ff0c4..714b1af 100644 --- a/us428control/Cus428State.h +++ b/us428control/Cus428State.h @@ -38,6 +38,7 @@ class Cus428State: public us428_lights{ ,aWheel_R(0) ,bSetLocate(false) ,uTransport(0) + ,aWheelSpeed(0) { init_us428_lights(); for (int v = 0; v < 5; ++v) { @@ -106,13 +107,17 @@ class Cus428State: public us428_lights{ private: void SendVolume(usX2Y_volume &V); struct us428ctls_sharedmem* us428ctls_sharedmem; - bool StateInputMonitor() { + bool StateInputMonitor() { return LightIs(eL_InputMonitor); } // Set the wheel differential. void WheelDelta(int W); + // Set the wheel differential. + void WheelStep(int dW); + // Set the wheel shuttle speed. + void WheelShuttle(int dW); // Get the curent wheel timecode. - void WheelTimecode(unsigned char *tc); + void LocateTimecode(unsigned char *tc); usX2Y_volume_t Volume[5]; char MuteInputMonitor, @@ -131,6 +136,8 @@ class Cus428State: public us428_lights{ bool bSetLocate; // Last/current transport state. unsigned char uTransport; + // Shuttle wheel absolute speed. + int aWheelSpeed; }; extern Cus428State* OneState; diff --git a/us428control/configure.in b/us428control/configure.in index d4da3fd..b900a70 100644 --- a/us428control/configure.in +++ b/us428control/configure.in @@ -1,5 +1,5 @@ AC_INIT(us428control.cc) -AM_INIT_AUTOMAKE(us428control, 0.4.2) +AM_INIT_AUTOMAKE(us428control, 0.4.4) AC_PROG_CXX AC_PROG_INSTALL AC_HEADER_STDC