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

Revision 2691, 30.4 kB (checked in by jwoithe, 4 years ago)

Initial attempt to address deprecation of auto_ptr.

C++11 deprecates auto_ptr, and gcc6 (and later versions) print compile time
warnings to this effect whenever it is encountered in the source. The
replacement type is either shared_ptr or unique_ptr depending on the usage.
For almost all usages within FFADO it seems unique_ptr could be the
appropriate choice, but the symantics are a little different to auto_ptr.
Shared_ptr on the other hand can be a drop-in replacement, although it comes
with considerable overheads which unique_ptr avoids. In the context of the
current usage, the extra overhead incurred is not critical.

The code-base cannot at this time change unconditionally to shared_ptr and
unique_ptr because these are not available in gcc4 unless "--std=c++11" is
given. When gcc4 is used certain older versions of dependent libraries must
be used and these in turn will cause compile failures in their header files
if "--std=c++11" is used (libxml++ being an example). At present there are
sufficient users of FFADO still on gcc4 to justify maintaining compatibility
with that gcc version.

The approach adopted at present is to define ffado_smartptr to be either
auto_ptr (if c++11 is not in use) or shared_ptr if it is. All auto_ptr
instances are then changed to ffado_smartptr. This should allow FFADO to be
compiled without errors or warnings on systems using gcc4 and above. Gcc6
defaults to the c++14 standard, so ffado_smartptr will be shared_ptr in that
case; thus the warnings will be avoided.

In time, once gcc4 drops out of common use, the ffado_smartptr instances can
be progressively migrated to unique_ptr or shared_ptr as is appropriate. It
has been pointed out in the ffado-devel mailing list by Jano Svitok (2 May
2017, subject "smart pointers Was: [FFADO-devel] Liquid Saffire 56") that
bebob_dl_mgr.cpp could use unique_ptr. shared_ptr should be ok in other
auto_ptr sites, but futher analysis may show that at least some of them can
use unique_ptr.

