root/trunk/libffado/src/bebob/bebob_avdevice.cpp

Revision 740, 14.9 kB (checked in by ppalmers, 13 years ago)

fix propagation of debug/verbose level

Line 
1 /*
2  * Copyright (C) 2005-2007 by Daniel Wagner
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 #include "config.h"
25
26 #include "bebob/bebob_avdevice.h"
27 #include "bebob/bebob_avdevice_subunit.h"
28 #include "bebob/bebob_mixer.h"
29
30 #include "bebob/focusrite/focusrite_saffire.h"
31 #include "bebob/focusrite/focusrite_saffirepro.h"
32 #include "bebob/terratec/terratec_device.h"
33
34 #include "libieee1394/configrom.h"
35 #include "libieee1394/ieee1394service.h"
36
37 #include "genericavc/avc_vendormodel.h"
38
39 #include "libavc/general/avc_plug_info.h"
40 #include "libavc/general/avc_extended_plug_info.h"
41 #include "libavc/general/avc_subunit_info.h"
42 #include "libavc/streamformat/avc_extended_stream_format.h"
43 #include "libutil/cmd_serialize.h"
44 #include "libavc/avc_definitions.h"
45
46 #include "debugmodule/debugmodule.h"
47
48 #include <iostream>
49 #include <sstream>
50 #include <unistd.h>
51 #include <sys/stat.h>
52
53 using namespace AVC;
54
55 namespace BeBoB {
56
57 AvDevice::AvDevice(std::auto_ptr< ConfigRom >( configRom ) )
58     : GenericAVC::AvDevice( configRom )
59     , m_Mixer ( 0 )
60 {
61     debugOutput( DEBUG_LEVEL_VERBOSE, "Created BeBoB::AvDevice (NodeID %d)\n",
62                  getConfigRom().getNodeId() );
63
64     // DM1500 based devices seem to upset the linux1394 stack when commands are
65     // sent too fast.
66     if (AVC::AVCCommand::getSleepAfterAVCCommand() < 200) {
67         AVC::AVCCommand::setSleepAfterAVCCommand( 200 );
68     }
69
70 }
71
72 AvDevice::~AvDevice()
73 {
74     destroyMixer();
75 }
76
77 bool
78 AvDevice::probe( ConfigRom& configRom )
79 {
80     unsigned int vendorId = configRom.getNodeVendorId();
81     unsigned int modelId = configRom.getModelId();
82
83     GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_bebob.txt" );
84     if ( vendorModel.parse() ) {
85         return vendorModel.isPresent( vendorId, modelId );
86     }
87
88     return false;
89 }
90
91 FFADODevice *
92 AvDevice::createDevice(std::auto_ptr<ConfigRom>( configRom ))
93 {
94     unsigned int vendorId = configRom->getNodeVendorId();
95     unsigned int modelId = configRom->getModelId();
96
97     switch (vendorId) {
98         case FW_VENDORID_TERRATEC:
99             return new Terratec::PhaseSeriesDevice(configRom);
100         case FW_VENDORID_FOCUSRITE:
101             switch(modelId) {
102                 case 0x00000003:
103                 case 0x00000006:
104                     return new Focusrite::SaffireProDevice(configRom);
105                 case 0x00000000:
106                     return new Focusrite::SaffireDevice(configRom);
107                 default: // return a plain BeBoB device
108                     return new AvDevice(configRom);
109            }
110         default:
111             return new AvDevice(configRom);
112     }
113     return NULL;
114 }
115
116 bool
117 AvDevice::discover()
118 {
119     unsigned int vendorId = getConfigRom().getNodeVendorId();
120     unsigned int modelId = getConfigRom().getModelId();
121
122     GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_bebob.txt" );
123     if ( vendorModel.parse() ) {
124         m_model = vendorModel.find( vendorId, modelId );
125     }
126
127     if (GenericAVC::VendorModel::isValid(m_model)) {
128         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
129                      m_model.vendor_name.c_str(),
130                      m_model.model_name.c_str());
131     } else return false;
132
133     if ( !Unit::discover() ) {
134         debugError( "Could not discover unit\n" );
135         return false;
136     }
137
138     if((getAudioSubunit( 0 ) == NULL)) {
139         debugError( "Unit doesn't have an Audio subunit.\n");
140         return false;
141     }
142     if((getMusicSubunit( 0 ) == NULL)) {
143         debugError( "Unit doesn't have a Music subunit.\n");
144         return false;
145     }
146
147     if(!buildMixer()) {
148         debugWarning("Could not build mixer\n");
149     }
150     return true;
151 }
152
153 bool
154 AvDevice::buildMixer()
155 {
156     debugOutput(DEBUG_LEVEL_VERBOSE, "Building a generic BeBoB mixer...\n");
157     // create a Mixer
158     // this removes the mixer if it already exists
159     // note: a mixer self-registers to it's parent
160     delete m_Mixer;
161
162     // create the mixer & register it
163     if(getAudioSubunit(0) == NULL) {
164         debugWarning("Could not find audio subunit, mixer not available.\n");
165         m_Mixer = NULL;
166     } else {
167         m_Mixer = new Mixer(*this);
168     }
169     if (m_Mixer) m_Mixer->setVerboseLevel(getDebugLevel());
170     return m_Mixer != NULL;
171 }
172
173 bool
174 AvDevice::destroyMixer()
175 {
176     delete m_Mixer;
177     return true;
178 }
179
180 void
181 AvDevice::showDevice()
182 {
183     debugOutput(DEBUG_LEVEL_NORMAL, "Device is a BeBoB device\n");
184     GenericAVC::AvDevice::showDevice();
185     flushDebugOutput();
186 }
187
188 void
189 AvDevice::setVerboseLevel(int l)
190 {
191     if (m_Mixer) m_Mixer->setVerboseLevel( l );
192     GenericAVC::AvDevice::setVerboseLevel( l );
193     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
194 }
195
196 AVC::Subunit*
197 AvDevice::createSubunit(AVC::Unit& unit,
198                         AVC::ESubunitType type,
199                         AVC::subunit_t id )
200 {
201     AVC::Subunit* s=NULL;
202     switch (type) {
203         case eST_Audio:
204             s=new BeBoB::SubunitAudio(unit, id );
205             break;
206         case eST_Music:
207             s=new BeBoB::SubunitMusic(unit, id );
208             break;
209         default:
210             s=NULL;
211             break;
212     }
213     if(s) s->setVerboseLevel(getDebugLevel());
214     return s;
215 }
216
217
218 AVC::Plug *
219 AvDevice::createPlug( AVC::Unit* unit,
220                       AVC::Subunit* subunit,
221                       AVC::function_block_type_t functionBlockType,
222                       AVC::function_block_type_t functionBlockId,
223                       AVC::Plug::EPlugAddressType plugAddressType,
224                       AVC::Plug::EPlugDirection plugDirection,
225                       AVC::plug_id_t plugId )
226 {
227
228     Plug *p= new BeBoB::Plug( unit,
229                               subunit,
230                               functionBlockType,
231                               functionBlockId,
232                               plugAddressType,
233                               plugDirection,
234                               plugId );
235     if (p) p->setVerboseLevel(getDebugLevel());
236     return p;
237 }
238
239 bool
240 AvDevice::propagatePlugInfo() {
241     // we don't have to propagate since we discover things
242     // another way
243     debugOutput(DEBUG_LEVEL_VERBOSE, "Skip plug info propagation\n");
244     return true;
245 }
246
247
248 int
249 AvDevice::getConfigurationIdSampleRate()
250 {
251     ExtendedStreamFormatCmd extStreamFormatCmd( get1394Service() );
252     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, 0 );
253     extStreamFormatCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
254                                                     PlugAddress::ePAM_Unit,
255                                                     unitPlugAddress ) );
256
257     extStreamFormatCmd.setNodeId( getNodeId() );
258     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
259     extStreamFormatCmd.setVerbose( getDebugLevel() );
260
261     if ( !extStreamFormatCmd.fire() ) {
262         debugError( "Stream format command failed\n" );
263         return false;
264     }
265
266     FormatInformation* formatInfo =
267         extStreamFormatCmd.getFormatInformation();
268     FormatInformationStreamsCompound* compoundStream
269         = dynamic_cast< FormatInformationStreamsCompound* > (
270             formatInfo->m_streams );
271     if ( compoundStream ) {
272         debugOutput(DEBUG_LEVEL_VERBOSE, "Sample rate 0x%02x\n",
273                     compoundStream->m_samplingFrequency );
274         return compoundStream->m_samplingFrequency;
275     }
276
277     debugError( "Could not retrieve sample rate\n" );
278     return 0;
279 }
280
281 int
282 AvDevice::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection )
283 {
284     ExtendedPlugInfoCmd extPlugInfoCmd( get1394Service() );
285     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
286                                      getNodeId() );
287     extPlugInfoCmd.setPlugAddress( PlugAddress( ePlugDirection,
288                                                 PlugAddress::ePAM_Unit,
289                                                 unitPlugAddress ) );
290     extPlugInfoCmd.setNodeId( getNodeId() );
291     extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
292     extPlugInfoCmd.setVerbose( getDebugLevel() );
293     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
294         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
295     extendedPlugInfoInfoType.initialize();
296     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
297
298     if ( !extPlugInfoCmd.fire() ) {
299         debugError( "Number of channels command failed\n" );
300         return false;
301     }
302
303     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
304     if ( infoType
305          && infoType->m_plugNrOfChns )
306     {
307         debugOutput(DEBUG_LEVEL_VERBOSE, "Number of channels 0x%02x\n",
308                     infoType->m_plugNrOfChns->m_nrOfChannels );
309         return infoType->m_plugNrOfChns->m_nrOfChannels;
310     }
311
312     debugError( "Could not retrieve number of channels\n" );
313     return 0;
314 }
315
316 int
317 AvDevice::getConfigurationIdSyncMode()
318 {
319     SignalSourceCmd signalSourceCmd( get1394Service() );
320     SignalUnitAddress signalUnitAddr;
321     signalUnitAddr.m_plugId = 0x01;
322     signalSourceCmd.setSignalDestination( signalUnitAddr );
323     signalSourceCmd.setNodeId( getNodeId() );
324     signalSourceCmd.setSubunitType( eST_Unit  );
325     signalSourceCmd.setSubunitId( 0xff );
326     signalSourceCmd.setVerbose( getDebugLevel() );
327
328     signalSourceCmd.setCommandType( AVCCommand::eCT_Status );
329
330     if ( !signalSourceCmd.fire() ) {
331         debugError( "Signal source command failed\n" );
332         return false;
333     }
334
335     SignalAddress* pSyncPlugSignalAddress = signalSourceCmd.getSignalSource();
336     SignalSubunitAddress* pSyncPlugSubunitAddress
337         = dynamic_cast<SignalSubunitAddress*>( pSyncPlugSignalAddress );
338     if ( pSyncPlugSubunitAddress ) {
339         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
340                     ( pSyncPlugSubunitAddress->m_subunitType << 3
341                       | pSyncPlugSubunitAddress->m_subunitId ) << 8
342                     | pSyncPlugSubunitAddress->m_plugId );
343
344         return ( pSyncPlugSubunitAddress->m_subunitType << 3
345                  | pSyncPlugSubunitAddress->m_subunitId ) << 8
346             | pSyncPlugSubunitAddress->m_plugId;
347     }
348
349     SignalUnitAddress* pSyncPlugUnitAddress
350       = dynamic_cast<SignalUnitAddress*>( pSyncPlugSignalAddress );
351     if ( pSyncPlugUnitAddress ) {
352         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
353                       0xff << 8 | pSyncPlugSubunitAddress->m_plugId );
354
355         return ( 0xff << 8 | pSyncPlugSubunitAddress->m_plugId );
356     }
357
358     debugError( "Could not retrieve sync mode\n" );
359     return 0;
360 }
361
362 int
363 AvDevice::getConfigurationId()
364 {
365     // create a unique configuration id.
366     int id = 0;
367     id = getConfigurationIdSampleRate();
368     id |= ( getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input )
369             + getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output ) ) << 8;
370     id |= getConfigurationIdSyncMode() << 16;
371
372     return id;
373 }
374
375 bool
376 AvDevice::serialize( Glib::ustring basePath,
377                      Util::IOSerialize& ser ) const
378 {
379     bool result;
380     result  = GenericAVC::AvDevice::serialize( basePath, ser );
381     return result;
382 }
383
384 bool
385 AvDevice::deserialize( Glib::ustring basePath,
386                        Util::IODeserialize& deser )
387 {
388     bool result;
389     result  = GenericAVC::AvDevice::deserialize( basePath, deser );
390     return result;
391 }
392
393 Glib::ustring
394 AvDevice::getCachePath()
395 {
396     Glib::ustring cachePath;
397     char* pCachePath;
398
399     string path = CACHEDIR;
400     if ( path.size() && path[0] == '~' ) {
401         path.erase( 0, 1 ); // remove ~
402         path.insert( 0, getenv( "HOME" ) ); // prepend the home path
403     }
404
405     if ( asprintf( &pCachePath, "%s/cache/",  path.c_str() ) < 0 ) {
406         debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
407         cachePath == "/var/cache/libffado/";
408     } else {
409         cachePath = pCachePath;
410         free( pCachePath );
411     }
412     return cachePath;
413 }
414
415 bool
416 AvDevice::loadFromCache()
417 {
418     Glib::ustring sDevicePath = getCachePath() + getConfigRom().getGuidString();
419
420     char* configId;
421     asprintf(&configId, "%08x", getConfigurationId() );
422     if ( !configId ) {
423         debugError( "could not create id string\n" );
424         return false;
425     }
426
427     Glib::ustring sFileName = sDevicePath + "/" + configId + ".xml";
428     free( configId );
429     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
430
431     struct stat buf;
432     if ( stat( sFileName.c_str(), &buf ) != 0 ) {
433         debugOutput( DEBUG_LEVEL_NORMAL,  "\"%s\" does not exist\n",  sFileName.c_str() );
434         return false;
435     } else {
436         if ( !S_ISREG( buf.st_mode ) ) {
437             debugOutput( DEBUG_LEVEL_NORMAL,  "\"%s\" is not a regular file\n",  sFileName.c_str() );
438             return false;
439         }
440     }
441
442     Util::XMLDeserialize deser( sFileName, getDebugLevel() );
443
444     bool result = deserialize( "", deser );
445     if ( result ) {
446         debugOutput( DEBUG_LEVEL_NORMAL, "could create valid bebob driver from %s\n",
447                      sFileName.c_str() );
448     }
449
450     return result;
451 }
452
453 bool
454 AvDevice::saveCache()
455 {
456     // the path looks like this:
457     // PATH_TO_CACHE + GUID + CONFIGURATION_ID
458     string tmp_path = getCachePath() + getConfigRom().getGuidString();
459
460     // the following piece should do something like
461     // 'mkdir -p some/path/with/some/dirs/which/do/not/exist'
462     vector<string> tokens;
463     tokenize( tmp_path, tokens, "/" );
464     string path;
465     for ( vector<string>::const_iterator it = tokens.begin();
466           it != tokens.end();
467           ++it )
468     {
469         path +=  "/" + *it;
470
471         struct stat buf;
472         if ( stat( path.c_str(), &buf ) == 0 ) {
473             if ( !S_ISDIR( buf.st_mode ) ) {
474                 debugError( "\"%s\" is not a directory\n",  path.c_str() );
475                 return false;
476             }
477         } else {
478             if (  mkdir( path.c_str(), S_IRWXU | S_IRWXG ) != 0 ) {
479                 debugError( "Could not create \"%s\" directory\n", path.c_str() );
480                 return false;
481             }
482         }
483     }
484
485     // come up with an unique file name for the current settings
486     char* configId;
487     asprintf(&configId, "%08x", BeBoB::AvDevice::getConfigurationId() );
488     if ( !configId ) {
489         debugError( "Could not create id string\n" );
490         return false;
491     }
492     string filename = path + "/" + configId + ".xml";
493     free( configId );
494     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", filename.c_str() );
495
496     Util::XMLSerialize ser( filename );
497     return serialize( "", ser );
498 }
499
500 } // end of namespace
Note: See TracBrowser for help on using the browser.