Mercurial > hg > touchkeys
changeset 28:cfbcd31a54e7
First attempt at "rescan devices". Reloads TouchKeys and MIDI in/out devices. Sets MIDI in/out to Disabled if previous device not found. Does not yet handle order of devices changing.
Also fix some bugs:
-- Can now disable Standalone mode
-- Poly-AT now accounts for transposition
-- If TK device stops on error, GUI reflects it
-- Possible crash on quit should be fixed (needs more testing)
author | Andrew McPherson <andrewm@eecs.qmul.ac.uk> |
---|---|
date | Sun, 02 Mar 2014 22:31:54 +0000 |
parents | eef567a60146 |
children | f3efbf2984c3 |
files | Source/GUI/ControlWindowMainComponent.cpp Source/GUI/ControlWindowMainComponent.h Source/GUI/KeyboardZoneComponent.cpp Source/GUI/KeyboardZoneComponent.h Source/GUI/MainWindow.cpp Source/Main.cpp Source/MainApplicationController.cpp Source/MainApplicationController.h Source/TouchKeys/OscMidiConverter.cpp Source/TouchKeys/TouchkeyDevice.cpp Source/TouchKeys/TouchkeyDevice.h |
diffstat | 11 files changed, 113 insertions(+), 62 deletions(-) [+] |
line wrap: on
line diff
--- a/Source/GUI/ControlWindowMainComponent.cpp Sun Mar 02 19:25:50 2014 +0000 +++ b/Source/GUI/ControlWindowMainComponent.cpp Sun Mar 02 22:31:54 2014 +0000 @@ -517,11 +517,20 @@ midiInputDeviceComboBox->addItem("Disabled", 1); midiInputDeviceComboBox->addItem("TouchKeys Standalone", 2); counter = kMidiInputDeviceComboBoxOffset; + + // Check whether the currently selected ID still exists while + // we build the list + bool lastSelectedDeviceExists = false; for(it = devices.begin(); it != devices.end(); ++it) { midiInputDeviceComboBox->addItem((*it).second.c_str(), counter); midiInputDeviceIDs_.push_back(it->first); + if(it->first == lastSelectedMidiInputID_) + lastSelectedDeviceExists = true; counter++; } + + if(!lastSelectedDeviceExists) + controller_->disableAllMIDIInputPorts(); } void ControlWindowMainComponent::updateOscHostPort() @@ -539,6 +548,14 @@ void ControlWindowMainComponent::synchronize() { if(controller_ == 0) return; + + bool devicesUpdated = false; + + if(controller_->devicesShouldUpdate() != lastControllerUpdateDeviceCount_) { + lastControllerUpdateDeviceCount_ = controller_->devicesShouldUpdate(); + updateInputDeviceList(); + devicesUpdated = true; + } // Update TouchKeys status #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST @@ -571,7 +588,7 @@ if(selectedMidiInputDevices.empty()) { midiInputDeviceComboBox->setSelectedId(1, dontSendNotification); } - else if(selectedMidiInputDevices.front() != lastSelectedMidiInputID_){ + else if(selectedMidiInputDevices.front() != lastSelectedMidiInputID_ || devicesUpdated){ // Input has changed from before. Find it in vector // If there is more than one selected ID, we will only take the first one for // the current UI. This affects the display but not the functionality. @@ -644,7 +661,7 @@ // Synchronize every tab component for(int tab = 0; tab < keyboardZoneTabbedComponent->getNumTabs(); tab++) { KeyboardZoneComponent *component = static_cast<KeyboardZoneComponent*> (keyboardZoneTabbedComponent->getTabContentComponent(tab)); - component->synchronize(); + component->synchronize(devicesUpdated); } // Update add/remove buttons
--- a/Source/GUI/ControlWindowMainComponent.h Sun Mar 02 19:25:50 2014 +0000 +++ b/Source/GUI/ControlWindowMainComponent.h Sun Mar 02 22:31:54 2014 +0000 @@ -50,6 +50,7 @@ void setMainApplicationController(MainApplicationController *controller) { // Attach the user interface to the controller and vice-versa controller_ = controller; + lastControllerUpdateDeviceCount_ = controller_->devicesShouldUpdate(); updateInputDeviceList(); } @@ -89,6 +90,8 @@ std::vector<int> midiInputDeviceIDs_; int lastSelectedMidiInputID_; int lastSegmentUniqueIdentifier_; + + int lastControllerUpdateDeviceCount_; //[/UserVariables] //==============================================================================
--- a/Source/GUI/KeyboardZoneComponent.cpp Sun Mar 02 19:25:50 2014 +0000 +++ b/Source/GUI/KeyboardZoneComponent.cpp Sun Mar 02 22:31:54 2014 +0000 @@ -424,7 +424,12 @@ { if(keyboardSegment_ == 0 || controller_ == 0) return; - + + if(forceUpdates) { + // Update the controls to reflect the current state + updateOutputDeviceList(); + } + // Update note ranges std::pair<int, int> range = keyboardSegment_->noteRange(); if(!rangeLowComboBox->hasKeyboardFocus(true) || forceUpdates) { @@ -444,7 +449,7 @@ // Update MIDI output status int selectedMidiOutputDevice = controller_->selectedMIDIOutputPort(keyboardSegment_->outputPort()); - if(selectedMidiOutputDevice != lastSelectedMidiOutputID_) { + if(selectedMidiOutputDevice != lastSelectedMidiOutputID_ || forceUpdates) { if(selectedMidiOutputDevice == MidiOutputController::kMidiOutputNotOpen) midiOutputDeviceComboBox->setSelectedId(1, dontSendNotification); #ifndef JUCE_WINDOWS @@ -573,15 +578,24 @@ snprintf(virtualPortName, 24, "Virtual Port (%d)", keyboardSegment_->outputPort()); midiOutputDeviceComboBox->addItem(virtualPortName, 2); #endif - + + // Check whether the currently selected ID still exists while + // we build the list + bool lastSelectedDeviceExists = false; int counter = kMidiOutputDeviceComboBoxOffset; for(it = devices.begin(); it != devices.end(); ++it) { if(it->first < 0) continue; midiOutputDeviceComboBox->addItem((*it).second.c_str(), counter); midiOutputDeviceIDs_.push_back(it->first); + if(it->first == lastSelectedMidiOutputID_) + lastSelectedDeviceExists = true; counter++; } + + if(!lastSelectedDeviceExists) { + controller_->disableMIDIOutputPort(keyboardSegment_->outputPort()); + } } // Create a popup menu containing a list of mapping factories
--- a/Source/GUI/KeyboardZoneComponent.h Sun Mar 02 19:25:50 2014 +0000 +++ b/Source/GUI/KeyboardZoneComponent.h Sun Mar 02 22:31:54 2014 +0000 @@ -54,8 +54,6 @@ controller_ = controller; mappingListComponent->setMainApplicationController(controller_); if(controller_ != 0) { - // Update the controls to reflect the current state - updateOutputDeviceList(); synchronize(true); } } @@ -64,8 +62,6 @@ keyboardSegment_ = segment; mappingListComponent->setKeyboardSegment(keyboardSegment_); if(controller_ != 0) { - // Update the controls to reflect the current state - updateOutputDeviceList(); synchronize(true); } }
--- a/Source/GUI/MainWindow.cpp Sun Mar 02 19:25:50 2014 +0000 +++ b/Source/GUI/MainWindow.cpp Sun Mar 02 22:31:54 2014 +0000 @@ -252,7 +252,7 @@ case kCommandRescanDevices: result.setInfo("Rescan Devices", "Rescans available TouchKeys and MIDI devices", controlCategory, 0); result.setTicked(false); - result.setActive(false); + result.setActive(true); result.addDefaultKeypress ('R', ModifierKeys::commandModifier); break; case kCommandEnableExperimentalMappings: @@ -290,7 +290,7 @@ case kCommandNewPreset: break; case kCommandRescanDevices: - std::cout << "Rescan\n"; + controller_.tellDevicesToUpdate(); break; case kCommandEnableExperimentalMappings: controller_.setExperimentalMappingsEnabled(!controller_.experimentalMappingsEnabled());
--- a/Source/Main.cpp Sun Mar 02 19:25:50 2014 +0000 +++ b/Source/Main.cpp Sun Mar 02 22:31:54 2014 +0000 @@ -51,6 +51,9 @@ void shutdown() { // Add your application's shutdown code here.. + if(controller_.touchkeyDeviceIsRunning()) + controller_.stopTouchkeyDevice(); + mainWindow_ = nullptr; // (deletes our window) controller_.setKeyboardDisplayWindow(0); // Delete display window and disconnect from controller
--- a/Source/MainApplicationController.cpp Sun Mar 02 19:25:50 2014 +0000 +++ b/Source/MainApplicationController.cpp Sun Mar 02 22:31:54 2014 +0000 @@ -48,6 +48,7 @@ touchkeyErrorMessage_(""), touchkeyAutodetecting_(false), touchkeyStandaloneModeEnabled_(false), + deviceUpdateCounter_(0), oscReceiveEnabled_(false), oscReceivePort_(kDefaultOscReceivePort), experimentalMappingsEnabled_(false), @@ -367,7 +368,7 @@ touchkeyStandaloneModeEnabled_ = false; // Go through all segments and disable standalone mode for(int i = 0; i < midiInputController_.numSegments(); i++) { - midiInputController_.segment(i)->enableTouchkeyStandaloneMode(); + midiInputController_.segment(i)->disableTouchkeyStandaloneMode(); } }
--- a/Source/MainApplicationController.h Sun Mar 02 19:25:50 2014 +0000 +++ b/Source/MainApplicationController.h Sun Mar 02 22:31:54 2014 +0000 @@ -211,6 +211,13 @@ void midiTouchkeysStandaloneModeDisable(); bool midiTouchkeysStandaloneModeIsEnabled() { return touchkeyStandaloneModeEnabled_; } + // *** Update sync methods *** + // The controller maintains a variable that tells when the devices should be updated + // by the control window component. Whenever it changes value, the devices should be rescanned. + + int devicesShouldUpdate() { return deviceUpdateCounter_; } + void tellDevicesToUpdate() { deviceUpdateCounter_++; } + // *** OSC device methods *** bool oscTransmitEnabled() { @@ -357,6 +364,8 @@ std::string touchkeyErrorMessage_; bool touchkeyAutodetecting_; bool touchkeyStandaloneModeEnabled_; + int deviceUpdateCounter_; // Unique number that increments every time devices should + // be rescanned // OSC information bool oscReceiveEnabled_;
--- a/Source/TouchKeys/OscMidiConverter.cpp Sun Mar 02 19:25:50 2014 +0000 +++ b/Source/TouchKeys/OscMidiConverter.cpp Sun Mar 02 22:31:54 2014 +0000 @@ -490,7 +490,8 @@ midiOutputController_->sendAftertouchChannel(port, channel, roundedControlValue); } else if(controller_ == MidiKeyboardSegment::kControlPolyphonicAftertouch && note >= 0) { - midiOutputController_->sendAftertouchPoly(port, channel, note, roundedControlValue); + midiOutputController_->sendAftertouchPoly(port, channel, note + keyboardSegment_.outputTransposition(), + roundedControlValue); } else if(controllerIs14Bit_) { // LSB for controllers 0-31 are found on controllers 32-63
--- a/Source/TouchKeys/TouchkeyDevice.cpp Sun Mar 02 19:25:50 2014 +0000 +++ b/Source/TouchKeys/TouchkeyDevice.cpp Sun Mar 02 22:31:54 2014 +0000 @@ -39,7 +39,7 @@ ioThread_(boost::bind(&TouchkeyDevice::runLoop, this, _1), "TouchKeyDevice::ioThread"), rawDataThread_(boost::bind(&TouchkeyDevice::rawDataRunLoop, this, _1), "TouchKeyDevice::rawDataThread"), autoGathering_(false), shouldStop_(false), sendRawOscMessages_(false), -verbose_(1), numOctaves_(0), lowestMidiNote_(48), lowestKeyPresentMidiNote_(48), +verbose_(0), numOctaves_(0), lowestMidiNote_(48), lowestKeyPresentMidiNote_(48), updatedLowestMidiNote_(48), deviceSoftwareVersion_(-1), deviceHardwareVersion_(-1), expectedLengthWhite_(kTransmissionLengthWhiteNewHardware), expectedLengthBlack_(kTransmissionLengthBlackNewHardware), deviceHasRGBLEDs_(false), @@ -130,39 +130,39 @@ // Open the device #ifdef _MSC_VER // Open the serial port - serialHandle_ = CreateFile(inputDevicePath, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if(serialHandle_ == INVALID_HANDLE_VALUE) { - Logger::writeToLog("Unable to open serial port " + String(inputDevicePath)); - return false; - } - - // Set some serial parameters, though they don't actually affect the operation - // of the port since it is all native USB - DCB serialParams = { 0 }; - serialParams.DCBlength = sizeof(serialParams); - - if(!BuildCommDCBA("baud=1000000 data=8 parity=N stop=1 dtr=on rts=on", &serialParams)) { - Logger::writeToLog("Unable to create port settings\n"); - CloseHandle(serialHandle_); - serialHandle_ = INVALID_HANDLE_VALUE; - return false; - } - - if(!SetCommState(serialHandle_, &serialParams)) { - Logger::writeToLog("Unable to set comm state\n"); - CloseHandle(serialHandle_); - serialHandle_ = INVALID_HANDLE_VALUE; - return false; - } - - // Set timeouts - COMMTIMEOUTS timeout = { 0 }; - timeout.ReadIntervalTimeout = MAXDWORD; - timeout.ReadTotalTimeoutConstant = 0; - timeout.ReadTotalTimeoutMultiplier = 0; - timeout.WriteTotalTimeoutConstant = 0; - timeout.WriteTotalTimeoutMultiplier = 0; - + serialHandle_ = CreateFile(inputDevicePath, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if(serialHandle_ == INVALID_HANDLE_VALUE) { + Logger::writeToLog("Unable to open serial port " + String(inputDevicePath)); + return false; + } + + // Set some serial parameters, though they don't actually affect the operation + // of the port since it is all native USB + DCB serialParams = { 0 }; + serialParams.DCBlength = sizeof(serialParams); + + if(!BuildCommDCBA("baud=1000000 data=8 parity=N stop=1 dtr=on rts=on", &serialParams)) { + Logger::writeToLog("Unable to create port settings\n"); + CloseHandle(serialHandle_); + serialHandle_ = INVALID_HANDLE_VALUE; + return false; + } + + if(!SetCommState(serialHandle_, &serialParams)) { + Logger::writeToLog("Unable to set comm state\n"); + CloseHandle(serialHandle_); + serialHandle_ = INVALID_HANDLE_VALUE; + return false; + } + + // Set timeouts + COMMTIMEOUTS timeout = { 0 }; + timeout.ReadIntervalTimeout = MAXDWORD; + timeout.ReadTotalTimeoutConstant = 0; + timeout.ReadTotalTimeoutMultiplier = 0; + timeout.WriteTotalTimeoutConstant = 0; + timeout.WriteTotalTimeoutMultiplier = 0; + if(!SetCommTimeouts(serialHandle_, &timeout)) { Logger::writeToLog("Unable to set timeouts\n"); CloseHandle(serialHandle_); @@ -444,18 +444,20 @@ } // Stop the run loop if applicable -void TouchkeyDevice::stopAutoGathering() { +void TouchkeyDevice::stopAutoGathering(bool writeStopCommandToDevice) { // Check if actually running if(!autoGathering_ || !isOpen()) return; // Stop any calibration in progress calibrationAbort(); - // Tell device to stop scanning - if(deviceWrite((char*)kCommandStopScanning, 5) < 0) { - if(verbose_ >= 1) - cout << "ERROR: unable to write stopAutoGather command. errno = " << errno << endl; - } + if(writeStopCommandToDevice) { + // Tell device to stop scanning + if(deviceWrite((char*)kCommandStopScanning, 5) < 0) { + if(verbose_ >= 1) + cout << "ERROR: unable to write stopAutoGather command. errno = " << errno << endl; + } + } // Setting this to true tells the run loop to exit what it's doing shouldStop_ = true; @@ -466,12 +468,15 @@ // Wait for run loop thread to finish. Set a timeout in case there's // some sort of device hangup - if(ioThread_.isThreadRunning()) - ioThread_.stopThread(3000); - if(ledThread_.isThreadRunning()) - ledThread_.stopThread(3000); - if(rawDataThread_.isThreadRunning()) - rawDataThread_.stopThread(3000); + if(ioThread_.getThreadId() != Thread::getCurrentThreadId()) + if(ioThread_.isThreadRunning()) + ioThread_.stopThread(3000); + if(ledThread_.getThreadId() != Thread::getCurrentThreadId()) + if(ledThread_.isThreadRunning()) + ledThread_.stopThread(3000); + if(rawDataThread_.getThreadId() != Thread::getCurrentThreadId()) + if(rawDataThread_.isThreadRunning()) + rawDataThread_.stopThread(3000); // Stop any currently playing notes keyboard_.sendMessage("/touchkeys/allnotesoff", "", LO_ARGS_END); @@ -1285,7 +1290,8 @@ if(errno != EAGAIN) { // EAGAIN just means no data was available if(verbose_ >= 1) cout << "Unable to read from device (error " << errno << "). Aborting.\n"; - shouldStop_ = true; + stopAutoGathering(false); + //shouldStop_ = true; } #ifdef _MSC_VER @@ -1422,7 +1428,8 @@ if(errno != EAGAIN) { // EAGAIN just means no data was available if(verbose_ >= 1) cout << "Unable to read from device (error " << errno << "). Aborting.\n"; - shouldStop_ = true; + stopAutoGathering(false); + //shouldStop_ = true; } #ifdef _MSC_VER
--- a/Source/TouchKeys/TouchkeyDevice.h Sun Mar 02 19:25:50 2014 +0000 +++ b/Source/TouchKeys/TouchkeyDevice.h Sun Mar 02 22:31:54 2014 +0000 @@ -232,7 +232,7 @@ // Start or stop the processing. startAutoGathering() returns // true on success. bool startAutoGathering(); - void stopAutoGathering(); + void stopAutoGathering(bool writeStopCommandToDevice = true); // Status query methods bool isOpen();