]> git.alsa-project.org Git - alsa-tools.git/commitdiff
Karsten Wiese <annabellesgarden@yahoo.de>:
authorTakashi Iwai <tiwai@suse.de>
Fri, 24 Oct 2003 14:01:45 +0000 (14:01 +0000)
committerTakashi Iwai <tiwai@suse.de>
Fri, 24 Oct 2003 14:01:45 +0000 (14:01 +0000)
This has more features:
- PCM-Volume adjusted to MasteVolumeSlider setting at device start.
- Direct Monitoring Functions adjustable directly on the US428
- Alsa Sequencer Output port for applications to receive the US428 sliders
etc.

us428control/Cus428Midi.cc [new file with mode: 0644]
us428control/Cus428Midi.h [new file with mode: 0644]
us428control/Cus428State.cc
us428control/Cus428State.h
us428control/Cus428_ctls.cc
us428control/Cus428_ctls.h
us428control/Makefile.am
us428control/configure.in
us428control/us428control.cc
us428control/usbus428ctldefs.h

diff --git a/us428control/Cus428Midi.cc b/us428control/Cus428Midi.cc
new file mode 100644 (file)
index 0000000..c9a5b6a
--- /dev/null
@@ -0,0 +1,62 @@
+#include <alsa/asoundlib.h>
+#include "Cus428Midi.h"
+
+
+char Cus428Midi::KnobParam[] = {
+       0x17,
+       0x16,
+       0x15,
+       0x14,
+       0x13,
+       0x2A,
+       0x29,
+       0x28,
+       -1,
+       0x10,
+       0x11,
+       0x18,
+       0x19,
+       0x1A,
+       -1,
+       -1,
+       -1,
+       -1,
+       0x2C,
+       0x2D,
+       0x2E,
+       0x2F,
+       -1,
+       -1,
+       0x20,
+       0x21,
+       0x22,
+       0x23,
+       0x24,
+       0x25,
+       0x26,
+       0x27,
+       0,
+       1,
+       2,
+       3,
+       4,
+       5,
+       6,
+       7,
+       -1,
+       -1,
+       -1,
+       -1,
+       -1,
+       -1,
+       -1,
+       -1,
+       0x30,
+       0x31,
+       0x32,
+       0x33,
+       0x34,
+       0x35,
+       0x36,
+       0x37,
+       };
diff --git a/us428control/Cus428Midi.h b/us428control/Cus428Midi.h
new file mode 100644 (file)
index 0000000..b33498f
--- /dev/null
@@ -0,0 +1,52 @@
+#include <sound/asequencer.h>
+#include "Cus428State.h"
+
+class Cus428Midi {
+ public:
+       Cus428Midi():
+               Seq(0){}
+
+       int CreatePorts(){
+               int Err;
+               if (0 <= (Err = snd_seq_open(&Seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK))) {
+                       snd_seq_set_client_name(Seq, "US-428");
+                       Err = snd_seq_create_simple_port(Seq, "Controls",
+                                                        SNDRV_SEQ_PORT_CAP_READ
+                                                        //|SNDRV_SEQ_PORT_CAP_WRITE    FIXME: Next Step is to make Lights switchable
+                                                        |SNDRV_SEQ_PORT_CAP_SUBS_READ
+                                                        /*|SNDRV_SEQ_PORT_CAP_SUBS_WRITE*/,
+                                                        SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC);
+                       if (Err >= 0) {
+                               Port = Err;
+                               snd_seq_ev_clear(&Ev);
+                               snd_seq_ev_set_direct(&Ev);
+                               snd_seq_ev_set_source(&Ev, Port);
+                               snd_seq_ev_set_subs(&Ev);
+                       }
+               }
+               return Err;
+       }
+
+       int SendMidiControl(char Param, char Val){
+               snd_seq_ev_set_controller(&Ev, 15, Param, Val & 0x7F);
+               SubMitEvent();
+               return 0;
+       } 
+
+       int SendMidiControl(Cus428State::eKnobs K, bool Down){
+               return SendMidiControl(KnobParam[K - Cus428State::eK_RECORD], Down ? 0x7F : 0);
+       }
+
+ private:
+       snd_seq_t *Seq;
+       int Port;
+       snd_seq_event_t Ev;
+       int SubMitEvent(){
+               snd_seq_event_output(Seq, &Ev);
+               snd_seq_drain_output(Seq);
+               return 0;
+       }
+       static char KnobParam[];
+};
+
+extern Cus428Midi Midi;
index 47e8ff356749f331c49c3f3af314e6658b1acb4a..ab8464e8d0204ac7b85d5a7398a74cb7777bb43a 100644 (file)
 
 #include <stdio.h>
 #include <string.h>
