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: }