root/trunk/libffado/src/genericavc/avc_vendormodel.cpp

Revision 607, 6.5 kB (checked in by ppalmers, 13 years ago)

- Fix file-based discovery. The previous code used a pointer to a

vendormodel entry. This pointer however pointed to a VendorModel?
object that was created on the stack of the discover function.
Hence the pointer becomes invalid when the discover function is
exited.

The changes incorporate using a VendorModelEntry? struct instead
of a pointer to it. So now the FFADODevice has it's own copy of
this struct, instead of a pointer to it.

Line 
1 /*
2  * Copyright (C) 2007 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 library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 #include "genericavc/avc_vendormodel.h"
25
26 #include <fstream>
27 #include <istream>
28 #include <iostream>
29 #include <iterator>
30 #include <cerrno>
31 #include <functional>
32 #include <algorithm>
33
34 using namespace std;
35
36 static void
37 tokenize(const string& str,
38          vector<string>& tokens,
39          const string& delimiters = " ")
40 {
41     // Skip delimiters at beginning.
42     string::size_type lastPos = str.find_first_not_of(delimiters, 0);
43     // Find first "non-delimiter".
44     string::size_type pos     = str.find_first_of(delimiters, lastPos);
45
46     while (string::npos != pos || string::npos != lastPos)
47     {
48         // Found a token, add it to the vector.
49         tokens.push_back(str.substr(lastPos, pos - lastPos));
50         // Skip delimiters.  Note the "not_of"
51         lastPos = str.find_first_not_of(delimiters, pos);
52         // Find next "non-delimiter"
53         pos = str.find_first_of(delimiters, lastPos);
54     }
55 }
56
57 //-------------------------------------------------
58
59 GenericAVC::VendorModelEntry::VendorModelEntry()
60     : vendor_id( 0 )
61     , model_id( 0 )
62 {
63 }
64
65 GenericAVC::VendorModelEntry::VendorModelEntry( const VendorModelEntry& rhs )
66     : vendor_id( rhs.vendor_id )
67     , model_id( rhs.model_id )
68     , vendor_name( rhs.vendor_name )
69     , model_name( rhs.model_name )
70 {
71 }
72
73 GenericAVC::VendorModelEntry&
74 GenericAVC::VendorModelEntry::operator = ( const VendorModelEntry& rhs )
75 {
76     // check for assignment to self
77     if ( this == &rhs ) return *this;
78
79     vendor_id   = rhs.vendor_id;
80     model_id    = rhs.model_id;
81     vendor_name = rhs.vendor_name;
82     model_name  = rhs.model_name;
83
84     return *this;
85 }
86
87 bool
88 GenericAVC::VendorModelEntry::operator == ( const VendorModelEntry& rhs ) const
89 {
90     bool equal=true;
91    
92     equal &= (vendor_id   == rhs.vendor_id);
93     equal &= (model_id    == rhs.model_id);
94     equal &= (vendor_name == rhs.vendor_name);
95     equal &= (model_name  == rhs.model_name);
96
97     return equal;
98 }
99
100 GenericAVC::VendorModelEntry::~VendorModelEntry()
101 {
102 }
103
104 GenericAVC::VendorModel::VendorModel( const char* filename )
105     : m_filename( filename )
106 {
107 }
108
109 GenericAVC::VendorModel::~VendorModel()
110 {
111 }
112
113
114 bool
115 GenericAVC::VendorModel::parse()
116 {
117     ifstream in ( m_filename.c_str() );
118
119     if ( !in ) {
120         perror( m_filename.c_str() );
121         return false;
122     }
123
124     string line;
125     while ( !getline( in,  line ).eof() ) {
126         string::size_type i = line.find_first_not_of( " \t\n\v" );
127         if ( i != string::npos && line[i] == '#' )
128             // this line starts with a '#' -> comment
129             continue;
130
131         vector<string> tokens;
132         tokenize( line, tokens, "," );
133
134         if ( tokens.size() < 4 )
135             // ignore this line, it has not all needed mandatory entries
136             continue;
137
138         VendorModelEntry vme;
139         vector<string>::const_iterator it = tokens.begin();
140         char* tail;
141
142         errno = 0;
143         vme.vendor_id   = strtol( it++->c_str(), &tail, 0 );
144         vme.model_id    = strtol( it++->c_str(), &tail, 0 );
145         vme.vendor_name = *it++;
146         vme.model_name  = *it++;
147
148         if ( errno )
149             // string -> int conversion failed
150             continue;
151
152         vector<string>::const_iterator end = tokens.end();
153         if ( it != end )
154             handleAdditionalEntries( vme, tokens, it, end );
155
156         m_vendorModelEntries.push_back( vme );
157     }
158
159     if ( !in.eof() ) {
160         cerr << "GenericAVC::VendorModel::VendorModel: error in parsing" << endl;
161         return false;
162     }
163
164     return true;
165 }
166
167 bool
168 GenericAVC::VendorModel::printTable() const
169 {
170     // Some debug output
171     cout << "vendorId\t\tmodelId\t\tvendorName\t\t\t\tmodelName" << endl;
172     for ( VendorModelEntryVector::const_iterator it = m_vendorModelEntries.begin();
173           it != m_vendorModelEntries.end();
174           ++it )
175     {
176         cout << it->vendor_id << "\t\t\t"
177              << it->model_id << "\t"
178              << it->vendor_name << "\t"
179              << it->model_name << endl;
180     }
181     return true;
182 }
183
184 bool
185 GenericAVC::VendorModel::handleAdditionalEntries(VendorModelEntry& vme,
186                                                  vector<string>& v,
187                                                  vector<string>::const_iterator& b,
188                                                  vector<string>::const_iterator& e )
189 {
190     return true;
191 }
192
193 class is_same : public unary_function<GenericAVC::VendorModelEntry, bool> {
194 public:
195     is_same( unsigned int vendor_id, unsigned model_id )
196         : m_vendor_id( vendor_id )
197         , m_model_id( model_id )
198     {}
199
200     bool operator () ( const GenericAVC::VendorModelEntry& vme ) const {
201         return vme.vendor_id == m_vendor_id && vme.model_id == m_model_id;
202     }
203
204 private:
205     unsigned int m_vendor_id;
206     unsigned int m_model_id;
207 };
208
209 GenericAVC::VendorModelEntry
210 GenericAVC::VendorModel::find( unsigned int vendor_id, unsigned model_id )
211 {
212     VendorModelEntryVector::iterator it =
213         find_if ( m_vendorModelEntries.begin(),
214                   m_vendorModelEntries.end(),
215                   is_same( vendor_id, model_id ) );
216     if ( it != m_vendorModelEntries.end() )
217         return *it;
218        
219     struct VendorModelEntry invalid;
220     return invalid;
221 }
222
223 bool
224 GenericAVC::VendorModel::isPresent( unsigned int vendor_id, unsigned model_id )
225 {
226     VendorModelEntryVector::iterator it =
227         find_if ( m_vendorModelEntries.begin(),
228                   m_vendorModelEntries.end(),
229                   is_same( vendor_id, model_id ) );
230     if ( it != m_vendorModelEntries.end() )
231         return true;
232
233     return false;
234 }
235
236 bool
237 GenericAVC::VendorModel::isValid( const GenericAVC::VendorModelEntry& vme )
238 {
239     struct VendorModelEntry invalid;
240     return !(vme==invalid);
241 }
242
243 const GenericAVC::VendorModelEntryVector&
244 GenericAVC::VendorModel::getVendorModelEntries() const
245 {
246     return m_vendorModelEntries;
247 }
Note: See TracBrowser for help on using the browser.