1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
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 "[Studio]"
17 
18 #include <iostream>
19 
20 #include "base/Studio.h"
21 #include "MidiDevice.h"
22 #include "AudioDevice.h"
23 #include "SoftSynthDevice.h"
24 #include "Instrument.h"
25 
26 #include "base/RecordIn.h"
27 #include "base/Segment.h"
28 #include "misc/Strings.h"
29 #include "Track.h"
30 #include "Composition.h"
31 #include "sequencer/RosegardenSequencer.h"
32 
33 #include <sstream>
34 #include <string>
35 
36 #include <QString>
37 
38 
39 using std::endl;
40 
41 
42 namespace Rosegarden
43 {
44 
45 Studio::Studio() :
46     amwShowAudioFaders(true),
47     amwShowSynthFaders(true),
48     amwShowAudioSubmasters(true),
49     amwShowUnassignedFaders(false),
50     m_midiThruFilter(0),
51     m_midiRecordFilter(0),
52     m_metronomeDevice(0)
53 {
54     // We _always_ have a buss with id zero, for the master out
55     m_busses.push_back(new Buss(0));
56 
57     // And we always create one audio record in
58     m_recordIns.push_back(new RecordIn());
59 
60     // And we always have one audio and one soft-synth device, whose
61     // IDs match the base instrument numbers (for no good reason
62     // except easy identifiability)
63     addDevice(QObject::tr("Audio").toUtf8().data(),
64               AudioInstrumentBase, AudioInstrumentBase,
65               Device::Audio);
66     addDevice(QObject::tr("Synth plugin").toUtf8().data(),
67               SoftSynthInstrumentBase, SoftSynthInstrumentBase,
68               Device::SoftSynth);
69 }
70 
71 Studio::~Studio()
72 {
73     DeviceListIterator dIt = m_devices.begin();
74 
75     for (; dIt != m_devices.end(); ++dIt)
76         delete(*dIt);
77 
78     m_devices.clear();
79 
80     for (size_t i = 0; i < m_busses.size(); ++i) {
81         delete m_busses[i];
82     }
83 
84     for (size_t i = 0; i < m_recordIns.size(); ++i) {
85         delete m_recordIns[i];
86     }
87 }
88 
89 void
90 Studio::addDevice(const std::string &name,
91                   DeviceId id,
92                   InstrumentId baseInstrumentId,
93                   Device::DeviceType type)
94 {
95     Device *d = nullptr;
96 
97     switch (type) {
98 
99         case Device::Midi:
100             d = new MidiDevice(id, baseInstrumentId, name, MidiDevice::Play);
101             break;
102 
103         case Device::Audio:
104             d = new AudioDevice(id, name);
105             break;
106 
107         case Device::SoftSynth:
108             d = new SoftSynthDevice(id, name);
109             break;
110 
snapY(int y)111         default:
112             RG_WARNING << "addDevice(): WARNING: unrecognised device type " << type;
113             return;
114     }
115 
116     m_devices.push_back(d);
117 }
118 
119 void
120 Studio::removeDevice(DeviceId id)
121 {
122     DeviceListIterator it;
123     for (it = m_devices.begin(); it != m_devices.end(); it++) {
124         if ((*it)->getId() == id) {
125             delete *it;
126             m_devices.erase(it);
127             return;
128         }
129     }
130 }
131 
132 void
setYSnap(int ysnap)133 Studio::resyncDeviceConnections()
134 {
135     // Sync all the MidiDevice connections to the current connections
136     // according to RosegardenSequencer.
137 
138     DeviceList *devices = getDevices();
139 
140     // For each Device
141     for (unsigned i = 0; i < devices->size(); ++i) {
142         // Only MidiDevice's have connections.
143         MidiDevice *midiDevice = dynamic_cast<MidiDevice *>((*devices)[i]);
144         if (!midiDevice)
145             continue;
146 
147         DeviceId deviceId = midiDevice->getId();
148         QString connection =
149                 RosegardenSequencer::getInstance()->getConnection(deviceId);
150 
151         midiDevice->setCurrentConnection(qstrtostr(connection));
152 
153         // If we are connected to something, but the user didn't ask for
154         // anything, we must have been connected up by
155         // AlsaDriver::connectSomething().  In that case, we'd better store
156         // the connection as the user selection in case the user actually
157         // likes it.
158         if (connection != ""  &&  midiDevice->getUserConnection() == "")
159             midiDevice->setUserConnection(qstrtostr(connection));
160     }
161 }
162 
163 
164 DeviceId
165 Studio::getSpareDeviceId(InstrumentId &baseInstrumentId)
166 {
167     InstrumentId highestMidiInstrumentId = MidiInstrumentBase;
168     bool foundInstrument = false;
169 
170     std::set<DeviceId> ids;
171     DeviceListIterator it;
172     for (it = m_devices.begin(); it != m_devices.end(); it++) {
173         ids.insert((*it)->getId());
174         if ((*it)->getType() == Device::Midi) {
175             InstrumentList il = (*it)->getAllInstruments();
176             for (size_t i = 0; i < il.size(); ++i) {
177                 if (il[i]->getId() > highestMidiInstrumentId) {
178                     highestMidiInstrumentId = il[i]->getId();
179                     foundInstrument = true;
180                 }
181             }
182         }
183     }
184 
185     if (!foundInstrument) {
186         baseInstrumentId = MidiInstrumentBase;
187     } else {
188         baseInstrumentId = ((highestMidiInstrumentId / 128) + 1) * 128;
189     }
190 
191     DeviceId id = 0;
192     while (ids.find(id) != ids.end()) ++id;
193     return id;
194 }
195 
196 InstrumentList
197 Studio::getAllInstruments()
198 {
199     InstrumentList list, subList;
200 
201     DeviceListIterator it;
202 
203     // Append lists
204     //
205     for (it = m_devices.begin(); it != m_devices.end(); it++)
206     {
207         // get sub list
208         subList = (*it)->getAllInstruments();
209 
210         // concetenate
211         list.insert(list.end(), subList.begin(), subList.end());
212     }
213 
214     return list;
215 
216 }
217 
218 InstrumentList
219 Studio::getPresentationInstruments() const
220 {
221     InstrumentList list;
222 
223     // For each device...
224     for (DeviceList::const_iterator it = m_devices.begin();
225          it != m_devices.end();
226          ++it) {
227         const MidiDevice *midiDevice = dynamic_cast<MidiDevice *>(*it);
228 
229         if (midiDevice) {
230             // skip read-only devices
231             if (midiDevice->getDirection() == MidiDevice::Record)
232                 continue;
233         }
234 
235         // get sub list
236         InstrumentList subList = (*it)->getPresentationInstruments();
237 
238         // concatenate
239         list.insert(list.end(), subList.begin(), subList.end());
240     }
241 
242     return list;
243 }
244 
245 Instrument *
246 Studio::getInstrumentById(InstrumentId id) const
247 {
248     // For each Device
249     for (std::vector<Device *>::const_iterator deviceIter = m_devices.begin();
250          deviceIter != m_devices.end();
251          ++deviceIter)
252     {
253         InstrumentList list = (*deviceIter)->getAllInstruments();
254 
255         for (InstrumentList::const_iterator instrumentIter = list.begin();
256              instrumentIter != list.end();
257              ++instrumentIter) {
258             if ((*instrumentIter)->getId() == id)
259                 return (*instrumentIter);
260         }
261     }
262 
263     return nullptr;
264 
265 }
266 
267 // From a user selection (from a "Presentation" list) return
268 // the matching Instrument
269 //
270 Instrument*
271 Studio::getInstrumentFromList(int index)
272 {
273     std::vector<Device*>::iterator it;
274     InstrumentList list;
275     InstrumentList::iterator iit;
276     int count = 0;
277 
278     for (it = m_devices.begin(); it != m_devices.end(); ++it)
279     {
280         MidiDevice *midiDevice = dynamic_cast<MidiDevice*>(*it);
281 
282         if (midiDevice)
283         {
284           // skip read-only devices
285           if (midiDevice->getDirection() == MidiDevice::Record)
286               continue;
287         }
288 
289         list = (*it)->getPresentationInstruments();
290 
291         for (iit = list.begin(); iit != list.end(); ++iit)
292         {
293             if (count == index)
294                 return (*iit);
295 
296             count++;
297         }
298     }
299 
300     return nullptr;
301 
302 }
303 
304 Instrument *
305 Studio::getInstrumentFor(const Segment *segment) const
306 {
307     if (!segment) return nullptr;
308     if (!segment->getComposition()) return nullptr;
309     TrackId tid = segment->getTrack();
310     Track *track = segment->getComposition()->getTrackById(tid);
311     if (!track) return nullptr;
312     return getInstrumentFor(track);
313 }
314 
315 Instrument *
316 Studio::getInstrumentFor(const Track *track) const
317 {
318     if (!track) return nullptr;
319     InstrumentId iid = track->getInstrument();
320     return getInstrumentById(iid);
321 }
322 
323 BussList
324 Studio::getBusses()
325 {
326     return m_busses;
327 }
328 
329 Buss *
330 Studio::getBussById(BussId id)
331 {
332     for (BussList::iterator i = m_busses.begin(); i != m_busses.end(); ++i) {
333         if ((*i)->getId() == id) return *i;
334     }
335     return nullptr;
336 }
337 
338 void
339 Studio::addBuss(Buss *buss)
340 {
341     if (buss->getId() != m_busses.size()) {
342         RG_WARNING << "addBuss() Precondition: Incoming buss has wrong ID.";
343     }
344 
345     m_busses.push_back(buss);
346 }
347 
348 #if 0
349 void
350 Studio::removeBuss(BussId id)
351 {
352     for (BussList::iterator i = m_busses.begin(); i != m_busses.end(); ++i) {
353         if ((*i)->getId() == id) {
354             delete *i;
355             m_busses.erase(i);
356             return;
357         }
358     }
359 }
360 #endif
361 
362 void
363 Studio::setBussCount(unsigned newBussCount)
364 {
365     // We have to have at least one for the master.
366     if (newBussCount < 1)
367         return;
368     // Reasonable limit.  Adjust if needed.
369     if (newBussCount > 16)
370         return;
371     // No change?  Bail.
372     if (newBussCount == m_busses.size())
373         return;
374 
375     // If we need to remove busses
376     if (newBussCount < m_busses.size()) {
377         int removeCount = m_busses.size() - newBussCount;
378 
379         // For each one that needs removing.
380         for (int i = 0; i < removeCount; ++i) {
381             // Delete the last buss.
382             delete m_busses.back();
383             // Remove it from the list.
384             m_busses.pop_back();
385         }
386     } else {  // We need to add busses
387         int addCount = newBussCount - m_busses.size();
388 
389         for (int i = 0; i < addCount; ++i) {
390             unsigned bussId = m_busses.size();
391             m_busses.push_back(new Buss(bussId));
392         }
393     }
394 
395 #if 0
396     Q_ASSERT_X(m_busses.size() == newBussCount,
397                "Studio::setBussCount()",
398                "Postcondition: Buss count is not as expected.");
399 
400     for (BussId bussId = 0; bussId < m_busses.size(); ++bussId) {
401         Q_ASSERT_X(m_busses[bussId]->getId() == bussId,
402                    "Studio::setBussCount()",
403                    "Postcondition: Buss has wrong ID.");
404     }
405 #endif
406 }
407 
408 PluginContainer *
409 Studio::getContainerById(InstrumentId id)
410 {
411     PluginContainer *pc = getInstrumentById(id);
412     if (pc) return pc;
413     else return getBussById(id);
414 }
415 
416 RecordIn *
417 Studio::getRecordIn(int number)
418 {
419     if (number >= 0  &&  number < int(m_recordIns.size()))
420         return m_recordIns[number];
421     else
422         return nullptr;
423 }
424 
425 void
426 Studio::setRecordInCount(unsigned newRecordInCount)
427 {
428     // Can't have zero.
429     if (newRecordInCount < 1)
430         return;
431     if (newRecordInCount > 32)
432         return;
433     // No change?  Bail.
434     if (newRecordInCount == m_recordIns.size())
435         return;
436 
437     // If we need to add some RecordIns.
438     if (newRecordInCount > m_recordIns.size()) {
439 
440         unsigned addCount = newRecordInCount - m_recordIns.size();
441 
442         for (unsigned i = 0; i < addCount; ++i) {
443             m_recordIns.push_back(new RecordIn());
444         }
445 
446     } else {  // We need to remove some.
447 
448         unsigned removeCount = m_recordIns.size() - newRecordInCount;
449 
450         // For each one that needs removing.
451         for (unsigned i = 0; i < removeCount; ++i) {
452             // Delete the last RecordIn.
453             delete m_recordIns.back();
454             // Remove it from the list.
455             m_recordIns.pop_back();
456         }
457     }
458 
459     // The mapped IDs get set by RosegardenDocument::initialiseStudio().
460 }
461 
462 // Clear down the devices  - the devices will clear down their
463 // own Instruments.
464 //
465 void
466 Studio::clear()
467 {
468     InstrumentList list;
469     std::vector<Device*>::iterator it;
470 
471     for (it = m_devices.begin(); it != m_devices.end(); ++it)
472         delete *it;
473 
474     m_devices.erase(m_devices.begin(), m_devices.end());
475 }
476 
477 std::string
478 Studio::toXmlString() const
479 {
480     return toXmlString(std::vector<DeviceId>());
481 }
482 
483 std::string
484 Studio::toXmlString(const std::vector<DeviceId> &devices) const
485 {
486     // See RoseXmlHandler for the read side of this.
487 
488     std::stringstream studio;
489 
490     studio << "<studio thrufilter=\"" << m_midiThruFilter
491            << "\" recordfilter=\"" << m_midiRecordFilter
492            << "\" audioinputpairs=\"" << m_recordIns.size()
493            << "\" metronomedevice=\"" << m_metronomeDevice
494            << "\" amwshowaudiofaders=\"" << amwShowAudioFaders
495            << "\" amwshowsynthfaders=\"" << amwShowSynthFaders
496            << "\" amwshowaudiosubmasters=\"" << amwShowAudioSubmasters
497            << "\" amwshowunassignedfaders=\"" << amwShowUnassignedFaders
498            << "\">" << endl << endl;
499 
500     studio << endl;
501 
502     // Get XML version of devices
503     //
504     if (devices.empty()) { // export all devices and busses
505 
506         for (DeviceListConstIterator it = m_devices.begin();
507              it != m_devices.end(); it++) {
508             studio << (*it)->toXmlString() << endl << endl;
509         }
510 
511         for (BussList::const_iterator it = m_busses.begin();
512              it != m_busses.end(); ++it) {
513             studio << (*it)->toXmlString() << endl << endl;
514         }
515 
516     } else {
517         for (std::vector<DeviceId>::const_iterator di(devices.begin());
518              di != devices.end(); ++di) {
519             Device *d = getDevice(*di);
520             if (!d) {
521                 RG_WARNING << "toXmlString(): WARNING: Unknown device id " << (*di);
522             } else {
523                 studio << d->toXmlString() << endl << endl;
524             }
525         }
526     }
527 
528     studio << endl << endl;
529 
530     studio << "</studio>" << endl;
531 
532     return studio.str();
533 }
534 
535 const MidiMetronome *
536 Studio::getMetronomeFromDevice(DeviceId id)
537 {
538     // For each Device
539     for (std::vector<Device *>::const_iterator deviceIter = m_devices.begin();
540          deviceIter != m_devices.end();
541          ++deviceIter) {
542 
543         //RG_DEBUG << "getMetronomeFromDevice(): Having a look at device " << (*it)->getId();
544 
545         // No ID match?  Try the next.
546         if ((*deviceIter)->getId() != id)
547             continue;
548 
549         MidiDevice *midiDevice = dynamic_cast<MidiDevice *>(*deviceIter);
550 
551         // If it's a MidiDevice and it has a metronome, return it.
552         if (midiDevice  &&
553             midiDevice->getMetronome()) {
554             //RG_DEBUG << "getMetronomeFromDevice(" << id << "): device is a MIDI device";
555             return midiDevice->getMetronome();
556         }
557 
558         SoftSynthDevice *ssDevice = dynamic_cast<SoftSynthDevice *>(*deviceIter);
559 
560         // If it's a SoftSynthDevice and it has a metronome, return it.
561         if (ssDevice  &&
562             ssDevice->getMetronome()) {
563             //RG_DEBUG << "getMetronomeFromDevice(" << id << "): device is a soft synth device";
564             return ssDevice->getMetronome();
565         }
566     }
567 
568     return nullptr;
569 }
570 
571 // Scan all MIDI devices for available channels and map
572 // them to a current program
573 
574 Instrument*
575 Studio::assignMidiProgramToInstrument(MidiByte program,
576                                       int msb, int lsb,
577                                       bool percussion)
578 {
579     MidiDevice *midiDevice;
580     std::vector<Device*>::iterator it;
581     Rosegarden::InstrumentList::iterator iit;
582     Rosegarden::InstrumentList instList;
583 
584     // Instruments that we may return
585     //
586     Rosegarden::Instrument *newInstrument = nullptr;
587     Rosegarden::Instrument *firstInstrument = nullptr;
588 
589     bool needBank = (msb >= 0 || lsb >= 0);
590     if (needBank) {
591         if (msb < 0) msb = 0;
592         if (lsb < 0) lsb = 0;
593     }
594 
595     // Pass one - search through all MIDI instruments looking for
596     // a match that we can re-use.  i.e. if we have a matching
597     // Program Change then we can use this Instrument.
598     //
599     for (it = m_devices.begin(); it != m_devices.end(); ++it)
600     {
601         midiDevice = dynamic_cast<MidiDevice*>(*it);
602 
603         if (midiDevice && midiDevice->getDirection() == MidiDevice::Play)
604         {
605             instList = (*it)->getPresentationInstruments();
606 
607             for (iit = instList.begin(); iit != instList.end(); ++iit)
608             {
609                 if (firstInstrument == nullptr)
610                     firstInstrument = *iit;
611 
612                 // If we find an Instrument sending the right program already.
613                 //
614                 if ((*iit)->sendsProgramChange() &&
615                     (*iit)->getProgramChange() == program &&
616                     (!needBank || ((*iit)->sendsBankSelect() &&
617                                    (*iit)->getMSB() == msb &&
618                                    (*iit)->getLSB() == lsb &&
619                                    (*iit)->isPercussion() == percussion)))
620                 {
621                     return (*iit);
622                 }
623                 else
624                 {
625                     // Ignore the program change and use the percussion
626                     // flag.
627                     //
628                     if ((*iit)->isPercussion() && percussion)
629                     {
630                         return (*iit);
631                     }
632 
633                     // Otherwise store the first Instrument for
634                     // possible use later.
635                     //
636                     if (newInstrument == nullptr &&
637                         (*iit)->sendsProgramChange() == false &&
638                         (*iit)->sendsBankSelect() == false &&
639                         (*iit)->isPercussion() == percussion)
640                         newInstrument = *iit;
641                 }
642             }
643         }
644     }
645 
646 
647     // Okay, if we've got this far and we have a new Instrument to use
648     // then use it.
649     //
650     if (newInstrument != nullptr)
651     {
652         newInstrument->setSendProgramChange(true);
653         newInstrument->setProgramChange(program);
654 
655         if (needBank) {
656             newInstrument->setSendBankSelect(true);
657             newInstrument->setPercussion(percussion);
658             newInstrument->setMSB(msb);
659             newInstrument->setLSB(lsb);
660         }
661     }
662     else // Otherwise we just reuse the first Instrument we found
663         newInstrument = firstInstrument;
664 
665 
666     return newInstrument;
667 }
668 
669 // Just make all of these Instruments available for automatic
670 // assignment in the assignMidiProgramToInstrument() method
671 // by invalidating the ProgramChange flag.
672 //
673 // This method sounds much more dramatic than it actually is -
674 // it could probably do with a rename.
675 //
676 //
677 void
678 Studio::unassignAllInstruments()
679 {
680     MidiDevice *midiDevice;
681     AudioDevice *audioDevice;
682     std::vector<Device*>::iterator it;
683     Rosegarden::InstrumentList::iterator iit;
684     Rosegarden::InstrumentList instList;
685     int channel = 0;
686 
687     for (it = m_devices.begin(); it != m_devices.end(); ++it)
688     {
689         midiDevice = dynamic_cast<MidiDevice*>(*it);
690 
691         if (midiDevice)
692         {
693             instList = (*it)->getPresentationInstruments();
694 
695             for (iit = instList.begin(); iit != instList.end(); ++iit)
696             {
697                 // Only for true MIDI Instruments - not System ones
698                 //
699                 if ((*iit)->getId() >= MidiInstrumentBase)
700                 {
701                     (*iit)->setSendBankSelect(false);
702                     (*iit)->setSendProgramChange(false);
703                     (*iit)->setNaturalChannel(channel);
704                     channel = ( channel + 1 ) % 16;
705                     (*iit)->setFixedChannel();
706                     // ??? This is a "reset" of the instrument.  It doesn't
707                     //     seem to make sense that we should send out the
708                     //     default values.
709                     //(*iit)->sendChannelSetup();
710 
711                     (*iit)->setPan(MidiMidValue);
712                     (*iit)->setVolume(100);
713 
714                 }
715             }
716         }
717         else
718         {
719             audioDevice = dynamic_cast<AudioDevice*>(*it);
720 
721             if (audioDevice)
722             {
723                 instList = (*it)->getPresentationInstruments();
724 
725                 for (iit = instList.begin(); iit != instList.end(); ++iit)
726                     (*iit)->emptyPlugins();
727             }
728         }
729     }
730 }
731 
732 void
733 Studio::clearMidiBanksAndPrograms()
734 {
735     MidiDevice *midiDevice;
736     std::vector<Device*>::iterator it;
737 
738     for (it = m_devices.begin(); it != m_devices.end(); ++it)
739     {
740         midiDevice = dynamic_cast<MidiDevice*>(*it);
741 
742         if (midiDevice)
743         {
744             midiDevice->clearProgramList();
745             midiDevice->clearBankList();
746         }
747     }
748 }
749 
750 void
751 Studio::clearBusses()
752 {
753     for (size_t i = 0; i < m_busses.size(); ++i) {
754         delete m_busses[i];
755     }
756     m_busses.clear();
757     m_busses.push_back(new Buss(0));
758 }
759 
760 void
761 Studio::clearRecordIns()
762 {
763     for (size_t i = 0; i < m_recordIns.size(); ++i) {
764         delete m_recordIns[i];
765     }
766     m_recordIns.clear();
767     m_recordIns.push_back(new RecordIn());
768 }
769 
770 Device *
771 Studio::getDevice(DeviceId id) const
772 {
773     //RG_DEBUG << "Studio[" << this << "]::getDevice(" << id << ")... ";
774 
775     std::vector<Device*>::const_iterator it;
776 
777     for (it = m_devices.begin(); it != m_devices.end(); ++it) {
778 
779         // possibly fix a following seg.fault :
780         if( ! (*it) ){
781             RG_WARNING << "getDevice(): WARNING: (*it) is nullptr";
782             continue;
783         }
784 
785         //RG_DEBUG << (*it)->getId();
786 
787         if ((*it)->getId() == id) {
788             //RG_DEBUG << "Found";
789             return (*it);
790         }
791     }
792 
793     //RG_DEBUG << "NOT found";
794 
795     return nullptr;
796 }
797 
798 Device *
799 Studio::getAudioDevice()
800 {
801     std::vector<Device*>::iterator it;
802 
803     for (it = m_devices.begin(); it != m_devices.end(); ++it) {
804         if ((*it)->getType() == Device::Audio) return *it;
805     }
806 
807     return nullptr;
808 }
809 
810 Device *
811 Studio::getSoftSynthDevice()
812 {
813     std::vector<Device*>::iterator it;
814 
815     for (it = m_devices.begin(); it != m_devices.end(); ++it) {
816         if ((*it)->getType() == Device::SoftSynth) return *it;
817     }
818 
819     return nullptr;
820 }
821 
822 std::string
823 Studio::getSegmentName(InstrumentId id)
824 {
825     MidiDevice *midiDevice;
826     std::vector<Device*>::iterator it;
827     Rosegarden::InstrumentList::iterator iit;
828     Rosegarden::InstrumentList instList;
829 
830     for (it = m_devices.begin(); it != m_devices.end(); ++it)
831     {
832         midiDevice = dynamic_cast<MidiDevice*>(*it);
833 
834         if (midiDevice)
835         {
836             instList = (*it)->getAllInstruments();
837 
838             for (iit = instList.begin(); iit != instList.end(); ++iit)
839             {
840                 if ((*iit)->getId() == id)
841                 {
842                     if ((*iit)->sendsProgramChange())
843                     {
844                         return (*iit)->getProgramName();
845                     }
846                     else
847                     {
848                         return midiDevice->getName() + " " + (*iit)->getName();
849                     }
850                 }
851             }
852         }
853     }
854 
855     return std::string("");
856 }
857 
858 InstrumentId
859 Studio::getAudioPreviewInstrument()
860 {
861     AudioDevice *audioDevice;
862     std::vector<Device*>::iterator it;
863 
864     for (it = m_devices.begin(); it != m_devices.end(); ++it)
865     {
866         audioDevice = dynamic_cast<AudioDevice*>(*it);
867 
868         // Just the first one will do - we can make this more
869         // subtle if we need to later.
870         //
871         if (audioDevice)
872             return audioDevice->getPreviewInstrument();
873     }
874 
875     // system instrument -  won't accept audio
876     return 0;
877 }
878 
879 bool
880 Studio::haveMidiDevices() const
881 {
882     Rosegarden::DeviceListConstIterator it = m_devices.begin();
883     for (; it != m_devices.end(); it++)
884     {
885         if ((*it)->getType() == Device::Midi) return true;
886     }
887     return false;
888 }
889 
890 
891 }
892 
893