root/trunk/libffado/src/libutil/Configuration.cpp

Revision 1531, 16.4 kB (checked in by ppalmers, 15 years ago)

svn merge -r 1506:HEAD svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
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 "Configuration.h"
25
26 #include <stdlib.h>
27
28 using namespace libconfig;
29 namespace Util {
30
31 IMPL_DEBUG_MODULE( Configuration, Configuration, DEBUG_LEVEL_NORMAL );
32
33 Configuration::Configuration()
34 {
35
36 }
37
38 Configuration::~Configuration()
39 {
40     while(m_ConfigFiles.size()) {
41         delete m_ConfigFiles.back();
42         m_ConfigFiles.pop_back();
43     }
44 }
45
46 bool
47 Configuration::openFile(std::string filename, enum eFileMode mode)
48 {
49     // check if not already open
50     if(findFileName(filename) >= 0) {
51         debugError("file already open\n");
52         return false;
53     }
54
55     ConfigFile *c = new ConfigFile(*this, filename, mode);
56     switch(mode) {
57         case eFM_ReadOnly:
58         case eFM_ReadWrite:
59             try {
60                 c->readFile();
61             } catch (FileIOException& e) {
62                 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not open file: %s\n", filename.c_str());
63                 delete c;
64                 return false;
65             } catch (ParseException& e) {
66                 debugWarning("Could not parse file: %s\n", filename.c_str());
67                 delete c;
68                 return false;
69             } catch (...) {
70                 debugWarning("Unknown exception when opening file: %s\n", filename.c_str());
71                 delete c;
72                 return false;
73             }
74             break;
75         default:
76             break;
77     }
78     m_ConfigFiles.push_back(c);
79     return true;
80 }
81
82 bool
83 Configuration::closeFile(std::string filename)
84 {
85     int idx = findFileName(filename);
86     if(idx >= 0) {
87         debugOutput(DEBUG_LEVEL_VERBOSE, "Closing config file: %s\n", filename.c_str());
88         ConfigFile *c = m_ConfigFiles.at(idx);
89         m_ConfigFiles.erase(m_ConfigFiles.begin()+idx);
90         delete c;
91         return true;
92     } else {
93         debugError("file not open\n");
94         return false;
95     }
96 }
97
98 bool
99 Configuration::saveFile(std::string name)
100 {
101     int idx = findFileName(name);
102     if(idx >= 0) {
103         ConfigFile *c = m_ConfigFiles.at(idx);
104         switch(c->getMode()) {
105         case eFM_ReadOnly:
106             debugOutput(DEBUG_LEVEL_VERBOSE, "Not saving readonly config file: %s\n", c->getName().c_str());
107             break;
108         case eFM_Temporary:
109             debugOutput(DEBUG_LEVEL_VERBOSE, "Not saving temporary config file: %s\n", c->getName().c_str());
110             break;
111         case eFM_ReadWrite:
112             debugOutput(DEBUG_LEVEL_VERBOSE, "Saving config file: %s\n", c->getName().c_str());
113             try {
114                 c->writeFile();
115             } catch (...) {
116                 debugError("Could not write file: %s\n", c->getName().c_str());
117                 return false;
118             }
119         default:
120             debugOutput(DEBUG_LEVEL_VERBOSE, "bad mode for file: %s\n", c->getName().c_str());
121         }
122     }
123     return true;
124 }
125
126 bool
127 Configuration::save()
128 {
129     bool retval = true;
130     for (unsigned int idx = 0; idx < m_ConfigFiles.size(); idx++) {
131         ConfigFile *c = m_ConfigFiles.at(idx);
132         switch(c->getMode()) {
133         case eFM_ReadOnly:
134             debugOutput(DEBUG_LEVEL_VERBOSE, "Not saving readonly config file: %s\n", c->getName().c_str());
135             break;
136         case eFM_Temporary:
137             debugOutput(DEBUG_LEVEL_VERBOSE, "Not saving temporary config file: %s\n", c->getName().c_str());
138             break;
139         case eFM_ReadWrite:
140             debugOutput(DEBUG_LEVEL_VERBOSE, "Saving config file: %s\n", c->getName().c_str());
141             try {
142                 c->writeFile();
143             } catch (...) {
144                 debugError("Could not write file: %s\n", c->getName().c_str());
145                 retval = false;
146             }
147         default:
148             debugOutput(DEBUG_LEVEL_VERBOSE, "bad mode for file: %s\n", c->getName().c_str());
149         }
150     }
151     return retval;
152 }
153
154 void
155 Configuration::ConfigFile::showSetting(libconfig::Setting &s, std::string prefix)
156 {
157     unsigned int children = s.getLength();
158     Setting::Type t = s.getType();
159
160     switch(t) {
161     case Setting::TypeGroup:
162         debugOutput(DEBUG_LEVEL_NORMAL, "  %sGroup: %s\n", prefix.c_str(), s.getName());
163         for(unsigned int i = 0; i < children; i++) {
164             showSetting(s[i], prefix + "  ");
165         }
166         break;
167     case Setting::TypeList:
168         debugOutput(DEBUG_LEVEL_NORMAL, "  %sList: %s\n", prefix.c_str(), s.getName());
169         for(unsigned int i = 0; i < children; i++) {
170             showSetting(s[i], prefix + "  ");
171         }
172         break;
173     case Setting::TypeArray:
174         debugOutput(DEBUG_LEVEL_NORMAL, "  %sArray: %s\n", prefix.c_str(), s.getName());
175         for(unsigned int i = 0; i < children; i++) {
176             showSetting(s[i], prefix + "  ");
177         }
178         break;
179     case Setting::TypeInt:
180         {
181             int32_t i = s;
182             debugOutput(DEBUG_LEVEL_NORMAL,
183                         "  %s%s = %ld (0x%08lX)\n",
184                         prefix.c_str(), s.getName(), i, i);
185         }
186         break;
187     case Setting::TypeInt64:
188         {
189             int64_t i = s;
190             debugOutput(DEBUG_LEVEL_NORMAL,
191                         "  %s%s = %lld (0x%016llX)\n",
192                         prefix.c_str(), s.getName(), i, i);
193         }
194         break;
195     case Setting::TypeFloat:
196         {
197             float f = s;
198             debugOutput(DEBUG_LEVEL_NORMAL,
199                         "  %s%s = %f\n",
200                         prefix.c_str(), s.getName(), f);
201         }
202         break;
203     case Setting::TypeString:
204         {
205             std::string str = s;
206             debugOutput(DEBUG_LEVEL_NORMAL,
207                         "  %s%s = %s\n",
208                         prefix.c_str(), s.getName(), str.c_str());
209         }
210         break;
211     case Setting::TypeBoolean:
212         {
213             bool b = s;
214             std::string str = (b?"true":"false");
215             debugOutput(DEBUG_LEVEL_NORMAL,
216                         "  %s%s = %s\n",
217                         prefix.c_str(), s.getName(), str.c_str());
218         }
219         break;
220     default:
221         {
222             debugOutput(DEBUG_LEVEL_NORMAL,
223                         "  %s%s = Unsupported Type\n",
224                         prefix.c_str(), s.getName());
225         }
226         break;
227     }
228 }
229
230 bool
231 Configuration::getValueForSetting(std::string path, int32_t &ref)
232 {
233     libconfig::Setting *s = getSetting( path );
234     if(s) {
235         // FIXME: this can be done using the libconfig methods
236         Setting::Type t = s->getType();
237         if(t == Setting::TypeInt) {
238             ref = *s;
239             debugOutput(DEBUG_LEVEL_VERBOSE, "path '%s' has value %d\n", path.c_str(), ref);
240             return true;
241         } else {
242             debugOutput(DEBUG_LEVEL_VERBOSE, "path '%s' has wrong type\n", path.c_str());
243             return false;
244         }
245     } else {
246         debugOutput(DEBUG_LEVEL_VERBOSE, "path '%s' not found\n", path.c_str());
247         return false;
248     }
249 }
250
251 bool
252 Configuration::getValueForSetting(std::string path, int64_t &ref)
253 {
254     libconfig::Setting *s = getSetting( path );
255     if(s) {
256         // FIXME: this can be done using the libconfig methods
257         Setting::Type t = s->getType();
258         if(t == Setting::TypeInt64) {
259             ref = *s;
260             debugOutput(DEBUG_LEVEL_VERBOSE, "path '%s' has value %d\n", path.c_str(), ref);
261             return true;
262         } else {
263             debugOutput(DEBUG_LEVEL_VERBOSE, "path '%s' has wrong type\n", path.c_str());
264             return false;
265         }
266     } else {
267         debugOutput(DEBUG_LEVEL_VERBOSE, "path '%s' not found\n", path.c_str());
268         return false;
269     }
270 }
271
272 bool
273 Configuration::getValueForSetting(std::string path, float &ref)
274 {
275     libconfig::Setting *s = getSetting( path );
276     if(s) {
277         // FIXME: this can be done using the libconfig methods
278         Setting::Type t = s->getType();
279         if(t == Setting::TypeFloat) {
280             ref = *s;
281             debugOutput(DEBUG_LEVEL_VERBOSE, "path '%s' has value %f\n", path.c_str(), ref);
282             return true;
283         } else {
284             debugOutput(DEBUG_LEVEL_VERBOSE, "path '%s' has wrong type\n", path.c_str());
285             return false;
286         }
287     } else {
288         debugOutput(DEBUG_LEVEL_VERBOSE, "path '%s' not found\n", path.c_str());
289         return false;
290     }
291 }
292
293 libconfig::Setting *
294 Configuration::getSetting( std::string path )
295 {
296     for ( std::vector<ConfigFile *>::iterator it = m_ConfigFiles.begin();
297       it != m_ConfigFiles.end();
298       ++it )
299     {
300         ConfigFile *c = *it;
301         try {
302             Setting &s = c->lookup(path);
303             return &s;
304         } catch (...) {
305             debugOutput(DEBUG_LEVEL_VERBOSE, "  %s has no setting %s\n",
306                         c->getName().c_str(), path.c_str());
307         }
308     }
309     return NULL;
310 }
311
312 bool
313 Configuration::getValueForDeviceSetting(unsigned int vendor_id, unsigned model_id, std::string setting, int32_t &ref)
314 {
315     libconfig::Setting *s = getDeviceSetting( vendor_id, model_id );
316     if(s) {
317         try {
318             return s->lookupValue(setting, ref);
319         } catch (...) {
320             debugOutput(DEBUG_LEVEL_VERBOSE, "Setting %s not found\n", setting.c_str());
321             return false;
322         }
323     } else {
324         debugOutput(DEBUG_LEVEL_VERBOSE, "device %X/%X not found\n", vendor_id, model_id);
325         return false;
326     }
327 }
328
329 bool
330 Configuration::getValueForDeviceSetting(unsigned int vendor_id, unsigned model_id, std::string setting, int64_t &ref)
331 {
332     libconfig::Setting *s = getDeviceSetting( vendor_id, model_id );
333     if(s) {
334         try {
335             return s->lookupValue(setting, ref);
336         } catch (...) {
337             debugOutput(DEBUG_LEVEL_VERBOSE, "Setting %s not found\n", setting.c_str());
338             return false;
339         }
340     } else {
341         debugOutput(DEBUG_LEVEL_VERBOSE, "device %X/%X not found\n", vendor_id, model_id);
342         return false;
343     }
344 }
345
346 bool
347 Configuration::getValueForDeviceSetting(unsigned int vendor_id, unsigned model_id, std::string setting, float &ref)
348 {
349     libconfig::Setting *s = getDeviceSetting( vendor_id, model_id );
350     if(s) {
351         try {
352             return s->lookupValue(setting, ref);
353         } catch (...) {
354             debugOutput(DEBUG_LEVEL_VERBOSE, "Setting %s not found\n", setting.c_str());
355             return false;
356         }
357     } else {
358         debugOutput(DEBUG_LEVEL_VERBOSE, "device %X/%X not found\n", vendor_id, model_id);
359         return false;
360     }
361 }
362
363 libconfig::Setting *
364 Configuration::getDeviceSetting( unsigned int vendor_id, unsigned model_id )
365 {
366     for ( std::vector<ConfigFile *>::iterator it = m_ConfigFiles.begin();
367       it != m_ConfigFiles.end();
368       ++it )
369     {
370         ConfigFile *c = *it;
371         try {
372             Setting &list = c->lookup("device_definitions");
373             unsigned int children = list.getLength();
374             for(unsigned int i = 0; i < children; i++) {
375                 Setting &s = list[i];
376                 try {
377                     Setting &vendorid = s["vendorid"];
378                     Setting &modelid = s["modelid"];
379                     uint32_t vid = vendorid;
380                     uint32_t mid = modelid;
381                     if (vendor_id == vid && model_id == mid) {
382                         debugOutput(DEBUG_LEVEL_VERBOSE,
383                                     "  device VME for %X:%x found in %s\n",
384                                     vendor_id, model_id, c->getName().c_str());
385                         c->showSetting(s);
386                         return &s;
387                     }
388                 } catch (...) {
389                     debugWarning("Bogus format\n");
390                 }
391             }
392         } catch (...) {
393             debugOutput(DEBUG_LEVEL_VERBOSE, "  %s has no device definitions\n", c->getName().c_str());
394         }
395     }
396     return NULL;
397 }
398
399
400
401 Configuration::VendorModelEntry
402 Configuration::findDeviceVME( unsigned int vendor_id, unsigned model_id )
403 {
404
405     // FIXME: clean this pointer/reference mess please
406     Setting *ps = getDeviceSetting(vendor_id, model_id);
407
408     if(ps) {
409         Setting &s = *ps;
410         try {
411             Setting &vendorid = s["vendorid"];
412             Setting &modelid = s["modelid"];
413             uint32_t vid = vendorid;
414             uint32_t mid = modelid;
415             if (vendor_id == vid && model_id == mid) {
416                 struct VendorModelEntry vme;
417                 vme.vendor_id = vendorid;
418                 vme.model_id = modelid;
419
420                 const char *tmp = s["vendorname"];
421                 vme.vendor_name = tmp;
422                 tmp = s["modelname"];
423                 vme.model_name = tmp;
424                 vme.driver = s["driver"];
425                 return vme;
426             } else {
427                 debugError("BUG: vendor/model found but not found?\n");
428             }
429         } catch (...) {
430             debugWarning("Bogus format\n");
431         }
432     }
433     struct VendorModelEntry invalid;
434     return invalid;
435 }
436
437 bool
438 Configuration::isDeviceVMEPresent( unsigned int vendor_id, unsigned model_id )
439 {
440     return isValid(findDeviceVME( vendor_id, model_id ));
441 }
442
443 bool
444 Configuration::isValid( const Configuration::VendorModelEntry& vme )
445 {
446     struct VendorModelEntry invalid;
447     return !(vme==invalid);
448 }
449
450 void
451 Configuration::ConfigFile::show()
452 {
453     debugOutput(DEBUG_LEVEL_NORMAL, " config file: %s\n", getName().c_str());
454     Setting &root = getRoot();
455     if(root.getLength()) {
456         showSetting(root, "");
457     } else {
458         debugOutput(DEBUG_LEVEL_NORMAL, "  Empty\n");
459     }
460 }
461
462 void
463 Configuration::show()
464 {
465     debugOutput(DEBUG_LEVEL_NORMAL, "Configuration:\n");
466     for (unsigned int idx = 0; idx < m_ConfigFiles.size(); idx++) {
467         ConfigFile *c = m_ConfigFiles.at(idx);
468         c->show();
469     }
470 }
471
472 int
473 Configuration::findFileName(std::string s) {
474     int i=0;
475     for ( std::vector<ConfigFile *>::iterator it = m_ConfigFiles.begin();
476       it != m_ConfigFiles.end();
477       ++it )
478     {
479         if((*it)->getName() == s) {
480             return i;
481         }
482         i++;
483     }
484     return -1;
485 }
486
487 void
488 Configuration::ConfigFile::readFile()
489 {
490     std::string filename = m_name;
491     // fix up the '~' as homedir
492     std::string::size_type pos = filename.find_first_of("~");
493     if(pos != std::string::npos) {
494         char *homedir = getenv("HOME");
495         if(homedir) {
496             std::string home = homedir;
497             filename.replace( pos, 1, home, 0, home.length());
498         }
499     }
500     Config::readFile(filename.c_str());
501 }
502
503 void
504 Configuration::ConfigFile::writeFile()
505 {
506     std::string filename = m_name;
507     // fix up the '~' as homedir
508     std::string::size_type pos = filename.find_first_of("~");
509     if(pos != std::string::npos) {
510         char *homedir = getenv("HOME");
511         if(homedir) {
512             std::string home = homedir;
513             filename.replace( pos, 1, home, 0, home.length());
514         }
515     }
516     Config::writeFile(filename.c_str());
517 }
518
519 Configuration::VendorModelEntry::VendorModelEntry()
520     : vendor_id( 0 )
521     , model_id( 0 )
522     , driver( 0 )
523 {
524 }
525
526 Configuration::VendorModelEntry::VendorModelEntry( const VendorModelEntry& rhs )
527     : vendor_id( rhs.vendor_id )
528     , model_id( rhs.model_id )
529     , vendor_name( rhs.vendor_name )
530     , model_name( rhs.model_name )
531     , driver( rhs.driver )
532 {
533 }
534
535 Configuration::VendorModelEntry&
536 Configuration::VendorModelEntry::operator = ( const VendorModelEntry& rhs )
537 {
538     // check for assignment to self
539     if ( this == &rhs ) return *this;
540
541     vendor_id   = rhs.vendor_id;
542     model_id    = rhs.model_id;
543     vendor_name = rhs.vendor_name;
544     model_name  = rhs.model_name;
545     driver      = rhs.driver;
546
547     return *this;
548 }
549
550 bool
551 Configuration::VendorModelEntry::operator == ( const VendorModelEntry& rhs ) const
552 {
553     bool equal=true;
554
555     equal &= (vendor_id   == rhs.vendor_id);
556     equal &= (model_id    == rhs.model_id);
557     equal &= (vendor_name == rhs.vendor_name);
558     equal &= (model_name  == rhs.model_name);
559     equal &= (driver      == rhs.driver);
560
561     return equal;
562 }
563
564 Configuration::VendorModelEntry::~VendorModelEntry()
565 {
566 }
567
568 } // namespace Util
Note: See TracBrowser for help on using the browser.