changeset 6:36fe60d0aadb

Improve OSC input support and enable in the main GUI. External OSC input isn't used yet (aside from internal OSC handling) but this allows a server to run on a specified port.
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Wed, 13 Nov 2013 23:40:53 +0000
parents 0bcbe28a25a2
children 353276611036
files Builds/MacOSX/TouchKeys.xcodeproj/project.xcworkspace/xcuserdata/apm.xcuserdatad/UserInterfaceState.xcuserstate Source/GUI/ControlWindowMainComponent.cpp Source/MainApplicationController.cpp Source/MainApplicationController.h Source/TouchKeys/Osc.cpp Source/TouchKeys/Osc.h
diffstat 6 files changed, 125 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
Binary file Builds/MacOSX/TouchKeys.xcodeproj/project.xcworkspace/xcuserdata/apm.xcuserdatad/UserInterfaceState.xcuserstate has changed
--- a/Source/GUI/ControlWindowMainComponent.cpp	Wed Nov 13 21:00:16 2013 +0000
+++ b/Source/GUI/ControlWindowMainComponent.cpp	Wed Nov 13 23:40:53 2013 +0000
@@ -407,6 +407,7 @@
     else if (buttonThatWasClicked == oscInputEnableButton)
     {
         //[UserButtonCode_oscInputEnableButton] -- add your button handler code here..
+        controller_->oscReceiveSetEnabled(oscInputEnableButton->getToggleState());
         //[/UserButtonCode_oscInputEnableButton]
     }
     else if (buttonThatWasClicked == playLogButton)
@@ -454,6 +455,10 @@
         return;
     if(&editor == oscHostTextEditor || &editor == oscPortTextEditor)
         updateOscHostPort();
+    else if(&editor == oscInputPortTextEditor) {
+        int port = atoi(oscInputPortTextEditor->getText().toUTF8());
+        controller_->oscReceiveSetPort(port);
+    }
 }
 
 void ControlWindowMainComponent::textEditorEscapeKeyPressed(TextEditor &editor)
@@ -568,6 +573,7 @@
     // Update OSC status
     oscEnableButton->setToggleState(controller_->oscTransmitEnabled(), dontSendNotification);
     oscEnableRawButton->setToggleState(controller_->oscTransmitRawDataEnabled(), dontSendNotification);
+    oscInputEnableButton->setToggleState(controller_->oscReceiveEnabled(), dontSendNotification);
 
     // Update the OSC fields only if the text editors aren't active
     if(!oscHostTextEditor->hasKeyboardFocus(true) && !oscPortTextEditor->hasKeyboardFocus(true)) {
@@ -585,6 +591,10 @@
             oscPortTextEditor->setText(lo_address_get_port(firstAddress), false);
         }
     }
+    if(!oscInputPortTextEditor->hasKeyboardFocus(true)) {
+        int port = controller_->oscReceivePort();
+        oscInputPortTextEditor->setText(String(port), false);
+    }
 
     // Set the octave button
     int octave = (controller_->touchkeyDeviceLowestMidiNote() / 12) - 1;
--- a/Source/MainApplicationController.cpp	Wed Nov 13 21:00:16 2013 +0000
+++ b/Source/MainApplicationController.cpp	Wed Nov 13 23:40:53 2013 +0000
@@ -37,10 +37,13 @@
 MainApplicationController::MainApplicationController()
 : midiInputController_(keyboardController_),
   touchkeyController_(keyboardController_),
+  oscReceiveEnabled_(false),
+  oscReceiver_(0, ""),
   touchkeyErrorOccurred_(false),
   touchkeyErrorMessage_(""),
   touchkeyAutodetecting_(false),
   touchkeyStandaloneModeEnabled_(false),
+  oscReceivePort_(kDefaultOscReceivePort),
   experimentalMappingsEnabled_(false),
 #ifndef TOUCHKEYS_NO_GUI
   keyboardDisplayWindow_(0),
@@ -59,9 +62,6 @@
     keyboardController_.setGUI(&keyboardDisplay_);
 	midiInputController_.setMidiOutputController(&midiOutputController_);
     
-    // Set the initial mode of the MIDI input controller
-    //segment = midiSegmentAdd();
-    
 	// Set the initial verbosity level of the TouchKeys devices
 	touchkeyController_.setVerboseLevel(2);
     
--- a/Source/MainApplicationController.h	Wed Nov 13 21:00:16 2013 +0000
+++ b/Source/MainApplicationController.h	Wed Nov 13 23:40:53 2013 +0000
@@ -47,6 +47,7 @@
 
 const char kDefaultOscTransmitHost[] = "127.0.0.1";
 const char kDefaultOscTransmitPort[] = "8000";
+const int kDefaultOscReceivePort = 8001;
 
 class InterfaceSelectorComponent;
 
@@ -226,6 +227,40 @@
         return oscTransmitter_.clearAddresses();
     }
     
+    // OSC Input (receiver) methods
+    // Enable or disable on the OSC receive, and report is status
+    bool oscReceiveEnabled() {
+        return oscReceiveEnabled_;
+    }
+    // Enable method returns true on success (false only if it was
+    // unable to set the port)
+    bool oscReceiveSetEnabled(bool enable) {
+        if(enable && !oscReceiveEnabled_) {
+            oscReceiveEnabled_ = true;
+            return oscReceiver_.setPort(oscReceivePort_);
+        }
+        else if(!enable && oscReceiveEnabled_) {
+            oscReceiveEnabled_ = false;
+            return oscReceiver_.setPort(0);
+        }
+        return true;
+    }
+    
+    // Whether the OSC server is running (false means couldn't open port)
+    bool oscReceiveRunning() {
+        return oscReceiver_.running();
+    }
+    // Get the current OSC receive port
+    int oscReceivePort() {
+        return oscReceivePort_;
+    }
+    // Set the current OSC receive port (returns true on success)
+    bool oscReceiveSetPort(int port) {
+        oscReceivePort_ = port;
+        return oscReceiver_.setPort(port);
+    }
+    
+    
     // *** Display methods ***
     
     KeyboardDisplay& keyboardDisplay() { return keyboardDisplay_; }
