This patch (not to be confused with my Diff Sensitivity patch) implements a MIDI track selection knob.

On my controller, I have a track selection knob which reports a signed, relative number which should be interpreted as a number of clicks in a clockwise or counter-clockwise direction. (Depending on the sign.)

In order to implement a slot which behaves properly, I had to add a MIDI_OPT_SELECTKNOB which should be useful in any situation where a relative control's current position shouldn't be remembered from event to event.

My track selection knob also generates a button event if it is pressed down. Since this button does not specify a particular channel, I added a slotLoadSelectedIntoFirstStopped, which allows a MIDI button to behave like double-clicking a track in the library.

Since this patch only adds features to the codebase (instead of altering older features) I don't expect it to affect anything else. It _should_ be safe to commit.

Once Mixxx HEAD has all the code necessary to write a working MIDI mapping for the Numark Total Control, I'll be contributing a complete MIDI mapping which can be included in the next release. :)

ttyl
--
Alex (Malex) Markley
 740.927.3588 - http://MalexMedia.Net/ - http://SermonMP3s.com/
Index: src/configobject.h
===================================================================
--- src/configobject.h	(revision 1900)
+++ src/configobject.h	(working copy)
@@ -44,7 +44,8 @@
     MIDI_OPT_BUTTON           = 6, // Button Down (!=00) and Button Up (00) events happen together
     MIDI_OPT_SWITCH           = 7, // Button Down (!=00) and Button Up (00) events happen seperately
     MIDI_OPT_HERC_JOG         = 8, // Generic hercules wierd range correction
-    MIDI_OPT_SPREAD64         = 9  // Accelerated difference from 64
+    MIDI_OPT_SPREAD64         = 9, // Accelerated difference from 64
+    MIDI_OPT_SELECTKNOB       = 10,// Relative knob which can be turned forever and outputs a signed value.
 } MidiOption;
 
 typedef QMap<char,char> MidiValueMap;
Index: src/configobject.cpp
===================================================================
--- src/configobject.cpp	(revision 1900)
+++ src/configobject.cpp	(working copy)
@@ -179,6 +179,8 @@
             midioption = MIDI_OPT_HERC_JOG;
         else if (optname == "spread64")
             midioption = MIDI_OPT_SPREAD64;
+        else if (optname == "selectknob")
+        	midioption = MIDI_OPT_SELECTKNOB;
         else {
             qWarning() << "Unknown option:" << optname;
             midioption = MIDI_OPT_NORMAL;
@@ -240,6 +242,8 @@
         midioption = MIDI_OPT_HERC_JOG;
     else if (option.contains("Spread64", false))
         midioption = MIDI_OPT_SPREAD64;
+    else if (option.contains("SelectKnob", false))
+        midioption = MIDI_OPT_SELECTKNOB;
     else
         midioption = MIDI_OPT_NORMAL;
     // Store string with corrected config value
@@ -293,6 +297,8 @@
         value.append(" Diff");
     else if (midioption == MIDI_OPT_SPREAD64)
         value.append(" Spread64");
+    else if (midioption == MIDI_OPT_SELECTKNOB)
+        value.append(" SelectKnob");
 
     qDebug() << "Config value:" << value;
     //qDebug() << "--1, midino: " << midino << ", midimask: " << midimask << ", midichannel: " << midichannel;
@@ -361,6 +367,17 @@
             _newmidivalue = _prevmidivalue + _newmidivalue;
         }
     }
