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

Revision 1229, 24.7 kB (checked in by ppalmers, 16 years ago)

implement discovery fallback (closes #121)

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