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

Revision 1338, 25.3 kB (checked in by wagi, 12 years ago)

- Add AV/C command for LRBalance feature function block
- Expose for each found feature function block one level feature

function mixer element and one left right balance feature
function mixer element.

- Add 'Volume' or 'LRBalance' as dbus

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