+    else if (midioption == MIDI_OPT_SELECTKNOB)
+    {
+        //Interpret 7-bit signed value using two's compliment.
+        if (_newmidivalue >= 64.)
+            _newmidivalue = _newmidivalue - 128.;
+        //Apply sensitivity to signed value.
+        if(sensitivity > 0)
+            _newmidivalue = _newmidivalue * ((double)sensitivity / 50.);
+        //Since this is a selection knob, we do not want to inherit previous values.
+        return _newmidivalue;
+    }
     else if (midioption == MIDI_OPT_BUTTON)
     {
         if (_newmidivalue != 0.) {
Index: src/track.h
===================================================================
--- src/track.h	(revision 1900)
+++ src/track.h	(working copy)
@@ -121,9 +121,11 @@
     /** Slots for loading the selected track into players */
     void slotLoadSelectedTrackCh1(double);
     void slotLoadSelectedTrackCh2(double);
+    void slotLoadSelectedIntoFirstStopped(double);
     /** Slots for moving the selection cursor in the track list */
     void slotSelectNextTrack(double);
     void slotSelectPrevTrack(double);
+    void slotSelectTrackKnob(double);
 
     /** Returns pointer to active playlist */
     TrackPlaylist *getActivePlaylist();
@@ -206,7 +208,7 @@
     /** Pointer to ControlObject for next/prev buttons */
     ControlObjectThreadMain *m_pNextTrackCh1, *m_pNextTrackCh2, *m_pPrevTrackCh1, *m_pPrevTrackCh2;
     /** Pointer to ControlObject for playlist navigation/loading into Players */
-    ControlObjectThreadMain *m_pLoadSelectedTrackCh1, *m_pLoadSelectedTrackCh2, *m_pSelectNextTrack, *m_pSelectPrevTrack;
+    ControlObjectThreadMain *m_pLoadSelectedTrackCh1, *m_pLoadSelectedTrackCh2, *m_pLoadSelectedIntoFirstStopped, *m_pSelectNextTrack, *m_pSelectPrevTrack, *m_pSelectTrackKnob;
     /** Pointer to ControlObject for play position */
     ControlObjectThreadMain *m_pPlayPositionCh1, *m_pPlayPositionCh2;
     /** Pointer to waveform summary generator */
Index: src/track.cpp
===================================================================
--- src/track.cpp	(revision 1900)
+++ src/track.cpp	(working copy)
@@ -214,12 +214,16 @@
     // Make controls for tracklist navigation and current track loading
     m_pLoadSelectedTrackCh1 = new ControlObjectThreadMain(new ControlObject(ConfigKey("[Channel1]","LoadSelectedTrack")));
     m_pLoadSelectedTrackCh2 = new ControlObjectThreadMain(new ControlObject(ConfigKey("[Channel2]","LoadSelectedTrack")));
+    m_pLoadSelectedIntoFirstStopped = new ControlObjectThreadMain(new ControlObject(ConfigKey("[Playlist]","LoadSelectedIntoFirstStopped")));
     m_pSelectNextTrack = new ControlObjectThreadMain(new ControlObject(ConfigKey("[Playlist]","SelectNextTrack")));
     m_pSelectPrevTrack = new ControlObjectThreadMain(new ControlObject(ConfigKey("[Playlist]","SelectPrevTrack")));
+    m_pSelectTrackKnob = new ControlObjectThreadMain(new ControlObject(ConfigKey("[Playlist]","SelectTrackKnob")));
     connect(m_pLoadSelectedTrackCh1, SIGNAL(valueChanged(double)), this, SLOT(slotLoadSelectedTrackCh1(double)));
     connect(m_pLoadSelectedTrackCh2, SIGNAL(valueChanged(double)), this, SLOT(slotLoadSelectedTrackCh2(double)));
+    connect(m_pLoadSelectedIntoFirstStopped, SIGNAL(valueChanged(double)), this, SLOT(slotLoadSelectedIntoFirstStopped(double)));
     connect(m_pSelectNextTrack, SIGNAL(valueChanged(double)), this, SLOT(slotSelectNextTrack(double)));
     connect(m_pSelectPrevTrack, SIGNAL(valueChanged(double)), this, SLOT(slotSelectPrevTrack(double)));
+    connect(m_pSelectTrackKnob, SIGNAL(valueChanged(double)), this, SLOT(slotSelectTrackKnob(double)));
 
     TrackPlaylist::setTrack(this);
 
@@ -1147,11 +1151,22 @@
         // Fetch the currently selected track
         index = m_pView->m_pTrackTableView->m_pSearchFilter->mapToSource(m_pView->m_pTrackTableView->currentIndex());
         pTrack = m_pView->m_pTrackTableView->m_pTable->m_pTrackPlaylist->getTrackAt(index.row());
-	// If there is one, load it
+        // If there is one, load it
         if (pTrack) slotLoadPlayer2(pTrack);
     }
 }
 
+void Track::slotLoadSelectedIntoFirstStopped(double v)
+{
+    if (v)
+    {
+        if (ControlObject::getControl(ConfigKey("[Channel1]","play"))->get()!=1.)
+            this->slotLoadSelectedTrackCh1(v);
+        else if (ControlObject::getControl(ConfigKey("[Channel2]","play"))->get()!=1.)
+            this->slotLoadSelectedTrackCh2(v);
+    }
+}
+
 void Track::slotSelectNextTrack(double v)
 {
     // Only move on key presses
@@ -1164,6 +1179,24 @@
     if (v) m_pView->m_pTrackTableView->selectPrevious();
 }
 
+void Track::slotSelectTrackKnob(double v)
+{
+    int i = (int)v;
+    while(i != 0)
+    {
+        if(i > 0)
+        {
+            m_pView->m_pTrackTableView->selectNext();
+            i--;
+        }
+        else
+        {
+            m_pView->m_pTrackTableView->selectPrevious();
+            i++;
+        }
+    }
+}
+
 void Track::slotNextTrackPlayer1(double v)
 {
     if (v && m_pTrackPlayer1)

Attachment: patch_selectknob.patch.asc
Description: application/pgp-encrypted

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
Mixxx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mixxx-devel

Reply via email to