root/trunk/libffado/src/genericavc/avc_avdevice.cpp

Revision 748, 22.6 kB (checked in by ppalmers, 16 years ago)

try to reorganize things such that less information is duplicated

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