andrewm@0: /* andrewm@0: TouchKeys: multi-touch musical keyboard control software andrewm@0: Copyright (c) 2013 Andrew McPherson andrewm@0: andrewm@0: This program is free software: you can redistribute it and/or modify andrewm@0: it under the terms of the GNU General Public License as published by andrewm@0: the Free Software Foundation, either version 3 of the License, or andrewm@0: (at your option) any later version. andrewm@0: andrewm@0: This program is distributed in the hope that it will be useful, andrewm@0: but WITHOUT ANY WARRANTY; without even the implied warranty of andrewm@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the andrewm@0: GNU General Public License for more details. andrewm@0: andrewm@0: You should have received a copy of the GNU General Public License andrewm@0: along with this program. If not, see . andrewm@0: andrewm@0: ===================================================================== andrewm@0: andrewm@0: TouchkeyMultiFingerTriggerMappingFactory.cpp: factory for the multiple- andrewm@0: finger trigger mapping, which performs actions when two or more fingers andrewm@0: are added or removed from the key. andrewm@0: */ andrewm@0: andrewm@0: #include "TouchkeyMultiFingerTriggerMappingFactory.h" andrewm@42: #include "TouchkeyMultiFingerTriggerMappingShortEditor.h" andrewm@42: andrewm@42: TouchkeyMultiFingerTriggerMappingFactory::TouchkeyMultiFingerTriggerMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment) andrewm@42: : TouchkeyBaseMappingFactory(keyboard, segment), andrewm@42: numTouchesForTrigger_(TouchkeyMultiFingerTriggerMapping::kDefaultNumTouchesForTrigger), andrewm@42: numFramesForTrigger_(TouchkeyMultiFingerTriggerMapping::kDefaultNumFramesForTrigger), andrewm@42: numConsecutiveTapsForTrigger_(TouchkeyMultiFingerTriggerMapping::kDefaultNumConsecutiveTapsForTrigger), andrewm@42: maxTapSpacing_(TouchkeyMultiFingerTriggerMapping::kDefaultMaxTapSpacing), andrewm@42: needsMidiNoteOn_(true), andrewm@42: triggerOnAction_(TouchkeyMultiFingerTriggerMapping::kDefaultTriggerOnAction), andrewm@42: triggerOffAction_(TouchkeyMultiFingerTriggerMapping::kDefaultTriggerOffAction), andrewm@42: triggerOnNoteNum_(TouchkeyMultiFingerTriggerMapping::kDefaultTriggerOnNoteNum), andrewm@42: triggerOffNoteNum_(TouchkeyMultiFingerTriggerMapping::kDefaultTriggerOffNoteNum), andrewm@42: triggerOnNoteVel_(TouchkeyMultiFingerTriggerMapping::kDefaultTriggerOnNoteVel), andrewm@42: triggerOffNoteVel_(TouchkeyMultiFingerTriggerMapping::kDefaultTriggerOffNoteVel) andrewm@42: { andrewm@42: andrewm@42: } andrewm@42: andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::setTouchesForTrigger(int touches) { andrewm@42: if(touches < 1) andrewm@42: touches = 1; andrewm@42: if(touches > 3) andrewm@42: touches = 3; andrewm@42: numTouchesForTrigger_ = touches; andrewm@42: } andrewm@42: andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::setFramesForTrigger(int frames) { andrewm@42: if(frames < 1) andrewm@42: frames = 1; andrewm@42: numFramesForTrigger_ = frames; andrewm@42: } andrewm@42: andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::setConsecutiveTapsForTrigger(int taps) { andrewm@42: if(taps < 1) andrewm@42: taps = 1; andrewm@42: numConsecutiveTapsForTrigger_ = taps; andrewm@42: } andrewm@42: andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::setMaxTimeBetweenTapsForTrigger(timestamp_diff_type timeDiff) { andrewm@42: if(timeDiff < 0) andrewm@42: timeDiff = 0; andrewm@42: maxTapSpacing_ = timeDiff; andrewm@42: } andrewm@42: andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::setNeedsMidiNoteOn(bool needsMidi) { andrewm@42: needsMidiNoteOn_ = needsMidi; andrewm@42: } andrewm@42: andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::setTriggerOnAction(int action) { andrewm@42: if(action > 0 && action < TouchkeyMultiFingerTriggerMapping::kActionMax) andrewm@42: triggerOnAction_ = action; andrewm@42: } andrewm@42: andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::setTriggerOffAction(int action) { andrewm@42: if(action > 0 && action < TouchkeyMultiFingerTriggerMapping::kActionMax) andrewm@42: triggerOffAction_ = action; andrewm@42: } andrewm@42: andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::setTriggerOnNoteNumber(int note) { andrewm@42: triggerOnNoteNum_ = note; andrewm@42: } andrewm@42: andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::setTriggerOffNoteNumber(int note) { andrewm@42: triggerOffNoteNum_ = note; andrewm@42: } andrewm@42: andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::setTriggerOnNoteVelocity(int velocity) { andrewm@42: if(velocity > 127) andrewm@42: velocity = 127; andrewm@42: triggerOnNoteVel_ = velocity; andrewm@42: } andrewm@42: andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::setTriggerOffNoteVelocity(int velocity) { andrewm@42: if(velocity > 127) andrewm@42: velocity = 127; andrewm@42: triggerOffNoteVel_ = velocity; andrewm@42: } andrewm@42: andrewm@49: #ifndef TOUCHKEYS_NO_GUI andrewm@42: // ***** GUI Support ***** andrewm@42: MappingEditorComponent* TouchkeyMultiFingerTriggerMappingFactory::createBasicEditor() { andrewm@42: return new TouchkeyMultiFingerTriggerMappingShortEditor(*this); andrewm@42: } andrewm@49: #endif andrewm@49: andrewm@49: // ****** OSC Control Support ****** andrewm@49: OscMessage* TouchkeyMultiFingerTriggerMappingFactory::oscControlMethod(const char *path, const char *types, andrewm@49: int numValues, lo_arg **values, void *data) { andrewm@49: // TODO andrewm@49: andrewm@49: // If no match, check the base class andrewm@49: return TouchkeyBaseMappingFactory::oscControlMethod(path, types, numValues, values, data); andrewm@49: } andrewm@36: andrewm@36: // ****** Preset Save/Load ****** andrewm@36: XmlElement* TouchkeyMultiFingerTriggerMappingFactory::getPreset() { andrewm@36: PropertySet properties; andrewm@36: andrewm@36: storeCommonProperties(properties); andrewm@36: andrewm@42: properties.setValue("numTouchesForTrigger", numTouchesForTrigger_); andrewm@42: properties.setValue("numFramesForTrigger", numFramesForTrigger_); andrewm@42: properties.setValue("numConsecutiveTapsForTrigger", numConsecutiveTapsForTrigger_); andrewm@42: properties.setValue("maxTapSpacing", maxTapSpacing_); andrewm@42: properties.setValue("needsMidiNoteOn", needsMidiNoteOn_); andrewm@42: properties.setValue("triggerOnAction", triggerOnAction_); andrewm@42: properties.setValue("triggerOffAction", triggerOffAction_); andrewm@42: properties.setValue("triggerOnNoteNum", triggerOnNoteNum_); andrewm@42: properties.setValue("triggerOffNoteNum", triggerOffNoteNum_); andrewm@42: properties.setValue("triggerOnNoteVel", triggerOnNoteVel_); andrewm@42: properties.setValue("triggerOffNoteVel", triggerOffNoteVel_); andrewm@36: andrewm@36: XmlElement* preset = properties.createXml("MappingFactory"); andrewm@36: preset->setAttribute("type", "MultiFingerTrigger"); andrewm@36: andrewm@36: return preset; andrewm@36: } andrewm@36: andrewm@36: bool TouchkeyMultiFingerTriggerMappingFactory::loadPreset(XmlElement const* preset) { andrewm@36: if(preset == 0) andrewm@36: return false; andrewm@36: andrewm@36: PropertySet properties; andrewm@36: properties.restoreFromXml(*preset); andrewm@36: andrewm@36: if(!loadCommonProperties(properties)) andrewm@36: return false; andrewm@36: andrewm@42: // Load specific properties andrewm@42: if(properties.containsKey("numTouchesForTrigger")) andrewm@42: numTouchesForTrigger_ = properties.getIntValue("numTouchesForTrigger"); andrewm@42: if(properties.containsKey("numFramesForTrigger")) andrewm@42: numFramesForTrigger_ = properties.getIntValue("numFramesForTrigger"); andrewm@42: if(properties.containsKey("numConsecutiveTapsForTrigger")) andrewm@42: numConsecutiveTapsForTrigger_ = properties.getIntValue("numConsecutiveTapsForTrigger"); andrewm@42: if(properties.containsKey("maxTapSpacing")) andrewm@42: maxTapSpacing_ = properties.getDoubleValue("maxTapSpacing"); andrewm@42: if(properties.containsKey("needsMidiNoteOn")) andrewm@42: needsMidiNoteOn_ = properties.getBoolValue("needsMidiNoteOn"); andrewm@42: if(properties.containsKey("triggerOnAction")) andrewm@42: triggerOnAction_ = properties.getBoolValue("triggerOnAction"); andrewm@42: if(properties.containsKey("triggerOffAction")) andrewm@42: triggerOffAction_ = properties.getBoolValue("triggerOffAction"); andrewm@42: if(properties.containsKey("triggerOnNoteNum")) andrewm@42: triggerOnNoteNum_ = properties.getBoolValue("triggerOnNoteNum"); andrewm@42: if(properties.containsKey("triggerOffNoteNum")) andrewm@42: triggerOffNoteNum_ = properties.getBoolValue("triggerOffNoteNum"); andrewm@42: if(properties.containsKey("triggerOnNoteVel")) andrewm@42: triggerOnNoteVel_ = properties.getBoolValue("triggerOnNoteVel"); andrewm@42: if(properties.containsKey("triggerOffNoteVel")) andrewm@42: triggerOffNoteVel_ = properties.getBoolValue("triggerOffNoteVel"); andrewm@36: andrewm@36: return true; andrewm@36: } andrewm@42: andrewm@42: // ***** Private Methods ***** andrewm@42: andrewm@42: // Set the initial parameters for a new mapping andrewm@42: void TouchkeyMultiFingerTriggerMappingFactory::initializeMappingParameters(int noteNumber, TouchkeyMultiFingerTriggerMapping *mapping) { andrewm@42: mapping->setTouchesForTrigger(numTouchesForTrigger_); andrewm@42: mapping->setFramesForTrigger(numFramesForTrigger_); andrewm@42: mapping->setConsecutiveTapsForTrigger(numConsecutiveTapsForTrigger_); andrewm@42: mapping->setMaxTimeBetweenTapsForTrigger(maxTapSpacing_); andrewm@42: mapping->setNeedsMidiNoteOn(needsMidiNoteOn_); andrewm@42: mapping->setTriggerOnAction(triggerOnAction_); andrewm@42: mapping->setTriggerOffAction(triggerOffAction_); andrewm@42: mapping->setTriggerOnNoteNumber(triggerOnNoteNum_); andrewm@42: mapping->setTriggerOffNoteNumber(triggerOffNoteNum_); andrewm@42: mapping->setTriggerOnNoteVelocity(triggerOnNoteVel_); andrewm@42: mapping->setTriggerOffNoteVelocity(triggerOffNoteVel_); andrewm@42: }