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

Revision 1235, 21.7 kB (checked in by ppalmers, 13 years ago)

svn merge -r 1231:1234 svn+ssh://ffadosvn@ffado.org/ffado/trunk/libffado

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 bool
177 AvDevice::discover()
178 {
179     unsigned int vendorId = getConfigRom().getNodeVendorId();
180     unsigned int modelId = getConfigRom().getModelId();
181
182     GenericAVC::VendorModel vendorModel( SHAREDIR "/ffado_driver_bebob.txt" );
183     if ( vendorModel.parse() ) {
184         m_model = vendorModel.find( vendorId, modelId );
185     }
186
187     if (GenericAVC::VendorModel::isValid(m_model)) {
188         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
189                      m_model.vendor_name.c_str(),
190                      m_model.model_name.c_str());
191     } else {
192         debugWarning("Using generic BeBoB support for unsupported device '%s %s'\n",
193                      getConfigRom().getVendorName().c_str(), getConfigRom().getModelName().c_str());
194     }
195
196     if ( !Unit::discover() ) {
197         debugError( "Could not discover unit\n" );
198         return false;
199     }
200
201     if((getAudioSubunit( 0 ) == NULL)) {
202         debugError( "Unit doesn't have an Audio subunit.\n");
203         return false;
204     }
205     if((getMusicSubunit( 0 ) == NULL)) {
206         debugError( "Unit doesn't have a Music subunit.\n");
207         return false;
208     }
209
210     if(!buildMixer()) {
211         debugWarning("Could not build mixer\n");
212     }
213     return true;
214 }
215
216 bool
217 AvDevice::buildMixer()
218 {
219     debugOutput(DEBUG_LEVEL_VERBOSE, "Building a generic BeBoB mixer...\n");
220     // create a Mixer
221     // this removes the mixer if it already exists
222     // note: a mixer self-registers to it's parent
223     delete m_Mixer;
224
225     // create the mixer & register it
226     if(getAudioSubunit(0) == NULL) {
227         debugWarning("Could not find audio subunit, mixer not available.\n");
228         m_Mixer = NULL;
229     } else {
230         m_Mixer = new Mixer(*this);
231     }
232     if (m_Mixer) m_Mixer->setVerboseLevel(getDebugLevel());
233     return m_Mixer != NULL;
234 }
235
236 bool
237 AvDevice::destroyMixer()
238 {
239     delete m_Mixer;
240     return true;
241 }
242
243 bool
244 AvDevice::setSelectorFBValue(int id, int value) {
245     FunctionBlockCmd fbCmd( get1394Service(),
246                             FunctionBlockCmd::eFBT_Selector,
247                             id,
248                             FunctionBlockCmd::eCA_Current );
249     fbCmd.setNodeId( getNodeId() );
250     fbCmd.setSubunitId( 0x00 );
251     fbCmd.setCommandType( AVCCommand::eCT_Control );
252     fbCmd.m_pFBSelector->m_inputFbPlugNumber = (value & 0xFF);
253     fbCmd.setVerboseLevel( getDebugLevel() );
254
255     if ( !fbCmd.fire() ) {
256         debugError( "cmd failed\n" );
257         return false;
258     }
259
260 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
261 //         Util::CoutSerializer se;
262 //         fbCmd.serialize( se );
263 //     }
264 //     
265     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
266         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
267     }
268
269     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
270 }
271
272 int
273 AvDevice::getSelectorFBValue(int id) {
274
275     FunctionBlockCmd fbCmd( get1394Service(),
276                             FunctionBlockCmd::eFBT_Selector,
277                             id,
278                             FunctionBlockCmd::eCA_Current );
279     fbCmd.setNodeId( getNodeId() );
280     fbCmd.setSubunitId( 0x00 );
281     fbCmd.setCommandType( AVCCommand::eCT_Status );
282     fbCmd.m_pFBSelector->m_inputFbPlugNumber = 0xFF;
283     fbCmd.setVerboseLevel( getDebugLevel() );
284
285     if ( !fbCmd.fire() ) {
286         debugError( "cmd failed\n" );
287         return -1;
288     }
289    
290 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
291 //         Util::CoutSerializer se;
292 //         fbCmd.serialize( se );
293 //     }
294
295     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
296         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
297     }
298    
299     return fbCmd.m_pFBSelector->m_inputFbPlugNumber;
300 }
301
302 bool
303 AvDevice::setFeatureFBVolumeValue(int id, int channel, int v) {
304
305     FunctionBlockCmd fbCmd( get1394Service(),
306                             FunctionBlockCmd::eFBT_Feature,
307                             id,
308                             FunctionBlockCmd::eCA_Current );
309     fbCmd.setNodeId( getNodeId() );
310     fbCmd.setSubunitId( 0x00 );
311     fbCmd.setCommandType( AVCCommand::eCT_Control );
312     fbCmd.m_pFBFeature->m_audioChannelNumber = channel;
313     fbCmd.m_pFBFeature->m_controlSelector = FunctionBlockFeature::eCSE_Feature_Volume;
314     fbCmd.m_pFBFeature->m_pVolume->m_volume = v;
315     fbCmd.setVerboseLevel( getDebugLevel() );
316
317     if ( !fbCmd.fire() ) {
318         debugError( "cmd failed\n" );
319         return false;
320     }
321
322 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
323 //         Util::CoutSerializer se;
324 //         fbCmd.serialize( se );
325 //     }
326    
327     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
328         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
329     }
330
331     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
332 }
333
334 int
335 AvDevice::getFeatureFBVolumeValue(int id, int channel) {
336     FunctionBlockCmd fbCmd( get1394Service(),
337                             FunctionBlockCmd::eFBT_Feature,
338                             id,
339                             FunctionBlockCmd::eCA_Current );
340     fbCmd.setNodeId( getNodeId() );
341     fbCmd.setSubunitId( 0x00 );
342     fbCmd.setCommandType( AVCCommand::eCT_Status );
343     fbCmd.m_pFBFeature->m_audioChannelNumber = channel;
344     fbCmd.m_pFBFeature->m_controlSelector = FunctionBlockFeature::eCSE_Feature_Volume;
345     fbCmd.m_pFBFeature->m_pVolume->m_volume = 0;
346     fbCmd.setVerboseLevel( getDebugLevel() );
347
348     if ( !fbCmd.fire() ) {
349         debugError( "cmd failed\n" );
350         return 0;
351     }
352    
353 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
354 //         Util::CoutSerializer se;
355 //         fbCmd.serialize( se );
356 //     }
357
358     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
359         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
360     }
361    
362     int16_t volume=(int16_t)(fbCmd.m_pFBFeature->m_pVolume->m_volume);
363    
364     return volume;
365 }
366
367 void
368 AvDevice::showDevice()
369 {
370     debugOutput(DEBUG_LEVEL_NORMAL, "Device is a BeBoB device\n");
371     GenericAVC::AvDevice::showDevice();
372     flushDebugOutput();
373 }
374
375 void
376 AvDevice::setVerboseLevel(int l)
377 {
378     if (m_Mixer) m_Mixer->setVerboseLevel( l );
379     GenericAVC::AvDevice::setVerboseLevel( l );
380     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
381 }
382
383 AVC::Subunit*
384 AvDevice::createSubunit(AVC::Unit& unit,
385                         AVC::ESubunitType type,
386                         AVC::subunit_t id )
387 {
388     AVC::Subunit* s=NULL;
389     switch (type) {
390         case eST_Audio:
391             s=new BeBoB::SubunitAudio(unit, id );
392             break;
393         case eST_Music:
394             s=new BeBoB::SubunitMusic(unit, id );
395             break;
396         default:
397             s=NULL;
398             break;
399     }
400     if(s) s->setVerboseLevel(getDebugLevel());
401     return s;
402 }
403
404
405 AVC::Plug *
406 AvDevice::createPlug( AVC::Unit* unit,
407                       AVC::Subunit* subunit,
408                       AVC::function_block_type_t functionBlockType,
409                       AVC::function_block_type_t functionBlockId,
410                       AVC::Plug::EPlugAddressType plugAddressType,
411                       AVC::Plug::EPlugDirection plugDirection,
412                       AVC::plug_id_t plugId )
413 {
414
415     Plug *p= new BeBoB::Plug( unit,
416                               subunit,
417                               functionBlockType,
418                               functionBlockId,
419                               plugAddressType,
420                               plugDirection,
421                               plugId );
422     if (p) p->setVerboseLevel(getDebugLevel());
423     return p;
424 }
425
426 bool
427 AvDevice::propagatePlugInfo() {
428     // we don't have to propagate since we discover things
429     // another way
430     debugOutput(DEBUG_LEVEL_VERBOSE, "Skip plug info propagation\n");
431     return true;
432 }
433
434
435 uint8_t
436 AvDevice::getConfigurationIdSampleRate()
437 {
438     ExtendedStreamFormatCmd extStreamFormatCmd( get1394Service() );
439     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR, 0 );
440     extStreamFormatCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
441                                                     PlugAddress::ePAM_Unit,
442                                                     unitPlugAddress ) );
443
444     extStreamFormatCmd.setNodeId( getNodeId() );
445     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
446     extStreamFormatCmd.setVerbose( getDebugLevel() );
447
448     if ( !extStreamFormatCmd.fire() ) {
449         debugError( "Stream format command failed\n" );
450         return false;
451     }
452
453     FormatInformation* formatInfo =
454         extStreamFormatCmd.getFormatInformation();
455     FormatInformationStreamsCompound* compoundStream
456         = dynamic_cast< FormatInformationStreamsCompound* > (
457             formatInfo->m_streams );
458     if ( compoundStream ) {
459         debugOutput(DEBUG_LEVEL_VERBOSE, "Sample rate 0x%02x\n",
460                     compoundStream->m_samplingFrequency );
461         return compoundStream->m_samplingFrequency;
462     }
463
464     debugError( "Could not retrieve sample rate\n" );
465     return 0;
466 }
467
468 uint8_t
469 AvDevice::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection )
470 {
471     ExtendedPlugInfoCmd extPlugInfoCmd( get1394Service() );
472     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
473                                      getNodeId() );
474     extPlugInfoCmd.setPlugAddress( PlugAddress( ePlugDirection,
475                                                 PlugAddress::ePAM_Unit,
476                                                 unitPlugAddress ) );
477     extPlugInfoCmd.setNodeId( getNodeId() );
478     extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
479     extPlugInfoCmd.setVerbose( getDebugLevel() );
480     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
481         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
482     extendedPlugInfoInfoType.initialize();
483     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
484
485     if ( !extPlugInfoCmd.fire() ) {
486         debugError( "Number of channels command failed\n" );
487         return false;
488     }
489
490     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
491     if ( infoType
492          && infoType->m_plugNrOfChns )
493     {
494         debugOutput(DEBUG_LEVEL_VERBOSE, "Number of channels 0x%02x\n",
495                     infoType->m_plugNrOfChns->m_nrOfChannels );
496         return infoType->m_plugNrOfChns->m_nrOfChannels;
497     }
498
499     debugError( "Could not retrieve number of channels\n" );
500     return 0;
501 }
502
503 uint8_t
504 AvDevice::getConfigurationIdSyncMode()
505 {
506     SignalSourceCmd signalSourceCmd( get1394Service() );
507     SignalUnitAddress signalUnitAddr;
508     signalUnitAddr.m_plugId = 0x01;
509     signalSourceCmd.setSignalDestination( signalUnitAddr );
510     signalSourceCmd.setNodeId( getNodeId() );
511     signalSourceCmd.setSubunitType( eST_Unit  );
512     signalSourceCmd.setSubunitId( 0xff );
513     signalSourceCmd.setVerbose( getDebugLevel() );
514
515     signalSourceCmd.setCommandType( AVCCommand::eCT_Status );
516
517     if ( !signalSourceCmd.fire() ) {
518         debugError( "Signal source command failed\n" );
519         return false;
520     }
521
522     SignalAddress* pSyncPlugSignalAddress = signalSourceCmd.getSignalSource();
523     SignalSubunitAddress* pSyncPlugSubunitAddress
524         = dynamic_cast<SignalSubunitAddress*>( pSyncPlugSignalAddress );
525     if ( pSyncPlugSubunitAddress ) {
526         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
527                     ( pSyncPlugSubunitAddress->m_subunitType << 3
528                       | pSyncPlugSubunitAddress->m_subunitId ) << 8
529                     | pSyncPlugSubunitAddress->m_plugId );
530
531         return ( pSyncPlugSubunitAddress->m_subunitType << 3
532                  | pSyncPlugSubunitAddress->m_subunitId ) << 8
533             | pSyncPlugSubunitAddress->m_plugId;
534     }
535
536     SignalUnitAddress* pSyncPlugUnitAddress
537       = dynamic_cast<SignalUnitAddress*>( pSyncPlugSignalAddress );
538     if ( pSyncPlugUnitAddress ) {
539         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
540                       0xff << 8 | pSyncPlugUnitAddress->m_plugId );
541
542         return ( 0xff << 8 | pSyncPlugUnitAddress->m_plugId );
543     }
544
545     debugError( "Could not retrieve sync mode\n" );
546     return 0;
547 }
548
549 uint64_t
550 AvDevice::getConfigurationId()
551 {
552     // create a unique configuration id.
553     uint64_t id = 0;
554     id = getConfigurationIdSampleRate();
555     id |= ( getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input )
556             + getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output ) ) << 8;
557     id |= getConfigurationIdSyncMode() << 16;
558
559     return id;
560 }
561
562 bool
563 AvDevice::serialize( std::string basePath,
564                      Util::IOSerialize& ser ) const
565 {
566     bool result;
567     result  = GenericAVC::AvDevice::serialize( basePath, ser );
568     return result;
569 }
570
571 bool
572 AvDevice::deserialize( std::string basePath,
573                        Util::IODeserialize& deser )
574 {
575     bool result;
576     result  = GenericAVC::AvDevice::deserialize( basePath, deser );
577     return result;
578 }
579
580 std::string
581 AvDevice::getCachePath()
582 {
583     std::string cachePath;
584     char* pCachePath;
585
586     string path = CACHEDIR;
587     if ( path.size() && path[0] == '~' ) {
588         path.erase( 0, 1 ); // remove ~
589         path.insert( 0, getenv( "HOME" ) ); // prepend the home path
590     }
591
592     if ( asprintf( &pCachePath, "%s/cache/",  path.c_str() ) < 0 ) {
593         debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
594         cachePath == "/var/cache/libffado/";
595     } else {
596         cachePath = pCachePath;
597         free( pCachePath );
598     }
599     return cachePath;
600 }
601
602 bool
603 AvDevice::loadFromCache()
604 {
605     std::string sDevicePath = getCachePath() + getConfigRom().getGuidString();
606
607     char* configId;
608     asprintf(&configId, "%016llx", getConfigurationId() );
609     if ( !configId ) {
610         debugError( "could not create id string\n" );
611         return false;
612     }
613
614     std::string sFileName = sDevicePath + "/" + configId + ".xml";
615     free( configId );
616     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
617
618     struct stat buf;
619     if ( stat( sFileName.c_str(), &buf ) != 0 ) {
620         debugOutput( DEBUG_LEVEL_NORMAL,  "\"%s\" does not exist\n",  sFileName.c_str() );
621         return false;
622     } else {
623         if ( !S_ISREG( buf.st_mode ) ) {
624             debugOutput( DEBUG_LEVEL_NORMAL,  "\"%s\" is not a regular file\n",  sFileName.c_str() );
625             return false;
626         }
627     }
628
629     Util::XMLDeserialize deser( sFileName, getDebugLevel() );
630
631     if (!deser.isValid()) {
632         debugOutput( DEBUG_LEVEL_NORMAL, "cache not valid: %s\n",
633                      sFileName.c_str() );
634         return false;
635     }
636
637     bool result = deserialize( "", deser );
638     if ( result ) {
639         debugOutput( DEBUG_LEVEL_NORMAL, "could create valid bebob driver from %s\n",
640                      sFileName.c_str() );
641     }
642
643     if(result) {
644         buildMixer();
645     }
646
647     return result;
648 }
649
650 bool
651 AvDevice::saveCache()
652 {
653     // the path looks like this:
654     // PATH_TO_CACHE + GUID + CONFIGURATION_ID
655     string tmp_path = getCachePath() + getConfigRom().getGuidString();
656
657     // the following piece should do something like
658     // 'mkdir -p some/path/with/some/dirs/which/do/not/exist'
659     vector<string> tokens;
660     tokenize( tmp_path, tokens, "/" );
661     string path;
662     for ( vector<string>::const_iterator it = tokens.begin();
663           it != tokens.end();
664           ++it )
665     {
666         path +=  "/" + *it;
667
668         struct stat buf;
669         if ( stat( path.c_str(), &buf ) == 0 ) {
670             if ( !S_ISDIR( buf.st_mode ) ) {
671                 debugError( "\"%s\" is not a directory\n",  path.c_str() );
672                 return false;
673             }
674         } else {
675             if (  mkdir( path.c_str(), S_IRWXU | S_IRWXG ) != 0 ) {
676                 debugError( "Could not create \"%s\" directory\n", path.c_str() );
677                 return false;
678             }
679         }
680     }
681
682     // come up with an unique file name for the current settings
683     char* configId;
684     asprintf(&configId, "%016llx", BeBoB::AvDevice::getConfigurationId() );
685     if ( !configId ) {
686         debugError( "Could not create id string\n" );
687         return false;
688     }
689     string filename = path + "/" + configId + ".xml";
690     free( configId );
691     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", filename.c_str() );
692
693     Util::XMLSerialize ser( filename );
694     return serialize( "", ser );
695 }
696
697 } // end of namespace
Note: See TracBrowser for help on using the browser.