root/branches/libffado-2.0/support/dbus/ffado-dbus-server.cpp

Revision 1196, 9.6 kB (checked in by wagi, 16 years ago)

set cache enable as default

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