annotate Source/Mappings/TouchkeyBaseMapping.cpp @ 56:b4a2d2ae43cf tip

merge
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Fri, 23 Nov 2018 15:48:14 +0000
parents 3580ffe87dc8
children
rev   line source
andrewm@0 1 /*
andrewm@0 2 TouchKeys: multi-touch musical keyboard control software
andrewm@0 3 Copyright (c) 2013 Andrew McPherson
andrewm@0 4
andrewm@0 5 This program is free software: you can redistribute it and/or modify
andrewm@0 6 it under the terms of the GNU General Public License as published by
andrewm@0 7 the Free Software Foundation, either version 3 of the License, or
andrewm@0 8 (at your option) any later version.
andrewm@0 9
andrewm@0 10 This program is distributed in the hope that it will be useful,
andrewm@0 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
andrewm@0 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
andrewm@0 13 GNU General Public License for more details.
andrewm@0 14
andrewm@0 15 You should have received a copy of the GNU General Public License
andrewm@0 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
andrewm@0 17
andrewm@0 18 =====================================================================
andrewm@0 19
andrewm@0 20 TouchkeyBaseMapping.cpp: base class from which all TouchKeys-specific
andrewm@0 21 mappings derive. Like its Mapping parent class, it handles a mapping
andrewm@0 22 for one specific note.
andrewm@0 23 */
andrewm@0 24
andrewm@0 25 #include "TouchkeyBaseMapping.h"
andrewm@0 26 #include "MappingFactory.h"
andrewm@0 27 #include "../TouchKeys/MidiOutputController.h"
andrewm@0 28
andrewm@0 29 // Main constructor takes references/pointers from objects which keep track
andrewm@0 30 // of touch location, continuous key position and the state detected from that
andrewm@0 31 // position. The PianoKeyboard object is strictly required as it gives access to
andrewm@0 32 // Scheduler and OSC methods. The others are optional since any given system may
andrewm@0 33 // contain only one of continuous key position or touch sensitivity
andrewm@0 34 TouchkeyBaseMapping::TouchkeyBaseMapping(PianoKeyboard &keyboard, MappingFactory *factory, int noteNumber, Node<KeyTouchFrame>* touchBuffer,
andrewm@0 35 Node<key_position>* positionBuffer, KeyPositionTracker* positionTracker,
andrewm@0 36 bool finishesAutomatically)
andrewm@0 37 : Mapping(keyboard, factory, noteNumber, touchBuffer, positionBuffer, positionTracker),
andrewm@0 38 controlName_(""), noteIsOn_(false), finished_(true), finishRequested_(false), finishesAutomatically_(finishesAutomatically)
andrewm@0 39 {
andrewm@0 40 setOscController(&keyboard_);
andrewm@0 41 }
andrewm@0 42
andrewm@0 43 // Copy constructor
andrewm@0 44 /*TouchkeyBaseMapping::TouchkeyBaseMapping(TouchkeyBaseMapping const& obj)
andrewm@0 45 : Mapping(obj), noteIsOn_(obj.noteIsOn_), finished_(obj.finished_), finishRequested_(obj.finishRequested_),
andrewm@0 46 finishesAutomatically_(obj.finishesAutomatically_)
andrewm@0 47 {
andrewm@0 48 setOscController(&keyboard_);
andrewm@0 49 }*/
andrewm@0 50
andrewm@0 51 TouchkeyBaseMapping::~TouchkeyBaseMapping() {
andrewm@0 52 #ifndef NEW_MAPPING_SCHEDULER
andrewm@0 53 try {
andrewm@0 54 disengage();
andrewm@0 55 }
andrewm@0 56 catch(...) {
andrewm@0 57 std::cerr << "~TouchkeyBaseMapping(): exception during disengage()\n";
andrewm@0 58 }
andrewm@0 59 #endif
andrewm@0 60 }
andrewm@0 61
andrewm@0 62 // Turn on mapping of data.
andrewm@0 63 void TouchkeyBaseMapping::engage() {
andrewm@0 64 Mapping::engage();
andrewm@0 65
andrewm@0 66 // Register for OSC callbacks on MIDI note on/off
andrewm@0 67 addOscListener("/midi/noteon");
andrewm@0 68 addOscListener("/midi/noteoff");
andrewm@0 69
andrewm@0 70 //cout << "TouchkeyBaseMapping::engage(): after TS " << keyboard_.schedulerCurrentTimestamp() << std::endl;
andrewm@0 71 }
andrewm@0 72
andrewm@0 73 // Turn off mapping of data. Remove our callback from the scheduler
andrewm@0 74 void TouchkeyBaseMapping::disengage(bool shouldDelete) {
andrewm@0 75 // Remove OSC listeners first
andrewm@0 76 removeOscListener("/midi/noteon");
andrewm@0 77 removeOscListener("/midi/noteoff");
andrewm@0 78
andrewm@0 79 // Don't send any change in bend, let it stay where it is
andrewm@0 80
andrewm@0 81 Mapping::disengage(shouldDelete);
andrewm@0 82
andrewm@0 83 noteIsOn_ = false;
andrewm@0 84 }
andrewm@0 85
andrewm@0 86 // Reset state back to defaults
andrewm@0 87 void TouchkeyBaseMapping::reset() {
andrewm@0 88 Mapping::reset();
andrewm@0 89 noteIsOn_ = false;
andrewm@0 90 }
andrewm@0 91
andrewm@0 92 // Set the name of the control
andrewm@0 93 void TouchkeyBaseMapping::setName(const std::string& name) {
andrewm@0 94 controlName_ = name;
andrewm@0 95 }
andrewm@0 96
andrewm@0 97 // OSC handler method. Called from PianoKeyboard when MIDI data comes in.
andrewm@0 98 bool TouchkeyBaseMapping::oscHandlerMethod(const char *path, const char *types, int numValues, lo_arg **values, void *data) {
andrewm@0 99 if(!strcmp(path, "/midi/noteon") && !noteIsOn_ && numValues >= 1) {
andrewm@0 100 if(types[0] == 'i' && values[0]->i == noteNumber_) {
andrewm@0 101 // First notify the subclass of this event
andrewm@0 102 if(numValues >= 3)
andrewm@0 103 midiNoteOnReceived(values[1]->i, values[2]->i);
andrewm@0 104
andrewm@0 105 // When the MIDI note goes on, if the mapping doesn't finish automatically,
andrewm@0 106 // make sure we indicate we're busy so the factory doesn't delete the mapping when
andrewm@0 107 // touch and MIDI both stop. In this case, the subclass is responsible for notifying
andrewm@0 108 // the factory when finished.
andrewm@0 109 if(!finishesAutomatically_)
andrewm@0 110 finished_ = false;
andrewm@0 111 noteIsOn_ = true;
andrewm@0 112 return false;
andrewm@0 113 }
andrewm@0 114 }
andrewm@0 115 else if(!strcmp(path, "/midi/noteoff") && noteIsOn_ && numValues >= 1) {
andrewm@0 116 if(types[0] == 'i' && values[0]->i == noteNumber_) {
andrewm@0 117 // MIDI note goes off.
andrewm@0 118
andrewm@0 119 // First notify the subclass of this event
andrewm@0 120 if(numValues >= 2)
andrewm@0 121 midiNoteOffReceived(values[1]->i);
andrewm@0 122
andrewm@0 123 noteIsOn_ = false;
andrewm@0 124 return false;
andrewm@0 125 }
andrewm@0 126 }
andrewm@0 127
andrewm@0 128 return false;
andrewm@0 129 }
andrewm@0 130
andrewm@0 131 // Override the requestFinish method to return whether the object
andrewm@0 132 // can be deleted now or not. If not, delete it when we've finished the
andrewm@0 133 // release processing
andrewm@0 134 bool TouchkeyBaseMapping::requestFinish() {
andrewm@0 135 finishRequested_ = true;
andrewm@0 136 return finished_;
andrewm@0 137 }
andrewm@0 138
andrewm@0 139 // Acknowledge that the mapping is finished. Only relevant if the mapping doesn't
andrewm@0 140 // finish automatically.
andrewm@0 141 void TouchkeyBaseMapping::acknowledgeFinish() {
andrewm@0 142 if(!finishRequested_ || finishesAutomatically_)
andrewm@0 143 return;
andrewm@0 144 factory_->mappingFinished(noteNumber_);
andrewm@0 145 }