The addressing of the auto_ptr issue was prompted by Xavier Forestier's
patch set submitted to ffado-devel in November 2016.

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 #include <libieee1394/IEC61883.h>
47
48 #include "stanton/scs.h"
49
50 namespace GenericAVC {
51
52 IMPL_DEBUG_MODULE( Device, Device, DEBUG_LEVEL_NORMAL );
53
54 Device::Device( DeviceManager& d, ffado_smartptr<ConfigRom>( configRom ))
55     : FFADODevice( d, configRom )
56 {
57     debugOutput( DEBUG_LEVEL_VERBOSE, "Created GenericAVC::Device (NodeID %d)\n",
58                  getConfigRom().getNodeId() );
59     addOption(Util::OptionContainer::Option("snoopMode",false));
60 }
61
62 Device::~Device()
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 Device::probe( Util::Configuration& c, ConfigRom& configRom, bool generic )
80 {
81     if(generic) {
82         // check if we have a music subunit
83         AVC::SubUnitInfoCmd subUnitInfoCmd( configRom.get1394Service() );
84         subUnitInfoCmd.setCommandType( AVC::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             AVC::subunit_type_t subunit_type
94                 = subUnitInfoCmd.m_table[i].m_subunit_type;
95             if (subunit_type == AVC::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         Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
105         return c.isValid(vme) && vme.driver == Util::Configuration::eD_GenericAVC;
106         return false;
107     }
108 }
109
110 FFADODevice *
111 Device::createDevice(DeviceManager& d, ffado_smartptr<ConfigRom>( configRom ))
112 {
113     unsigned int vendorId = configRom->getNodeVendorId();
114     unsigned int modelId = configRom->getModelId();
115
116     switch (vendorId) {
117         case FW_VENDORID_STANTON:
118             if (modelId == 0x00001000 ) {
119                 return new Stanton::ScsDevice(d, configRom);
120             }
121         default:
122             return new GenericAVC::Device(d, configRom);
123     }
124     return NULL;
125 }
126
127 bool
128 Device::discover()
129 {
130     Util::MutexLockHelper lock(m_DeviceMutex);
131
132     unsigned int vendorId = getConfigRom().getNodeVendorId();
133     unsigned int modelId = getConfigRom().getModelId();
134
135     Util::Configuration &c = getDeviceManager().getConfiguration();
136     Util::Configuration::VendorModelEntry vme = c.findDeviceVME( vendorId, modelId );
137
138     if (c.isValid(vme) && vme.driver == Util::Configuration::eD_GenericAVC) {
139         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
140                      vme.vendor_name.c_str(),
141                      vme.model_name.c_str());
142     } else {
143         debugWarning("Using generic AV/C support for unsupported device '%s %s'\n",
144                      getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
145     }
146     return discoverGeneric();
147 }
148
149 bool
150 Device::discoverGeneric()
151 {
152     if ( !Unit::discover() ) {
153         debugError( "Could not discover unit\n" );
154         return false;
155     }
156
157     if((getAudioSubunit( 0 ) == NULL)) {
158         debugError( "Unit doesn't have an Audio subunit.\n");
159         return false;
160     }
161     if((getMusicSubunit( 0 ) == NULL)) {
162         debugError( "Unit doesn't have a Music subunit.\n");
163         return false;
164     }
165     return true;
166 }
167
168 void
169 Device::setVerboseLevel(int l)
170 {
171     Util::MutexLockHelper lock(m_DeviceMutex);
172     setDebugLevel(l);
173     m_pPlugManager->setVerboseLevel(l);
174     FFADODevice::setVerboseLevel(l);
175     AVC::Unit::setVerboseLevel(l);
176     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
177 }
178
179 enum FFADODevice::eStreamingState
180 Device::getStreamingState()
181 {
182     // check the IEC plug control registers to see if the device is streaming
183     // a bit of a hack, but will do until we come up with something better
184     struct iec61883_oPCR oPCR0;
185     struct iec61883_iPCR iPCR0;
186    
187     quadlet_t *oPCR0q = (quadlet_t *)&oPCR0;
188     quadlet_t *iPCR0q = (quadlet_t *)&iPCR0;
189    
190     if(!get1394Service().read(getNodeId() | 0xFFC0, CSR_REGISTER_BASE + CSR_O_PCR_0, 1, oPCR0q)) {
191         debugWarning("Could not read oPCR0 register\n");
192     }
193     if(!get1394Service().read(getNodeId() | 0xFFC0, CSR_REGISTER_BASE + CSR_I_PCR_0, 1, iPCR0q)) {
194         debugWarning("Could not read iPCR0 register\n");
195     }
196
197     *oPCR0q = CondSwapFromBus32(*oPCR0q);
198     *iPCR0q = CondSwapFromBus32(*iPCR0q);
199
200     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "iPCR0: %08X, oPCR0: %08X\n", *iPCR0q, *oPCR0q);
201
202     if(iPCR0.n_p2p_connections > 0 && oPCR0.n_p2p_connections > 0) {
203         return eSS_Both;
204     } else if (iPCR0.n_p2p_connections > 0) {
205         return eSS_Receiving;
206     } else if (oPCR0.n_p2p_connections > 0) {
207         return eSS_Sending;
208     } else {
209         return eSS_Idle;
210     }
211 }
212
213 int
214 Device::getSamplingFrequency( ) {
215     AVC::Plug* inputPlug = getPlugById( m_pcrPlugs, AVC::Plug::eAPD_Input, 0 );
216     if ( !inputPlug ) {
217         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
218         return false;
219     }
220     AVC::Plug* outputPlug = getPlugById( m_pcrPlugs, AVC::Plug::eAPD_Output, 0 );
221     if ( !outputPlug ) {
222         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
223         return false;
224     }
225
226     int samplerate_playback=inputPlug->getSampleRate();
227     int samplerate_capture=outputPlug->getSampleRate();
228
229     if (samplerate_playback != samplerate_capture) {
230         debugWarning("Samplerates for capture and playback differ!\n");
231     }
232     return samplerate_capture;
233 }
234
235 bool
236 Device::setSamplingFrequency( int s )
237 {
238     Util::MutexLockHelper lock(m_DeviceMutex);
239     bool snoopMode=false;
240     if(!getOption("snoopMode", snoopMode)) {
241         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
242     }
243
244     if(snoopMode) {
245         int current_sr=getSamplingFrequency();
246         if (current_sr != s ) {
247             debugError("In snoop mode it is impossible to set the sample rate.\n");
248             debugError("Please start the client with the correct setting.\n");
249             return false;
250         }
251         return true;
252     } else {
253         AVC::Plug* plug = getPlugById( m_pcrPlugs, AVC::Plug::eAPD_Input, 0 );
254         if ( !plug ) {
255             debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
256             return false;
257         }
258
259         if ( !plug->setSampleRate( s ) )
260         {
261             debugError( "setSampleRate: Setting sample rate failed\n" );
262             return false;
263         }
264
265         plug = getPlugById( m_pcrPlugs, AVC::Plug::eAPD_Output,  0 );
266         if ( !plug ) {
267             debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
268             return false;
269         }
270
271         if ( !plug->setSampleRate( s ) )
272         {
273             debugError( "setSampleRate: Setting sample rate failed\n" );
274             return false;
275         }
276
277         debugOutput( DEBUG_LEVEL_VERBOSE,
278                      "setSampleRate: Set sample rate to %d\n",
279                      s );
280         return true;
281     }
282     // not executable
283     return false;
284
285 }
286
287 bool
288 Device::supportsSamplingFrequency( int s )
289 {
290     Util::MutexLockHelper lock(m_DeviceMutex);
291
292     AVC::Plug* plug = getPlugById( m_pcrPlugs, AVC::Plug::eAPD_Input, 0 );
293     if ( !plug ) {
294         debugError( "Could not retrieve iso input plug 0\n" );
295         return false;
296     }
297
298     if ( !plug->supportsSampleRate( s ) )
299     {
300         debugError( "sample rate not supported by input plug\n" );
301         return false;
302     }
303
304     plug = getPlugById( m_pcrPlugs, AVC::Plug::eAPD_Output,  0 );
305     if ( !plug ) {
306         debugError( "Could not retrieve iso output plug 0\n" );
307         return false;
308     }
309
310     if ( !plug->supportsSampleRate( s ) )
311     {
312         debugError( "sample rate not supported by output plug\n" );
313         return false;
314     }
315     return true;
316 }
317
318 #define GENERICAVC_CHECK_AND_ADD_SR(v, x) \
319     { if(supportsSamplingFrequency(x)) \
320       v.push_back(x); }
321
322 std::vector<int>
323 Device::getSupportedSamplingFrequencies()
324 {
325     if (m_supported_frequencies_cache.size() == 0) {
326         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 22050);
327         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 24000);
328         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 32000);
329         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 44100);
330         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 48000);
331         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 88200);
332         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 96000);
333         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 176400);
334         GENERICAVC_CHECK_AND_ADD_SR(m_supported_frequencies_cache, 192000);
335     }
336     return m_supported_frequencies_cache;
337 }
338
339 FFADODevice::ClockSourceVector
340 Device::getSupportedClockSources() {
341     FFADODevice::ClockSourceVector r;
342
343     Util::MutexLockHelper lock(m_DeviceMutex);
344
345     AVC::PlugVector syncMSUInputPlugs = m_pPlugManager->getPlugsByType(
346         AVC::eST_Music,
347         0,
348         0xff,
349         0xff,
350         AVC::Plug::eAPA_SubunitPlug,
351         AVC::Plug::eAPD_Input,
352         AVC::Plug::eAPT_Sync );
353     if ( !syncMSUInputPlugs.size() ) {
354         // there exist devices which do not have a sync plug
355         // or their av/c model is broken.
356         return r;
357     }
358
359     for ( SyncInfoVector::const_iterator it
360               = getSyncInfos().begin();
361           it != getSyncInfos().end();
362           ++it )
363     {
364         const SyncInfo si=*it;
365
366         ClockSource s=syncInfoToClockSource(*it);
367         r.push_back(s);
368     }
369     return r;
370 }
371
372 bool
373 Device::setActiveClockSource(ClockSource s) {
374     AVC::Plug *src = m_pPlugManager->getPlug( s.id );
375     if (!src) {
376         debugError("Could not find plug with id %d\n", s.id);
377         return false;
378     }
379
380     Util::MutexLockHelper lock(m_DeviceMutex);
381     for ( SyncInfoVector::const_iterator it
382               = getSyncInfos().begin();
383           it != getSyncInfos().end();
384           ++it )
385     {
386         const SyncInfo si=*it;
387
388         if (si.m_source==src) {
389             return setActiveSync(si);
390         }
391     }
392     return false;
393 }
394
395 FFADODevice::ClockSource
396 Device::getActiveClockSource() {
397     const SyncInfo* si=getActiveSyncInfo();
398     if ( !si ) {
399         debugError( "Could not retrieve active sync information\n" );
400         ClockSource s;
401         s.type=eCT_Invalid;
402         return s;
403     }
404     debugOutput(DEBUG_LEVEL_VERBOSE, "Active Sync mode:  %s\n", si->m_description.c_str() );
405
406     return syncInfoToClockSource(*si);
407 }
408
409 FFADODevice::ClockSource
410 Device::syncInfoToClockSource(const SyncInfo& si) {
411     ClockSource s;
412
413     // the description is easy
414     // it can be that we overwrite it later
415     s.description=si.m_description;
416
417     // FIXME: always valid at the moment
418     s.valid=true;
419
420     assert(si.m_source);
421     s.id=si.m_source->getGlobalId();
422
423     // now figure out what type this is
424     switch(si.m_source->getPlugType()) {
425         case AVC::Plug::eAPT_IsoStream:
426             s.type=eCT_SytMatch;
427             break;
428         case AVC::Plug::eAPT_Sync:
429             if(si.m_source->getPlugAddressType() == AVC::Plug::eAPA_PCR) {
430                 s.type=eCT_SytStream; // this is logical
431             } else if(si.m_source->getPlugAddressType() == AVC::Plug::eAPA_SubunitPlug) {
432                 s.type=eCT_Internal; // this assumes some stuff
433             } else if(si.m_source->getPlugAddressType() == AVC::Plug::eAPA_ExternalPlug) {
434                 std::string plugname=si.m_source->getName();
435                 s.description=plugname;
436                 // this is basically due to Focusrites interpretation
437                 if(plugname.find( "SPDIF", 0 ) != string::npos) {
438                     s.type=eCT_SPDIF; // this assumes the name will tell us
439                 } else {
440                     s.type=eCT_WordClock; // this assumes a whole lot more
441                 }
442             } else {
443                 s.type=eCT_Invalid;
444             }
445             break;
446         case AVC::Plug::eAPT_Digital:
447             if(si.m_source->getPlugAddressType() == AVC::Plug::eAPA_ExternalPlug) {
448                 std::string plugname=si.m_source->getName();
449                 s.description=plugname;
450                 // this is basically due to Focusrites interpretation
451                 if(plugname.find( "ADAT", 0 ) != string::npos) {
452                     s.type=eCT_ADAT; // this assumes the name will tell us
453                 } else if(plugname.find( "SPDIF", 0 ) != string::npos) {
454                     s.type=eCT_SPDIF; // this assumes the name will tell us
455                 } else {
456                     s.type=eCT_WordClock; // this assumes a whole lot more
457                 }
458             } else {
459                 s.type=eCT_Invalid;
460             }
461             break;
462         default:
463             s.type=eCT_Invalid; break;
464     }
465
466     // is it active?
467     const SyncInfo* active=getActiveSyncInfo();
468     if (active) {
469         if ((active->m_source == si.m_source)
470            && (active->m_destination == si.m_destination))
471            s.active=true;
472         else s.active=false;
473     } else s.active=false;
474
475     return s;
476 }
477
478 bool
479 Device::lock() {
480     bool snoopMode=false;
481     Util::MutexLockHelper lock(m_DeviceMutex);
482     if(!getOption("snoopMode", snoopMode)) {
483         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
484     }
485
486     if (snoopMode) {
487         // don't lock
488     } else {
489 //         return Unit::reserve(4);
490     }
491
492     return true;
493 }
494
495 bool
496 Device::unlock() {
497     bool snoopMode=false;
498     Util::MutexLockHelper lock(m_DeviceMutex);
499     if(!getOption("snoopMode", snoopMode)) {
500         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
501     }
502
503     if (snoopMode) {
504         // don't unlock
505     } else {
506 //         return Unit::reserve(0);
507     }
508     return true;
509 }
510
511 void
512 Device::showDevice()
513 {
514     FFADODevice::showDevice();
515
516     AVC::Unit::show();
517     flushDebugOutput();
518 }
519
520 bool
521 Device::prepare() {
522     bool snoopMode = false;
523     Util::MutexLockHelper lock(m_DeviceMutex);
524     if(!getOption("snoopMode", snoopMode)) {
525         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
526     }
527
528     ///////////
529     // get plugs
530
531     AVC::Plug* inputPlug = getPlugById( m_pcrPlugs, AVC::Plug::eAPD_Input, 0 );
532     if ( !inputPlug ) {
533         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
534         return false;
535     }
536     AVC::Plug* outputPlug = getPlugById( m_pcrPlugs, AVC::Plug::eAPD_Output, 0 );
537     if ( !outputPlug ) {
538         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
539         return false;
540     }
541
542     // get the device specific and/or global SP configuration
543     Util::Configuration &config = getDeviceManager().getConfiguration();
544     // base value is the config.h value
545     float recv_sp_dll_bw = STREAMPROCESSOR_DLL_BW_HZ;
546     float xmit_sp_dll_bw = STREAMPROCESSOR_DLL_BW_HZ;
547
548     int xmit_max_cycles_early_transmit = AMDTP_MAX_CYCLES_TO_TRANSMIT_EARLY;
549     int xmit_transfer_delay = AMDTP_TRANSMIT_TRANSFER_DELAY;
550     int xmit_min_cycles_before_presentation = AMDTP_MIN_CYCLES_BEFORE_PRESENTATION;
551
552     // we can override that globally
553     config.getValueForSetting("streaming.common.recv_sp_dll_bw", recv_sp_dll_bw);
554     config.getValueForSetting("streaming.common.xmit_sp_dll_bw", xmit_sp_dll_bw);
555     config.getValueForSetting("streaming.amdtp.xmit_max_cycles_early_transmit", xmit_max_cycles_early_transmit);
556     config.getValueForSetting("streaming.amdtp.xmit_transfer_delay", xmit_transfer_delay);
557     config.getValueForSetting("streaming.amdtp.xmit_min_cycles_before_presentation", xmit_min_cycles_before_presentation);
558
559     // or override in the device section
560     uint32_t vendorid = getConfigRom().getNodeVendorId();
561     uint32_t modelid = getConfigRom().getModelId();
562     config.getValueForDeviceSetting(vendorid, modelid, "recv_sp_dll_bw", recv_sp_dll_bw);
563     config.getValueForDeviceSetting(vendorid, modelid, "xmit_sp_dll_bw", xmit_sp_dll_bw);
564     config.getValueForDeviceSetting(vendorid, modelid, "xmit_max_cycles_early_transmit", xmit_max_cycles_early_transmit);
565     config.getValueForDeviceSetting(vendorid, modelid, "xmit_transfer_delay", xmit_transfer_delay);
566     config.getValueForDeviceSetting(vendorid, modelid, "xmit_min_cycles_before_presentation", xmit_min_cycles_before_presentation);
567
568     // initialize the SP's
569     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing receive processor...\n");
570     // create & add streamprocessors
571     Streaming::StreamProcessor *p;
572
573     if ( outputPlug->getNrOfChannels() == 0 ) {
574         debugError("Receive plug has no channels\n");
575         return false;
576     }
577     p = new Streaming::AmdtpReceiveStreamProcessor(*this,
578                              outputPlug->getNrOfChannels());
579
580     if(!p->init()) {
581         debugFatal("Could not initialize receive processor!\n");
582         delete p;
583         return false;
584     }
585
586     if (!addPlugToProcessor(*outputPlug, p,
587         Streaming::Port::E_Capture)) {
588         debugFatal("Could not add plug to processor!\n");
589         delete p;
590         return false;
591     }
592
593     if(!p->setDllBandwidth(recv_sp_dll_bw)) {
594         debugFatal("Could not set DLL bandwidth\n");
595         delete p;
596         return false;
597     }
598
599     m_receiveProcessors.push_back(p);
600
601     // do the transmit processor
602     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing transmit processor%s...\n",
603             (snoopMode?" in snoop mode":""));
604     if (snoopMode) {
605         // we are snooping, so this is receive too.
606         p=new Streaming::AmdtpReceiveStreamProcessor(*this,
607                                   inputPlug->getNrOfChannels());
608     } else {
609         Streaming::AmdtpTransmitStreamProcessor *t;
610         t = new Streaming::AmdtpTransmitStreamProcessor(*this,
611                                 inputPlug->getNrOfChannels());
612         #if AMDTP_ALLOW_PAYLOAD_IN_NODATA_XMIT
613             // FIXME: it seems that some BeBoB devices can't handle NO-DATA without payload
614             // FIXME: make this a config value too
615             t->sendPayloadForNoDataPackets(true);
616         #endif
617
618         // transmit control parameters
619         t->setMaxCyclesToTransmitEarly(xmit_max_cycles_early_transmit);
620         t->setTransferDelay(xmit_transfer_delay);
621         t->setMinCyclesBeforePresentation(xmit_min_cycles_before_presentation);
622
623         p=t;
624     }
625
626     if(!p->init()) {
627         debugFatal("Could not initialize transmit processor %s!\n",
628             (snoopMode?" in snoop mode":""));
629         delete p;
630         return false;
631     }
632
633     if (snoopMode) {
634         if (!addPlugToProcessor(*inputPlug, p,
635             Streaming::Port::E_Capture)) {
636             debugFatal("Could not add plug to processor!\n");
637             return false;
638         }
639         if(!p->setDllBandwidth(recv_sp_dll_bw)) {
640             debugFatal("Could not set DLL bandwidth\n");
641             delete p;
642             return false;
643         }
644     } else {
645         if (!addPlugToProcessor(*inputPlug, p,
646             Streaming::Port::E_Playback)) {
647             debugFatal("Could not add plug to processor!\n");
648             return false;
649         }
650         if(!p->setDllBandwidth(xmit_sp_dll_bw)) {
651             debugFatal("Could not set DLL bandwidth\n");
652             delete p;
653             return false;
654         }
655     }
656
657     // we put this SP into the transmit SP vector,
658     // no matter if we are in snoop mode or not
659     // this allows us to find out what direction
660     // a certain stream should have.
661     m_transmitProcessors.push_back(p);
662
663     return true;
664 }
665
666 bool
667 Device::addPlugToProcessor(
668     AVC::Plug& plug,
669     Streaming::StreamProcessor *processor,
670     Streaming::AmdtpAudioPort::E_Direction direction) {
671
672     std::string id=std::string("dev?");
673     if(!getOption("id", id)) {
674         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
675     }
676
677     AVC::Plug::ClusterInfoVector& clusterInfos = plug.getClusterInfos();
678     for ( AVC::Plug::ClusterInfoVector::const_iterator it = clusterInfos.begin();
679           it != clusterInfos.end();
680           ++it )
681     {
682         const AVC::Plug::ClusterInfo* clusterInfo = &( *it );
683
684         AVC::Plug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos;
685         for ( AVC::Plug::ChannelInfoVector::const_iterator it = channelInfos.begin();
686               it != channelInfos.end();
687               ++it )
688         {
689             const AVC::Plug::ChannelInfo* channelInfo = &( *it );
690             std::ostringstream portname;
691
692             portname << id << "_" << channelInfo->m_name;
693
694             Streaming::Port *p=NULL;
695             switch(clusterInfo->m_portType) {
696             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_Speaker:
697             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_Headphone:
698             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_Microphone:
699             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_Line:
700             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_Analog:
701                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding audio channel %s (pos=0x%02X, loc=0x%02X)\n",
702                     channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location);
703                 p=new Streaming::AmdtpAudioPort(
704                         *processor,
705                         portname.str(),
706                         direction,
707                         channelInfo->m_streamPosition,
708                         channelInfo->m_location,
709                         Streaming::AmdtpPortInfo::E_MBLA
710                 );
711                 break;
712
713             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_MIDI:
714                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding MIDI channel '%s' (pos=0x%02X, loc=0x%02X)\n",
715                     portname.str().c_str() /*channelInfo->m_name.c_str()*/,
716                     channelInfo->m_streamPosition, processor->getPortCount(Streaming::Port::E_Midi));
717                 p=new Streaming::AmdtpMidiPort(
718                         *processor,
719                         portname.str(),
720                         direction,
721                         channelInfo->m_streamPosition,
722                         // Workaround for out-of-spec hardware
723                         // should be:
724                         // channelInfo->m_location,
725                         // but now we renumber the midi channels' location as they
726                         // are discovered
727                         processor->getPortCount(Streaming::Port::E_Midi),
728                         Streaming::AmdtpPortInfo::E_Midi
729                 );
730
731                 break;
732             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_SPDIF:
733             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_ADAT:
734             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_TDIF:
735             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_MADI:
736             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_Digital:
737                 debugOutput(DEBUG_LEVEL_VERBOSE, " Adding digital audio channel %s (pos=0x%02X, loc=0x%02X)\n",
738                     channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location);
739                 p=new Streaming::AmdtpAudioPort(
740                         *processor,
741                         portname.str(),
742                         direction,
743                         channelInfo->m_streamPosition,
744                         channelInfo->m_location,
745                         Streaming::AmdtpPortInfo::E_MBLA
746                 );
747                 break;
748
749             case AVC::ExtendedPlugInfoClusterInfoSpecificData::ePT_NoType:
750             default:
751             // unsupported
752                 break;
753             }
754
755             if (!p) {
756                 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", channelInfo->m_name.c_str());
757             }
758          }
759     }
760     return true;
761 }
762
763 int
764 Device::getStreamCount() {
765     int retval;
766     Util::MutexLockHelper lock(m_DeviceMutex);
767     retval = m_receiveProcessors.size() + m_transmitProcessors.size();
768     return retval;
769 }
770
771 Streaming::StreamProcessor *
772 Device::getStreamProcessorByIndex(int i) {
773
774     if (i<(int)m_receiveProcessors.size()) {
775         return m_receiveProcessors.at(i);
776     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
777         return m_transmitProcessors.at(i-m_receiveProcessors.size());
778     }
779
780     return NULL;
781 }
782
783 bool
784 Device::startStreamByIndex(int i) {
785     int iso_channel=-1;
786     bool snoopMode=false;
787     if(!getOption("snoopMode", snoopMode)) {
788         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
789     }
790
791     if (i<(int)m_receiveProcessors.size()) {
792         int n=i;
793         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
794
795         if(snoopMode) { // a stream from the device to another host
796             // FIXME: put this into a decent framework!
797             // we should check the oPCR[n] on the device
798             struct iec61883_oPCR opcr;
799             if (iec61883_get_oPCRX(
800                     get1394Service().getHandle(),
801                     getConfigRom().getNodeId() | 0xffc0,
802                     (quadlet_t *)&opcr,
803                     n)) {
804
805                 debugWarning("Error getting the channel for SP %d\n",i);
806                 return false;
807             }
808
809             iso_channel=opcr.channel;
810         } else {
811             iso_channel=get1394Service().allocateIsoChannelCMP(
812                 getConfigRom().getNodeId() | 0xffc0, n,
813                 get1394Service().getLocalNodeId()| 0xffc0, -1);
814         }
815         if (iso_channel<0) {
816             debugError("Could not allocate ISO channel for SP %d\n",i);
817             return false;
818         }
819
820         debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel);
821
822         p->setChannel(iso_channel);
823         return true;
824
825     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
826         int n=i-m_receiveProcessors.size();
827         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
828
829         if(snoopMode) { // a stream from another host to the device
830             // FIXME: put this into a decent framework!
831             // we should check the iPCR[n] on the device
832             struct iec61883_iPCR ipcr;
833             if (iec61883_get_iPCRX(
834                     get1394Service().getHandle(),
835                     getConfigRom().getNodeId() | 0xffc0,
836                     (quadlet_t *)&ipcr,
837                     n)) {
838
839                 debugWarning("Error getting the channel for SP %d\n",i);
840                 return false;
841             }
842
843             iso_channel=ipcr.channel;
844
845         } else {
846             iso_channel=get1394Service().allocateIsoChannelCMP(
847                 get1394Service().getLocalNodeId()| 0xffc0, -1,
848                 getConfigRom().getNodeId() | 0xffc0, n);
849         }
850
851         if (iso_channel<0) {
852             debugError("Could not allocate ISO channel for SP %d\n",i);
853             return false;
854         }
855
856         debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel);
857
858         p->setChannel(iso_channel);
859         return true;
860     }
861
862     debugError("SP index %d out of range!\n",i);
863     return false;
864 }
865
866 bool
867 Device::stopStreamByIndex(int i) {
868     bool snoopMode=false;
869     if(!getOption("snoopMode", snoopMode)) {
870         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
871     }
872
873     if (i<(int)m_receiveProcessors.size()) {
874         int n=i;
875         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
876
877         // can't stop it if it's not running
878         if(p->getChannel() == -1) {
879             debugOutput(DEBUG_LEVEL_VERBOSE, "SP %d not running\n",i);
880             return true;
881         }
882
883         if(snoopMode) {
884
885         } else {
886             // deallocate ISO channel
887             if(!get1394Service().freeIsoChannel(p->getChannel())) {
888                 debugError("Could not deallocate iso channel for SP %d\n",i);
889                 return false;
890             }
891         }
892         p->setChannel(-1);
893
894         return true;
895
896     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
897         int n=i-m_receiveProcessors.size();
898         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
899
900         // can't stop it if it's not running
901         if(p->getChannel() == -1) {
902             debugOutput(DEBUG_LEVEL_VERBOSE, "SP %d not running\n",i);
903             return true;
904         }
905
906         if(snoopMode) {
907
908         } else {
909             // deallocate ISO channel
910             if(!get1394Service().freeIsoChannel(p->getChannel())) {
911                 debugError("Could not deallocate iso channel for SP %d\n",i);
912                 return false;
913             }
914         }
915         p->setChannel(-1);
916
917         return true;
918     }
919
920     debugError("SP index %d out of range!\n",i);
921     return false;
922 }
923
924 bool
925 Device::serialize( std::string basePath, Util::IOSerialize& ser ) const
926 {
927     bool result;
928     result  = AVC::Unit::serialize( basePath, ser );
929     result &= serializeOptions( basePath + "Options", ser );
930     return result;
931 }
932
933 bool
934 Device::deserialize( std::string basePath, Util::IODeserialize& deser )
935 {
936     bool result;
937     result = AVC::Unit::deserialize( basePath, deser );
938     return result;
939 }
940
941 }
Note: See TracBrowser for help on using the browser.