changeset 48:2a9e5576905e

Added support for keyboards which don't begin and end on C; also fixed a Yosemite GUI bug (may affect other platforms).
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Mon, 05 Jan 2015 18:06:43 +0000
parents e314677c49f6
children 90ce403d0dc5
files Source/MainApplicationController.cpp Source/TouchKeys/TouchkeyDevice.cpp Source/TouchKeys/TouchkeyDevice.h
diffstat 3 files changed, 43 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/Source/MainApplicationController.cpp	Sat Jan 03 23:08:40 2015 +0000
+++ b/Source/MainApplicationController.cpp	Mon Jan 05 18:06:43 2015 +0000
@@ -174,7 +174,11 @@
 #ifndef TOUCHKEYS_NO_GUI
     if(keyboardDisplayWindow_ != 0) {
         keyboardDisplayWindow_->getConstrainer()->setFixedAspectRatio(keyboardDisplay_.keyboardAspectRatio());
-        keyboardDisplayWindow_->setBoundsConstrained(keyboardDisplayWindow_->getBounds());
+        
+        Rectangle<int> bounds = keyboardDisplayWindow_->getBounds();
+        if(bounds.getY() < 44)
+            bounds.setY(44);
+        keyboardDisplayWindow_->setBoundsConstrained(bounds);
     }
 #endif
     
--- a/Source/TouchKeys/TouchkeyDevice.cpp	Sat Jan 03 23:08:40 2015 +0000
+++ b/Source/TouchKeys/TouchkeyDevice.cpp	Mon Jan 05 18:06:43 2015 +0000
@@ -40,7 +40,8 @@
 rawDataThread_(boost::bind(&TouchkeyDevice::rawDataRunLoop, this, _1), "TouchKeyDevice::rawDataThread"),
 autoGathering_(false), shouldStop_(false), sendRawOscMessages_(false),
 verbose_(0), numOctaves_(0), lowestMidiNote_(48), lowestKeyPresentMidiNote_(48),
-updatedLowestMidiNote_(48), deviceSoftwareVersion_(-1), deviceHardwareVersion_(-1),
+updatedLowestMidiNote_(48), lowestNotePerOctave_(0),
+deviceSoftwareVersion_(-1), deviceHardwareVersion_(-1),
 expectedLengthWhite_(kTransmissionLengthWhiteNewHardware),
 expectedLengthBlack_(kTransmissionLengthBlackNewHardware), deviceHasRGBLEDs_(false),
 ledThread_(boost::bind(&TouchkeyDevice::ledUpdateLoop, this, _1), "TouchKeyDevice::ledThread"),
@@ -374,11 +375,20 @@
                             // be different from lowest connected key.
                             if(status.softwareVersionMajor >= 2) {
                                 lowestKeyPresentMidiNote_ = octaveKeyToMidi(0, status.lowestHardwareNote);
+                                
+                                if(status.softwareVersionMinor == 1) {
+                                    // Version 2.1 uses the lowest MIDI note to handle keyboards which don't
+                                    // begin and end at C, e.g. E-E or F-F keyboards.
+                                    lowestNotePerOctave_ = status.lowestHardwareNote;
+                                }
+                                else {
+                                    lowestNotePerOctave_ = 0;
+                                }
                             }
                             else if(lowestKeyPresentMidiNote_ == 127) // No keys found and old device software
                                 lowestKeyPresentMidiNote_ = lowestMidiNote_;
    
-                            keyboard_.setKeyboardGUIRange(lowestKeyPresentMidiNote_, lowestMidiNote_ + 12*numOctaves_);
+                            keyboard_.setKeyboardGUIRange(lowestKeyPresentMidiNote_, lowestMidiNote_ + 12*numOctaves_ + lowestNotePerOctave_);
                             calibrationInit(12*numOctaves_ + 1); // One more for the top C
 						}
 						else {
@@ -1208,10 +1218,31 @@
         lowestKeyPresentMidiNote_ += (note - lowestMidiNote_);
         lowestMidiNote_ = updatedLowestMidiNote_ = note;
         if(isOpen())
-            keyboard_.setKeyboardGUIRange(lowestMidiNote_, lowestMidiNote_ + 12*numOctaves_);
+            keyboard_.setKeyboardGUIRange(lowestKeyPresentMidiNote_, lowestMidiNote_ + 12*numOctaves_ + lowestNotePerOctave_);
     }
 }
 
+// Convert an octave and key designation into a MIDI note
+int TouchkeyDevice::octaveKeyToMidi(int octave, int key) {
+    int midi = lowestMidiNote_ + octave*12 + key;
+    
+    if(lowestNotePerOctave_ == 0)
+        return midi;
+    
+    // For keyboards which do not change octaves at C (e.g. E-E and F-F keyboards),
+    // the lowest note numbers are actually one octave higher (e.g. an octave might start
+    // at E, meaning C-Eb are part of the next higher octave).
+    // Also, the "top C" (key 12) has a special designation as being the top of
+    // whichever note the keyboard began at.
+    
+    if(key == 12)
+        midi = lowestMidiNote_ + octave*12 + key + lowestNotePerOctave_;
+    else if(key < lowestNotePerOctave_)
+        midi += 12;
+    
+    return midi;
+}
+
 // Loop for sending LED updates to the device, which must happen
 // in a separate thread from data collection so the device's capacity
 // to process incoming data doesn't gate its transmission of sensor data
@@ -1628,7 +1659,7 @@
                 if(keyboard_.key(i)->touchIsActive())
                     keyboard_.key(i)->touchOff(lastTimestamp_);
         
-        keyboard_.setKeyboardGUIRange(lowestMidiNote_, lowestMidiNote_ + 12*numOctaves_);
+        keyboard_.setKeyboardGUIRange(lowestKeyPresentMidiNote_, lowestMidiNote_ + 12*numOctaves_ + lowestNotePerOctave_);
     }
 	
 	//ioMutex_.exit();
--- a/Source/TouchKeys/TouchkeyDevice.h	Sat Jan 03 23:08:40 2015 +0000
+++ b/Source/TouchKeys/TouchkeyDevice.h	Mon Jan 05 18:06:43 2015 +0000
@@ -296,10 +296,10 @@
     
 	// Conversion between touchkey # and MIDI note
 	int lowestMidiNote() { return lowestMidiNote_; }
-    int highestMidiNote() { return lowestMidiNote_ + 12*numOctaves_; }
+    int highestMidiNote() { return lowestMidiNote_ + 12*numOctaves_ + lowestNotePerOctave_; }
     int lowestKeyPresentMidiNote() { return lowestKeyPresentMidiNote_; } // What is the lowest key actually connected?
 	void setLowestMidiNote(int note);
-	int octaveKeyToMidi(int octave, int key) { return lowestMidiNote_ + octave*12 + key; }
+    int octaveKeyToMidi(int octave, int key);
     
     // Sensor data display
     void setSensorDisplay(RawSensorDisplay *display) { sensorDisplay_ = display; }
@@ -378,6 +378,7 @@
 	int lowestMidiNote_;		// MIDI note number for the lowest C on the lowest octave
     int lowestKeyPresentMidiNote_; // MIDI note number for the lowest key actually attached
     int updatedLowestMidiNote_; // Lowest MIDI note if changed; held separately for thread sync
+    int lowestNotePerOctave_;   // Note which starts each octave, for non C-to-C keyboards
 	set<int> keysPresent_;		// Which keys (octave and note) are present on this device?
     int deviceSoftwareVersion_; // Which version of the device we're talking to
     int deviceHardwareVersion_; // Which version of the device hardware is running