root/branches/libffado-2.0/src/bebob/bebob_avdevice.cpp

Revision 1288, 21.8 kB (checked in by ppalmers, 16 years ago)

implement samplerate control through the mixer panels. disabled by default due to potential issues with rediscovery and a running jackd

Line 
1 /*
2  * Copyright (C) 2005-2008 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 program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
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 #include "bebob/mackie/onyxmixer.h"
34 #include "bebob/edirol/edirol_fa101.h"
35 #include "bebob/edirol/edirol_fa66.h"
36 #include "bebob/esi/quatafire610.h"
37
38 #include "libieee1394/configrom.h"
39 #include "libieee1394/ieee1394service.h"
40
41 #include "genericavc/avc_vendormodel.h"
42
43 #include "libavc/general/avc_plug_info.h"
44 #include "libavc/general/avc_extended_plug_info.h"
45 #include "libavc/general/avc_subunit_info.h"
46 #include "libavc/streamformat/avc_extended_stream_format.h"
47 #include "libutil/cmd_serialize.h"
48 #include "libavc/avc_definitions.h"
49
50 #include "debugmodule/debugmodule.h"
51
52 #include <iostream>
53 #include <sstream>
54 #include <unistd.h>
55 #include <cstdlib>
56 #include <cstring>
57 #include <sys/stat.h>
58
59 using namespace AVC;
60
61 namespace BeBoB {
62
63 AvDevice::AvDevice( DeviceManager& d, std::auto_ptr< ConfigRom >( configRom ) )
64     : GenericAVC::AvDevice( d, configRom )
65     , m_Mixer ( 0 )
66 {
67     debugOutput( DEBUG_LEVEL_VERBOSE, "Created BeBoB::AvDevice (NodeID %d)\n",
68                  getConfigRom().getNodeId() );
69
70     // DM1500 based devices seem to upset the linux1394 stack when commands are
71     // sent too fast.
72     if (AVC::AVCCommand::getSleepAfterAVCCommand() < 200) {
73         AVC::AVCCommand::setSleepAfterAVCCommand( 200 );
74     }
75
76 }
77
78 AvDevice::~AvDevice()
79 {
80     destroyMixer();
81 }
82
83 bool
84 AvDevice::probe( ConfigRom& configRom, bool generic )
85 {
86     if(generic) {
87         return false;
88         // try a bebob-specific command to check for the firmware
89         ExtendedPlugInfoCmd extPlugInfoCmd( configRom.get1394Service() );
90         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
91                                          configRom.getNodeId() );
92         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
93                                                     PlugAddress::ePAM_Unit,
94                                                     unitPlugAddress ) );
95         extPlugInfoCmd.setNodeId( configRom.getNodeId() );
96         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
97         extPlugInfoCmd.setVerbose( configRom.getVerboseLevel() );
98         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
99             ExtendedPlugInfoInfoType::eIT_NoOfChannels );
100         extendedPlugInfoInfoType.initialize();
101         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
102    
103         if ( !extPlugInfoCmd.fire() ) {
104             debugError( "Number of channels command failed\n" );
105             return false;
106         }
107    
108         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
109         if ( infoType
110             && infoType->m_plugNrOfChns )
111         {
112             return true;
113         }
114         return false;
115     } else {
116         // check if device is in supported devices list
117         unsigned int vendorId = configRom.getNodeVendorId();
118         unsigned int modelId = configRom.getModelId();
119
120         GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_bebob.txt" );
121         if ( vendorModel.parse() ) {
122             return vendorModel.isPresent( vendorId, modelId );
123         }
124         return false;
125     }
126 }
127
128 FFADODevice *
129 AvDevice::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
130 {
131     unsigned int vendorId = configRom->getNodeVendorId();
132     unsigned int modelId = configRom->getModelId();
133
134     switch (vendorId) {
135         case FW_VENDORID_MACKIE:
136             if (modelId == 0x00010065 ) {
137                 return new Mackie::OnyxMixerDevice(d, configRom);
138             }
139         case FW_VENDORID_EDIROL:
140             switch (modelId) {
141                 case 0x00010048:
142                     return new Edirol::EdirolFa101Device(d, configRom);
143                 case 0x00010049:
144                     return new Edirol::EdirolFa66Device(d, configRom);
145                 default:
146                     return new AvDevice(d, configRom);
147             }
148         case FW_VENDORID_ESI:
149             if (modelId == 0x00010064) {
150                 return new ESI::QuataFireDevice(d, configRom);
151             }
152             break;
153         case FW_VENDORID_TERRATEC:
154             switch(modelId) {
155                 case 0x00000003:
156                     return new Terratec::Phase88Device(d, configRom);
157                 default: // return a plain BeBoB device
158                     return new AvDevice(d, configRom);
159             }
160         case FW_VENDORID_FOCUSRITE:
161             switch(modelId) {
162                 case 0x00000003:
163                 case 0x00000006:
164                     return new Focusrite::SaffireProDevice(d, configRom);
165                 case 0x00000000:
166                     return new Focusrite::SaffireDevice(d, configRom);
167                 default: // return a plain BeBoB device
168                     return new AvDevice(d, configRom);
169            }
170         default:
171             return new AvDevice(d, configRom);
172     }
173     return NULL;
174 }
175
176 #define BEBOB_CHECK_AND_ADD_SR(v, x) \
177     { if(supportsSamplingFrequency(x)) \
178       v.push_back(x); }
179 bool
180 AvDevice::discover()
181 {
182     unsigned int vendorId = getConfigRom().getNodeVendorId();
183     unsigned int modelId = getConfigRom().getModelId();
184
185     GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_bebob.txt" );
186     if ( vendorModel.parse() ) {
187         m_model = vendorModel.find( vendorId, modelId );
188     }
189
190     if (GenericAVC::VendorModel::isValid(m_model)) {
191         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
192                      m_model.vendor_name.c_str(),
193                      m_model.model_name.c_str());
194     } else {
195         debugWarning("Using generic BeBoB support for unsupported device '%s %s'\n",
196                      getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
197     }
198
199     if ( !Unit::discover() ) {
200         debugError( "Could not discover unit\n" );
201         return false;
202     }
203
204     if((getAudioSubunit( 0 ) == NULL)) {
205         debugError( "Unit doesn't have an Audio subunit.\n");
206         return false;
207     }
208     if((getMusicSubunit( 0 ) == NULL)) {
209         debugError( "Unit doesn't have a Music subunit.\n");
210         return false;
211     }
212
213     if(!buildMixer()) {
214         debugWarning("Could not build mixer\n");
215     }
216     return true;
217 }
218
219 bool
220 AvDevice::buildMixer()
221 {
222     debugOutput(DEBUG_LEVEL_VERBOSE, "Building a generic BeBoB mixer...\n");
223     // create a Mixer
224     // this removes the mixer if it already exists
225     // note: a mixer self-registers to it's parent
226     delete m_Mixer;
227
228     // create the mixer & register it
229     if(getAudioSubunit(0) == NULL) {
230         debugWarning("Could not find audio subunit, mixer not available.\n");
231         m_Mixer = NULL;
232     } else {
233         m_Mixer = new Mixer(*this);
234     }
235     if (m_Mixer) m_Mixer->setVerboseLevel(getDebugLevel());
236     return m_Mixer != NULL;
237 }
238
239 bool
240 AvDevice::destroyMixer()
241 {
242     delete m_Mixer;
243     return true;
244 }
245
246 bool
247 AvDevice::setSelectorFBValue(int id, int value) {
248     FunctionBlockCmd fbCmd( get1394Service(),
249                             FunctionBlockCmd::eFBT_Selector,
250                             id,
251                             FunctionBlockCmd::eCA_Current );
252     fbCmd.setNodeId( getNodeId() );
253     fbCmd.setSubunitId( 0x00 );
254     fbCmd.setCommandType( AVCCommand::eCT_Control );
255     fbCmd.m_pFBSelector->m_inputFbPlugNumber = (value & 0xFF);
256     fbCmd.setVerboseLevel( getDebugLevel() );
257
258     if ( !fbCmd.fire() ) {
259         debugError( "cmd failed\n" );
260         return false;
261     }
262
263 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
264 //         Util::CoutSerializer se;
265 //         fbCmd.serialize( se );
266 //     }
267 //     
268     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
269         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
270     }
271
272     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
273 }
274
275 int
276 AvDevice::getSelectorFBValue(int id) {
277
278     FunctionBlockCmd fbCmd( get1394Service(),
279                             FunctionBlockCmd::eFBT_Selector,
280                             id,
281                             FunctionBlockCmd::eCA_Current );
282     fbCmd.setNodeId( getNodeId() );
283     fbCmd.setSubunitId( 0x00 );
284     fbCmd.setCommandType( AVCCommand::eCT_Status );
285     fbCmd.m_pFBSelector->m_inputFbPlugNumber = 0xFF;
286     fbCmd.setVerboseLevel( getDebugLevel() );
287
288     if ( !fbCmd.fire() ) {
289         debugError( "cmd failed\n" );
290         return -1;
291     }
292    
293 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
294 //         Util::CoutSerializer se;
295 //         fbCmd.serialize( se );
296 //     }
297
298     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
299         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
300     }
301    
302     return fbCmd.m_pFBSelector->m_inputFbPlugNumber;
303 }
304
305 bool
306 AvDevice::setFeatureFBVolumeValue(int id, int channel, int v) {
307
308     FunctionBlockCmd fbCmd( get1394Service(),
309                             FunctionBlockCmd::eFBT_Feature,
310                             id,
311                             FunctionBlockCmd::eCA_Current );
312     fbCmd.setNodeId( getNodeId() );
313     fbCmd.setSubunitId( 0x00 );
314     fbCmd.setCommandType( AVCCommand::eCT_Control );
315     fbCmd.m_pFBFeature->m_audioChannelNumber = channel;
316     fbCmd.m_pFBFeature->m_controlSelector = FunctionBlockFeature::eCSE_Feature_Volume;
317     fbCmd.m_pFBFeature->m_pVolume->m_volume = v;
318     fbCmd.setVerboseLevel( getDebugLevel() );
319
320     if ( !fbCmd.fire() ) {
321         debugError( "cmd failed\n" );
322         return false;
323     }
324
325 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
326 //         Util::CoutSerializer se;
327 //         fbCmd.serialize( se );
328 //     }
329    
330     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
331         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
332     }
333
334     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
335 }
336
337 int
338 AvDevice::getFeatureFBVolumeValue(int id, int channel) {
339     FunctionBlockCmd fbCmd( get1394Service(),
340                             FunctionBlockCmd::eFBT_Feature,
341                             id,
342                             FunctionBlockCmd::eCA_Current );
343     fbCmd.setNodeId( getNodeId() );
344     fbCmd.setSubunitId( 0x00 );
345     fbCmd.setCommandType( AVCCommand::eCT_Status );
346     fbCmd.m_pFBFeature->m_audioChannelNumber = channel;
347     fbCmd.m_pFBFeature->m_controlSelector = FunctionBlockFeature::eCSE_Feature_Volume;
348     fbCmd.m_pFBFeature->m_pVolume->m_volume = 0;
349     fbCmd.setVerboseLevel( getDebugLevel() );
350
351     if ( !fbCmd.fire() ) {
352         debugError( "cmd failed\n" );
353         return 0;
354     }
355    
356 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
357 //         Util::CoutSerializer se;
358 //         fbCmd.serialize( se );
359 //     }
360
361     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
362         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
363     }
364    
365     int16_t volume=(int16_t)(fbCmd.m_pFBFeature->m_pVolume->m_volume);
366    
367     return volume;
368 }
369
370 void
371 AvDevice::showDevice()
372 {
373     debugOutput(DEBUG_LEVEL_NORMAL, "Device is a BeBoB device\n");
374     GenericAVC::AvDevice::showDevice();
375     flushDebugOutput();
376 }
377
378 void
379 AvDevice::setVerboseLevel(int l)
380 {
381     if (m_Mixer) m_Mixer->setVerboseLevel( l );
382     GenericAVC::AvDevice::setVerboseLevel( l );
383     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
384 }
385
386 AVC::Subunit*
387 AvDevice::createSubunit(AVC::Unit& unit,
388                         AVC::ESubunitType type,
389                         AVC::subunit_t id )
390 {
391     AVC::Subunit* s=NULL;
392     switch (type) {
393         case eST_Audio:
394             s=new BeBoB::SubunitAudio(unit, id );
395             break;
396         case eST_Music:
397             s=new BeBoB::SubunitMusic(unit, id );
398             break;
399         default:
400             s=NULL;
401             break;
402     }
403     if(s) s->setVerboseLevel(getDebugLevel());
404     return s;
405 }
406
407
408 AVC::Plug *
409 AvDevice::createPlug( AVC::Unit* unit,
410                       AVC::Subunit* subunit,
411                       AVC::function_block_type_t functionBlockType,
412                       AVC::function_block_type_t functionBlockId,
413                       AVC::Plug::EPlugAddressType plugAddressType,
414                       AVC::Plug::EPlugDirection plugDirection,
415                       AVC::plug_id_t plugId,
416                       int globalId )
417 {
418
419     Plug *p= new BeBoB::Plug( unit,
420                               subunit,
421                               functionBlockType,
422                               functionBlockId,
423                               plugAddressType,
424                               plugDirection,
425                               plugId,
426                               globalId );
427     if (p) p->setVerboseLevel(getDebugLevel());
428     return p;
429 }
430
431 bool
432 AvDevice::propagatePlugInfo() {
433     // we don't have to propagate since we discover things
434     // another way
435     debugOutput(DEBUG_LEVEL_VERBOSE, "Skip plug info propagation\n");
436     return true;
437 }
438
439 uint8_t
440 AvDevice::getConfigurationIdSampleRate()
441 {
442     ExtendedStreamFormatCmd extStreamFormatCmd( get1394Service() );
443     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, 0 );
444     extStreamFormatCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
445                                                     PlugAddress::ePAM_Unit,
446                                                     unitPlugAddress ) );
447
448     extStreamFormatCmd.setNodeId( getNodeId() );
449     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
450     extStreamFormatCmd.setVerbose( getDebugLevel() );
451
452     if ( !extStreamFormatCmd.fire() ) {
453         debugError( "Stream format command failed\n" );
454         return 0;
455     }
456
457     FormatInformation* formatInfo =
458         extStreamFormatCmd.getFormatInformation();
459     FormatInformationStreamsCompound* compoundStream
460         = dynamic_cast< FormatInformationStreamsCompound* > (
461             formatInfo->m_streams );
462     if ( compoundStream ) {
463         debugOutput(DEBUG_LEVEL_VERBOSE, "Sample rate 0x%02x\n",
464                     compoundStream->m_samplingFrequency );
465         return compoundStream->m_samplingFrequency;
466     }
467
468     debugError( "Could not retrieve sample rate\n" );
469     return 0;
470 }
471
472 uint8_t
473 AvDevice::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection )
474 {
475     ExtendedPlugInfoCmd extPlugInfoCmd( get1394Service() );
476     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
477                                      0 );
478     extPlugInfoCmd.setPlugAddress( PlugAddress( ePlugDirection,
479                                                 PlugAddress::ePAM_Unit,
480                                                 unitPlugAddress ) );
481     extPlugInfoCmd.setNodeId( getNodeId() );
482     extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
483     extPlugInfoCmd.setVerbose( getDebugLevel() );
484     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
485         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
486     extendedPlugInfoInfoType.initialize();
487     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
488
489     if ( !extPlugInfoCmd.fire() ) {
490         debugError( "Number of channels command failed\n" );
491         return 0;
492     }
493
494     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
495     if ( infoType
496          && infoType->m_plugNrOfChns )
497     {
498         debugOutput(DEBUG_LEVEL_VERBOSE, "Number of channels 0x%02x\n",
499                     infoType->m_plugNrOfChns->m_nrOfChannels );
500         return infoType->m_plugNrOfChns->m_nrOfChannels;
501     }
502
503     debugError( "Could not retrieve number of channels\n" );
504     return 0;
505 }
506
507 uint16_t
508 AvDevice::getConfigurationIdSyncMode()
509 {
510     SignalSourceCmd signalSourceCmd( get1394Service() );
511     SignalUnitAddress signalUnitAddr;
512     signalUnitAddr.m_plugId = 0x01;
513     signalSourceCmd.setSignalDestination( signalUnitAddr );
514     signalSourceCmd.setNodeId( getNodeId() );
515     signalSourceCmd.setSubunitType( eST_Unit  );
516     signalSourceCmd.setSubunitId( 0xff );
517     signalSourceCmd.setVerbose( getDebugLevel() );
518
519     signalSourceCmd.setCommandType( AVCCommand::eCT_Status );
520
521     if ( !signalSourceCmd.fire() ) {
522         debugError( "Signal source command failed\n" );
523         return 0;
524     }
525
526     SignalAddress* pSyncPlugSignalAddress = signalSourceCmd.getSignalSource();
527     SignalSubunitAddress* pSyncPlugSubunitAddress
528         = dynamic_cast<SignalSubunitAddress*>( pSyncPlugSignalAddress );
529     if ( pSyncPlugSubunitAddress ) {
530         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
531                     ( pSyncPlugSubunitAddress->m_subunitType << 3
532                       | pSyncPlugSubunitAddress->m_subunitId ) << 8
533                     | pSyncPlugSubunitAddress->m_plugId );
534
535         return ( pSyncPlugSubunitAddress->m_subunitType << 3
536                  | pSyncPlugSubunitAddress->m_subunitId ) << 8
537             | pSyncPlugSubunitAddress->m_plugId;
538     }
539
540     SignalUnitAddress* pSyncPlugUnitAddress
541       = dynamic_cast<SignalUnitAddress*>( pSyncPlugSignalAddress );
542     if ( pSyncPlugUnitAddress ) {
543         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
544                       0xff << 8 | pSyncPlugUnitAddress->m_plugId );
545
546         return ( 0xff << 8 | pSyncPlugUnitAddress->m_plugId );
547     }
548
549     debugError( "Could not retrieve sync mode\n" );
550     return 0;
551 }
552
553 uint64_t
554 AvDevice::getConfigurationId()
555 {
556     // create a unique configuration id.
557     uint64_t id = 0;
558     id = getConfigurationIdSampleRate();
559     id |= getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input ) << 8;
560     id |= getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output ) << 16;
561     id |= ((uint64_t)getConfigurationIdSyncMode()) << 24;
562     return id;
563 }
564
565 bool
566 AvDevice::serialize( std::string basePath,
567                      Util::IOSerialize& ser ) const
568 {
569     bool result;
570     result  = GenericAVC::AvDevice::serialize( basePath, ser );
571     return result;
572 }
573
574 bool
575 AvDevice::deserialize( std::string basePath,
576                        Util::IODeserialize& deser )
577 {
578     bool result;
579     result  = GenericAVC::AvDevice::deserialize( basePath, deser );
580     return result;
581 }
582
583 std::string
584 AvDevice::getCachePath()
585 {
586     std::string cachePath;
587     char* pCachePath;
588
589     string path = CACHEDIR;
590     if ( path.size() && path[0] == '~' ) {
591         path.erase( 0, 1 ); // remove ~
592         path.insert( 0, getenv( "HOME" ) ); // prepend the home path
593     }
594
595     if ( asprintf( &pCachePath, "%s/cache/",  path.c_str() ) < 0 ) {
596         debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
597         cachePath == "/var/cache/libffado/";
598     } else {
599         cachePath = pCachePath;
600         free( pCachePath );
601     }
602     return cachePath;
603 }
604
605 bool
606 AvDevice::loadFromCache()
607 {
608     std::string sDevicePath = getCachePath() + getConfigRom().getGuidString();
609
610     char* configId;
611     asprintf(&configId, "%016llx", getConfigurationId() );
612     if ( !configId ) {
613         debugError( "could not create id string\n" );
614         return false;
615     }
616
617     std::string sFileName = sDevicePath + "/" + configId + ".xml";
618     free( configId );
619     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
620
621     struct stat buf;
622     if ( stat( sFileName.c_str(), &buf ) != 0 ) {
623         debugOutput( DEBUG_LEVEL_NORMAL,  "\"%s\" does not exist\n",  sFileName.c_str() );
624         return false;
625     } else {
626         if ( !S_ISREG( buf.st_mode ) ) {
627             debugOutput( DEBUG_LEVEL_NORMAL,  "\"%s\" is not a regular file\n",  sFileName.c_str() );
628             return false;
629         }
630     }
631
632     Util::XMLDeserialize deser( sFileName, getDebugLevel() );
633
634     if (!deser.isValid()) {
635         debugOutput( DEBUG_LEVEL_NORMAL, "cache not valid: %s\n",
636                      sFileName.c_str() );
637         return false;
638     }
639
640     bool result = deserialize( "", deser );
641     if ( result ) {
642         debugOutput( DEBUG_LEVEL_NORMAL, "could create valid bebob driver from %s\n",
643                      sFileName.c_str() );
644     }
645
646     if(result) {
647         buildMixer();
648     }
649
650     return result;
651 }
652
653 bool
654 AvDevice::saveCache()
655 {
656     // the path looks like this:
657     // PATH_TO_CACHE + GUID + CONFIGURATION_ID
658     string tmp_path = getCachePath() + getConfigRom().getGuidString();
659
660     // the following piece should do something like
661     // 'mkdir -p some/path/with/some/dirs/which/do/not/exist'
662     vector<string> tokens;
663     tokenize( tmp_path, tokens, "/" );
664     string path;
665     for ( vector<string>::const_iterator it = tokens.begin();
666           it != tokens.end();
667           ++it )
668     {
669         path +=  "/" + *it;
670
671         struct stat buf;
672         if ( stat( path.c_str(), &buf ) == 0 ) {
673             if ( !S_ISDIR( buf.st_mode ) ) {
674                 debugError( "\"%s\" is not a directory\n",  path.c_str() );
675                 return false;
676             }
677         } else {
678             if (  mkdir( path.c_str(), S_IRWXU | S_IRWXG ) != 0 ) {
679                 debugError( "Could not create \"%s\" directory\n", path.c_str() );
680                 return false;
681             }
682         }
683     }
684
685     // come up with an unique file name for the current settings
686     char* configId;
687     asprintf(&configId, "%016llx", BeBoB::AvDevice::getConfigurationId() );
688     if ( !configId ) {
689         debugError( "Could not create id string\n" );
690         return false;
691     }
692     string filename = path + "/" + configId + ".xml";
693     free( configId );
694     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", filename.c_str() );
695
696     Util::XMLSerialize ser( filename );
697     return serialize( "", ser );
698 }
699
700 } // end of namespace
Note: See TracBrowser for help on using the browser.