# HG changeset patch # User Andrew McPherson # Date 1384386053 0 # Node ID 36fe60d0aadbe6f126b23b199db5fb3d6b27f0f8 # Parent 0bcbe28a25a25727a776282f1d9700a0ecee48a2 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. diff -r 0bcbe28a25a2 -r 36fe60d0aadb Builds/MacOSX/TouchKeys.xcodeproj/project.xcworkspace/xcuserdata/apm.xcuserdatad/UserInterfaceState.xcuserstate Binary file Builds/MacOSX/TouchKeys.xcodeproj/project.xcworkspace/xcuserdata/apm.xcuserdatad/UserInterfaceState.xcuserstate has changed diff -r 0bcbe28a25a2 -r 36fe60d0aadb Source/GUI/ControlWindowMainComponent.cpp --- 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; diff -r 0bcbe28a25a2 -r 36fe60d0aadb Source/MainApplicationController.cpp --- 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); diff -r 0bcbe28a25a2 -r 36fe60d0aadb Source/MainApplicationController.h --- 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_; diff -r 0bcbe28a25a2 -r 36fe60d0aadb Source/TouchKeys/Osc.cpp --- 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. diff -r 0bcbe28a25a2 -r 36fe60d0aadb Source/TouchKeys/Osc.h --- 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