Mercurial > hg > touchkeys
diff Source/Mappings/TouchkeyBaseMapping.cpp @ 0:3580ffe87dc8
First commit of TouchKeys public pre-release.
author | Andrew McPherson <andrewm@eecs.qmul.ac.uk> |
---|---|
date | Mon, 11 Nov 2013 18:19:35 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/Mappings/TouchkeyBaseMapping.cpp Mon Nov 11 18:19:35 2013 +0000 @@ -0,0 +1,145 @@ +/* + TouchKeys: multi-touch musical keyboard control software + Copyright (c) 2013 Andrew McPherson + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + ===================================================================== + + TouchkeyBaseMapping.cpp: base class from which all TouchKeys-specific + mappings derive. Like its Mapping parent class, it handles a mapping + for one specific note. +*/ + +#include "TouchkeyBaseMapping.h" +#include "MappingFactory.h" +#include "../TouchKeys/MidiOutputController.h" + +// Main constructor takes references/pointers from objects which keep track +// of touch location, continuous key position and the state detected from that +// position. The PianoKeyboard object is strictly required as it gives access to +// Scheduler and OSC methods. The others are optional since any given system may +// contain only one of continuous key position or touch sensitivity +TouchkeyBaseMapping::TouchkeyBaseMapping(PianoKeyboard &keyboard, MappingFactory *factory, int noteNumber, Node<KeyTouchFrame>* touchBuffer, + Node<key_position>* positionBuffer, KeyPositionTracker* positionTracker, + bool finishesAutomatically) +: Mapping(keyboard, factory, noteNumber, touchBuffer, positionBuffer, positionTracker), + controlName_(""), noteIsOn_(false), finished_(true), finishRequested_(false), finishesAutomatically_(finishesAutomatically) +{ + setOscController(&keyboard_); +} + +// Copy constructor +/*TouchkeyBaseMapping::TouchkeyBaseMapping(TouchkeyBaseMapping const& obj) +: Mapping(obj), noteIsOn_(obj.noteIsOn_), finished_(obj.finished_), finishRequested_(obj.finishRequested_), + finishesAutomatically_(obj.finishesAutomatically_) +{ + setOscController(&keyboard_); +}*/ + +TouchkeyBaseMapping::~TouchkeyBaseMapping() { +#ifndef NEW_MAPPING_SCHEDULER + try { + disengage(); + } + catch(...) { + std::cerr << "~TouchkeyBaseMapping(): exception during disengage()\n"; + } +#endif +} + +// Turn on mapping of data. +void TouchkeyBaseMapping::engage() { + Mapping::engage(); + + // Register for OSC callbacks on MIDI note on/off + addOscListener("/midi/noteon"); + addOscListener("/midi/noteoff"); + + //cout << "TouchkeyBaseMapping::engage(): after TS " << keyboard_.schedulerCurrentTimestamp() << std::endl; +} + +// Turn off mapping of data. Remove our callback from the scheduler +void TouchkeyBaseMapping::disengage(bool shouldDelete) { + // Remove OSC listeners first + removeOscListener("/midi/noteon"); + removeOscListener("/midi/noteoff"); + + // Don't send any change in bend, let it stay where it is + + Mapping::disengage(shouldDelete); + + noteIsOn_ = false; +} + +// Reset state back to defaults +void TouchkeyBaseMapping::reset() { + Mapping::reset(); + noteIsOn_ = false; +} + +// Set the name of the control +void TouchkeyBaseMapping::setName(const std::string& name) { + controlName_ = name; +} + +// OSC handler method. Called from PianoKeyboard when MIDI data comes in. +bool TouchkeyBaseMapping::oscHandlerMethod(const char *path, const char *types, int numValues, lo_arg **values, void *data) { + if(!strcmp(path, "/midi/noteon") && !noteIsOn_ && numValues >= 1) { + if(types[0] == 'i' && values[0]->i == noteNumber_) { + // First notify the subclass of this event + if(numValues >= 3) + midiNoteOnReceived(values[1]->i, values[2]->i); + + // When the MIDI note goes on, if the mapping doesn't finish automatically, + // make sure we indicate we're busy so the factory doesn't delete the mapping when + // touch and MIDI both stop. In this case, the subclass is responsible for notifying + // the factory when finished. + if(!finishesAutomatically_) + finished_ = false; + noteIsOn_ = true; + return false; + } + } + else if(!strcmp(path, "/midi/noteoff") && noteIsOn_ && numValues >= 1) { + if(types[0] == 'i' && values[0]->i == noteNumber_) { + // MIDI note goes off. + + // First notify the subclass of this event + if(numValues >= 2) + midiNoteOffReceived(values[1]->i); + + noteIsOn_ = false; + return false; + } + } + + return false; +} + +// Override the requestFinish method to return whether the object +// can be deleted now or not. If not, delete it when we've finished the +// release processing +bool TouchkeyBaseMapping::requestFinish() { + finishRequested_ = true; + return finished_; +} + +// Acknowledge that the mapping is finished. Only relevant if the mapping doesn't +// finish automatically. +void TouchkeyBaseMapping::acknowledgeFinish() { + if(!finishRequested_ || finishesAutomatically_) + return; + factory_->mappingFinished(noteNumber_); +}