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