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

Revision 1498, 13.5 kB (checked in by ppalmers, 15 years ago)

Merge all changes from 2.0 branch into trunk (since r1361). This _should_ contain all forward merges done in the mean time. At this moment in time both branches should be in sync.

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                 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not parse file: %s\n", filename.c_str());
67                 delete c;
68                 return false;
69             } catch (...) {
70                 debugOutput(DEBUG_LEVEL_VERBOSE, "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 libconfig::Setting *
273 Configuration::getSetting( std::string path )
274 {
275     for ( std::vector<ConfigFile *>::iterator it = m_ConfigFiles.begin();
276       it != m_ConfigFiles.end();
277       ++it )
278     {
279         ConfigFile *c = *it;
280         try {
281             Setting &s = c->lookup(path);
282             return &s;
283         } catch (...) {
284             debugOutput(DEBUG_LEVEL_VERBOSE, "  %s has no setting %s\n",
285                         c->getName().c_str(), path.c_str());
286         }
287     }
288     return NULL;
289 }
290
291
292 Configuration::VendorModelEntry
293 Configuration::findDeviceVME( unsigned int vendor_id, unsigned model_id )
294 {
295     for ( std::vector<ConfigFile *>::iterator it = m_ConfigFiles.begin();
296       it != m_ConfigFiles.end();
297       ++it )
298     {
299         ConfigFile *c = *it;
300         try {
301             Setting &list = c->lookup("device_definitions");
302             unsigned int children = list.getLength();
303             for(unsigned int i = 0; i < children; i++) {
304                 Setting &s = list[i];
305                 try {
306                     Setting &vendorid = s["vendorid"];
307                     Setting &modelid = s["modelid"];
308                     uint32_t vid = vendorid;
309                     uint32_t mid = modelid;
310                     if (vendor_id == vid && model_id == mid) {
311                         struct VendorModelEntry vme;
312                         vme.vendor_id = vendorid;
313                         vme.model_id = modelid;
314
315                         const char *tmp = s["vendorname"];
316                         vme.vendor_name = tmp;
317                         tmp = s["modelname"];
318                         vme.model_name = tmp;
319                         vme.driver = s["driver"];
320                         debugOutput(DEBUG_LEVEL_VERBOSE,
321                                     "  device VME for %X:%x found in %s\n",
322                                     vendor_id, model_id, c->getName().c_str());
323                         c->showSetting(s);
324                         return vme;
325                     }
326                 } catch (...) {
327                     debugWarning("Bogus format\n");
328                 }
329             }
330         } catch (...) {
331             debugOutput(DEBUG_LEVEL_VERBOSE, "  %s has no device definitions\n", c->getName().c_str());
332         }
333     }
334     struct VendorModelEntry invalid;
335     return invalid;
336 }
337
338 bool
339 Configuration::isDeviceVMEPresent( unsigned int vendor_id, unsigned model_id )
340 {
341     return isValid(findDeviceVME( vendor_id, model_id ));
342 }
343
344 bool
345 Configuration::isValid( const Configuration::VendorModelEntry& vme )
346 {
347     struct VendorModelEntry invalid;
348     return !(vme==invalid);
349 }
350
351 void
352 Configuration::ConfigFile::show()
353 {
354     debugOutput(DEBUG_LEVEL_NORMAL, " config file: %s\n", getName().c_str());
355     Setting &root = getRoot();
356     if(root.getLength()) {
357         showSetting(root, "");
358     } else {
359         debugOutput(DEBUG_LEVEL_NORMAL, "  Empty\n");
360     }
361 }
362
363 void
364 Configuration::show()
365 {
366     debugOutput(DEBUG_LEVEL_NORMAL, "Configuration:\n");
367     for (unsigned int idx = 0; idx < m_ConfigFiles.size(); idx++) {
368         ConfigFile *c = m_ConfigFiles.at(idx);
369         c->show();
370     }
371 }
372
373 int
374 Configuration::findFileName(std::string s) {
375     int i=0;
376     for ( std::vector<ConfigFile *>::iterator it = m_ConfigFiles.begin();
377       it != m_ConfigFiles.end();
378       ++it )
379     {
380         if((*it)->getName() == s) {
381             return i;
382         }
383         i++;
384     }
385     return -1;
386 }
387
388 void
389 Configuration::ConfigFile::readFile()
390 {
391     std::string filename = m_name;
392     // fix up the '~' as homedir
393     std::string::size_type pos = filename.find_first_of("~");
394     if(pos != std::string::npos) {
395         char *homedir = getenv("HOME");
396         if(homedir) {
397             std::string home = homedir;
398             filename.replace( pos, 1, home, 0, home.length());
399         }
400     }
401     Config::readFile(filename.c_str());
402 }
403
404 void
405 Configuration::ConfigFile::writeFile()
406 {
407     std::string filename = m_name;
408     // fix up the '~' as homedir
409     std::string::size_type pos = filename.find_first_of("~");
410     if(pos != std::string::npos) {
411         char *homedir = getenv("HOME");
412         if(homedir) {
413             std::string home = homedir;
414             filename.replace( pos, 1, home, 0, home.length());
415         }
416     }
417     Config::writeFile(filename.c_str());
418 }
419
420 Configuration::VendorModelEntry::VendorModelEntry()
421     : vendor_id( 0 )
422     , model_id( 0 )
423     , driver( 0 )
424 {
425 }
426
427 Configuration::VendorModelEntry::VendorModelEntry( const VendorModelEntry& rhs )
428     : vendor_id( rhs.vendor_id )
429     , model_id( rhs.model_id )
430     , vendor_name( rhs.vendor_name )
431     , model_name( rhs.model_name )
432     , driver( rhs.driver )
433 {
434 }
435
436 Configuration::VendorModelEntry&
437 Configuration::VendorModelEntry::operator = ( const VendorModelEntry& rhs )
438 {
439     // check for assignment to self
440     if ( this == &rhs ) return *this;
441
442     vendor_id   = rhs.vendor_id;
443     model_id    = rhs.model_id;
444     vendor_name = rhs.vendor_name;
445     model_name  = rhs.model_name;
446     driver      = rhs.driver;
447
448     return *this;
449 }
450
451 bool
452 Configuration::VendorModelEntry::operator == ( const VendorModelEntry& rhs ) const
453 {
454     bool equal=true;
455
456     equal &= (vendor_id   == rhs.vendor_id);
457     equal &= (model_id    == rhs.model_id);
458     equal &= (vendor_name == rhs.vendor_name);
459     equal &= (model_name  == rhs.model_name);
460     equal &= (driver      == rhs.driver);
461
462     return equal;
463 }
464
465 Configuration::VendorModelEntry::~VendorModelEntry()
466 {
467 }
468
469 } // namespace Util
Note: See TracBrowser for help on using the browser.