-#include "Cus428State.h"
+#include <alsa/asoundlib.h>
+#include "Cus428Midi.h"
 
 extern int verbose;
 
-void
-us428_lights::init_us428_lights()
+
+
+void us428_lights::init_us428_lights()
 {
        int i = 0;
        memset(this, 0, sizeof(*this));
@@ -33,8 +35,14 @@ us428_lights::init_us428_lights()
                Light[ i].Offset = i + 0x19;
 }
 
-int 
-Cus428State::LightSend()
+
+void Cus428State::InitDevice(void)
+{
+       SliderChangedTo(eFaderM, ((unsigned char*)(us428ctls_sharedmem->CtlSnapShot + us428ctls_sharedmem->CtlSnapShotLast))[eFaderM]);
+}
+
+
+int Cus428State::LightSend()
 {
        int Next = us428ctls_sharedmem->p4outLast + 1;
        if(Next < 0  ||  Next >= N_us428_p4out_BUFS)
@@ -44,14 +52,8 @@ Cus428State::LightSend()
        return us428ctls_sharedmem->p4outLast = Next;
 }
 
-void 
-Cus428State::SliderChangedTo(int S, unsigned char New)
+void Cus428State::SendVolume(usX2Y_volume &V)
 {
-       if ((S >= eFader4 || S < 0) && S != eFaderM)
-               return;
-
-       usX2Y_volume V;
-       V.SetTo(S, New);
        int Next = us428ctls_sharedmem->p4outLast + 1;
        if (Next < 0  ||  Next >= N_us428_p4out_BUFS)
                Next = 0;
@@ -60,24 +62,107 @@ Cus428State::SliderChangedTo(int S, unsigned char New)
        us428ctls_sharedmem->p4outLast = Next;
 }
 
+void Cus428State::SliderChangedTo(int S, unsigned char New)
+{
+       if (StateInputMonitor() && S <= eFader3
+           || S == eFaderM) {
+               usX2Y_volume &V = Volume[S >= eFader4 ? eFader4 : S];
+               V.SetTo(S, New);
+               if (S == eFaderM || !LightIs(eL_Mute0 + S))
+                       SendVolume(V);
+       } else
+               Midi.SendMidiControl(0x40 + S, ((unsigned char*)us428_ctls)[S] / 2);
+
+}
+
 
