/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Rosegarden A sequencer and musical notation editor. Copyright 2000-2011 the Rosegarden development team. See the AUTHORS file for more details. 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 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include #include "MappedStudio.h" #include "SoundDriver.h" #include "PluginFactory.h" #include "misc/Strings.h" #include "misc/Debug.h" #include // for mutex // #define DEBUG_MAPPEDSTUDIO 1 namespace Rosegarden { static pthread_mutex_t _mappedObjectContainerLock; #ifdef DEBUG_MAPPEDSTUDIO static int _approxLockCount = 0; #endif static inline void getLock(const char *file, int line) { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "Acquiring MappedStudio container lock at " << file << ":" << line << ": count " << _approxLockCount++ << std::endl; #endif pthread_mutex_lock(&_mappedObjectContainerLock); } static inline void releaseLock(const char *file, int line) { pthread_mutex_unlock(&_mappedObjectContainerLock); #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "Released container lock at " << file << ":" << line << ": count " << --_approxLockCount << std::endl; #endif } #define GET_LOCK getLock(__FILE__,__LINE__) #define RELEASE_LOCK releaseLock(__FILE__,__LINE__) // These stream functions are stolen and adapted from Qt3 QVector // // ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. // QDataStream& operator>>(QDataStream& s, MappedObjectIdList& v) { v.clear(); Q_UINT32 c; s >> c; v.resize(c); for (Q_UINT32 i = 0; i < c; ++i) { MappedObjectId t; s >> t; v[i] = t; } return s; } QDataStream& operator<<(QDataStream& s, const MappedObjectIdList& v) { s << (Q_UINT32)v.size(); MappedObjectIdList::const_iterator it = v.begin(); for ( ; it != v.end(); ++it ) s << *it; return s; } QDataStream& operator>>(QDataStream& s, MappedObjectPropertyList& v) { v.clear(); Q_UINT32 c; s >> c; v.resize(c); for (Q_UINT32 i = 0; i < c; ++i) { MappedObjectProperty t; s >> t; v[i] = t; } return s; } QDataStream& operator<<(QDataStream& s, const MappedObjectPropertyList& v) { s << (Q_UINT32)v.size(); MappedObjectPropertyList::const_iterator it = v.begin(); for ( ; it != v.end(); ++it ) s << *it; return s; } QDataStream& operator>>(QDataStream& s, MappedObjectValueList& v) { v.clear(); Q_UINT32 c; s >> c; v.resize(c); for (Q_UINT32 i = 0; i < c; ++i) { MappedObjectValue t; s >> t; v[i] = t; } return s; } QDataStream& operator<<(QDataStream& s, const MappedObjectValueList& v) { s << (Q_UINT32)v.size(); MappedObjectValueList::const_iterator it = v.begin(); for ( ; it != v.end(); ++it ) s << *it; return s; } // Define our object properties - these can be queried and set. // // General things // const MappedObjectProperty MappedObject::Name = "name"; const MappedObjectProperty MappedObject::Instrument = "instrument"; const MappedObjectProperty MappedObject::Position = "position"; const MappedObjectProperty MappedConnectableObject::ConnectionsIn = "connectionsIn"; const MappedObjectProperty MappedConnectableObject::ConnectionsOut = "connectionsOut"; const MappedObjectProperty MappedAudioFader::Channels = "channels"; const MappedObjectProperty MappedAudioFader::FaderLevel = "faderLevel"; const MappedObjectProperty MappedAudioFader::FaderRecordLevel = "faderRecordLevel"; const MappedObjectProperty MappedAudioFader::Pan = "pan"; const MappedObjectProperty MappedAudioFader::InputChannel = "inputChannel"; const MappedObjectProperty MappedAudioBuss::BussId = "bussId"; const MappedObjectProperty MappedAudioBuss::Level = "level"; const MappedObjectProperty MappedAudioBuss::Pan = "pan"; const MappedObjectProperty MappedAudioInput::InputNumber = "inputNumber"; const MappedObjectProperty MappedPluginSlot::Identifier = "identifier"; const MappedObjectProperty MappedPluginSlot::PluginName = "pluginname"; const MappedObjectProperty MappedPluginSlot::Label = "label"; const MappedObjectProperty MappedPluginSlot::Author = "author"; const MappedObjectProperty MappedPluginSlot::Copyright = "copyright"; const MappedObjectProperty MappedPluginSlot::Category = "category"; const MappedObjectProperty MappedPluginSlot::PortCount = "portcount"; const MappedObjectProperty MappedPluginSlot::Ports = "ports"; const MappedObjectProperty MappedPluginSlot::Instrument = "instrument"; const MappedObjectProperty MappedPluginSlot::Position = "position"; const MappedObjectProperty MappedPluginSlot::Bypassed = "bypassed"; const MappedObjectProperty MappedPluginSlot::Programs = "programs"; const MappedObjectProperty MappedPluginSlot::Program = "program"; const MappedObjectProperty MappedPluginSlot::Configuration = "configuration"; const MappedObjectProperty MappedPluginPort::PortNumber = "portnumber"; const MappedObjectProperty MappedPluginPort::Name = "name"; const MappedObjectProperty MappedPluginPort::Minimum = "minimum"; const MappedObjectProperty MappedPluginPort::Maximum = "maximum"; const MappedObjectProperty MappedPluginPort::Default = "default"; const MappedObjectProperty MappedPluginPort::DisplayHint = "displayhint"; const MappedObjectProperty MappedPluginPort::Value = "value"; // --------- MappedObject --------- // void MappedObject::addChild(MappedObject *object) { std::vector::iterator it = m_children.begin(); for (; it != m_children.end(); it++) if ((*it) == object) return ; m_children.push_back(object); } void MappedObject::removeChild(MappedObject *object) { std::vector::iterator it = m_children.begin(); for (; it != m_children.end(); it++) { if ((*it) == object) { m_children.erase(it); return ; } } } // Return all child ids // MappedObjectPropertyList MappedObject::getChildren() { MappedObjectPropertyList list; std::vector::iterator it = m_children.begin(); for (; it != m_children.end(); it++) list.push_back(QString("%1").arg((*it)->getId())); return list; } // Return all child ids of a certain type // MappedObjectPropertyList MappedObject::getChildren(MappedObjectType type) { MappedObjectPropertyList list; std::vector::iterator it = m_children.begin(); for (; it != m_children.end(); it++) { if ((*it)->getType() == type) list.push_back(QString("%1").arg((*it)->getId())); } return list; } void MappedObject::destroyChildren() { // remove references from the studio as well as from the object MappedObject *studioObject = getParent(); while (!dynamic_cast(studioObject)) studioObject = studioObject->getParent(); // see note in destroy() below std::vector children = m_children; m_children.clear(); std::vector::iterator it = children.begin(); for (; it != children.end(); it++) (*it)->destroy(); // remove from studio and destroy } // Destroy this object and remove it from the studio and // do the same for all its children. // void MappedObject::destroy() { MappedObject *studioObject = getParent(); while (!dynamic_cast(studioObject)) studioObject = studioObject->getParent(); MappedStudio *studio = dynamic_cast(studioObject); // The destroy method on each child calls studio->clearObject, // which calls back on the parent (in this case us) to remove the // child. (That's necessary for the case of destroying a plugin, // where we need to remove it from its plugin manager -- etc.) So // we don't want to be iterating over m_children here, as it will // change from under us. std::vector children = m_children; m_children.clear(); std::vector::iterator it = children.begin(); for (; it != children.end(); it++) { (*it)->destroy(); } (void)studio->clearObject(m_id); delete this; } // ------- MappedStudio ------- // MappedStudio::MappedStudio() : MappedObject(0, "MappedStudio", Studio, 0), m_runningObjectId(1) { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); #ifdef HAVE_PTHREAD_MUTEX_RECURSIVE pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); #else #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(__FreeBSD__) pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); #else pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); #endif #endif pthread_mutex_init(&_mappedObjectContainerLock, &attr); } MappedStudio::~MappedStudio() { #ifdef DEBUG_MAPPEDSTUDIO std::cout << "MappedStudio::~MappedStudio" << std::endl; #endif clear(); } // Object factory // MappedObject* MappedStudio::createObject(MappedObjectType type) { GET_LOCK; MappedObject *mO = 0; // Ensure we've got an empty slot // while (getObjectById(m_runningObjectId)) m_runningObjectId++; mO = createObject(type, m_runningObjectId); // If we've got a new object increase the running id // if (mO) m_runningObjectId++; RELEASE_LOCK; return mO; } MappedObject* MappedStudio::createObject(MappedObjectType type, MappedObjectId id) { GET_LOCK; // fail if the object already exists and it's not zero if (id != 0 && getObjectById(id)) { RELEASE_LOCK; return 0; } MappedObject *mO = 0; if (type == MappedObject::AudioFader) { mO = new MappedAudioFader(this, id, 2); // channels // push to the studio's child stack addChild(mO); } else if (type == MappedObject::AudioBuss) { mO = new MappedAudioBuss(this, id); // push to the studio's child stack addChild(mO); } else if (type == MappedObject::AudioInput) { mO = new MappedAudioInput(this, id); // push to the studio's child stack addChild(mO); } else if (type == MappedObject::PluginSlot) { mO = new MappedPluginSlot(this, id); addChild(mO); } else if (type == MappedObject::PluginPort) { mO = new MappedPluginPort(this, id); // reset the port's parent after creation outside this method } // Insert if (mO) { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "Adding object " << id << " to category " << type << std::endl; #endif m_objects[type][id] = mO; } RELEASE_LOCK; return mO; } MappedObject* MappedStudio::getObjectOfType(MappedObjectType type) { MappedObject *rv = 0; GET_LOCK; MappedObjectCategory &category = m_objects[type]; if (!category.empty()) rv = category.begin()->second; RELEASE_LOCK; return rv; } std::vector MappedStudio::getObjectsOfType(MappedObjectType type) { std::vector rv; GET_LOCK; MappedObjectCategory &category = m_objects[type]; for (MappedObjectCategory::iterator i = category.begin(); i != category.end(); ++i) { rv.push_back(i->second); } RELEASE_LOCK; return rv; } unsigned int MappedStudio::getObjectCount(MappedObjectType type) { unsigned int count = 0; GET_LOCK; MappedObjectCategory &category = m_objects[type]; count = (unsigned int)category.size(); RELEASE_LOCK; return count; } bool MappedStudio::destroyObject(MappedObjectId id) { GET_LOCK; MappedObject *obj = getObjectById(id); bool rv = false; if (obj) { obj->destroy(); rv = true; } RELEASE_LOCK; return rv; } bool MappedStudio::connectObjects(MappedObjectId mId1, MappedObjectId mId2) { GET_LOCK; bool rv = false; // objects must exist and be of connectable types MappedConnectableObject *obj1 = dynamic_cast(getObjectById(mId1)); MappedConnectableObject *obj2 = dynamic_cast(getObjectById(mId2)); if (obj1 && obj2) { obj1->addConnection(MappedConnectableObject::Out, mId2); obj2->addConnection(MappedConnectableObject::In, mId1); rv = true; } RELEASE_LOCK; return rv; } bool MappedStudio::disconnectObjects(MappedObjectId mId1, MappedObjectId mId2) { GET_LOCK; bool rv = false; // objects must exist and be of connectable types MappedConnectableObject *obj1 = dynamic_cast(getObjectById(mId1)); MappedConnectableObject *obj2 = dynamic_cast(getObjectById(mId2)); if (obj1 && obj2) { obj1->removeConnection(MappedConnectableObject::Out, mId2); obj2->removeConnection(MappedConnectableObject::In, mId1); rv = true; } RELEASE_LOCK; return rv; } bool MappedStudio::disconnectObject(MappedObjectId mId) { GET_LOCK; bool rv = false; MappedConnectableObject *obj = dynamic_cast(getObjectById(mId)); if (obj) { while (1) { MappedObjectValueList list = obj->getConnections(MappedConnectableObject::In); if (list.empty()) break; MappedObjectId otherId = MappedObjectId(*list.begin()); disconnectObjects(otherId, mId); } while (1) { MappedObjectValueList list = obj->getConnections(MappedConnectableObject::Out); if (list.empty()) break; MappedObjectId otherId = MappedObjectId(*list.begin()); disconnectObjects(mId, otherId); } } rv = true; RELEASE_LOCK; return rv; } // Clear down the whole studio // void MappedStudio::clear() { GET_LOCK; for (MappedObjectMap::iterator i = m_objects.begin(); i != m_objects.end(); ++i) { for (MappedObjectCategory::iterator j = i->second.begin(); j != i->second.end(); ++j) { delete j->second; } } m_objects.clear(); // reset running object id m_runningObjectId = 1; RELEASE_LOCK; } bool MappedStudio::clearObject(MappedObjectId id) { bool rv = false; GET_LOCK; for (MappedObjectMap::iterator i = m_objects.begin(); i != m_objects.end(); ++i) { MappedObjectCategory::iterator j = i->second.find(id); if (j != i->second.end()) { // if the object has a parent other than the studio, // persuade that parent to abandon it MappedObject *parent = j->second->getParent(); if (parent && !dynamic_cast(parent)) { parent->removeChild(j->second); } i->second.erase(j); rv = true; break; } } RELEASE_LOCK; return rv; } MappedObjectPropertyList MappedStudio::getPropertyList(const MappedObjectProperty &property) { MappedObjectPropertyList list; if (property == "") { // something } return list; } bool MappedStudio::getProperty(const MappedObjectProperty &, MappedObjectValue &) { return false; } MappedObject* MappedStudio::getObjectById(MappedObjectId id) { GET_LOCK; MappedObject *rv = 0; for (MappedObjectMap::iterator i = m_objects.begin(); i != m_objects.end(); ++i) { MappedObjectCategory::iterator j = i->second.find(id); if (j != i->second.end()) { rv = j->second; break; } } RELEASE_LOCK; return rv; } MappedObject* MappedStudio::getObjectByIdAndType(MappedObjectId id, MappedObjectType type) { GET_LOCK; MappedObject *rv = 0; MappedObjectCategory &category = m_objects[type]; MappedObjectCategory::iterator i = category.find(id); if (i != category.end()) { rv = i->second; } RELEASE_LOCK; return rv; } MappedObject* MappedStudio::getFirst(MappedObjectType type) { return getObjectOfType(type); } MappedObject* MappedStudio::getNext(MappedObject *object) { GET_LOCK; MappedObjectCategory &category = m_objects[object->getType()]; bool next = false; MappedObject *rv = 0; for (MappedObjectCategory::iterator i = category.begin(); i != category.end(); ++i) { if (i->second->getId() == object->getId()) next = true; else if (next) { rv = i->second; break; } } RELEASE_LOCK; return rv; } void MappedStudio::setProperty(const MappedObjectProperty &property, MappedObjectValue /*value*/) { if (property == "") {} } MappedAudioFader * MappedStudio::getAudioFader(InstrumentId id) { GET_LOCK; MappedObjectCategory &category = m_objects[AudioFader]; MappedAudioFader *rv = 0; for (MappedObjectCategory::iterator i = category.begin(); i != category.end(); ++i) { MappedAudioFader *fader = dynamic_cast(i->second); if (fader && (fader->getInstrument() == id)) { rv = fader; break; } } RELEASE_LOCK; return rv; } MappedAudioBuss * MappedStudio::getAudioBuss(int bussNumber) { GET_LOCK; MappedObjectCategory &category = m_objects[AudioBuss]; MappedAudioBuss *rv = 0; for (MappedObjectCategory::iterator i = category.begin(); i != category.end(); ++i) { MappedAudioBuss *buss = dynamic_cast(i->second); if (buss && (buss->getBussId() == bussNumber)) { rv = buss; break; } } RELEASE_LOCK; return rv; } MappedAudioInput * MappedStudio::getAudioInput(int inputNumber) { GET_LOCK; MappedObjectCategory &category = m_objects[AudioInput]; MappedAudioInput *rv = 0; for (MappedObjectCategory::iterator i = category.begin(); i != category.end(); ++i) { MappedAudioInput *input = dynamic_cast(i->second); if (input && (input->getInputNumber() == inputNumber)) { rv = input; break; } } RELEASE_LOCK; return rv; } // -------------- MappedConnectableObject ----------------- // // MappedConnectableObject::MappedConnectableObject(MappedObject *parent, const std::string &name, MappedObjectType type, MappedObjectId id): MappedObject(parent, name, type, id) {} MappedConnectableObject::~MappedConnectableObject() {} void MappedConnectableObject::setConnections(ConnectionDirection dir, MappedObjectValueList conns) { if (dir == In) m_connectionsIn = conns; else m_connectionsOut = conns; } void MappedConnectableObject::addConnection(ConnectionDirection dir, MappedObjectId id) { MappedObjectValueList &list = (dir == In ? m_connectionsIn : m_connectionsOut); for (MappedObjectValueList::iterator i = list.begin(); i != list.end(); ++i) { if (*i == id) { return ; } } list.push_back(MappedObjectValue(id)); } void MappedConnectableObject::removeConnection(ConnectionDirection dir, MappedObjectId id) { MappedObjectValueList &list = (dir == In ? m_connectionsIn : m_connectionsOut); for (MappedObjectValueList::iterator i = list.begin(); i != list.end(); ++i) { if (*i == id) { list.erase(i); return ; } } } MappedObjectValueList MappedConnectableObject::getConnections(ConnectionDirection dir) { if (dir == In) return m_connectionsIn; else return m_connectionsOut; } // ------------ MappedAudioFader ---------------- // MappedAudioFader::MappedAudioFader(MappedObject *parent, MappedObjectId id, MappedObjectValue channels): MappedConnectableObject(parent, "MappedAudioFader", AudioFader, id), m_level(0.0), // dB m_recordLevel(0.0), m_instrumentId(0), m_pan(0), m_channels(channels), m_inputChannel(0) {} MappedAudioFader::~MappedAudioFader() {} MappedObjectPropertyList MappedAudioFader::getPropertyList(const MappedObjectProperty &property) { MappedObjectPropertyList list; if (property == "") { list.push_back(MappedAudioFader::FaderLevel); list.push_back(MappedAudioFader::FaderRecordLevel); list.push_back(MappedObject::Instrument); list.push_back(MappedAudioFader::Pan); list.push_back(MappedAudioFader::Channels); list.push_back(MappedConnectableObject::ConnectionsIn); list.push_back(MappedConnectableObject::ConnectionsOut); } else if (property == MappedObject::Instrument) { list.push_back(MappedObjectProperty("%1").arg(m_instrumentId)); } else if (property == MappedAudioFader::FaderLevel) { list.push_back(MappedObjectProperty("%1").arg(m_level)); } else if (property == MappedAudioFader::FaderRecordLevel) { list.push_back(MappedObjectProperty("%1").arg(m_recordLevel)); } else if (property == MappedAudioFader::Channels) { list.push_back(MappedObjectProperty("%1").arg(m_channels)); } else if (property == MappedAudioFader::InputChannel) { list.push_back(MappedObjectProperty("%1").arg(m_inputChannel)); } else if (property == MappedAudioFader::Pan) { list.push_back(MappedObjectProperty("%1").arg(m_pan)); } else if (property == MappedConnectableObject::ConnectionsIn) { MappedObjectValueList::const_iterator it = m_connectionsIn.begin(); for ( ; it != m_connectionsIn.end(); ++it) { list.push_back(QString("%1").arg(*it)); } } else if (property == MappedConnectableObject::ConnectionsOut) { MappedObjectValueList::const_iterator it = m_connectionsOut.begin(); for ( ; it != m_connectionsOut.end(); ++it) { list.push_back(QString("%1").arg(*it)); } } return list; } bool MappedAudioFader::getProperty(const MappedObjectProperty &property, MappedObjectValue &value) { if (property == FaderLevel) { value = m_level; } else if (property == Instrument) { value = m_instrumentId; } else if (property == FaderRecordLevel) { value = m_recordLevel; } else if (property == Channels) { value = m_channels; } else if (property == InputChannel) { value = m_inputChannel; } else if (property == Pan) { value = m_pan; } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedAudioFader::getProperty - " << "unsupported or non-scalar property" << std::endl; #endif return false; } return true; } void MappedAudioFader::setProperty(const MappedObjectProperty &property, MappedObjectValue value) { bool updateLevels = false; if (property == MappedAudioFader::FaderLevel) { m_level = value; updateLevels = true; } else if (property == MappedObject::Instrument) { m_instrumentId = InstrumentId(value); updateLevels = true; } else if (property == MappedAudioFader::FaderRecordLevel) { m_recordLevel = value; } else if (property == MappedAudioFader::Channels) { m_channels = value; } else if (property == MappedAudioFader::InputChannel) { m_inputChannel = value; } else if (property == MappedAudioFader::Pan) { m_pan = value; updateLevels = true; } else if (property == MappedConnectableObject::ConnectionsIn) { m_connectionsIn.clear(); m_connectionsIn.push_back(value); } else if (property == MappedConnectableObject::ConnectionsOut) { m_connectionsOut.clear(); m_connectionsOut.push_back(value); } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedAudioFader::setProperty - " << "unsupported property" << std::endl; #endif return ; } /* std::cout << "MappedAudioFader::setProperty - " << property << " = " << value << std::endl; */ if (updateLevels) { MappedStudio *studio = dynamic_cast(getParent()); if (studio) { studio->getSoundDriver()->setAudioInstrumentLevels (m_instrumentId, m_level, m_pan); } } } // ---------------- MappedAudioBuss ------------------- // // MappedAudioBuss::MappedAudioBuss(MappedObject *parent, MappedObjectId id) : MappedConnectableObject(parent, "MappedAudioBuss", AudioBuss, id), m_bussId(0), m_level(0), m_pan(0) {} MappedAudioBuss::~MappedAudioBuss() {} MappedObjectPropertyList MappedAudioBuss::getPropertyList(const MappedObjectProperty &property) { MappedObjectPropertyList list; if (property == "") { list.push_back(MappedAudioBuss::BussId); list.push_back(MappedAudioBuss::Level); list.push_back(MappedAudioBuss::Pan); list.push_back(MappedConnectableObject::ConnectionsIn); list.push_back(MappedConnectableObject::ConnectionsOut); } else if (property == BussId) { list.push_back(MappedObjectProperty("%1").arg(m_bussId)); } else if (property == Level) { list.push_back(MappedObjectProperty("%1").arg(m_level)); } else if (property == MappedConnectableObject::ConnectionsIn) { MappedObjectValueList::const_iterator it = m_connectionsIn.begin(); for ( ; it != m_connectionsIn.end(); ++it) { list.push_back(QString("%1").arg(*it)); } } else if (property == MappedConnectableObject::ConnectionsOut) { MappedObjectValueList::const_iterator it = m_connectionsOut.begin(); for ( ; it != m_connectionsOut.end(); ++it) { list.push_back(QString("%1").arg(*it)); } } return list; } bool MappedAudioBuss::getProperty(const MappedObjectProperty &property, MappedObjectValue &value) { if (property == BussId) { value = m_bussId; } else if (property == Level) { value = m_level; } else if (property == Pan) { value = m_pan; } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedAudioBuss::getProperty - " << "unsupported or non-scalar property" << std::endl; #endif return false; } return true; } void MappedAudioBuss::setProperty(const MappedObjectProperty &property, MappedObjectValue value) { bool updateLevels = false; if (property == MappedAudioBuss::BussId) { m_bussId = (int)value; updateLevels = true; } else if (property == MappedAudioBuss::Level) { m_level = value; updateLevels = true; } else if (property == MappedAudioBuss::Pan) { m_pan = value; updateLevels = true; } else if (property == MappedConnectableObject::ConnectionsIn) { m_connectionsIn.clear(); m_connectionsIn.push_back(value); } else if (property == MappedConnectableObject::ConnectionsOut) { m_connectionsOut.clear(); m_connectionsOut.push_back(value); } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedAudioBuss::setProperty - " << "unsupported property" << std::endl; #endif return ; } if (updateLevels) { MappedStudio *studio = dynamic_cast(getParent()); if (studio) { studio->getSoundDriver()->setAudioBussLevels (m_bussId, m_level, m_pan); } } } std::vector MappedAudioBuss::getInstruments() { std::vector rv; GET_LOCK; MappedObject *studioObject = getParent(); while (!dynamic_cast(studioObject)) studioObject = studioObject->getParent(); std::vector objects = static_cast(studioObject)-> getObjectsOfType(MappedObject::AudioFader); for (std::vector::iterator i = objects.begin(); i != objects.end(); ++i) { MappedAudioFader *fader = dynamic_cast(*i); if (fader) { MappedObjectValueList connections = fader->getConnections (MappedConnectableObject::Out); if (!connections.empty() && (*connections.begin() == getId())) { rv.push_back(fader->getInstrument()); } } } RELEASE_LOCK; return rv; } // ---------------- MappedAudioInput ------------------- // // MappedAudioInput::MappedAudioInput(MappedObject *parent, MappedObjectId id) : MappedConnectableObject(parent, "MappedAudioInput", AudioInput, id) {} MappedAudioInput::~MappedAudioInput() {} MappedObjectPropertyList MappedAudioInput::getPropertyList(const MappedObjectProperty &property) { MappedObjectPropertyList list; if (property == "") { list.push_back(MappedAudioInput::InputNumber); } else if (property == InputNumber) { list.push_back(MappedObjectProperty("%1").arg(m_inputNumber)); } return list; } bool MappedAudioInput::getProperty(const MappedObjectProperty &property, MappedObjectValue &value) { if (property == InputNumber) { value = m_inputNumber; } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedAudioInput::getProperty - " << "no properties available" << std::endl; #endif } return false; } void MappedAudioInput::setProperty(const MappedObjectProperty &property, MappedObjectValue value) { if (property == InputNumber) { m_inputNumber = value; } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedAudioInput::setProperty - " << "no properties available" << std::endl; #endif } return ; } MappedPluginSlot::MappedPluginSlot(MappedObject *parent, MappedObjectId id) : MappedObject(parent, "MappedPluginSlot", PluginSlot, id) { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedPluginSlot::MappedPluginSlot: id = " << id << std::endl; #endif } MappedPluginSlot::~MappedPluginSlot() { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedPluginSlot::~MappedPluginSlot: id = " << getId() << ", identifier = " << m_identifier << std::endl; #endif if (m_identifier != "") { // shut down and remove the plugin instance we have running MappedStudio *studio = dynamic_cast(getParent()); if (studio) { SoundDriver *drv = studio->getSoundDriver(); if (drv) { drv->removePluginInstance(m_instrument, m_position); } } } } MappedObjectPropertyList MappedPluginSlot::getPropertyList(const MappedObjectProperty &property) { MappedObjectPropertyList list; if (property == "") { list.push_back(PortCount); list.push_back(Instrument); list.push_back(Bypassed); list.push_back(PluginName); list.push_back(Label); list.push_back(Author); list.push_back(Copyright); list.push_back(Category); } else if (property == Programs) { // The set of available programs is dynamic -- it can change // while a plugin is instantiated. So we query it on demand // each time. MappedStudio *studio = dynamic_cast(getParent()); if (studio) { QStringList programs = studio->getSoundDriver()->getPluginInstancePrograms(m_instrument, m_position); for (int i = 0; i < int(programs.count()); ++i) { list.push_back(programs[i]); } } } else { std::cerr << "MappedPluginSlot::getPropertyList: not a list property" << std::endl; } return list; } bool MappedPluginSlot::getProperty(const MappedObjectProperty &property, MappedObjectValue &value) { if (property == PortCount) { value = m_portCount; } else if (property == Instrument) { value = m_instrument; } else if (property == Position) { value = m_position; } else if (property == Bypassed) { value = m_bypassed; } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedPluginSlot::getProperty - " << "unsupported or non-scalar property" << std::endl; #endif return false; } return true; } bool MappedPluginSlot::getStringProperty(const MappedObjectProperty &property, QString &value) { if (property == Identifier) { value = m_identifier; } else if (property == PluginName) { value = m_name; } else if (property == Label) { value = m_label; } else if (property == Author) { value = m_author; } else if (property == Copyright) { value = m_copyright; } else if (property == Category) { value = m_category; } else if (property == Program) { MappedStudio *studio = dynamic_cast(getParent()); if (studio) { value = studio->getSoundDriver()->getPluginInstanceProgram(m_instrument, m_position); } } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedPluginSlot::getProperty - " << "unsupported or non-scalar property" << std::endl; #endif return false; } return true; } QString MappedPluginSlot::getProgram(int bank, int program) { MappedStudio *studio = dynamic_cast(getParent()); if (studio) { return studio->getSoundDriver()->getPluginInstanceProgram(m_instrument, m_position, bank, program); } return QString(); } unsigned long MappedPluginSlot::getProgram(QString name) { MappedStudio *studio = dynamic_cast(getParent()); if (studio) { return studio->getSoundDriver()->getPluginInstanceProgram(m_instrument, m_position, name); } return 0; } void MappedPluginSlot::setProperty(const MappedObjectProperty &property, MappedObjectValue value) { if (property == Instrument) { m_instrument = InstrumentId(value); } else if (property == PortCount) { m_portCount = int(value); } else if (property == Position) { m_position = int(value); } else if (property == Bypassed) { m_bypassed = bool(value); MappedStudio *studio = dynamic_cast(getParent()); if (studio) { studio->getSoundDriver()->setPluginInstanceBypass(m_instrument, m_position, m_bypassed); } } } void MappedPluginSlot::setStringProperty(const MappedObjectProperty &property, QString value) { RG_DEBUG << "MappedPluginSlot::setStringProperty: " << property << " -> " << value << endl; if (property == Identifier) { if (m_identifier == value) return ; // shut down and remove the plugin instance we have running MappedStudio *studio = dynamic_cast(getParent()); if (studio) { SoundDriver *drv = studio->getSoundDriver(); if (drv) { // We don't call drv->removePluginInstance at this // point: the sequencer will deal with that when we // call setPluginInstance below. If we removed the // instance here, we might cause the library we want // for the new plugin instance to be unloaded and then // loaded again, which is hardly the most efficient. m_identifier = value; // populate myself and my ports PluginFactory *factory = PluginFactory::instanceFor(m_identifier); if (!factory) { std::cerr << "WARNING: MappedPluginSlot::setProperty(identifier): No plugin factory for identifier " << m_identifier << "!" << std::endl; m_identifier = ""; return ; } factory->populatePluginSlot(m_identifier, *this); // now create the new instance drv->setPluginInstance(m_instrument, m_identifier, m_position); } } m_configuration.clear(); } else if (property == PluginName) { m_name = value; } else if (property == Label) { m_label = value; } else if (property == Author) { m_author = value; } else if (property == Copyright) { m_copyright = value; } else if (property == Category) { m_category = value; } else if (property == Program) { MappedStudio *studio = dynamic_cast(getParent()); if (studio) { studio->getSoundDriver()->setPluginInstanceProgram(m_instrument, m_position, value); } } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedPluginSlot::setProperty - " << "unsupported or non-scalar property" << std::endl; #endif } } void MappedPluginSlot::setPropertyList(const MappedObjectProperty &property, const MappedObjectPropertyList &values) { if (property == Configuration) { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedPluginSlot::setPropertyList(configuration): configuration is:" << std::endl; #endif MappedStudio *studio = dynamic_cast(getParent()); for (MappedObjectPropertyList::const_iterator i = values.begin(); i != values.end(); ++i) { QString key = *i; QString value = *++i; #ifdef DEBUG_MAPPEDSTUDIO std::cerr << key << " = " << value << std::endl; #endif if (m_configuration.find(key) != m_configuration.end() && m_configuration[key] == value) { continue; } if (studio) { QString rv = studio->getSoundDriver()->configurePlugin(m_instrument, m_position, key, value); if (!rv.isEmpty()) { throw(rv); } } } m_configuration.clear(); for (MappedObjectPropertyList::const_iterator i = values.begin(); i != values.end(); ++i) { QString key = *i; QString value = *++i; m_configuration[key] = value; } } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedPluginSlot::setPropertyList - " << "not a list property" << std::endl; #endif } } void MappedPluginSlot::setPort(unsigned long portNumber, float value) { std::vector ports = getChildObjects(); std::vector::iterator it = ports.begin(); MappedPluginPort *port = 0; for (; it != ports.end(); it++) { port = dynamic_cast(*it); if (port && (unsigned long)port->getPortNumber() == portNumber) { port->setValue(value); } } } float MappedPluginSlot::getPort(unsigned long portNumber) { std::vector ports = getChildObjects(); std::vector::iterator it = ports.begin(); MappedPluginPort *port = 0; for (; it != ports.end(); it++) { port = dynamic_cast(*it); if (port && (unsigned long)port->getPortNumber() == portNumber) { return port->getValue(); } } return 0; } MappedPluginPort::MappedPluginPort(MappedObject *parent, MappedObjectId id) : MappedObject(parent, "MappedPluginPort", PluginPort, id) {} MappedPluginPort::~MappedPluginPort() {} MappedObjectPropertyList MappedPluginPort::getPropertyList(const MappedObjectProperty &property) { MappedObjectPropertyList list; if (property == "") { list.push_back(PortNumber); list.push_back(Minimum); list.push_back(Maximum); list.push_back(Default); list.push_back(DisplayHint); list.push_back(Value); list.push_back(Name); } else { std::cerr << "MappedPluginSlot::getPropertyList: not a list property" << std::endl; } return list; } bool MappedPluginPort::getProperty(const MappedObjectProperty &property, MappedObjectValue &value) { if (property == PortNumber) { value = m_portNumber; } else if (property == Minimum) { value = m_minimum; } else if (property == Maximum) { value = m_maximum; } else if (property == Default) { value = m_default; } else if (property == DisplayHint) { value = m_displayHint; } else if (property == Value) { return getValue(); } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedPluginPort::getProperty - " << "unsupported or non-scalar property" << std::endl; #endif return false; } return true; } bool MappedPluginPort::getStringProperty(const MappedObjectProperty &property, QString &value) { if (property == Name) { value = m_name; } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedPluginPort::getProperty - " << "unsupported or non-scalar property" << std::endl; #endif return false; } return true; } void MappedPluginPort::setValue(MappedObjectValue value) { MappedPluginSlot *slot = dynamic_cast(getParent()); if (slot) { MappedStudio *studio = dynamic_cast(slot->getParent()); if (studio) { SoundDriver *drv = studio->getSoundDriver(); if (drv) { drv->setPluginInstancePortValue(slot->getInstrument(), slot->getPosition(), m_portNumber, value); } } } } float MappedPluginPort::getValue() const { const MappedPluginSlot *slot = dynamic_cast(getParent()); if (slot) { const MappedStudio *studio = dynamic_cast(slot->getParent()); if (studio) { SoundDriver *drv = const_cast(studio->getSoundDriver()); if (drv) { return drv->getPluginInstancePortValue(slot->getInstrument(), slot->getPosition(), m_portNumber); } } } return 0; } void MappedPluginPort::setProperty(const MappedObjectProperty &property, MappedObjectValue value) { if (property == PortNumber) { m_portNumber = int(value); } else if (property == Minimum) { m_minimum = value; } else if (property == Maximum) { m_maximum = value; } else if (property == Default) { m_default = value; } else if (property == DisplayHint) { m_displayHint = PluginPort::PortDisplayHint(value); } else if (property == Value) { setValue(value); } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedPluginPort::setProperty - " << "unsupported or non-scalar property" << std::endl; #endif } } void MappedPluginPort::setStringProperty(const MappedObjectProperty &property, QString value) { if (property == Name) { m_name = value; } else { #ifdef DEBUG_MAPPEDSTUDIO std::cerr << "MappedPluginPort::setProperty - " << "unsupported or non-scalar property" << std::endl; #endif } } }