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: MappingFactorySplitter.cpp: MappingFactory subclass which in turn contains andrewm@0: several factories, routing all incoming method calls to each of them. andrewm@0: */ andrewm@0: andrewm@0: #include "MappingFactorySplitter.h" andrewm@0: andrewm@0: // Look up a mapping with the given note number andrewm@0: Mapping* MappingFactorySplitter::mapping(int noteNumber) { andrewm@0: // TODO: find a mapping in any of the factories andrewm@0: if(factories_.empty()) andrewm@0: return 0; andrewm@0: return (*factories_.begin())->mapping(noteNumber); andrewm@0: } andrewm@0: andrewm@0: // Return a list of all active notes andrewm@0: std::vector MappingFactorySplitter::activeMappings() { andrewm@0: // TODO: merge all active factories andrewm@0: if(factories_.empty()) { andrewm@0: return std::vector(); andrewm@0: } andrewm@0: return (*factories_.begin())->activeMappings(); andrewm@0: } andrewm@0: andrewm@0: // Remove all active mappings andrewm@0: void MappingFactorySplitter::removeAllMappings() { andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->removeAllMappings(); andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // Suspend messages from a particular note andrewm@0: void MappingFactorySplitter::suspendMapping(int noteNumber) { andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->suspendMapping(noteNumber); andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // Suspend messages from all notes andrewm@0: void MappingFactorySplitter::suspendAllMappings() { andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->suspendAllMappings(); andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // Resume messages from a particular note andrewm@0: void MappingFactorySplitter::resumeMapping(int noteNumber, bool resend) { andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->resumeMapping(noteNumber, resend); andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // Resume messages from all notes andrewm@0: void MappingFactorySplitter::resumeAllMappings(bool resend) { andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->resumeAllMappings(resend); andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // Whether the component parts of this mapping are bypassed andrewm@0: int MappingFactorySplitter::bypassed() { andrewm@0: if(factories_.empty()) andrewm@0: return bypassNewMappings_; andrewm@0: bool bypassOn = false, bypassOff = false; andrewm@0: andrewm@0: std::list::iterator it; andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: if((*it)->bypassed()) andrewm@0: bypassOn = true; andrewm@0: else andrewm@0: bypassOff = true; andrewm@0: } andrewm@0: andrewm@0: // Three states: all on, all off, or some on + some off (mixed) andrewm@0: if(bypassOn && !bypassOff) andrewm@0: return kBypassOn; andrewm@0: if(bypassOff && !bypassOn) andrewm@0: return kBypassOff; andrewm@0: return kBypassMixed; andrewm@0: } andrewm@0: andrewm@0: // Set whether the component parts are bypassed andrewm@0: void MappingFactorySplitter::setBypassed(bool bypass) { andrewm@0: std::list::iterator it; andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->setBypassed(bypass); andrewm@0: } andrewm@0: bypassNewMappings_ = bypass; andrewm@0: } andrewm@0: andrewm@0: // Add a factory to the list andrewm@0: void MappingFactorySplitter::addFactory(MappingFactory* factory) { andrewm@0: if(bypassNewMappings_) andrewm@0: factory->setBypassed(true); andrewm@0: factories_.push_back(factory); andrewm@0: } andrewm@0: andrewm@0: // Remove a factory from the list andrewm@0: void MappingFactorySplitter::removeFactory(MappingFactory* factory) { andrewm@0: // Assume allocation/deallocation takes place elsewhere andrewm@0: std::list::iterator it = factories_.begin(); andrewm@0: andrewm@0: while(it != factories_.end()) { andrewm@0: if(*it == factory) andrewm@0: factories_.erase(it++); andrewm@0: else andrewm@0: it++; andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // Remove all factories from the list andrewm@0: void MappingFactorySplitter::removeAllFactories() { andrewm@0: // Assume allocation/deallocation takes place elsewhere andrewm@0: factories_.clear(); andrewm@0: } andrewm@0: andrewm@33: // Generate XML element with preset settings andrewm@33: XmlElement* MappingFactorySplitter::getPreset() { andrewm@33: XmlElement *preset = new XmlElement("MappingFactory"); andrewm@33: preset->setAttribute("type", "Splitter"); andrewm@33: return preset; andrewm@33: } andrewm@33: andrewm@33: bool MappingFactorySplitter::loadPreset(XmlElement const* preset) { andrewm@33: return true; andrewm@33: } andrewm@33: andrewm@0: // Touch becomes active on a key where it wasn't previously andrewm@0: void MappingFactorySplitter::touchBegan(int noteNumber, bool midiNoteIsOn, bool keyMotionActive, andrewm@0: Node* touchBuffer, andrewm@0: Node* positionBuffer, andrewm@0: KeyPositionTracker* positionTracker) { andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->touchBegan(noteNumber, midiNoteIsOn, keyMotionActive, andrewm@0: touchBuffer, positionBuffer, positionTracker); andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // Touch ends on a key where it wasn't previously andrewm@0: void MappingFactorySplitter::touchEnded(int noteNumber, bool midiNoteIsOn, bool keyMotionActive, andrewm@0: Node* touchBuffer, andrewm@0: Node* positionBuffer, andrewm@0: KeyPositionTracker* positionTracker) { andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->touchEnded(noteNumber, midiNoteIsOn, keyMotionActive, andrewm@0: touchBuffer, positionBuffer, positionTracker); andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // MIDI note on for a key andrewm@0: void MappingFactorySplitter::midiNoteOn(int noteNumber, bool touchIsOn, bool keyMotionActive, andrewm@0: Node* touchBuffer, andrewm@0: Node* positionBuffer, andrewm@0: KeyPositionTracker* positionTracker) { andrewm@0: andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->midiNoteOn(noteNumber, touchIsOn, keyMotionActive, andrewm@0: touchBuffer, positionBuffer, positionTracker); andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // MIDI note off for a key andrewm@0: void MappingFactorySplitter::midiNoteOff(int noteNumber, bool touchIsOn, bool keyMotionActive, andrewm@0: Node* touchBuffer, andrewm@0: Node* positionBuffer, andrewm@0: KeyPositionTracker* positionTracker) { andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->midiNoteOff(noteNumber, touchIsOn, keyMotionActive, andrewm@0: touchBuffer, positionBuffer, positionTracker); andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // Key goes active from continuous key position andrewm@0: void MappingFactorySplitter::keyMotionActive(int noteNumber, bool midiNoteIsOn, bool touchIsOn, andrewm@0: Node* touchBuffer, andrewm@0: Node* positionBuffer, andrewm@0: KeyPositionTracker* positionTracker) { andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->keyMotionActive(noteNumber, midiNoteIsOn, touchIsOn, andrewm@0: touchBuffer, positionBuffer, positionTracker); andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // Key goes idle from continuous key position andrewm@0: void MappingFactorySplitter::keyMotionIdle(int noteNumber, bool midiNoteIsOn, bool touchIsOn, andrewm@0: Node* touchBuffer, andrewm@0: Node* positionBuffer, andrewm@0: KeyPositionTracker* positionTracker) { andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->keyMotionIdle(noteNumber, midiNoteIsOn, touchIsOn, andrewm@0: touchBuffer, positionBuffer, positionTracker); andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: // MIDI note about to begin andrewm@0: void MappingFactorySplitter::noteWillBegin(int noteNumber, int midiChannel, int midiVelocity) { andrewm@0: std::list::iterator it; andrewm@0: andrewm@0: for(it = factories_.begin(); it != factories_.end(); ++it) { andrewm@0: (*it)->noteWillBegin(noteNumber, midiChannel, midiVelocity); andrewm@0: } andrewm@0: }