@@ -282,12 +317,17 @@
     MidiOutputController midiOutputController_;
     TouchkeyDevice touchkeyController_;
     OscTransmitter oscTransmitter_;
+    OscReceiver oscReceiver_;
     
     bool touchkeyErrorOccurred_;
     std::string touchkeyErrorMessage_;
     bool touchkeyAutodetecting_;
     bool touchkeyStandaloneModeEnabled_;
-
+    
+    // OSC information
+    bool oscReceiveEnabled_;
+    int oscReceivePort_;
+    
     // Mapping objects
     bool experimentalMappingsEnabled_;
     
--- a/Source/TouchKeys/Osc.cpp	Wed Nov 13 21:00:16 2013 +0000
+++ b/Source/TouchKeys/Osc.cpp	Wed Nov 13 23:40:53 2013 +0000
@@ -379,6 +379,37 @@
     return 1;
 }
 
+// Set the current port for the OSC receiver object. This implies stopping and
+// restarting the server. Returns true on success.
+bool OscReceiver::setPort(const int port)
+{
+    // Stop existing server if running
+    if(oscServerThread_ != 0) {
+        lo_server_thread_del_method(oscServerThread_, NULL, NULL);
+        lo_server_thread_stop(oscServerThread_);
+        lo_server_thread_free(oscServerThread_);
+        oscServerThread_ = 0;
+    }
+    
+    // Port value 0 indicates to turn off; this always succeeds.
+    if(port == 0) {
+        return true;
+    }
+    
+    // Now create a new one on the new port
+    char portStr[16];
+    snprintf(portStr, 16, "%d", port);
+    
+    oscServerThread_ = lo_server_thread_new(portStr, staticErrorHandler);
+    if(oscServerThread_ != 0) {
+        lo_server_thread_add_method(oscServerThread_, NULL, NULL, OscReceiver::staticHandler, (void *)this);
+        lo_server_thread_start(oscServerThread_);
+        return true;
+    }
+    
+    return false;
+}
+
 #pragma mark OscTransmitter
 
 // Add a new transmit address.  Returns the index of the new address.
--- a/Source/TouchKeys/Osc.h	Wed Nov 13 21:00:16 2013 +0000
+++ b/Source/TouchKeys/Osc.h	Wed Nov 13 23:40:53 2013 +0000
@@ -96,18 +96,42 @@
 class OscReceiver : public OscMessageSource
 {
 public:
-	OscReceiver(lo_server_thread thread, const char *prefix) {
-		oscServerThread_ = thread;
-		globalPrefix_.assign(prefix);
+	OscReceiver(const int port, const char *prefix) {
+        globalPrefix_.assign(prefix);
 		useThru_ = false;
-		lo_server_thread_add_method(thread, NULL, NULL, OscReceiver::staticHandler, (void *)this);
-	}	
+        
+        // Only start the server if the port is positive
+        if(port > 0) {
+            char portStr[16];
+            snprintf(portStr, 16, "%d", port);
+            
+            oscServerThread_ = lo_server_thread_new(portStr, staticErrorHandler);
+            if(oscServerThread_ != 0) {
+                lo_server_thread_add_method(oscServerThread_, NULL, NULL, OscReceiver::staticHandler, (void *)this);
+                lo_server_thread_start(oscServerThread_);
+            }
+        }
+        else
+            oscServerThread_ = 0;
+	}
 	
 	void setThruAddress(lo_address thruAddr, const char *prefix) {
 		thruAddress_ = thruAddr;
 		thruPrefix_.assign(prefix);
 		useThru_ = true;
 	}
+    
+    // Check whether the server is operating
+    bool running() { return (oscServerThread_ != 0); }
+    
+    // Get or set the current port. Setting the port requires restarting the server.
+    // setPort() returns true on success; false if an error occurred (which will leave the server not running).
+    const int port() {
+        if(oscServerThread_ == 0)
+            return 0;
+        return lo_server_get_port(oscServerThread_);
+    }
+    bool setPort(const int port);
 	
 	// staticHandler() is called by liblo with new OSC messages.  Its only function is to pass control
 	// to the object-specific handler method, which has access to all internal variables.
@@ -115,11 +139,19 @@
 	int handler(const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *data);
 	static int staticHandler(const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *userData) {
 		return ((OscReceiver *)userData)->handler(path, types, argv, argc, msg, userData);
-	}	
+	}
+    
+    // staticErrorHandler() is called by liblo when an error occurs. For now, ignore errors.
+    
+    static void staticErrorHandler(int num, const char *msg, const char *path) {}
 	
 	~OscReceiver() {
-		lo_server_thread_del_method(oscServerThread_, NULL, NULL);
-	}	
+        if(oscServerThread_ != 0) {
+            lo_server_thread_del_method(oscServerThread_, NULL, NULL);
+            lo_server_thread_stop(oscServerThread_);
+            lo_server_thread_free(oscServerThread_);
+        }
+	}
 	
 private:
 	lo_server_thread oscServerThread_;		// Thread that handles received OSC messages