root/branches/libffado-2.0/src/genericavc/avc_avdevice.cpp

Revision 1299, 26.2 kB (checked in by ppalmers, 13 years ago)

implement configuration file mechanism to ease device support and packaging. this mechanism replaces the vendormodel text files. it loads two files, one system-wide and a second in the user directory. the user config file takes precedence. this should ease adding
device id's on a per-user base. it also allows for other settings to be carried by the same 'Configuration' object (present in the devicemanager). The idea is that it will also replace the OptionContainer? mechanism on the long run, and allow for easy integration
of system options (e.g. the pre-transmit amount).

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copyright (C) 2005-2008 by Daniel Wagner
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "devicemanager.h"
26 #include "genericavc/avc_avdevice.h"
27
28 #include "libieee1394/configrom.h"
29 #include "libieee1394/ieee1394service.h"
30
31 #include "libavc/avc_definitions.h"
32 #include "libavc/general/avc_plug_info.h"
33 #include "libavc/general/avc_extended_plug_info.h"
34 #include "libavc/general/avc_subunit_info.h"
35
36 #include "debugmodule/debugmodule.h"
37
38 #include <string>
39 #include <stdint.h>
40 #include <assert.h>
41 #include "libutil/ByteSwap.h"
42 #include <iostream>
43 #include <sstream>
44
45 #include <libraw1394/csr.h>
46
47 using namespace AVC;
48
49 namespace GenericAVC {
50
51 IMPL_DEBUG_MODULE( AvDevice, AvDevice, DEBUG_LEVEL_NORMAL );
52
53 AvDevice::AvDevice( DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
54     : FFADODevice( d, configRom )
55 {
56     debugOutput( DEBUG_LEVEL_VERBOSE, "Created GenericAVC::AvDevice (NodeID %d)\n",
57                  getConfigRom().getNodeId() );
58     addOption(Util::OptionContainer::Option("snoopMode",false));
59 }
60
61 AvDevice::~AvDevice()
62 {
63     for ( StreamProcessorVectorIterator it = m_receiveProcessors.begin();
64           it != m_receiveProcessors.end();
65           ++it )
66     {
67         delete *it;
68     }
69     for ( StreamProcessorVectorIterator it = m_transmitProcessors.begin();
70           it != m_transmitProcessors.end();
71           ++it )
72     {
73         delete *it;
74     }
75 }
76
77 bool
78 AvDevice::probe( Util::Configuration& c, ConfigRom& configRom, bool generic )
79 {
80     if(generic) {
81         // check if we have a music subunit
82         SubUnitInfoCmd subUnitInfoCmd( configRom.get1394Service() );
83         subUnitInfoCmd.setCommandType( AVCCommand::eCT_Status );
84         subUnitInfoCmd.m_page = 0;
85         subUnitInfoCmd.setNodeId( configRom.getNodeId() );
86         subUnitInfoCmd.setVerbose( configRom.getVerboseLevel() );
87         if ( !subUnitInfoCmd.fire() ) {
88             debugError( "Subunit info command failed\n" );
89             return false;
90         }
91         for ( int i = 0; i < subUnitInfoCmd.getNrOfValidEntries(); ++i ) {
92             subunit_type_t subunit_type
93                 = subUnitInfoCmd.m_table[i].m_subunit_type;
94             if (subunit_type == eST_Music) return true;
95         }
96
97         return false;
98     } else {
99         // check if device is in supported devices list
100         unsigned int vendorId = configRom.getNodeVendorId();
101         unsigned int modelId = configRom.getModelId();
102
103         Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
104         return c.isValid(vme) && vme.driver == Util::Configuration::eD_GenericAVC;
105         return false;
106     }
107 }
108
109 FFADODevice *
110 AvDevice::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
111 {
112     return new AvDevice(d, configRom );
113 }
114
115 bool
116 AvDevice::discover()
117 {
118     Util::MutexLockHelper lock(m_DeviceMutex);
119
120     unsigned int vendorId = getConfigRom().getNodeVendorId();
121     unsigned int modelId = getConfigRom().getModelId();
122
123     Util::Configuration &c = getDeviceManager().getConfiguration();
124     Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
125
126     if (c.isValid(vme) && vme.driver == Util::Configuration::eD_GenericAVC) {
127         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
128                      vme.vendor_name.c_str(),
129                      vme.model_name.c_str());
130     } else {
131         debugWarning("Using generic AV/C support for unsupported device '%s %s'\n",
132                      getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
133     }
134     return discoverGeneric();
135 }
136
137 bool
138 AvDevice::discoverGeneric()
139 {
140     if ( !Unit::discover() ) {
141         debugError( "Could not discover unit\n" );
142         return false;
143     }
144
145     if((getAudioSubunit( 0 ) == NULL)) {
146         debugError( "Unit doesn't have an Audio subunit.\n");
147         return false;
148     }
149     if((getMusicSubunit( 0 ) == NULL)) {
150         debugError( "Unit doesn't have a Music subunit.\n");
151         return false;
152     }
153     return true;
154 }
155
156 void
157 AvDevice::setVerboseLevel(int l)
158 {
159     Util::MutexLockHelper lock(m_DeviceMutex);
160     setDebugLevel(l);
161     m_pPlugManager->setVerboseLevel(l);
162     FFADODevice::setVerboseLevel(l);
163     AVC::Unit::setVerboseLevel(l);
164     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
165 }
166
167 int
168 AvDevice::getSamplingFrequency( ) {
169     AVC::Plug* inputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Input, 0 );
170     if ( !inputPlug ) {
171         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
172         return false;
173     }
174     AVC::Plug* outputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Output, 0 );
175     if ( !outputPlug ) {
176         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
177         return false;
178     }
179
180     int samplerate_playback=inputPlug->getSampleRate();
181     int samplerate_capture=outputPlug->getSampleRate();
182
183     if (samplerate_playback != samplerate_capture) {
184         debugWarning("Samplerates for capture and playback differ!\n");
185     }
186     return samplerate_capture;
187 }
188
189 bool
190 AvDevice::setSamplingFrequency( int s )
191 {
192     Util::MutexLockHelper lock(m_DeviceMutex);
193     bool snoopMode=false;
194     if(!getOption("snoopMode", snoopMode)) {
195         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
196     }
197
198     if(snoopMode) {
199         int current_sr=getSamplingFrequency();
200         if (current_sr != s ) {
201             debugError("In snoop mode it is impossible to set the sample rate.\n");
202             debugError("Please start the client with the correct setting.\n");
203             return false;
204         }
205         return true;
206     } else {
207         AVC::Plug* plug = getPlugById( m_pcrPlugs, Plug::eAPD_Input, 0 );
208         if ( !plug ) {
209             debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
210             return false;
211         }
212
213         if ( !plug->setSampleRate( s ) )
214         {
215             debugError( "setSampleRate: Setting sample rate failed\n" );
216             return false;
217         }
218
219         plug = getPlugById( m_pcrPlugs, Plug::eAPD_Output,  0 );
220         if ( !plug ) {
221             debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
222             return false;
223         }
224
225         if ( !plug->setSampleRate( s ) )
226         {
227             debugError( "setSampleRate: Setting sample rate failed\n" );
228             return false;
229         }
230
231         debugOutput( DEBUG_LEVEL_VERBOSE,
232                      "setSampleRate: Set sample rate to %d\n",
233                      s );
234         return true;
235     }
236     // not executable
237     return false;
238
239 }
240
241 bool
242 AvDevice::supportsSamplingFrequency( int s )
243 {
244     Util::MutexLockHelper lock(m_DeviceMutex);
245
246     AVC::Plug* plug = getPlugById( m_pcrPlugs, Plug::eAPD_Input, 0 );
247     if ( !plug ) {
248         debugError( "Could not retrieve iso input plug 0\n" );
249         return false;
250     }
251
252     if ( !plug->supportsSampleRate( s ) )
253     {
254         debugError( "sample rate not supported by input plug\n" );
255         return false;
256     }
257
258     plug = getPlugById( m_pcrPlugs, Plug::eAPD_Output,  0 );
259     if ( !plug ) {
260         debugError( "Could not retrieve iso output plug 0\n" );
261         return false;
262     }
263
264     if ( !plug->supportsSampleRate( s ) )
265     {
266         debugError( "sample rate not supported by output plug\n" );
267         return false;
268     }
269     return true;
270 }
271
272 #define GENERICAVC_CHECK_AND_ADD_SR(v, x) \
273     { if(supportsSamplingFrequency(x)) \
274       v.push_back(x); }
275
276 std::vector<int>
277 AvDevice::getSupportedSamplingFrequencies()
278 {
279     if (m_supported_frequencies_cache.size() == 0) {
280         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 22050);
281         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 24000);
282         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 32000);
283         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 44100);
284         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 48000);
285         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 88200);
286         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 96000);
287         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 176400);
288         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 192000);
289     }
290     return m_supported_frequencies_cache;
291 }
292
293 FFADODevice::ClockSourceVector
294 AvDevice::getSupportedClockSources() {
295     FFADODevice::ClockSourceVector r;
296
297     Util::MutexLockHelper lock(m_DeviceMutex);
298
299     PlugVector syncMSUInputPlugs = m_pPlugManager->getPlugsByType(
300         eST_Music,
301         0,
302         0xff,
303         0xff,
304         Plug::eAPA_SubunitPlug,
305         Plug::eAPD_Input,
306         Plug::eAPT_Sync );
307     if ( !syncMSUInputPlugs.size() ) {
308         // there exist devices which do not have a sync plug
309         // or their av/c model is broken.
310         return r;
311     }
312
313     for ( SyncInfoVector::const_iterator it
314               = getSyncInfos().begin();
315           it != getSyncInfos().end();
316           ++it )
317     {
318         const SyncInfo si=*it;
319
320         ClockSource s=syncInfoToClockSource(*it);
321         r.push_back(s);
322     }
323     return r;
324 }
325
326 bool
327 AvDevice::setActiveClockSource(ClockSource s) {
328     Plug *src=m_pPlugManager->getPlug( s.id );
329     if (!src) {
330         debugError("Could not find plug with id %d\n", s.id);
331         return false;
332     }
333
334     Util::MutexLockHelper lock(m_DeviceMutex);
335     for ( SyncInfoVector::const_iterator it
336               = getSyncInfos().begin();
337           it != getSyncInfos().end();
338           ++it )
339     {
340         const SyncInfo si=*it;
341
342         if (si.m_source==src) {
343             return setActiveSync(si);
344         }
345     }
346     return false;
347 }
348
349 FFADODevice::ClockSource
350 AvDevice::getActiveClockSource() {
351     const SyncInfo* si=getActiveSyncInfo();
352     if ( !si ) {
353         debugError( "Could not retrieve active sync information\n" );
354         ClockSource s;
355         s.type=eCT_Invalid;
356         return s;
357     }
358     debugOutput(DEBUG_LEVEL_VERBOSE, "Active Sync mode:  %s\n", si->m_description.c_str() );
359
360     return syncInfoToClockSource(*si);
361 }
362
363 FFADODevice::ClockSource
364 AvDevice::syncInfoToClockSource(const SyncInfo& si) {
365     ClockSource s;
366
367     // the description is easy
368     // it can be that we overwrite it later
369     s.description=si.m_description;
370
371     // FIXME: always valid at the moment
372     s.valid=true;
373
374     assert(si.m_source);
375     s.id=si.m_source->getGlobalId();
376
377     // now figure out what type this is
378     switch(si.m_source->getPlugType()) {
379         case Plug::eAPT_IsoStream:
380             s.type=eCT_SytMatch;
381             break;
382         case Plug::eAPT_Sync:
383             if(si.m_source->getPlugAddressType() == Plug::eAPA_PCR) {
384                 s.type=eCT_SytStream; // this is logical
385             } else if(si.m_source->getPlugAddressType() == Plug::eAPA_SubunitPlug) {
386                 s.type=eCT_Internal; // this assumes some stuff
387             } else if(si.m_source->getPlugAddressType() == Plug::eAPA_ExternalPlug) {
388                 std::string plugname=si.m_source->getName();
389                 s.description=plugname;
390                 // this is basically due to Focusrites interpretation
391                 if(plugname.find( "SPDIF", 0 ) != string::npos) {
392                     s.type=eCT_SPDIF; // this assumes the name will tell us
393                 } else {
394                     s.type=eCT_WordClock; // this assumes a whole lot more
395                 }
396             } else {
397                 s.type=eCT_Invalid;
398             }
399             break;
400         case Plug::eAPT_Digital:
401             if(si.m_source->getPlugAddressType() == Plug::eAPA_ExternalPlug) {
402                 std::string plugname=si.m_source->getName();
403                 s.description=plugname;
404                 // this is basically due to Focusrites interpretation
405                 if(plugname.find( "ADAT", 0 ) != string::npos) {
406                     s.type=eCT_ADAT; // this assumes the name will tell us
407                 } else if(plugname.find( "SPDIF", 0 ) != string::npos) {
408                     s.type=eCT_SPDIF; // this assumes the name will tell us
409                 } else {
410                     s.type=eCT_WordClock; // this assumes a whole lot more
411                 }
412             } else {
413                 s.type=eCT_Invalid;
414             }
415             break;
416         default:
417             s.type=eCT_Invalid; break;
418     }
419
420     // is it active?
421     const SyncInfo* active=getActiveSyncInfo();
422     if (active) {
423         if ((active->m_source == si.m_source)
424            && (active->m_destination == si.m_destination))
425            s.active=true;
426         else s.active=false;
427     } else s.active=false;
428
429     return s;
430 }
431
432 bool
433 AvDevice::lock() {
434     bool snoopMode=false;
435     Util::MutexLockHelper lock(m_DeviceMutex);
436     if(!getOption("snoopMode", snoopMode)) {
437         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
438     }
439
440     if (snoopMode) {
441         // don't lock
442     } else {
443 //         return Unit::reserve(4);
444     }
445
446     return true;
447 }
448
449 bool
450 AvDevice::unlock() {
451     bool snoopMode=false;
452     Util::MutexLockHelper lock(m_DeviceMutex);
453     if(!getOption("snoopMode", snoopMode)) {
454         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
455     }
456
457     if (snoopMode) {
458         // don't unlock
459     } else {
460 //         return Unit::reserve(0);
461     }
462     return true;
463 }
464
465 void
466 AvDevice::showDevice()
467 {
468     FFADODevice::showDevice();
469
470     AVC::Unit::show();
471     flushDebugOutput();
472 }
473
474 bool
475 AvDevice::prepare() {
476     bool snoopMode=false;
477     Util::MutexLockHelper lock(m_DeviceMutex);
478     if(!getOption("snoopMode", snoopMode)) {
479         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
480     }
481
482     ///////////
483     // get plugs
484
485     AVC::Plug* inputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Input, 0 );
486     if ( !inputPlug ) {
487         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
488         return false;
489     }
490     AVC::Plug* outputPlug = getPlugById( m_pcrPlugs, Plug::eAPD_Output, 0 );
491     if ( !outputPlug ) {
492         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
493         return false;
494     }
495
496     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing receive processor...\n");
497     // create & add streamprocessors
498     Streaming::StreamProcessor *p;
499
500     if ( outputPlug->getNrOfChannels() == 0 ) {
501         debugError("Receive plug has no channels\n");
502         return false;
503     }
504     p = new Streaming::AmdtpReceiveStreamProcessor(*this,
505                              outputPlug->getNrOfChannels());
506
507     if(!p->init()) {
508         debugFatal("Could not initialize receive processor!\n");
509         delete p;
510         return false;
511     }
512
513     if (!addPlugToProcessor(*outputPlug, p,
514         Streaming::Port::E_Capture)) {
515         debugFatal("Could not add plug to processor!\n");
516         delete p;
517         return false;
518     }
519
520     m_receiveProcessors.push_back(p);
521
522     // do the transmit processor
523     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing transmit processor%s...\n",
524             (snoopMode?" in snoop mode":""));
525     if (snoopMode) {
526         // we are snooping, so this is receive too.
527         p=new Streaming::AmdtpReceiveStreamProcessor(*this,
528                                   inputPlug->getNrOfChannels());
529     } else {
530         Streaming::AmdtpTransmitStreamProcessor * t;
531         t=new Streaming::AmdtpTransmitStreamProcessor(*this,
532                                 inputPlug->getNrOfChannels());
533         #if AMDTP_ALLOW_PAYLOAD_IN_NODATA_XMIT
534             // FIXME: it seems that some BeBoB devices can't handle NO-DATA without payload
535             t->sendPayloadForNoDataPackets(true);
536         #endif
537         p=t;
538     }
539
540     if(!p->init()) {
541         debugFatal("Could not initialize transmit processor %s!\n",
542             (snoopMode?" in snoop mode":""));
543         delete p;
544         return false;
545     }
546
547     if (snoopMode) {
548         if (!addPlugToProcessor(*inputPlug, p,
549             Streaming::Port::E_Capture)) {
550             debugFatal("Could not add plug to processor!\n");
551             return false;
552         }
553     } else {
554         if (!addPlugToProcessor(*inputPlug, p,
555             Streaming::Port::E_Playback)) {
556             debugFatal("Could not add plug to processor!\n");
557             return false;
558         }
559     }
560
561     // we put this SP into the transmit SP vector,
562     // no matter if we are in snoop mode or not
563     // this allows us to find out what direction
564     // a certain stream should have.
565     m_transmitProcessors.push_back(p);
566
567     return true;
568 }
569
570 bool
571 AvDevice::addPlugToProcessor(
572     AVC::Plug& plug,
573     Streaming::StreamProcessor *processor,
574     Streaming::AmdtpAudioPort::E_Direction direction) {
575
576     std::string id=std::string("dev?");
577     if(!getOption("id", id)) {
578         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
579     }
580
581     Plug::ClusterInfoVector& clusterInfos = plug.getClusterInfos();
582     for ( Plug::ClusterInfoVector::const_iterator it = clusterInfos.begin();
583           it != clusterInfos.end();
584           ++it )
585     {
586         const Plug::ClusterInfo* clusterInfo = &( *it );
587
588         Plug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos;
589         for ( Plug::ChannelInfoVector::const_iterator it = channelInfos.begin();
590               it != channelInfos.end();
591               ++it )
592         {
593             const Plug::ChannelInfo* channelInfo = &( *it );
594             std::ostringstream portname;
595
596             portname << id << "_" << channelInfo->m_name;
597
598             Streaming::Port *p=NULL;
599             switch(clusterInfo->m_portType) {
600             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Speaker:
601             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Headphone:
602             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Microphone:
603             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Line:
604             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Analog:
605                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding audio channel %s (pos=0x%02X, loc=0x%02X)\n",
606                     channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location);
607                 p=new Streaming::AmdtpAudioPort(
608                         *processor,
609                         portname.str(),
610                         direction,
611                         channelInfo->m_streamPosition,
612                         channelInfo->m_location,
613                         Streaming::AmdtpPortInfo::E_MBLA
614                 );
615                 break;
616
617             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MIDI:
618                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding MIDI channel %s (pos=0x%02X, loc=0x%02X)\n",
619                     channelInfo->m_name.c_str(), channelInfo->m_streamPosition, processor->getPortCount(Streaming::Port::E_Midi));
620                 p=new Streaming::AmdtpMidiPort(
621                         *processor,
622                         portname.str(),
623                         direction,
624                         channelInfo->m_streamPosition,
625                         // Workaround for out-of-spec hardware
626                         // should be:
627                         // channelInfo->m_location,
628                         // but now we renumber the midi channels' location as they
629                         // are discovered
630                         processor->getPortCount(Streaming::Port::E_Midi),
631                         Streaming::AmdtpPortInfo::E_Midi
632                 );
633
634                 break;
635             case ExtendedPlugInfoClusterInfoSpecificData::ePT_SPDIF:
636             case ExtendedPlugInfoClusterInfoSpecificData::ePT_ADAT:
637             case ExtendedPlugInfoClusterInfoSpecificData::ePT_TDIF:
638             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MADI:
639             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Digital:
640                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding digital audio channel %s (pos=0x%02X, loc=0x%02X)\n",
641                     channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location);
642                 p=new Streaming::AmdtpAudioPort(
643                         *processor,
644                         portname.str(),
645                         direction,
646                         channelInfo->m_streamPosition,
647                         channelInfo->m_location,
648                         Streaming::AmdtpPortInfo::E_MBLA
649                 );
650                 break;
651
652             case ExtendedPlugInfoClusterInfoSpecificData::ePT_NoType:
653             default:
654             // unsupported
655                 break;
656             }
657
658             if (!p) {
659                 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->m_name.c_str());
660             }
661          }
662     }
663     return true;
664 }
665
666 int
667 AvDevice::getStreamCount() {
668     int retval;
669     Util::MutexLockHelper lock(m_DeviceMutex);
670     retval = m_receiveProcessors.size() + m_transmitProcessors.size();
671     return retval;
672 }
673
674 Streaming::StreamProcessor *
675 AvDevice::getStreamProcessorByIndex(int i) {
676
677     if (i<(int)m_receiveProcessors.size()) {
678         return m_receiveProcessors.at(i);
679     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
680         return m_transmitProcessors.at(i-m_receiveProcessors.size());
681     }
682
683     return NULL;
684 }
685
686 bool
687 AvDevice::startStreamByIndex(int i) {
688     int iso_channel=-1;
689     bool snoopMode=false;
690     if(!getOption("snoopMode", snoopMode)) {
691         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
692     }
693
694     if (i<(int)m_receiveProcessors.size()) {
695         int n=i;
696         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
697
698         if(snoopMode) { // a stream from the device to another host
699             // FIXME: put this into a decent framework!
700             // we should check the oPCR[n] on the device
701             struct iec61883_oPCR opcr;
702             if (iec61883_get_oPCRX(
703                     get1394Service().getHandle(),
704                     getConfigRom().getNodeId() | 0xffc0,
705                     (quadlet_t *)&opcr,
706                     n)) {
707
708                 debugWarning("Error getting the channel for SP %d\n",i);
709                 return false;
710             }
711
712             iso_channel=opcr.channel;
713         } else {
714             iso_channel=get1394Service().allocateIsoChannelCMP(
715                 getConfigRom().getNodeId() | 0xffc0, n,
716                 get1394Service().getLocalNodeId()| 0xffc0, -1);
717         }
718         if (iso_channel<0) {
719             debugError("Could not allocate ISO channel for SP %d\n",i);
720             return false;
721         }
722
723         debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel);
724
725         p->setChannel(iso_channel);
726         return true;
727
728     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
729         int n=i-m_receiveProcessors.size();
730         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
731
732         if(snoopMode) { // a stream from another host to the device
733             // FIXME: put this into a decent framework!
734             // we should check the iPCR[n] on the device
735             struct iec61883_iPCR ipcr;
736             if (iec61883_get_iPCRX(
737                     get1394Service().getHandle(),
738                     getConfigRom().getNodeId() | 0xffc0,
739                     (quadlet_t *)&ipcr,
740                     n)) {
741
742                 debugWarning("Error getting the channel for SP %d\n",i);
743                 return false;
744             }
745
746             iso_channel=ipcr.channel;
747
748         } else {
749             iso_channel=get1394Service().allocateIsoChannelCMP(
750                 get1394Service().getLocalNodeId()| 0xffc0, -1,
751                 getConfigRom().getNodeId() | 0xffc0, n);
752         }
753
754         if (iso_channel<0) {
755             debugError("Could not allocate ISO channel for SP %d\n",i);
756             return false;
757         }
758
759         debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel);
760
761         p->setChannel(iso_channel);
762         return true;
763     }
764
765     debugError("SP index %d out of range!\n",i);
766     return false;
767 }
768
769 bool
770 AvDevice::stopStreamByIndex(int i) {
771     bool snoopMode=false;
772     if(!getOption("snoopMode", snoopMode)) {
773         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
774     }
775
776     if (i<(int)m_receiveProcessors.size()) {
777         int n=i;
778         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
779
780         // can't stop it if it's not running
781         if(p->getChannel() == -1) {
782             debugOutput(DEBUG_LEVEL_VERBOSE, "SP %d not running\n",i);
783             return true;
784         }
785
786         if(snoopMode) {
787
788         } else {
789             // deallocate ISO channel
790             if(!get1394Service().freeIsoChannel(p->getChannel())) {
791                 debugError("Could not deallocate iso channel for SP %d\n",i);
792                 return false;
793             }
794         }
795         p->setChannel(-1);
796
797         return true;
798
799     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
800         int n=i-m_receiveProcessors.size();
801         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
802
803         // can't stop it if it's not running
804         if(p->getChannel() == -1) {
805             debugOutput(DEBUG_LEVEL_VERBOSE, "SP %d not running\n",i);
806             return true;
807         }
808
809         if(snoopMode) {
810
811         } else {
812             // deallocate ISO channel
813             if(!get1394Service().freeIsoChannel(p->getChannel())) {
814                 debugError("Could not deallocate iso channel for SP %d\n",i);
815                 return false;
816             }
817         }
818         p->setChannel(-1);
819
820         return true;
821     }
822
823     debugError("SP index %d out of range!\n",i);
824     return false;
825 }
826
827 bool
828 AvDevice::serialize( std::string basePath, Util::IOSerialize& ser ) const
829 {
830     bool result;
831     result  = AVC::Unit::serialize( basePath, ser );
832     result &= serializeOptions( basePath + "Options", ser );
833     return result;
834 }
835
836 bool
837 AvDevice::deserialize( std::string basePath, Util::IODeserialize& deser )
838 {
839     bool result;
840     result = AVC::Unit::deserialize( basePath, deser );
841     return result;
842 }
843
844 }
Note: See TracBrowser for help on using the browser.