]> git.alsa-project.org Git - alsa-tools.git/commitdiff
From Rui Nuno Capela <rncbc@rncbc.org>:
authorTakashi Iwai <tiwai@suse.de>
Mon, 2 Aug 2004 11:53:45 +0000 (11:53 +0000)
committerTakashi Iwai <tiwai@suse.de>
Mon, 2 Aug 2004 11:53:45 +0000 (11:53 +0000)
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 :)

us428control/Cus428Midi.cc
us428control/Cus428State.cc
us428control/Cus428State.h
us428control/configure.in

index ff25084760cce913496d68277c559a2ab0546833..554c1ffa083b6cba39a34d30f290d73d9062e2d2 100644 (file)
@@ -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:
index 5e1ab0da87b67c213885e229a99a3b69ad87eb16..5f25152d96f21865b7d00276eedf49b11ba9d841 100644 (file)
@@ -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;
 
index 93ff0c45f084118e69ae82e95cfeb2aac462b015..714b1afef2f04993b1fa78b669c9473ad090fd3f 100644 (file)
@@ -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;
index d4da3fdfa9f97b4097a17135cf0f44ae573a0ffd..b900a70a549bdca2eb90ccdbee42f604921d904c 100644 (file)
@@ -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