You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rosegarden/src/sound/MappedStudio.cpp

1718 lines
44 KiB

/*
Rosegarden
A sequencer and musical notation editor.
This program is Copyright 2000-2008
Guillaume Laurent <glaurent@telegraph-road.org>,
Chris Cannam <cannam@all-day-breakfast.com>,
Richard Bown <bownie@bownie.com>
The moral right of the authors to claim authorship of this work
has been asserted.
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 <iostream>
#include "MappedStudio.h"
#include "SoundDriver.h"
#include "PluginFactory.h"
#include <pthread.h> // 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 TQt3 tqvaluevector.h
//
// ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
//
TQDataStream& operator>>(TQDataStream& s, MappedObjectIdList& v)
{
v.clear();
TQ_UINT32 c;
s >> c;
v.resize(c);
for (TQ_UINT32 i = 0; i < c; ++i) {
MappedObjectId t;
s >> t;
v[i] = t;
}
return s;
}
TQDataStream& operator<<(TQDataStream& s, const MappedObjectIdList& v)
{
s << (TQ_UINT32)v.size();
MappedObjectIdList::const_iterator it = v.begin();
for ( ; it != v.end(); ++it )
s << *it;
return s;
}
TQDataStream& operator>>(TQDataStream& s, MappedObjectPropertyList& v)
{
v.clear();
TQ_UINT32 c;
s >> c;
v.resize(c);
for (TQ_UINT32 i = 0; i < c; ++i) {
MappedObjectProperty t;
s >> t;
v[i] = t;
}
return s;
}
TQDataStream& operator<<(TQDataStream& s, const MappedObjectPropertyList& v)
{
s << (TQ_UINT32)v.size();
MappedObjectPropertyList::const_iterator it = v.begin();
for ( ; it != v.end(); ++it )
s << *it;
return s;
}
TQDataStream& operator>>(TQDataStream& s, MappedObjectValueList& v)
{
v.clear();
TQ_UINT32 c;
s >> c;
v.resize(c);
for (TQ_UINT32 i = 0; i < c; ++i) {
MappedObjectValue t;
s >> t;
v[i] = t;
}
return s;
}
TQDataStream& operator<<(TQDataStream& s, const MappedObjectValueList& v)
{
s << (TQ_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<MappedObject*>::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<MappedObject*>::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<MappedObject*>::iterator it = m_children.begin();
for (; it != m_children.end(); it++)
list.push_back(TQString("%1").arg((*it)->getId()));
return list;
}
// Return all child ids of a certain type
//
MappedObjectPropertyList
MappedObject::getChildren(MappedObjectType type)
{
MappedObjectPropertyList list;
std::vector<MappedObject*>::iterator it = m_children.begin();
for (; it != m_children.end(); it++) {
if ((*it)->getType() == type)
list.push_back(TQString("%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<MappedStudio*>(studioObject))
studioObject = studioObject->getParent();
// see note in destroy() below
std::vector<MappedObject *> children = m_children;
m_children.clear();
std::vector<MappedObject *>::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<MappedStudio*>(studioObject))
studioObject = studioObject->getParent();
MappedStudio *studio = dynamic_cast<MappedStudio*>(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<MappedObject *> children = m_children;
m_children.clear();
std::vector<MappedObject *>::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
#ifdef PTHREAD_MUTEX_RECURSIVE
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<MappedObject *>
MappedStudio::getObjectsOfType(MappedObjectType type)
{
std::vector<MappedObject *> 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 = 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<MappedConnectableObject *>(getObjectById(mId1));
MappedConnectableObject *obj2 =
dynamic_cast<MappedConnectableObject *>(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<MappedConnectableObject *>(getObjectById(mId1));
MappedConnectableObject *obj2 =
dynamic_cast<MappedConnectableObject *>(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<MappedConnectableObject *>(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<MappedStudio *>(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<MappedAudioFader *>(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<MappedAudioBuss *>(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<MappedAudioInput *>(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(TQString("%1").arg(*it));
}
} else if (property == MappedConnectableObject::ConnectionsOut) {
MappedObjectValueList::const_iterator
it = m_connectionsOut.begin();
for ( ; it != m_connectionsOut.end(); ++it) {
list.push_back(TQString("%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<MappedStudio*>(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(TQString("%1").arg(*it));
}
} else if (property == MappedConnectableObject::ConnectionsOut) {
MappedObjectValueList::const_iterator
it = m_connectionsOut.begin();
for ( ; it != m_connectionsOut.end(); ++it) {
list.push_back(TQString("%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<MappedStudio*>(getParent());
if (studio) {
studio->getSoundDriver()->setAudioBussLevels
(m_bussId, m_level, m_pan);
}
}
}
std::vector<InstrumentId>
MappedAudioBuss::getInstruments()
{
std::vector<InstrumentId> rv;
GET_LOCK;
MappedObject *studioObject = getParent();
while (!dynamic_cast<MappedStudio *>(studioObject))
studioObject = studioObject->getParent();
std::vector<MappedObject *> objects =
static_cast<MappedStudio *>(studioObject)->
getObjectsOfType(MappedObject::AudioFader);
for (std::vector<MappedObject *>::iterator i = objects.begin();
i != objects.end(); ++i) {
MappedAudioFader *fader = dynamic_cast<MappedAudioFader *>(*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<MappedStudio*>(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<MappedStudio*>(getParent());
if (studio) {
TQStringList 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::getProperty(const MappedObjectProperty &property,
TQString &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<MappedStudio*>(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;
}
TQString
MappedPluginSlot::getProgram(int bank, int program)
{
MappedStudio *studio =
dynamic_cast<MappedStudio*>(getParent());
if (studio) {
return
studio->getSoundDriver()->getPluginInstanceProgram(m_instrument,
m_position,
bank,
program);
}
return TQString();
}
unsigned long
MappedPluginSlot::getProgram(TQString name)
{
MappedStudio *studio =
dynamic_cast<MappedStudio*>(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<MappedStudio*>(getParent());
if (studio) {
studio->getSoundDriver()->setPluginInstanceBypass(m_instrument,
m_position,
m_bypassed);
}
}
}
void
MappedPluginSlot::setProperty(const MappedObjectProperty &property,
TQString value)
{
if (property == Identifier) {
if (m_identifier == value)
return ;
// shut down and remove the plugin instance we have running
MappedStudio *studio =
dynamic_cast<MappedStudio*>(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.ascii() << "!" << 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<MappedStudio*>(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<MappedStudio*>(getParent());
for (MappedObjectPropertyList::const_iterator i = values.begin();
i != values.end(); ++i) {
TQString key = *i;
TQString 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) {
TQString rv =
studio->getSoundDriver()->configurePlugin(m_instrument,
m_position,
key, value);
if (!rv.isNull() && rv != "") {
throw(rv);
}
}
}
m_configuration.clear();
for (MappedObjectPropertyList::const_iterator i = values.begin();
i != values.end(); ++i) {
TQString key = *i;
TQString 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<MappedObject*> ports = getChildObjects();
std::vector<MappedObject*>::iterator it = ports.begin();
MappedPluginPort *port = 0;
for (; it != ports.end(); it++) {
port = dynamic_cast<MappedPluginPort *>(*it);
if (port && (unsigned long)port->getPortNumber() == portNumber) {
port->setValue(value);
}
}
}
float
MappedPluginSlot::getPort(unsigned long portNumber)
{
std::vector<MappedObject*> ports = getChildObjects();
std::vector<MappedObject*>::iterator it = ports.begin();
MappedPluginPort *port = 0;
for (; it != ports.end(); it++) {
port = dynamic_cast<MappedPluginPort *>(*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::getProperty(const MappedObjectProperty &property,
TQString &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<MappedPluginSlot *>(getParent());
if (slot) {
MappedStudio *studio =
dynamic_cast<MappedStudio *>(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<const MappedPluginSlot *>(getParent());
if (slot) {
const MappedStudio *studio =
dynamic_cast<const MappedStudio *>(slot->getParent());
if (studio) {
SoundDriver *drv =
const_cast<SoundDriver *>(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::setProperty(const MappedObjectProperty &property,
TQString value)
{
if (property == Name) {
m_name = value;
} else {
#ifdef DEBUG_MAPPEDSTUDIO
std::cerr << "MappedPluginPort::setProperty - "
<< "unsupported or non-scalar property" << std::endl;
#endif
}
}
}