root/trunk/libffado/support/dbus/ffado-dbus-server.cpp

Revision 1336, 9.6 kB (checked in by ppalmers, 16 years ago)

Bring trunk up to date with branches/libffado-2.0:

"""
svn merge -r 1254:1299 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1301:1320 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1322:1323 svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
svn merge -r 1329:HEAD svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0
"""

Add getSupportedSamplingFrequencies() to DICE, RME and Metric Halo AvDevices?

Line 
1 /*
2  * Copyright (C) 2005-2008 by Daniel Wagner
3  * Copyright (C) 2005-2008 by Pieter Palmers
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 /*
26  * This version uses the CPP API
27  */
28
29 #include "version.h"
30
31 #include <semaphore.h>
32
33 #include "libffado/ffado.h"
34
35 #include "debugmodule/debugmodule.h"
36 #include "fbtypes.h"
37 #include "devicemanager.h"
38 #include "ffadodevice.h"
39
40 #include <dbus-c++/dbus.h>
41 #include "controlserver.h"
42 #include "libcontrol/BasicElements.h"
43
44 #include "libutil/Functors.h"
45
46 #include <signal.h>
47
48 #include <argp.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52
53 #include <vector>
54 #include <string>
55 #include <iostream>
56 #include <sstream>
57
58 using namespace std;
59
60 DECLARE_GLOBAL_DEBUG_MODULE;
61
62 // DBUS stuff
63 DBus::BusDispatcher dispatcher;
64 DBusControl::Container *container = NULL;
65 DBus::Connection * global_conn;
66 DeviceManager *m_deviceManager = NULL;
67
68 // signal handler
69 int run=1;
70 sem_t run_sem;
71
72 static void sighandler (int sig)
73 {
74     run = 0;
75     dispatcher.leave();
76     sem_post(&run_sem);
77 }
78
79 // global's
80 const char *argp_program_version = PACKAGE_STRING;
81 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
82
83 // Program documentation.
84 static char doc[] = "ffado-dbus-server -- expose the mixer features of connected FFADO devices through DBus\n\n"
85                     ;
86
87 // A description of the arguments we accept.
88 static char args_doc[] = "";
89
90 struct arguments
91 {
92     short silent;
93     short verbose;
94     int   use_cache;
95     int   port;
96     int   node_id;
97     int   node_id_set;
98     const char* args[2];
99 };
100
101 // The options we understand.
102 static struct argp_option options[] = {
103     {"quiet",    'q',       0,    0,  "Don't produce any output" },
104     {"silent",   's',       0,    OPTION_ALIAS },
105
106     {"verbose",  'v', "level",    0,  "Produce verbose output" },
107 #if ENABLE_DISCOVERY_CACHE
108     {"cache",    'c', "enable",   0,  "Use AVC model cache" },
109 #endif
110
111     {"node",     'n',    "id",    0,  "Only expose mixer of a device on a specific node" },
112     {"port",     'p',    "nr",    0,  "IEEE1394 Port to use" },
113     { 0 }
114 };
115
116 //-------------------------------------------------------------
117
118 // Parse a single option.
119 static error_t
120 parse_opt( int key, char* arg, struct argp_state* state )
121 {
122     // Get the input argument from `argp_parse', which we
123     // know is a pointer to our arguments structure.
124     struct arguments* arguments = ( struct arguments* ) state->input;
125     char* tail;
126
127     errno = 0;
128     switch (key) {
129     case 'q': case 's':
130         arguments->silent = 1;
131         break;
132     case 'v':
133         if (arg) {
134             arguments->verbose = strtol( arg, &tail, 0 );
135             if ( errno ) {
136                 debugError( "Could not parse 'verbose' argument\n" );
137                 return ARGP_ERR_UNKNOWN;
138             }
139         }
140         break;
141     case 'c':
142         if (arg) {
143             arguments->use_cache = strtol( arg, &tail, 0 );
144             if ( errno ) {
145                 fprintf( stderr,  "Could not parse 'cache' argument\n" );
146                 return ARGP_ERR_UNKNOWN;
147             }
148         }
149         break;
150     case 'p':
151         if (arg) {
152             arguments->port = strtol( arg, &tail, 0 );
153             if ( errno ) {
154                 debugError( "Could not parse 'port' argument\n" );
155                 return ARGP_ERR_UNKNOWN;
156             }
157         } else {
158             if ( errno ) {
159                 debugError("Could not parse 'port' argumen\n" );
160                 return ARGP_ERR_UNKNOWN;
161             }
162         }
163         break;
164     case 'n':
165         if (arg) {
166             arguments->node_id = strtol( arg, &tail, 0 );
167             if ( errno ) {
168                 debugError( "Could not parse 'node' argument\n" );
169                 return ARGP_ERR_UNKNOWN;
170             }
171             arguments->node_id_set=1;
172         } else {
173             if ( errno ) {
174                 debugError("Could not parse 'node' argumen\n" );
175                 return ARGP_ERR_UNKNOWN;
176             }
177         }
178         break;
179     case ARGP_KEY_ARG:
180         if (state->arg_num >= 1) {
181             // Too many arguments.
182             argp_usage( state );
183         }
184         arguments->args[state->arg_num] = arg;
185         break;
186     case ARGP_KEY_END:
187         if (state->arg_num < 0) {
188         // Not enough arguments.
189         argp_usage( state );
190         }
191         break;
192     default:
193         return ARGP_ERR_UNKNOWN;
194     }
195     return 0;
196 }
197
198 // Our argp parser.
199 static struct argp argp = { options, parse_opt, args_doc, doc };
200
201 int exitfunction( int retval ) {
202     debugOutput( DEBUG_LEVEL_NORMAL, "Debug output flushed...\n" );
203     flushDebugOutput();
204     return retval;
205 }
206
207 void
208 preUpdateHandler()
209 {
210     debugOutput( DEBUG_LEVEL_NORMAL, "got pre-update notification...\n" );
211     // stop receiving dbus events since the control structure is going to
212     // be changed
213     dispatcher.leave();
214 }
215
216 void
217 postUpdateHandler()
218 {
219     debugOutput( DEBUG_LEVEL_NORMAL, "got post-update notification...\n" );
220     // the signal handlers registered by the elements should have taken
221     // care of updating the control tree
222
223     // signal that we can start receiving dbus events again
224     sem_post(&run_sem);
225 }
226
227 int
228 main( int argc, char **argv )
229 {
230     struct arguments arguments;
231
232     // Default values.
233     arguments.silent      = 0;
234     arguments.verbose     = DEBUG_LEVEL_NORMAL;
235     arguments.use_cache   = 1;
236     arguments.port        = 0;
237     arguments.node_id     = 0;
238     arguments.node_id_set = 0; // if we don't specify a node, discover all
239     arguments.args[0]     = "";
240     arguments.args[1]     = "";
241
242     setDebugLevel(arguments.verbose);
243
244     // Parse our arguments; every option seen by `parse_opt' will
245     // be reflected in `arguments'.
246     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
247         debugError("Could not parse command line\n" );
248         return exitfunction(-1);
249     }
250
251     debugOutput( DEBUG_LEVEL_NORMAL, "verbose level = %d\n", arguments.verbose);
252     debugOutput( DEBUG_LEVEL_NORMAL, "Using ffado library version: %s\n\n", ffado_get_version() );
253
254     m_deviceManager = new DeviceManager();
255     if ( !m_deviceManager ) {
256         debugError("Could not allocate device manager\n" );
257         return exitfunction(-1);
258     }
259     if ( !m_deviceManager->initialize() ) {
260         debugError("Could not initialize device manager\n" );
261         delete m_deviceManager;
262         return exitfunction(-1);
263     }
264     if ( arguments.verbose ) {
265         m_deviceManager->setVerboseLevel(arguments.verbose);
266     }
267     if ( !m_deviceManager->discover(arguments.use_cache) ) {
268         debugError("Could not discover devices\n" );
269         delete m_deviceManager;
270         return exitfunction(-1);
271     }
272
273     // add pre-update handler
274     Util::Functor* preupdate_functor = new Util::CallbackFunctor0< void (*)() >
275                 ( &preUpdateHandler, false );
276     if ( !preupdate_functor ) {
277         debugFatal( "Could not create pre-update handler\n" );
278         return false;
279     }
280     if(!m_deviceManager->registerPreUpdateNotification(preupdate_functor)) {
281         debugError("could not register pre-update notifier");
282     }
283     // add post-update handler
284     Util::Functor* postupdate_functor = new Util::CallbackFunctor0< void (*)() >
285                 ( &postUpdateHandler, false );
286     if ( !postupdate_functor ) {
287         debugFatal( "Could not create post-update handler\n" );
288         return false;
289     }
290     if(!m_deviceManager->registerPostUpdateNotification(postupdate_functor)) {
291         debugError("could not register post-update notifier");
292     }
293
294     signal (SIGINT, sighandler);
295    
296     DBus::_init_threading();
297
298     // test DBUS stuff
299     DBus::default_dispatcher = &dispatcher;
300     DBus::Connection conn = DBus::Connection::SessionBus();
301     global_conn = &conn;
302     conn.request_name("org.ffado.Control");
303
304     // lock the control tree such that it does not get modified while we build our view
305     m_deviceManager->lockControl();
306     container = new DBusControl::Container(conn, "/org/ffado/Control/DeviceManager",
307                                             NULL, *m_deviceManager);
308     // unlock the control tree since the tree is built
309     m_deviceManager->unlockControl();
310
311     printMessage("DBUS test service running\n");
312     printMessage("press ctrl-c to stop it & exit\n");
313    
314     while(run) {
315         debugOutput( DEBUG_LEVEL_NORMAL, "dispatching...\n");
316         dispatcher.enter();
317         debugOutput( DEBUG_LEVEL_NORMAL, " dispatcher exited...\n");
318         sem_wait(&run_sem);
319         debugOutput( DEBUG_LEVEL_NORMAL, " activity handled...\n");
320     }
321    
322     if(!m_deviceManager->unregisterPreUpdateNotification(preupdate_functor)) {
323         debugError("could not unregister pre update notifier");
324     }
325     delete preupdate_functor;
326     if(!m_deviceManager->unregisterPostUpdateNotification(postupdate_functor)) {
327         debugError("could not unregister post update notifier");
328     }
329     delete postupdate_functor;
330     delete container;
331
332     signal (SIGINT, SIG_DFL);
333
334     printMessage("server stopped\n");
335     delete m_deviceManager;
336     return exitfunction(0);
337 }
Note: See TracBrowser for help on using the browser.