-void 
-Cus428State::KnobChangedTo(eKnobs K, bool V)
+void Cus428State::KnobChangedTo(eKnobs K, bool V)
 {
-       switch (K) {  
-       case eK_InputMonitor:
-               if (verbose > 1)
-                       printf("Knob InputMonitor now %i", V);
+       switch (K & ~(StateInputMonitor() ? 3 : -1)) {
+       case eK_Select0:
+               if (V) {
+                       int S = eL_Select0 + (K & 7);
+                       Light[eL_Select0 / 8].Value = 0;
+                       LightSet(S, !LightIs(S));
+                       LightSend();
+               }
+               break;
+       case eK_Mute0:
                if (V) {
-                       LightSet(eL_InputMonitor, ! LightIs(eL_InputMonitor));
+                       int M = eL_Mute0 + (K & 7);
+                       LightSet(M, !LightIs(M));
                        LightSend();
+                       if (StateInputMonitor()) {
+                               usX2Y_volume V = Volume[M - eL_Mute0];
+                               if (LightIs(M))
+                                       V.LH = V.LL = V.RL = V.RH = 0;
+                               SendVolume(V);
+                       }
                }
-               if (verbose > 1)
-                       printf(" Light is %i\n", LightIs(eL_InputMonitor));
                break;
        default:
-               if (verbose > 1)
-                       printf("Knob %i now %i\n", K, V);
+               switch (K) {
+               case eK_InputMonitor:
+                       if (verbose > 1)
+                               printf("Knob InputMonitor now %i", V);
+                       if (V) {
+                               if (StateInputMonitor()) {
+                                       SelectInputMonitor = Light[0].Value;
+                                       MuteInputMonitor = Light[2].Value;
+                               } else {
+                                       Select = Light[0].Value;
+                                       Mute = Light[2].Value;
+                               }
+                               LightSet(eL_InputMonitor, ! StateInputMonitor());
+                               Light[0].Value = StateInputMonitor() ? SelectInputMonitor : Select;
+                               Light[2].Value = StateInputMonitor() ? MuteInputMonitor : Mute;
+                               LightSend();
+                       }
+                       if (verbose > 1)
+                               printf(" Light is %i\n", LightIs(eL_InputMonitor));
+                       break;
+               default:
+                       if (verbose > 1)
+                               printf("Knob %i now %i\n", K, V);
+                       Midi.SendMidiControl(K, V);
+               }
        }
 }
 
+
+void Cus428State::WheelChangedTo(E_In84 W, char Diff)
+{
+       char Param;
+       switch (W) {
+       case eWheelPan:
+               if (StateInputMonitor() && Light[0].Value) {
+                       int index = 0;
+
+                       while( index < 4 && (1 << index) !=  Light[0].Value)
+                               index++;
+
+                       if (index >= 4)
+                               return;
+
+                       Volume[index].PanTo(Diff, us428_ctls->Knob(eK_SET));
+                       if (!LightIs(eL_Mute0 + index))
+                               SendVolume(Volume[index]);
+                       return;
+               }
+               Param = 0x4D;
+               break;
+       case eWheelGain:
+               Param = 0x48;
+               break;
+       case eWheelFreq:
+               Param = 0x49;
+               break;
+       case eWheelQ:
+               Param = 0x4A;
+               break;
+       case eWheel:
+               Param = 0x60;
+               break;
+       }
+       Midi.SendMidiControl(Param, ((unsigned char*)us428_ctls)[W]);
+}
index 35c5dd64ef5fe69f97669cae5c10f1db08331782..a2779fb22a8e78f247ff43cc09ff0a219a543cb1 100644 (file)
 
 #include "Cus428_ctls.h"
 
-class Cus428State: public us428_lights, public Cus428_ctls{
+class Cus428State: public us428_lights{
  public:
        Cus428State(struct us428ctls_sharedmem* Pus428ctls_sharedmem)
                :us428ctls_sharedmem(Pus428ctls_sharedmem)
+               ,MuteInputMonitor(0)
+               ,Mute(0)
+               ,us428_ctls(0)
                {
                        init_us428_lights();
+                       for (int v = 0; v < 5; ++v) {
+                               Volume[v].init(v);
+                       }
                }
        enum eKnobs{
-               eK_RECORD = 72,
-               eK_PLAY = 73,
+               eK_RECORD =     72,
+               eK_PLAY,
                eK_STOP,
-               eK_InputMonitor = 80
+               eK_FFWD,
+               eK_REW,
+               eK_SOLO,
+               eK_REC,
+               eK_NULL,
+               eK_InputMonitor,        // = 80
+               eK_BANK_L,
+               eK_BANK_R,
+               eK_LOCATE_L,
+               eK_LOCATE_R,
+               eK_SET =        85,
+               eK_INPUTCD =    87,
+               eK_HIGH =       90,
+               eK_HIMID,
+               eK_LOWMID,
+               eK_LOW,
+               eK_Select0 =    96,
+               eK_Mute0 =      104,
+               eK_Mute1,
+               eK_Mute2,
+               eK_Mute3,
+               eK_Mute4,
+               eK_Mute5,
+               eK_Mute6,
+               eK_Mute7,
+               eK_AUX1 =       120,
+               eK_AUX2,
+               eK_AUX3,
+               eK_AUX4,
+               eK_ASGN,
+               eK_F1,
+               eK_F2,
+               eK_F3,
        };
+       void InitDevice(void);
        void KnobChangedTo(eKnobs K, bool V);
        void SliderChangedTo(int S, unsigned char New);
+       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:
        int LightSend();
+       void SendVolume(usX2Y_volume &V);
        struct us428ctls_sharedmem* us428ctls_sharedmem;
+       bool   StateInputMonitor() {
+               return  LightIs(eL_InputMonitor);
+       }
+       usX2Y_volume_t  Volume[5];
+       char            MuteInputMonitor,
+                       Mute,
+                       SelectInputMonitor,
+                       Select;
+       Cus428_ctls     *us428_ctls;
 };
 
 extern Cus428State* OneState;
index 4bbe32ded191cc75bae026af086a97dbac6e6954..5f6d24e3882b20c2f859c219bf19c59d57e5abbb 100644 (file)
@@ -31,27 +31,31 @@ Cus428_ctls::dump(int n)
        for (int m = 0; m < n; m++)
                printf("   ");
        for (; n < sizeof(*this); n++)
-               printf("%02hhX ", ((char*)this)[ n]);
+               printf("%02hhX ", ((char*)this)[n]);
        printf("\n");
 }
 
 void 
 Cus428_ctls::analyse(Cus428_ctls& Previous, unsigned n)
 {
-       for (; n < 9; n++) {            //Sliders
-               char Diff = ((unsigned char*)this)[ n] - ((unsigned char*)&Previous)[ n];
+       OneState->Set_us428_ctls(this);
+       for (; n < 9; n++) {                    //Sliders
+               char Diff = ((unsigned char*)this)[n] - ((unsigned char*)&Previous)[n];
                if (Diff)
-                       OneState->SliderChangedTo(n, ((unsigned char*)this)[ n]);               
+                       OneState->SliderChangedTo(n, ((unsigned char*)this)[n]);                
        }
-       for (; n < 16; n++) {           //Knobs
-               unsigned char Diff = ((unsigned char*)this)[ n] ^ ((unsigned char*)&Previous)[ n];
+       for (; n < 16; n++) {                   //Knobs
+               unsigned char Diff = ((unsigned char*)this)[n] ^ ((unsigned char*)&Previous)[n];
                unsigned o = 0;
                while (o < 8) {
                        if (Diff & (1 << o))
-                               OneState->KnobChangedTo((Cus428State::eKnobs)(8*n + o), ((unsigned char*)this)[ n] & (1 << o));
+                               OneState->KnobChangedTo((Cus428State::eKnobs)(8*n + o), ((unsigned char*)this)[n] & (1 << o));
                        ++o;
                }
        }
-       for (; n < sizeof(*this); n++)
-               ;                       //wheels
+       for (; n < sizeof(*this); n++) {        //wheels
+               char Diff = ((unsigned char*)this)[ n] - ((unsigned char*)&Previous)[n];
+               if (Diff)
+                       OneState->WheelChangedTo((E_In84)n, Diff);                              
+       }       
 }
index 71bd8497c896f206764894d2f733ee14a36e13ce..db5a28416a55fb2770989920e8a68de8ac2e98d1 100644 (file)
@@ -27,6 +27,9 @@ class Cus428_ctls: public us428_ctls{
  public:
        void dump(int n = 0);
        void analyse(Cus428_ctls& Previous, unsigned n = 0);
+       bool Knob( int K) {
+               return ((char*)this)[K / 8] & (1 << K % 8);
+       }
 };
 
 #endif
index a5765b2f096e6eca6c15af9e8f20e9779fe020a4..27b028591114fbcc3614375ddbe3ed6bc64123d4 100644 (file)
@@ -3,8 +3,7 @@ AUTOMAKE_OPTIONS = 1.3 foreign
 
 bin_PROGRAMS = us428control
 
-us428control_SOURCES = us428control.cc Cus428State.cc Cus428_ctls.cc
-us428control_HEADERS = Cus428State.h Cus428_ctls.h usbus428ctldefs.h
+us428control_SOURCES = us428control.cc Cus428State.cc Cus428_ctls.cc Cus428Midi.cc
 
 EXTRA_DIST = depcomp
 
index c39bfbd43272e8ccea18095ab10c4650da526bad..c7d6696076a6e03551cef20ea10c9eede230c383 100644 (file)
@@ -1,5 +1,5 @@
 AC_INIT(us428control.cc)
-AM_INIT_AUTOMAKE(us428control, 0.1)
+AM_INIT_AUTOMAKE(us428control, 0.3)
 AC_PROG_CXX
 AC_PROG_INSTALL
 AC_HEADER_STDC
index 65f130ec13f413c1d3195125cad6384f3beaf55d..a9707851f1cebe3f937d45f33538a9e9caf38b37 100644 (file)
@@ -31,6 +31,7 @@
 #include <alsa/asoundlib.h>
 #include "Cus428_ctls.h"
 #include "Cus428State.h"
+#include "Cus428Midi.h"
 
 
 #define PROGNAME               "us428control"
@@ -41,6 +42,8 @@
 
 int verbose = 1;
 
+Cus428Midi Midi;
+
 
 static void error(const char *fmt, ...)
 {
@@ -56,7 +59,7 @@ static void error(const char *fmt, ...)
 
 static void usage(void)
 {
-       printf("Tascam US-428 Contol\n");
+       printf("Tascam US-428 Control\n");
        printf("version %s\n", VERSION);
        printf("usage: "PROGNAME" [-v verbosity_level 0..2] [-c card] [-D device] [-u usb-device]\n");
 }
@@ -104,8 +107,10 @@ int US428Control(const char* DevName)
                perror("mmap failed:");
                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))
index 7ca55ab40977d41748e05df0e83737a9091fa06c..0b65a29758d263bbb84da7f563ef8b1630b692c8 100644 (file)
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-enum E_In84{
+#ifdef __cplusplus
+#include <string.h>
+extern int verbose;
+#endif
+
+enum E_In84 {
        eFader0 = 0,
        eFader1,
        eFader2,
@@ -76,18 +81,63 @@ enum {
 };
 
 typedef struct usX2Y_volume {
-       unsigned char Channel,
-               LH,
-               LL,
-               RH,
-               RL;
+       unsigned char   Channel,
+                       LH,
+                       LL,
+                       RH,
+                       RL;
+       unsigned char   Slider;
+       char            Pan,
+                       Mute;
 #ifdef __cplusplus
        public:
+       void init(unsigned char _Channel) {
+               memset(this, 0, sizeof(*this));
+               Channel = _Channel;
+       }
        int Scale(){return 0x40;}
+
+       void calculate() {
+               int lPan = (int)Pan * Slider / 0x80;
+               int ValL = (Slider - lPan) * Scale();
+               LH = ValL >> 8;
+               LL = ValL;
+               int ValR = (Slider + lPan) * Scale();
+               RH = ValR >> 8;
+               RL = ValR;
+               if (2 < verbose)
+                       printf("S=% 3i, P=% 3i, lP=% 3i, VL=%05i, VR=%05i\n", (int)Slider, (int)Pan, (int)lPan, ValL, ValR);
+       }
+
        void SetTo(unsigned char _Channel, int RawValue){
+               Slider = RawValue;
                Channel = eFaderM == _Channel ? 4 : _Channel;
-               LH = RH = (RawValue *= Scale()) >> 8;
-               LL = RL = RawValue;
+               calculate();
+       }
+       void PanTo(int RawValue, bool Grob) {
+               int NewPan;
+               if (Grob) {
+                       static int GrobVals[] = {-128, -64, 0, 64, 127};
+                       int i = 4;
+                       while (i >= 0 && GrobVals[i] > Pan) 
+                               i--;
+                       if (GrobVals[i] != Pan  &&  RawValue < 0)
+                               i++;
+
+                       if (i >= 0) {
+                               if ((i += RawValue) >= 0  &&  i < 5)
+                                       NewPan = GrobVals[i];
+                               else
+                                       return;
+                       }
+
+               } else {
+                       NewPan = Pan + RawValue;
+               }
+               if (NewPan < -128  ||  NewPan > 127)
+                       return;
+               Pan = NewPan;
+               calculate();
        }
 #endif
 } usX2Y_volume_t;
@@ -97,16 +147,18 @@ struct us428_lights{
 #ifdef __cplusplus
        public:
        enum eLight{
+               eL_Select0 = 0,
+               eL_Mute0 = 16,
                eL_InputMonitor = 25
        };
-       bool LightIs(eLight L){
+       bool LightIs(int L){
                return Light[L / 8].Value & (1 << (L % 8));
        }
-       void LightSet(eLight L, bool Value){
+       void LightSet(int L, bool Value){
                if (Value)
                        Light[L / 8].Value |= (1 << (L % 8));
                else
-                       Light[L / 8].Value &= (~1 << (L % 8));
+                       Light[L / 8].Value &= ~(1 << (L % 8));
        }
        void init_us428_lights();
 #endif