1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
mallctl_bool_get(const char * name,bool expected,const char * func,int line)4     Rosegarden
5     A sequencer and musical notation editor.
6     Copyright 2000-2021 the Rosegarden development team.
7     See the AUTHORS file for more details.
8 
9     This program is free software; you can redistribute it and/or
10     modify it under the terms of the GNU General Public License as
11     published by the Free Software Foundation; either version 2 of the
12     License, or (at your option) any later version.  See the file
13     COPYING included with this distribution for more information.
14 */
15 
16 #define RG_MODULE_STRING "[MappedStudio]"
17 
18 
19 #include "MappedStudio.h"
20 #include "SoundDriver.h"
21 #include "PluginFactory.h"
22 #include "misc/Strings.h"
23 #include "misc/Debug.h"
24 
25 #include <pthread.h> // for mutex
26 
27 // #define DEBUG_MAPPEDSTUDIO 1
28 
29 namespace Rosegarden
30 {
31 
32 static pthread_mutex_t mappedObjectContainerLock;
33 
34 #ifdef DEBUG_MAPPEDSTUDIO
35 static int approxLockCount = 0;
36 #endif
37 
38 static inline void getLock(const char *file, int line)
39 {
40 #ifdef DEBUG_MAPPEDSTUDIO
41     std::cerr << "Acquiring MappedStudio container lock at " << file << ":" << line << ": count " << approxLockCount++ << std::endl;
42 #else
43     (void)file; (void)line;
44 #endif
45 
46     pthread_mutex_lock(&mappedObjectContainerLock);
47 }
48 
49 static inline void releaseLock(const char *file, int line)
50 {
51     pthread_mutex_unlock(&mappedObjectContainerLock);
52 #ifdef DEBUG_MAPPEDSTUDIO
53 
54     std::cerr << "Released container lock at " << file << ":" << line << ": count " << --approxLockCount << std::endl;
55 #else
56     (void)file; (void)line;
57 #endif
58 }
59 
60 #define GET_LOCK getLock(__FILE__,__LINE__)
61 #define RELEASE_LOCK releaseLock(__FILE__,__LINE__)
62 
63 // These stream functions are stolen and adapted from Qt3 QVector
64 //
65 // ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
66 //
67 QDataStream& operator>>(QDataStream& s, MappedObjectIdList& v)
68 {
69     v.clear();
70     quint32 c;
71     s >> c;
72     v.resize(c);
73     for (quint32 i = 0; i < c; ++i) {
74         MappedObjectId t;
75         s >> t;
76         v[i] = t;
77     }
78     return s;
79 }
80 
81 QDataStream& operator<<(QDataStream& s, const MappedObjectIdList& v)
82 {
83     s << (quint32)v.size();
84     MappedObjectIdList::const_iterator it = v.begin();
85     for ( ; it != v.end(); ++it )
86         s << *it;
87     return s;
88 }
89 
90 QDataStream& operator>>(QDataStream& s, MappedObjectPropertyList& v)
91 {
92     v.clear();
93     quint32 c;
94     s >> c;
95     v.resize(c);
96     for (quint32 i = 0; i < c; ++i) {
97         MappedObjectProperty t;
98         s >> t;
99         v[i] = t;
100     }
101     return s;
102 }
103 
104 QDataStream& operator<<(QDataStream& s, const MappedObjectPropertyList& v)
105 {
106     s << (quint32)v.size();
107     MappedObjectPropertyList::const_iterator it = v.begin();
108     for ( ; it != v.end(); ++it )
109         s << *it;
110     return s;
111 }
112 
113 QDataStream& operator>>(QDataStream& s, MappedObjectValueList& v)
114 {
115     v.clear();
116     quint32 c;
117     s >> c;
118     v.resize(c);
119     for (quint32 i = 0; i < c; ++i) {
120         MappedObjectValue t;
121         s >> t;
122         v[i] = t;
123     }
124     return s;
125 }
126 
127 QDataStream& operator<<(QDataStream& s, const MappedObjectValueList& v)
128 {
129     s << (quint32)v.size();
130     MappedObjectValueList::const_iterator it = v.begin();
131     for ( ; it != v.end(); ++it )
132         s << *it;
133     return s;
134 }
135 
136 // Define our object properties - these can be queried and set.
137 //
138 
139 // General things
140 //
141 const MappedObjectProperty MappedObject::Name = "name";
142 const MappedObjectProperty MappedObject::Instrument = "instrument";
143 const MappedObjectProperty MappedObject::Position = "position";
144 
145 const MappedObjectProperty MappedConnectableObject::ConnectionsIn = "connectionsIn";
146 const MappedObjectProperty MappedConnectableObject::ConnectionsOut = "connectionsOut";
147 
148 const MappedObjectProperty MappedAudioFader::Channels = "channels";
149 const MappedObjectProperty MappedAudioFader::FaderLevel = "faderLevel";
150 const MappedObjectProperty MappedAudioFader::FaderRecordLevel = "faderRecordLevel";
151 const MappedObjectProperty MappedAudioFader::Pan = "pan";
152 const MappedObjectProperty MappedAudioFader::InputChannel = "inputChannel";
153 
154 const MappedObjectProperty MappedAudioBuss::BussId = "bussId";
155 const MappedObjectProperty MappedAudioBuss::Level = "level";
156 const MappedObjectProperty MappedAudioBuss::Pan = "pan";
157 
158 const MappedObjectProperty MappedAudioInput::InputNumber = "inputNumber";
159 
160 const MappedObjectProperty MappedPluginSlot::Identifier = "identifier";
161 const MappedObjectProperty MappedPluginSlot::PluginName = "pluginname";
162 const MappedObjectProperty MappedPluginSlot::Label = "label";
163 const MappedObjectProperty MappedPluginSlot::Author = "author";
164 const MappedObjectProperty MappedPluginSlot::Copyright = "copyright";
165 const MappedObjectProperty MappedPluginSlot::Category = "category";
166 const MappedObjectProperty MappedPluginSlot::PortCount = "portcount";
167 const MappedObjectProperty MappedPluginSlot::Ports = "ports";
168 const MappedObjectProperty MappedPluginSlot::Instrument = "instrument";
169 const MappedObjectProperty MappedPluginSlot::Position = "position";
170 const MappedObjectProperty MappedPluginSlot::Bypassed = "bypassed";
171 const MappedObjectProperty MappedPluginSlot::Programs = "programs";
172 const MappedObjectProperty MappedPluginSlot::Program = "program";
173 const MappedObjectProperty MappedPluginSlot::Configuration = "configuration";
174 
175 const MappedObjectProperty MappedPluginPort::PortNumber = "portnumber";
176 const MappedObjectProperty MappedPluginPort::Name = "name";
177 const MappedObjectProperty MappedPluginPort::Minimum = "minimum";
178 const MappedObjectProperty MappedPluginPort::Maximum = "maximum";
179 const MappedObjectProperty MappedPluginPort::Default = "default";
180 const MappedObjectProperty MappedPluginPort::DisplayHint = "displayhint";
181 const MappedObjectProperty MappedPluginPort::Value = "value";
182 
183 // --------- MappedObject ---------
184 //
185 
186 void
187 MappedObject::addChild(MappedObject *object)
188 {
189     std::vector<MappedObject*>::iterator it = m_children.begin();
190     for (; it != m_children.end(); ++it)
191         if ((*it) == object)
192             return ;
193 
194     m_children.push_back(object);
195 }
196 
197 void
198 MappedObject::removeChild(MappedObject *object)
199 {
200     std::vector<MappedObject*>::iterator it = m_children.begin();
201     for (; it != m_children.end(); ++it) {
202         if ((*it) == object) {
203             m_children.erase(it);
204             return ;
205         }
206     }
207 }
208 
209 // Return all child ids
210 //
211 MappedObjectPropertyList
212 MappedObject::getChildren()
213 {
214     MappedObjectPropertyList list;
215     std::vector<MappedObject*>::iterator it = m_children.begin();
216     for (; it != m_children.end(); ++it)
217         list.push_back(QString("%1").arg((*it)->getId()));
218 
219     return list;
220 }
221 
222 
223 // Return all child ids of a certain type
224 //
225 MappedObjectPropertyList
226 MappedObject::getChildren(MappedObjectType type)
227 {
228     MappedObjectPropertyList list;
229     std::vector<MappedObject*>::iterator it = m_children.begin();
230     for (; it != m_children.end(); ++it) {
231         if ((*it)->getType() == type)
232             list.push_back(QString("%1").arg((*it)->getId()));
233     }
234 
235     return list;
236 }
237 
238 void
239 MappedObject::destroyChildren()
240 {
241     // remove references from the studio as well as from the object
242     MappedObject *studioObject = getParent();
243     while (!dynamic_cast<MappedStudio*>(studioObject))
244         studioObject = studioObject->getParent();
245 
246     // see note in destroy() below
247 
248     std::vector<MappedObject *> children = m_children;
249     m_children.clear();
250 
251     std::vector<MappedObject *>::iterator it = children.begin();
252     for (; it != children.end(); ++it)
253         (*it)->destroy(); // remove from studio and destroy
254 }
255 
256 // Destroy this object and remove it from the studio and
257 // do the same for all its children.
258 //
259 void
260 MappedObject::destroy()
261 {
262     MappedObject *studioObject = getParent();
263     while (!dynamic_cast<MappedStudio*>(studioObject))
264         studioObject = studioObject->getParent();
265 
266     MappedStudio *studio = dynamic_cast<MappedStudio*>(studioObject);
267 
268     // The destroy method on each child calls studio->clearObject,
269     // which calls back on the parent (in this case us) to remove the
270     // child.  (That's necessary for the case of destroying a plugin,
271     // where we need to remove it from its plugin manager -- etc.)  So
272     // we don't want to be iterating over m_children here, as it will
273     // change from under us.
274 
275     std::vector<MappedObject *> children = m_children;
276     m_children.clear();
277 
278     std::vector<MappedObject *>::iterator it = children.begin();
279     for (; it != children.end(); ++it) {
280         (*it)->destroy();
281     }
282 
283     (void)studio->clearObject(m_id);
284     delete this;
285 }
286 
287 
288 // ------- MappedStudio -------
289 //
290 
291 MappedStudio::MappedStudio() :
292         MappedObject(nullptr,
293                      "MappedStudio",
294                      Studio,
295                      0),
296         m_runningObjectId(1)
297 {
298     pthread_mutexattr_t attr;
299     pthread_mutexattr_init(&attr);
300 #ifdef HAVE_PTHREAD_MUTEX_RECURSIVE
301 
302     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
303 #else
304 #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(__FreeBSD__)
305 
306     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
307 #else
308 
309     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
310 #endif
311 #endif
312 
313     pthread_mutex_init(&mappedObjectContainerLock, &attr);
314 }
315 
316 MappedStudio::~MappedStudio()
317 {
318 #ifdef DEBUG_MAPPEDSTUDIO
319     std::cout << "MappedStudio::~MappedStudio" << std::endl;
320 #endif
321 
322     clear();
323 }
324 
325 
326 // Object factory
327 //
328 MappedObject*
329 MappedStudio::createObject(MappedObjectType type)
330 {
331     GET_LOCK;
332 
333     MappedObject *mO = nullptr;
334 
335     // Ensure we've got an empty slot
336     //
337     while (getObjectById(m_runningObjectId)) m_runningObjectId++;
338 
339     mO = createObject(type, m_runningObjectId);
340 
341     // If we've got a new object increase the running id
342     //
343     if (mO) m_runningObjectId++;
344 
345     RELEASE_LOCK;
346     return mO;
347 }
348 
349 MappedObject*
350 MappedStudio::createObject(MappedObjectType type,
351                            MappedObjectId id)
352 {
353     GET_LOCK;
354 
355     // fail if the object already exists and it's not zero
356     if (id != 0 && getObjectById(id)) {
357         RELEASE_LOCK;
358         return nullptr;
359     }
360 
361     MappedObject *mO = nullptr;
362 
363     if (type == MappedObject::AudioFader) {
364         mO = new MappedAudioFader(this,
365                                   id,
366                                   2); // channels
367 
368         // push to the studio's child stack
369         addChild(mO);
370     } else if (type == MappedObject::AudioBuss) {
371         mO = new MappedAudioBuss(this,
372                                  id);
373 
374         // push to the studio's child stack
375         addChild(mO);
376     } else if (type == MappedObject::AudioInput) {
377         mO = new MappedAudioInput(this,
378                                   id);
379 
380         // push to the studio's child stack
381         addChild(mO);
382     } else if (type == MappedObject::PluginSlot) {
383         mO = new MappedPluginSlot(this,
384                                   id);
385         addChild(mO);
386     } else if (type == MappedObject::PluginPort) {
387         mO = new MappedPluginPort(this,
388                                   id);
389         // reset the port's parent after creation outside this method
390     }
391 
392     // Insert
393     if (mO) {
394 #ifdef DEBUG_MAPPEDSTUDIO
395         std::cerr << "Adding object " << id << " to category " << type << std::endl;
396 #endif
397 
398         m_objects[type][id] = mO;
399     }
400 
401     RELEASE_LOCK;
402 
403     return mO;
404 }
405 
406 MappedObject*
407 MappedStudio::getObjectOfType(MappedObjectType type)
408 {
409     MappedObject *rv = nullptr;
410 
411     GET_LOCK;
412 
413     MappedObjectCategory &category = m_objects[type];
414     if (!category.empty())
415         rv = category.begin()->second;
416 
417     RELEASE_LOCK;
418 
419     return rv;
420 }
421 
422 std::vector<MappedObject *>
423 MappedStudio::getObjectsOfType(MappedObjectType type)
424 {
425     std::vector<MappedObject *> rv;
426 
427     GET_LOCK;
428 
429     MappedObjectCategory &category = m_objects[type];
430 
431     for (MappedObjectCategory::iterator i = category.begin();
432             i != category.end(); ++i) {
433         rv.push_back(i->second);
434     }
435 
436     RELEASE_LOCK;
437 
438     return rv;
439 }
440 
441 unsigned int
442 MappedStudio::getObjectCount(MappedObjectType type)
443 {
444     unsigned int count = 0;
445 
446     GET_LOCK;
447 
448     MappedObjectCategory &category = m_objects[type];
449     count = (unsigned int)category.size();
450 
451     RELEASE_LOCK;
452 
453     return count;
454 }
455 
456 
457 bool
458 MappedStudio::destroyObject(MappedObjectId id)
459 {
460     GET_LOCK;
461 
462     MappedObject *obj = getObjectById(id);
463 
464     bool rv = false;
465 
466     if (obj) {
467         obj->destroy();
468         rv = true;
469     }
470 
471     RELEASE_LOCK;
472 
473     return rv;
474 }
475 
476 bool
477 MappedStudio::connectObjects(MappedObjectId mId1, MappedObjectId mId2)
478 {
479     GET_LOCK;
480 
481     bool rv = false;
482 
483     // objects must exist and be of connectable types
484     MappedConnectableObject *obj1 =
485         dynamic_cast<MappedConnectableObject *>(getObjectById(mId1));
486     MappedConnectableObject *obj2 =
487         dynamic_cast<MappedConnectableObject *>(getObjectById(mId2));
488 
489     if (obj1 && obj2) {
490         obj1->addConnection(MappedConnectableObject::Out, mId2);
491         obj2->addConnection(MappedConnectableObject::In, mId1);
492         rv = true;
493     }
494 
495     RELEASE_LOCK;
496 
497     return rv;
498 }
499 
500 bool
501 MappedStudio::disconnectObjects(MappedObjectId mId1, MappedObjectId mId2)
502 {
503     GET_LOCK;
504 
505     bool rv = false;
506 
507     // objects must exist and be of connectable types
508     MappedConnectableObject *obj1 =
509         dynamic_cast<MappedConnectableObject *>(getObjectById(mId1));
510     MappedConnectableObject *obj2 =
511         dynamic_cast<MappedConnectableObject *>(getObjectById(mId2));
512 
513     if (obj1 && obj2) {
514         obj1->removeConnection(MappedConnectableObject::Out, mId2);
515         obj2->removeConnection(MappedConnectableObject::In, mId1);
516         rv = true;
517     }
518 
519     RELEASE_LOCK;
520 
521     return rv;
522 }
523 
524 bool
525 MappedStudio::disconnectObject(MappedObjectId mId)
526 {
527     GET_LOCK;
528 
529     bool rv = false;
530 
531     MappedConnectableObject *obj =
532         dynamic_cast<MappedConnectableObject *>(getObjectById(mId));
533 
534     if (obj) {
535         while (1) {
536             MappedObjectValueList list =
537                 obj->getConnections(MappedConnectableObject::In);
538             if (list.empty())
539                 break;
540             MappedObjectId otherId = MappedObjectId(*list.begin());
541             disconnectObjects(otherId, mId);
542         }
543         while (1) {
544             MappedObjectValueList list =
545                 obj->getConnections(MappedConnectableObject::Out);
546             if (list.empty())
547                 break;
548             MappedObjectId otherId = MappedObjectId(*list.begin());
549             disconnectObjects(mId, otherId);
550         }
551     }
552 
553     rv = true;
554 
555     RELEASE_LOCK;
556 
557     return rv;
558 }
559 
560 
561 
562 // Clear down the whole studio
563 //
564 void
565 MappedStudio::clear()
566 {
567     GET_LOCK;
568 
569     for (MappedObjectMap::iterator i = m_objects.begin();
570             i != m_objects.end(); ++i) {
571 
572         for (MappedObjectCategory::iterator j = i->second.begin();
573                 j != i->second.end(); ++j) {
574 
575             delete j->second;
576         }
577     }
578 
579     m_objects.clear();
580 
581     // reset running object id
582     m_runningObjectId = 1;
583 
584     RELEASE_LOCK;
585 }
586 
587 bool
588 MappedStudio::clearObject(MappedObjectId id)
589 {
590     bool rv = false;
591 
592     GET_LOCK;
593 
594     for (MappedObjectMap::iterator i = m_objects.begin();
595             i != m_objects.end(); ++i) {
596 
597         MappedObjectCategory::iterator j = i->second.find(id);
598         if (j != i->second.end()) {
599             // if the object has a parent other than the studio,
600             // persuade that parent to abandon it
601             MappedObject *parent = j->second->getParent();
602             if (parent && !dynamic_cast<MappedStudio *>(parent)) {
603                 parent->removeChild(j->second);
604             }
605 
606             i->second.erase(j);
607             rv = true;
608             break;
609         }
610     }
611 
612     RELEASE_LOCK;
613 
614     return rv;
615 }
616 
617 
618 MappedObjectPropertyList
619 MappedStudio::getPropertyList(const MappedObjectProperty &property)
620 {
621     MappedObjectPropertyList list;
622 
623     if (property == "") {
624         // something
625     }
626 
627     return list;
628 }
629 
630 bool
631 MappedStudio::getProperty(const MappedObjectProperty &,
632                           MappedObjectValue &)
633 {
634     return false;
635 }
636 
637 MappedObject*
638 MappedStudio::getObjectById(MappedObjectId id)
639 {
640     GET_LOCK;
641     MappedObject *rv = nullptr;
642 
643     for (MappedObjectMap::iterator i = m_objects.begin();
644             i != m_objects.end(); ++i) {
645 
646         MappedObjectCategory::iterator j = i->second.find(id);
647         if (j != i->second.end()) {
648             rv = j->second;
649             break;
650         }
651     }
652 
653     RELEASE_LOCK;
654     return rv;
655 }
656 
657 MappedObject*
658 MappedStudio::getObjectByIdAndType(MappedObjectId id, MappedObjectType type)
659 {
660     GET_LOCK;
661     MappedObject *rv = nullptr;
662 
663     MappedObjectCategory &category = m_objects[type];
664     MappedObjectCategory::iterator i = category.find(id);
665     if (i != category.end()) {
666         rv = i->second;
667     }
668 
669     RELEASE_LOCK;
670     return rv;
671 }
672 
673 MappedObject*
674 MappedStudio::getFirst(MappedObjectType type)
675 {
676     return getObjectOfType(type);
677 }
678 
679 MappedObject*
680 MappedStudio::getNext(MappedObject *object)
681 {
682     GET_LOCK;
683 
684     MappedObjectCategory &category = m_objects[object->getType()];
685 
686     bool next = false;
687     MappedObject *rv = nullptr;
688 
689     for (MappedObjectCategory::iterator i = category.begin();
690             i != category.end(); ++i) {
691         if (i->second->getId() == object->getId())
692             next = true;
693         else if (next) {
694             rv = i->second;
695             break;
696         }
697     }
698 
699     RELEASE_LOCK;
700     return rv;
701 }
702 
703 void
704 MappedStudio::setProperty(const MappedObjectProperty &property,
705                           MappedObjectValue /*value*/)
706 {
707     if (property == "") {}
708 
709 }
710 
711 MappedAudioFader *
712 MappedStudio::getAudioFader(InstrumentId id)
713 {
714     GET_LOCK;
715 
716     MappedObjectCategory &category = m_objects[AudioFader];
717     MappedAudioFader *rv = nullptr;
718 
719     for (MappedObjectCategory::iterator i = category.begin();
720             i != category.end(); ++i) {
721         MappedAudioFader *fader = dynamic_cast<MappedAudioFader *>(i->second);
722         if (fader && (fader->getInstrument() == id)) {
723             rv = fader;
724             break;
725         }
726     }
727 
728     RELEASE_LOCK;
729     return rv;
730 }
731 
732 MappedAudioBuss *
733 MappedStudio::getAudioBuss(int bussNumber)
734 {
735     GET_LOCK;
736 
737     MappedObjectCategory &category = m_objects[AudioBuss];
738     MappedAudioBuss *rv = nullptr;
739 
740     for (MappedObjectCategory::iterator i = category.begin();
741             i != category.end(); ++i) {
742         MappedAudioBuss *buss = dynamic_cast<MappedAudioBuss *>(i->second);
743         if (buss && (buss->getBussId() == bussNumber)) {
744             rv = buss;
745             break;
746         }
747     }
748 
749     RELEASE_LOCK;
750     return rv;
751 }
752 
753 MappedAudioInput *
754 MappedStudio::getAudioInput(int inputNumber)
755 {
756     GET_LOCK;
757 
758     MappedObjectCategory &category = m_objects[AudioInput];
759     MappedAudioInput *rv = nullptr;
760 
761     for (MappedObjectCategory::iterator i = category.begin();
762             i != category.end(); ++i) {
763         MappedAudioInput *input = dynamic_cast<MappedAudioInput *>(i->second);
764         if (input && (input->getInputNumber() == inputNumber)) {
765             rv = input;
766             break;
767         }
768     }
769 
770     RELEASE_LOCK;
771     return rv;
772 }
773 
774 
775 // -------------- MappedConnectableObject -----------------
776 //
777 //
778 MappedConnectableObject::MappedConnectableObject(MappedObject *parent,
779         const std::string &name,
780         MappedObjectType type,
781         MappedObjectId id):
782         MappedObject(parent,
783                      name,
784                      type,
785                      id)
786 {}
787 
788 MappedConnectableObject::~MappedConnectableObject()
789 {}
790 
791 void
792 MappedConnectableObject::setConnections(ConnectionDirection dir,
793                                         MappedObjectValueList conns)
794 {
795     if (dir == In)
796         m_connectionsIn = conns;
797     else
798         m_connectionsOut = conns;
799 }
800 
801 void
802 MappedConnectableObject::addConnection(ConnectionDirection dir,
803                                        MappedObjectId id)
804 {
805     MappedObjectValueList &list =
806         (dir == In ? m_connectionsIn : m_connectionsOut);
807 
808     for (MappedObjectValueList::iterator i = list.begin(); i != list.end(); ++i) {
809         if (*i == id) {
810             return ;
811         }
812     }
813 
814     list.push_back(MappedObjectValue(id));
815 }
816 
817 void
818 MappedConnectableObject::removeConnection(ConnectionDirection dir,
819         MappedObjectId id)
820 {
821     MappedObjectValueList &list =
822         (dir == In ? m_connectionsIn : m_connectionsOut);
823 
824     for (MappedObjectValueList::iterator i = list.begin(); i != list.end(); ++i) {
825         if (*i == id) {
826             list.erase(i);
827             return ;
828         }
829     }
830 }
831 
832 MappedObjectValueList
833 MappedConnectableObject::getConnections(ConnectionDirection dir)
834 {
835     if (dir == In)
836         return m_connectionsIn;
837     else
838         return m_connectionsOut;
839 }
840 
841 
842 // ------------ MappedAudioFader ----------------
843 //
844 MappedAudioFader::MappedAudioFader(MappedObject *parent,
845                                    MappedObjectId id,
846                                    MappedObjectValue channels):
847         MappedConnectableObject(parent,
848                                 "MappedAudioFader",
849                                 AudioFader,
850                                 id),
851         m_level(0.0),  // dB
852         m_recordLevel(0.0),
853         m_instrumentId(0),
854         m_pan(0),
855         m_channels(channels),
856         m_inputChannel(0)
857 {}
858 
859 MappedAudioFader::~MappedAudioFader()
860 {}
861 
862 
863 MappedObjectPropertyList
864 MappedAudioFader::getPropertyList(const MappedObjectProperty &property)
865 {
866     MappedObjectPropertyList list;
867 
868     if (property == "") {
869         list.push_back(MappedAudioFader::FaderLevel);
870         list.push_back(MappedAudioFader::FaderRecordLevel);
871         list.push_back(MappedObject::Instrument);
872         list.push_back(MappedAudioFader::Pan);
873         list.push_back(MappedAudioFader::Channels);
874         list.push_back(MappedConnectableObject::ConnectionsIn);
875         list.push_back(MappedConnectableObject::ConnectionsOut);
876     } else if (property == MappedObject::Instrument) {
877         list.push_back(MappedObjectProperty("%1").arg(m_instrumentId));
878     } else if (property == MappedAudioFader::FaderLevel) {
879         list.push_back(MappedObjectProperty("%1").arg(m_level));
880     } else if (property == MappedAudioFader::FaderRecordLevel) {
881         list.push_back(MappedObjectProperty("%1").arg(m_recordLevel));
882     } else if (property == MappedAudioFader::Channels) {
883         list.push_back(MappedObjectProperty("%1").arg(m_channels));
884     } else if (property == MappedAudioFader::InputChannel) {
885         list.push_back(MappedObjectProperty("%1").arg(m_inputChannel));
886     } else if (property == MappedAudioFader::Pan) {
887         list.push_back(MappedObjectProperty("%1").arg(m_pan));
888     } else if (property == MappedConnectableObject::ConnectionsIn) {
889         MappedObjectValueList::const_iterator
890         it = m_connectionsIn.begin();
891 
892         for ( ; it != m_connectionsIn.end(); ++it) {
893             list.push_back(QString("%1").arg(*it));
894         }
895     } else if (property == MappedConnectableObject::ConnectionsOut) {
896         MappedObjectValueList::const_iterator
897         it = m_connectionsOut.begin();
898 
899         for ( ; it != m_connectionsOut.end(); ++it) {
900             list.push_back(QString("%1").arg(*it));
901         }
902     }
903 
904     return list;
905 }
906 
907 bool
908 MappedAudioFader::getProperty(const MappedObjectProperty &property,
909                               MappedObjectValue &value)
910 {
911     if (property == FaderLevel) {
912         value = m_level;
913     } else if (property == Instrument) {
914         value = m_instrumentId;
915     } else if (property == FaderRecordLevel) {
916         value = m_recordLevel;
917     } else if (property == Channels) {
918         value = m_channels;
919     } else if (property == InputChannel) {
920         value = m_inputChannel;
921     } else if (property == Pan) {
922         value = m_pan;
923     } else {
924 #ifdef DEBUG_MAPPEDSTUDIO
925         std::cerr << "MappedAudioFader::getProperty - "
926         << "unsupported or non-scalar property" << std::endl;
927 #endif
928 
929         return false;
930     }
931     return true;
932 }
933 
934 void
935 MappedAudioFader::setProperty(const MappedObjectProperty &property,
936                               MappedObjectValue value)
937 {
938     bool updateLevels = false;
939 
940     if (property == MappedAudioFader::FaderLevel) {
941         m_level = value;
942         updateLevels = true;
943     } else if (property == MappedObject::Instrument) {
944         m_instrumentId = InstrumentId(value);
945         updateLevels = true;
946     } else if (property == MappedAudioFader::FaderRecordLevel) {
947         m_recordLevel = value;
948     } else if (property == MappedAudioFader::Channels) {
949         m_channels = value;
950     } else if (property == MappedAudioFader::InputChannel) {
951         m_inputChannel = value;
952     } else if (property == MappedAudioFader::Pan) {
953         m_pan = value;
954         updateLevels = true;
955     } else if (property == MappedConnectableObject::ConnectionsIn) {
956         m_connectionsIn.clear();
957         m_connectionsIn.push_back(value);
958     } else if (property == MappedConnectableObject::ConnectionsOut) {
959         m_connectionsOut.clear();
960         m_connectionsOut.push_back(value);
961     } else {
962 #ifdef DEBUG_MAPPEDSTUDIO
963         std::cerr << "MappedAudioFader::setProperty - "
964         << "unsupported property" << std::endl;
965 #endif
966 
967         return ;
968     }
969 
970     /*
971     std::cout << "MappedAudioFader::setProperty - "
972               << property << " = " << value << std::endl;
973               */
974 
975     if (updateLevels) {
976         MappedStudio *studio =
977             dynamic_cast<MappedStudio*>(getParent());
978 
979         if (studio) {
980             studio->getSoundDriver()->setAudioInstrumentLevels
981             (m_instrumentId, m_level, m_pan);
982         }
983     }
984 }
985 
986 // ---------------- MappedAudioBuss -------------------
987 //
988 //
989 MappedAudioBuss::MappedAudioBuss(MappedObject *parent,
990                                  MappedObjectId id) :
991         MappedConnectableObject(parent,
992                                 "MappedAudioBuss",
993                                 AudioBuss,
994                                 id),
995         m_bussId(0),
996         m_level(0),
997         m_pan(0)
998 {}
999 
1000 MappedAudioBuss::~MappedAudioBuss()
1001 {}
1002 
1003 MappedObjectPropertyList
1004 MappedAudioBuss::getPropertyList(const MappedObjectProperty &property)
1005 {
1006     MappedObjectPropertyList list;
1007 
1008     if (property == "") {
1009         list.push_back(MappedAudioBuss::BussId);
1010         list.push_back(MappedAudioBuss::Level);
1011         list.push_back(MappedAudioBuss::Pan);
1012         list.push_back(MappedConnectableObject::ConnectionsIn);
1013         list.push_back(MappedConnectableObject::ConnectionsOut);
1014     } else if (property == BussId) {
1015         list.push_back(MappedObjectProperty("%1").arg(m_bussId));
1016     } else if (property == Level) {
1017         list.push_back(MappedObjectProperty("%1").arg(m_level));
1018     } else if (property == MappedConnectableObject::ConnectionsIn) {
1019         MappedObjectValueList::const_iterator
1020         it = m_connectionsIn.begin();
1021 
1022         for ( ; it != m_connectionsIn.end(); ++it) {
1023             list.push_back(QString("%1").arg(*it));
1024         }
1025     } else if (property == MappedConnectableObject::ConnectionsOut) {
1026         MappedObjectValueList::const_iterator
1027         it = m_connectionsOut.begin();
1028 
1029         for ( ; it != m_connectionsOut.end(); ++it) {
1030             list.push_back(QString("%1").arg(*it));
1031         }
1032     }
1033 
1034     return list;
1035 }
1036 
1037 bool
1038 MappedAudioBuss::getProperty(const MappedObjectProperty &property,
1039                              MappedObjectValue &value)
1040 {
1041     if (property == BussId) {
1042         value = m_bussId;
1043     } else if (property == Level) {
1044         value = m_level;
1045     } else if (property == Pan) {
1046         value = m_pan;
1047     } else {
1048 #ifdef DEBUG_MAPPEDSTUDIO
1049         std::cerr << "MappedAudioBuss::getProperty - "
1050         << "unsupported or non-scalar property" << std::endl;
1051 #endif
1052 
1053         return false;
1054     }
1055     return true;
1056 }
1057 
1058 void
1059 MappedAudioBuss::setProperty(const MappedObjectProperty &property,
1060                              MappedObjectValue value)
1061 {
1062     bool updateLevels = false;
1063 
1064     if (property == MappedAudioBuss::BussId) {
1065         m_bussId = (int)value;
1066         updateLevels = true;
1067     } else if (property == MappedAudioBuss::Level) {
1068         m_level = value;
1069         updateLevels = true;
1070     } else if (property == MappedAudioBuss::Pan) {
1071         m_pan = value;
1072         updateLevels = true;
1073     } else if (property == MappedConnectableObject::ConnectionsIn) {
1074         m_connectionsIn.clear();
1075         m_connectionsIn.push_back(value);
1076     } else if (property == MappedConnectableObject::ConnectionsOut) {
1077         m_connectionsOut.clear();
1078         m_connectionsOut.push_back(value);
1079     } else {
1080 #ifdef DEBUG_MAPPEDSTUDIO
1081         std::cerr << "MappedAudioBuss::setProperty - "
1082         << "unsupported property" << std::endl;
1083 #endif
1084 
1085         return ;
1086     }
1087 
1088     if (updateLevels) {
1089         MappedStudio *studio =
1090             dynamic_cast<MappedStudio*>(getParent());
1091 
1092         if (studio) {
1093             studio->getSoundDriver()->setAudioBussLevels
1094             (m_bussId, m_level, m_pan);
1095         }
1096     }
1097 }
1098 
1099 std::vector<InstrumentId>
1100 MappedAudioBuss::getInstruments()
1101 {
1102     std::vector<InstrumentId> rv;
1103 
1104     GET_LOCK;
1105 
1106     MappedObject *studioObject = getParent();
1107     while (!dynamic_cast<MappedStudio *>(studioObject))
1108         studioObject = studioObject->getParent();
1109 
1110     std::vector<MappedObject *> objects =
1111         static_cast<MappedStudio *>(studioObject)->
1112         getObjectsOfType(MappedObject::AudioFader);
1113 
1114     for (std::vector<MappedObject *>::iterator i = objects.begin();
1115             i != objects.end(); ++i) {
1116         MappedAudioFader *fader = dynamic_cast<MappedAudioFader *>(*i);
1117         if (fader) {
1118             MappedObjectValueList connections = fader->getConnections
1119                                                 (MappedConnectableObject::Out);
1120             if (!connections.empty() && (*connections.begin() == getId())) {
1121                 rv.push_back(fader->getInstrument());
1122             }
1123         }
1124     }
1125 
1126     RELEASE_LOCK;
1127 
1128     return rv;
1129 }
1130 
1131 
1132 // ---------------- MappedAudioInput -------------------
1133 //
1134 //
1135 MappedAudioInput::MappedAudioInput(MappedObject *parent,
1136                                    MappedObjectId id) :
1137         MappedConnectableObject(parent,
1138                                 "MappedAudioInput",
1139                                 AudioInput,
1140                                 id)
1141 {}
1142 
1143 MappedAudioInput::~MappedAudioInput()
1144 {}
1145 
1146 MappedObjectPropertyList
1147 MappedAudioInput::getPropertyList(const MappedObjectProperty &property)
1148 {
1149     MappedObjectPropertyList list;
1150 
1151     if (property == "") {
1152         list.push_back(MappedAudioInput::InputNumber);
1153     } else if (property == InputNumber) {
1154         list.push_back(MappedObjectProperty("%1").arg(m_inputNumber));
1155     }
1156 
1157     return list;
1158 }
1159 
1160 bool
1161 MappedAudioInput::getProperty(const MappedObjectProperty &property,
1162                               MappedObjectValue &value)
1163 {
1164     if (property == InputNumber) {
1165         value = m_inputNumber;
1166     } else {
1167 #ifdef DEBUG_MAPPEDSTUDIO
1168         std::cerr << "MappedAudioInput::getProperty - "
1169         << "no properties available" << std::endl;
1170 #endif
1171 
1172     }
1173     return false;
1174 }
1175 
1176 void
1177 MappedAudioInput::setProperty(const MappedObjectProperty &property,
1178                               MappedObjectValue value)
1179 {
1180     if (property == InputNumber) {
1181         m_inputNumber = value;
1182     } else {
1183 #ifdef DEBUG_MAPPEDSTUDIO
1184         std::cerr << "MappedAudioInput::setProperty - "
1185         << "no properties available" << std::endl;
1186 #endif
1187 
1188     }
1189     return ;
1190 }
1191 
1192 
1193 MappedPluginSlot::MappedPluginSlot(MappedObject *parent, MappedObjectId id) :
1194         MappedObject(parent, "MappedPluginSlot", PluginSlot, id)
1195 {
1196 #ifdef DEBUG_MAPPEDSTUDIO
1197     std::cerr << "MappedPluginSlot::MappedPluginSlot: id = " << id << std::endl;
1198 #endif
1199 }
1200 
1201 MappedPluginSlot::~MappedPluginSlot()
1202 {
1203 #ifdef DEBUG_MAPPEDSTUDIO
1204     std::cerr << "MappedPluginSlot::~MappedPluginSlot: id = " << getId() << ", identifier = " << m_identifier << std::endl;
1205 #endif
1206 
1207     if (m_identifier != "") {
1208 
1209         // shut down and remove the plugin instance we have running
1210 
1211         MappedStudio *studio =
1212             dynamic_cast<MappedStudio*>(getParent());
1213 
1214         if (studio) {
1215             SoundDriver *drv = studio->getSoundDriver();
1216 
1217             if (drv) {
1218                 drv->removePluginInstance(m_instrument, m_position);
1219             }
1220         }
1221     }
1222 }
1223 
1224 MappedObjectPropertyList
1225 MappedPluginSlot::getPropertyList(const MappedObjectProperty &property)
1226 {
1227     MappedObjectPropertyList list;
1228 
1229     if (property == "") {
1230         list.push_back(PortCount);
1231         list.push_back(Instrument);
1232         list.push_back(Bypassed);
1233         list.push_back(PluginName);
1234         list.push_back(Label);
1235         list.push_back(Author);
1236         list.push_back(Copyright);
1237         list.push_back(Category);
1238     } else if (property == Programs) {
1239 
1240         // The set of available programs is dynamic -- it can change
1241         // while a plugin is instantiated.  So we query it on demand
1242         // each time.
1243 
1244         MappedStudio *studio =
1245             dynamic_cast<MappedStudio*>(getParent());
1246 
1247         if (studio) {
1248             QStringList programs =
1249                 studio->getSoundDriver()->getPluginInstancePrograms(m_instrument,
1250                         m_position);
1251 
1252             for (int i = 0; i < int(programs.count()); ++i) {
1253                 list.push_back(programs[i]);
1254             }
1255         }
1256 
1257     } else {
1258         std::cerr << "MappedPluginSlot::getPropertyList: not a list property"
1259         << std::endl;
1260     }
1261 
1262     return list;
1263 }
1264 
1265 bool
1266 MappedPluginSlot::getProperty(const MappedObjectProperty &property,
1267                               MappedObjectValue &value)
1268 {
1269     if (property == PortCount) {
1270         value = m_portCount;
1271     } else if (property == Instrument) {
1272         value = m_instrument;
1273     } else if (property == Position) {
1274         value = m_position;
1275     } else if (property == Bypassed) {
1276         value = m_bypassed;
1277     } else {
1278 #ifdef DEBUG_MAPPEDSTUDIO
1279         std::cerr << "MappedPluginSlot::getProperty - "
1280         << "unsupported or non-scalar property" << std::endl;
1281 #endif
1282 
1283         return false;
1284     }
1285     return true;
1286 }
1287 
1288 bool
1289 MappedPluginSlot::getStringProperty(const MappedObjectProperty &property,
1290                                     QString &value)
1291 {
1292     if (property == Identifier) {
1293         value = m_identifier;
1294     } else if (property == PluginName) {
1295         value = m_name;
1296     } else if (property == Label) {
1297         value = m_label;
1298     } else if (property == Author) {
1299         value = m_author;
1300     } else if (property == Copyright) {
1301         value = m_copyright;
1302     } else if (property == Category) {
1303         value = m_category;
1304     } else if (property == Program) {
1305 
1306         MappedStudio *studio =
1307             dynamic_cast<MappedStudio*>(getParent());
1308 
1309         if (studio) {
1310             value = studio->getSoundDriver()->getPluginInstanceProgram(m_instrument,
1311                     m_position);
1312         }
1313     } else {
1314 #ifdef DEBUG_MAPPEDSTUDIO
1315         std::cerr << "MappedPluginSlot::getProperty - "
1316         << "unsupported or non-scalar property" << std::endl;
1317 #endif
1318 
1319         return false;
1320     }
1321     return true;
1322 }
1323 
1324 QString
1325 MappedPluginSlot::getProgram(int bank, int program)
1326 {
1327     MappedStudio *studio =
1328         dynamic_cast<MappedStudio*>(getParent());
1329 
1330     if (studio) {
1331         return
1332             studio->getSoundDriver()->getPluginInstanceProgram(m_instrument,
1333                     m_position,
1334                     bank,
1335                     program);
1336     }
1337 
1338     return QString();
1339 }
1340 
1341 unsigned long
1342 MappedPluginSlot::getProgram(QString name)
1343 {
1344     MappedStudio *studio =
1345         dynamic_cast<MappedStudio*>(getParent());
1346 
1347     if (studio) {
1348         return
1349             studio->getSoundDriver()->getPluginInstanceProgram(m_instrument,
1350                     m_position,
1351                     name);
1352     }
1353 
1354     return 0;
1355 }
1356 
1357 void
1358 MappedPluginSlot::setProperty(const MappedObjectProperty &property,
1359                               MappedObjectValue value)
1360 {
1361     if (property == Instrument) {
1362         m_instrument = InstrumentId(value);
1363     } else if (property == PortCount) {
1364         m_portCount = int(value);
1365     } else if (property == Position) {
1366         m_position = int(value);
1367     } else if (property == Bypassed) {
1368         m_bypassed = bool(value);
1369 
1370         MappedStudio *studio =
1371             dynamic_cast<MappedStudio*>(getParent());
1372 
1373         if (studio) {
1374             studio->getSoundDriver()->setPluginInstanceBypass(m_instrument,
1375                     m_position,
1376                     m_bypassed);
1377         }
1378     }
1379 }
1380 
1381 void
1382 MappedPluginSlot::setStringProperty(const MappedObjectProperty &property,
1383                                     QString value)
1384 {
1385     RG_DEBUG << "MappedPluginSlot::setStringProperty: "
1386              << property << " -> " << value;
1387 
1388     if (property == Identifier) {
1389 
1390         if (m_identifier == value)
1391             return ;
1392 
1393         // shut down and remove the plugin instance we have running
1394 
1395         MappedStudio *studio =
1396             dynamic_cast<MappedStudio*>(getParent());
1397 
1398         if (studio) {
1399             SoundDriver *drv = studio->getSoundDriver();
1400 
1401             if (drv) {
1402 
1403                 // We don't call drv->removePluginInstance at this
1404                 // point: the sequencer will deal with that when we
1405                 // call setPluginInstance below.  If we removed the
1406                 // instance here, we might cause the library we want
1407                 // for the new plugin instance to be unloaded and then
1408                 // loaded again, which is hardly the most efficient.
1409 
1410                 m_identifier = value;
1411 
1412                 // populate myself and my ports
1413                 PluginFactory *factory = PluginFactory::instanceFor(m_identifier);
1414                 if (!factory) {
1415                     std::cerr << "WARNING: MappedPluginSlot::setProperty(identifier): No plugin factory for identifier " << m_identifier << "!" << std::endl;
1416                     m_identifier = "";
1417                     return ;
1418                 }
1419 
1420                 factory->populatePluginSlot(m_identifier, *this);
1421 
1422                 // now create the new instance
1423                 drv->setPluginInstance(m_instrument,
1424                                        m_identifier,
1425                                        m_position);
1426             }
1427         }
1428 
1429         m_configuration.clear();
1430 
1431     } else if (property == PluginName) {
1432         m_name = value;
1433     } else if (property == Label) {
1434         m_label = value;
1435     } else if (property == Author) {
1436         m_author = value;
1437     } else if (property == Copyright) {
1438         m_copyright = value;
1439     } else if (property == Category) {
1440         m_category = value;
1441     } else if (property == Program) {
1442 
1443         MappedStudio *studio =
1444             dynamic_cast<MappedStudio*>(getParent());
1445 
1446         if (studio) {
1447             studio->getSoundDriver()->setPluginInstanceProgram(m_instrument,
1448                     m_position,
1449                     value);
1450         }
1451     } else {
1452 
1453 #ifdef DEBUG_MAPPEDSTUDIO
1454         std::cerr << "MappedPluginSlot::setProperty - "
1455         << "unsupported or non-scalar property" << std::endl;
1456 #endif
1457 
1458     }
1459 }
1460 
1461 void
1462 MappedPluginSlot::setPropertyList(const MappedObjectProperty &property,
1463                                   const MappedObjectPropertyList &values)
1464 {
1465     if (property == Configuration) {
1466 
1467 #ifdef DEBUG_MAPPEDSTUDIO
1468         std::cerr << "MappedPluginSlot::setPropertyList(configuration): configuration is:" << std::endl;
1469 #endif
1470 
1471         MappedStudio *studio =
1472             dynamic_cast<MappedStudio*>(getParent());
1473 
1474         for (MappedObjectPropertyList::const_iterator i = values.begin();
1475                 i != values.end(); ++i) {
1476 
1477             QString key = *i;
1478             QString value = *++i;
1479 
1480 #ifdef DEBUG_MAPPEDSTUDIO
1481             std::cerr << key << " = " << value << std::endl;
1482 #endif
1483 
1484             if (m_configuration.find(key) != m_configuration.end() &&
1485                 m_configuration[key] == value) {
1486                 continue;
1487             }
1488 
1489             if (studio) {
1490                 QString rv =
1491                     studio->getSoundDriver()->configurePlugin(m_instrument,
1492                             m_position,
1493                             key, value);
1494                 if (!rv.isEmpty()) {
1495                     throw(rv);
1496                 }
1497             }
1498         }
1499 
1500         m_configuration.clear();
1501 
1502         for (MappedObjectPropertyList::const_iterator i = values.begin();
1503              i != values.end(); ++i) {
1504 
1505             QString key = *i;
1506             QString value = *++i;
1507 
1508             m_configuration[key] = value;
1509         }
1510     } else {
1511 
1512 #ifdef DEBUG_MAPPEDSTUDIO
1513         std::cerr << "MappedPluginSlot::setPropertyList - "
1514         << "not a list property" << std::endl;
1515 #endif
1516 
1517     }
1518 }
1519 
1520 void
1521 MappedPluginSlot::setPort(unsigned long portNumber, float value)
1522 {
1523     std::vector<MappedObject*> ports = getChildObjects();
1524     std::vector<MappedObject*>::iterator it = ports.begin();
1525     MappedPluginPort *port = nullptr;
1526 
1527     for (; it != ports.end(); ++it) {
1528         port = dynamic_cast<MappedPluginPort *>(*it);
1529         if (port && (unsigned long)port->getPortNumber() == portNumber) {
1530             port->setValue(value);
1531         }
1532     }
1533 }
1534 
1535 float
1536 MappedPluginSlot::getPort(unsigned long portNumber)
1537 {
1538     std::vector<MappedObject*> ports = getChildObjects();
1539     std::vector<MappedObject*>::iterator it = ports.begin();
1540     MappedPluginPort *port = nullptr;
1541 
1542     for (; it != ports.end(); ++it) {
1543         port = dynamic_cast<MappedPluginPort *>(*it);
1544         if (port && (unsigned long)port->getPortNumber() == portNumber) {
1545             return port->getValue();
1546         }
1547     }
1548 
1549     return 0;
1550 }
1551 
1552 
1553 MappedPluginPort::MappedPluginPort(MappedObject *parent, MappedObjectId id) :
1554         MappedObject(parent, "MappedPluginPort", PluginPort, id)
1555 {}
1556 
1557 MappedPluginPort::~MappedPluginPort()
1558 {}
1559 
1560 MappedObjectPropertyList
1561 MappedPluginPort::getPropertyList(const MappedObjectProperty &property)
1562 {
1563     MappedObjectPropertyList list;
1564 
1565     if (property == "") {
1566         list.push_back(PortNumber);
1567         list.push_back(Minimum);
1568         list.push_back(Maximum);
1569         list.push_back(Default);
1570         list.push_back(DisplayHint);
1571         list.push_back(Value);
1572         list.push_back(Name);
1573     } else {
1574         std::cerr << "MappedPluginSlot::getPropertyList: not a list property"
1575         << std::endl;
1576     }
1577 
1578     return list;
1579 }
1580 
1581 bool
1582 MappedPluginPort::getProperty(const MappedObjectProperty &property,
1583                               MappedObjectValue &value)
1584 {
1585     if (property == PortNumber) {
1586         value = m_portNumber;
1587     } else if (property == Minimum) {
1588         value = m_minimum;
1589     } else if (property == Maximum) {
1590         value = m_maximum;
1591     } else if (property == Default) {
1592         value = m_default;
1593     } else if (property == DisplayHint) {
1594         value = m_displayHint;
1595     } else if (property == Value) {
1596         return getValue();
1597     } else {
1598 #ifdef DEBUG_MAPPEDSTUDIO
1599         std::cerr << "MappedPluginPort::getProperty - "
1600         << "unsupported or non-scalar property" << std::endl;
1601 #endif
1602 
1603         return false;
1604     }
1605     return true;
1606 }
1607 
1608 bool
1609 MappedPluginPort::getStringProperty(const MappedObjectProperty &property,
1610                                     QString &value)
1611 {
1612     if (property == Name) {
1613         value = m_name;
1614     } else {
1615 
1616 #ifdef DEBUG_MAPPEDSTUDIO
1617         std::cerr << "MappedPluginPort::getProperty - "
1618         << "unsupported or non-scalar property" << std::endl;
1619 #endif
1620 
1621         return false;
1622     }
1623     return true;
1624 }
1625 
1626 void
1627 MappedPluginPort::setValue(MappedObjectValue value)
1628 {
1629     MappedPluginSlot *slot =
1630         dynamic_cast<MappedPluginSlot *>(getParent());
1631 
1632     if (slot) {
1633 
1634         MappedStudio *studio =
1635             dynamic_cast<MappedStudio *>(slot->getParent());
1636 
1637         if (studio) {
1638             SoundDriver *drv = studio->getSoundDriver();
1639 
1640             if (drv) {
1641                 drv->setPluginInstancePortValue(slot->getInstrument(),
1642                                                 slot->getPosition(),
1643                                                 m_portNumber, value);
1644             }
1645         }
1646     }
1647 }
1648 
1649 float
1650 MappedPluginPort::getValue() const
1651 {
1652     const MappedPluginSlot *slot =
1653         dynamic_cast<const MappedPluginSlot *>(getParent());
1654 
1655     if (slot) {
1656 
1657         const MappedStudio *studio =
1658             dynamic_cast<const MappedStudio *>(slot->getParent());
1659 
1660         if (studio) {
1661             SoundDriver *drv =
1662                 const_cast<SoundDriver *>(studio->getSoundDriver());
1663 
1664             if (drv) {
1665                 return drv->getPluginInstancePortValue(slot->getInstrument(),
1666                                                        slot->getPosition(),
1667                                                        m_portNumber);
1668             }
1669         }
1670     }
1671 
1672     return 0;
1673 }
1674 
1675 void
1676 MappedPluginPort::setProperty(const MappedObjectProperty &property,
1677                               MappedObjectValue value)
1678 {
1679     if (property == PortNumber) {
1680         m_portNumber = int(value);
1681     } else if (property == Minimum) {
1682         m_minimum = value;
1683     } else if (property == Maximum) {
1684         m_maximum = value;
1685     } else if (property == Default) {
1686         m_default = value;
1687     } else if (property == DisplayHint) {
1688         m_displayHint = PluginPort::PortDisplayHint(value);
1689     } else if (property == Value) {
1690         setValue(value);
1691     } else {
1692 #ifdef DEBUG_MAPPEDSTUDIO
1693         std::cerr << "MappedPluginPort::setProperty - "
1694         << "unsupported or non-scalar property" << std::endl;
1695 #endif
1696 
1697     }
1698 }
1699 
1700 
1701 void
1702 MappedPluginPort::setStringProperty(const MappedObjectProperty &property,
1703                                     QString value)
1704 {
1705     if (property == Name) {
1706         m_name = value;
1707     } else {
1708 
1709 #ifdef DEBUG_MAPPEDSTUDIO
1710         std::cerr << "MappedPluginPort::setProperty - "
1711         << "unsupported or non-scalar property" << std::endl;
1712 #endif
1713 
1714     }
1715 }
1716 
1717 
1718 }
1719 
1720 
1721 
1722