root/branches/streaming-rework/tests/test-freebob.cpp

Revision 437, 15.8 kB (checked in by pieterpalmers, 16 years ago)

- made test-freebob use debugmodule infrastructure
- test-mixer now takes a port argument

Line 
1 /* test-freebob.c
2  * Copyright (C) 2005 by Daniel Wagner
3  * Copyright (C) 2007 by Pieter Palmers
4  *
5  * This file is part of FreeBoB.
6  *
7  * FreeBoB is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  * FreeBoB is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with FreeBoB; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19  * MA 02111-1307 USA.
20  */
21
22 /*
23  * This version uses the CPP API
24  */
25
26 #include <config.h>
27
28 #include "libfreebob/freebob.h"
29
30 #include "debugmodule/debugmodule.h"
31 #include "fbtypes.h"
32 #include "devicemanager.h"
33 #include "iavdevice.h"
34
35 #include <signal.h>
36
37 #include <argp.h>
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <string.h>
41
42 #include <vector>
43 #include <string>
44 #include <iostream>
45 #include <sstream>
46
47 #include <lo/lo.h>
48
49 using namespace std;
50
51 DECLARE_GLOBAL_DEBUG_MODULE;
52
53 // prototypes & stuff for listing the OSC space
54 void list_osc_paths(lo_server s, lo_address t, const char *path);
55 void list_osc_params(lo_server s, lo_address t, const char *path);
56 string osc_param_get_value(lo_server s, lo_address t, const char *path, const char *param);
57
58 vector<string> osc_paths;
59 vector<string> osc_params;
60 string osc_value;
61
62 int osc_path_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
63     void *data, void *user_data);
64    
65 int osc_param_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
66     void *data, void *user_data);
67    
68 int osc_data_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
69     void *data, void *user_data);
70    
71 void osc_error_handler(int num, const char *msg, const char *path);
72
73 // signal handler
74 int run=1;
75 static void sighandler (int sig)
76 {
77     run = 0;
78 }
79
80 // global's
81 const char *argp_program_version = PACKAGE_STRING;
82 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
83
84 // Program documentation.
85 static char doc[] = "FreeBoB -- a driver for Firewire Audio devices (test application)\n\n"
86                     "OPERATION: Discover\n"
87                     "           SetSamplerate\n"
88                     "           ListOscSpace\n"
89                     "           OscServer\n";
90
91 // A description of the arguments we accept.
92 static char args_doc[] = "OPERATION";
93
94 struct arguments
95 {
96     short silent;
97     short verbose;
98     int   port;
99     int   node_id;
100     int   node_id_set;
101     char* args[2]; 
102 };
103
104 // The options we understand.
105 static struct argp_option options[] = {
106     {"quiet",    'q',       0,    0,  "Don't produce any output" },
107     {"silent",   's',       0,    OPTION_ALIAS },
108
109     {"verbose",  'v', "level",    0,  "Produce verbose output" },
110
111
112     {"node",     'n',    "id",    0,  "Node to use" },
113     {"port",     'p',    "nr",    0,  "IEEE1394 Port to use" },
114     { 0 }
115 };
116
117 //-------------------------------------------------------------
118
119 // Parse a single option.
120 static error_t
121 parse_opt( int key, char* arg, struct argp_state* state )
122 {
123     // Get the input argument from `argp_parse', which we
124     // know is a pointer to our arguments structure.
125     struct arguments* arguments = ( struct arguments* ) state->input;
126     char* tail;
127
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 'p':
142         if (arg) {
143             arguments->port = strtol( arg, &tail, 0 );
144             if ( errno ) {
145                 debugError(  "Could not parse 'port' argument\n" );
146                 return ARGP_ERR_UNKNOWN;
147             }
148         } else {
149             if ( errno ) {
150                 debugError( "Could not parse 'port' argumen\n" );
151                 return ARGP_ERR_UNKNOWN;
152             }
153         }
154         break;
155     case 'n':
156         if (arg) {
157             arguments->node_id = strtol( arg, &tail, 0 );
158             if ( errno ) {
159                 debugError(  "Could not parse 'node' argument\n" );
160                 return ARGP_ERR_UNKNOWN;
161             }
162             arguments->node_id_set=1;
163         } else {
164             if ( errno ) {
165                 debugError( "Could not parse 'node' argumen\n" );
166                 return ARGP_ERR_UNKNOWN;
167             }
168         }
169         break;
170     case ARGP_KEY_ARG:
171         if (state->arg_num >= 2) {
172             // Too many arguments.
173             argp_usage( state );
174         }
175         arguments->args[state->arg_num] = arg;
176         break;
177     case ARGP_KEY_END:
178         if (state->arg_num < 1) {
179         // Not enough arguments.
180         argp_usage( state );
181         }
182         break;
183     default:
184         return ARGP_ERR_UNKNOWN;
185     }
186     return 0;
187 }
188
189 // Our argp parser.
190 static struct argp argp = { options, parse_opt, args_doc, doc };
191
192 int
193 main( int argc, char **argv )
194 {
195     struct arguments arguments;
196
197     // Default values.
198     arguments.silent      = 0;
199     arguments.verbose     = DEBUG_LEVEL_NORMAL;
200     arguments.port        = 0;
201     arguments.node_id     = 0;
202     arguments.node_id_set = 0; // if we don't specify a node, discover all
203     arguments.args[0]     = "";
204     arguments.args[1]     = "";
205
206     // Parse our arguments; every option seen by `parse_opt' will
207     // be reflected in `arguments'.
208     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
209         debugError( "Could not parse command line\n" );
210         return -1;
211     }
212
213     setDebugLevel(arguments.verbose);
214
215     debugOutput(DEBUG_LEVEL_NORMAL, "verbose level = %d\n", arguments.verbose);
216
217     debugOutput(DEBUG_LEVEL_NORMAL,  "Using freebob library version: %s\n\n", freebob_get_version() );
218    
219     if ( strcmp( arguments.args[0], "Discover" ) == 0 ) {
220         DeviceManager *m_deviceManager = new DeviceManager();
221         if ( !m_deviceManager ) {
222             debugError( "Could not allocate device manager\n" );
223             return -1;
224         }
225         if ( !m_deviceManager->initialize( arguments.port ) ) {
226             debugError( "Could not initialize device manager\n" );
227             delete m_deviceManager;
228             return -1;
229         }
230
231         m_deviceManager->setVerboseLevel(arguments.verbose);
232         if ( !m_deviceManager->discover() ) {
233             debugError( "Could not discover devices\n" );
234             delete m_deviceManager;
235             return -1;
236         }
237        
238         int devices_on_bus = m_deviceManager->getNbDevices();
239         debugOutput(DEBUG_LEVEL_NORMAL, "port = %d, devices_on_bus = %d\n", arguments.port, devices_on_bus);
240        
241         for(int i=0;i<devices_on_bus;i++) {
242             int node_id=m_deviceManager->getDeviceNodeId(i);
243             debugOutput(DEBUG_LEVEL_NORMAL, " device = %d, node = %d\n", i, node_id);
244             IAvDevice* avDevice = m_deviceManager->getAvDevice( node_id );
245             if ( avDevice ) {
246                 avDevice->showDevice();
247             }
248         }
249        
250         delete m_deviceManager;
251         return 0;
252     } else if ( strcmp( arguments.args[0], "SetSamplerate" ) == 0 ) {
253         char* tail;
254         int samplerate = strtol( arguments.args[1], &tail, 0 );
255         if ( errno ) {
256             debugError(  "Could not parse samplerate argument\n" );
257             return -1;
258         }
259        
260         DeviceManager *m_deviceManager = new DeviceManager();
261         if ( !m_deviceManager ) {
262             debugError( "Could not allocate device manager\n" );
263             return -1;
264         }
265         if ( !m_deviceManager->initialize( arguments.port ) ) {
266             debugError( "Could not initialize device manager\n" );
267             delete m_deviceManager;
268             return -1;
269         }
270        
271         m_deviceManager->setVerboseLevel(arguments.verbose);
272         if ( !m_deviceManager->discover() ) {
273             debugError( "Could not discover devices\n" );
274             delete m_deviceManager;
275             return -1;
276         }
277    
278         if(arguments.node_id_set) {
279             IAvDevice* avDevice = m_deviceManager->getAvDevice( arguments.node_id );
280             if ( avDevice ) {
281                 if ( avDevice->setSampleRate( parseSampleRate( samplerate ) ) ) {
282                     m_deviceManager->discover();
283                 } else {
284                     debugError( "Could not set samplerate\n" );
285                 }
286             }
287         } else {
288             int i=0;
289                
290             int devices_on_bus = m_deviceManager->getNbDevices();
291             debugOutput(DEBUG_LEVEL_NORMAL, "  port = %d, devices_on_bus = %d\n", arguments.port, devices_on_bus);
292    
293             for(i=0;i<devices_on_bus;i++) {
294                 int node_id=m_deviceManager->getDeviceNodeId(i);
295                 debugOutput(DEBUG_LEVEL_NORMAL, "  set samplerate for device = %d, node = %d\n", i, node_id);
296                 IAvDevice* avDevice = m_deviceManager->getAvDevice( node_id );
297                 if ( avDevice ) {
298                     if ( !avDevice->setSampleRate( parseSampleRate( samplerate ) ) ) {
299                         debugError( "Could not set samplerate\n" );
300                     }
301                 }
302             }
303         }
304         delete m_deviceManager;
305         return 0;
306     } else if ( strcmp( arguments.args[0], "ListOscSpace" ) == 0 ) {
307         // list osc space by using OSC messages
308         // a server is assumed to be present
309        
310         /* start a new server.
311         when sending a message from this context, the response
312         address will be set to this server's address.
313         */
314         lo_server s = lo_server_new(NULL, osc_error_handler);
315         lo_address t = lo_address_new(NULL, "17820");
316        
317         list_osc_paths(s, t, "/");
318        
319         lo_address_free(t);
320         lo_server_free(s);
321        
322     } else if ( strcmp( arguments.args[0], "OscServer" ) == 0 ) {
323         DeviceManager *m_deviceManager = new DeviceManager();
324         if ( !m_deviceManager ) {
325             debugError( "Could not allocate device manager\n" );
326             return -1;
327         }
328         if ( !m_deviceManager->initialize( arguments.port ) ) {
329             debugError( "Could not initialize device manager\n" );
330             delete m_deviceManager;
331             return -1;
332         }
333        
334         m_deviceManager->setVerboseLevel(arguments.verbose);
335         if ( !m_deviceManager->discover() ) {
336             debugError( "Could not discover devices\n" );
337             delete m_deviceManager;
338             return -1;
339         }
340
341         debugOutput(DEBUG_LEVEL_NORMAL, "server started\n");
342         debugOutput(DEBUG_LEVEL_NORMAL, "press ctrl-c to stop it & continue\n");
343        
344         signal (SIGINT, sighandler);
345        
346         run=1;
347         while(run) {
348             sleep(1);
349             fflush(stdout);
350             fflush(stderr);
351         }
352         signal (SIGINT, SIG_DFL);
353        
354         debugOutput(DEBUG_LEVEL_NORMAL, "server stopped\n");
355         delete m_deviceManager;
356         return 0;
357        
358     } else {
359         debugOutput(DEBUG_LEVEL_NORMAL,  "unknown operation\n" );
360     }
361
362 }
363
364 void list_osc_paths(lo_server s, lo_address t, const char *path) {
365     vector<string> my_paths;
366    
367     debugOutput(DEBUG_LEVEL_NORMAL, "listing path: %s\n", path);
368    
369     osc_paths.clear();
370     lo_server_add_method(s, "/response", NULL, osc_path_response_handler, NULL);
371
372     if (lo_send(t, path, "s", "list") == -1) {
373         debugOutput(DEBUG_LEVEL_NORMAL, " OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));
374     }
375
376     if (lo_server_recv_noblock(s, 1000) == 0) {
377         debugOutput(DEBUG_LEVEL_NORMAL, "timeout\n");
378         return;
379     }
380    
381     lo_server_del_method(s, "/response", NULL);
382    
383     list_osc_params(s, t, path);
384    
385     my_paths=osc_paths;
386     for ( vector<string>::iterator it = my_paths.begin();
387             it != my_paths.end();
388             ++it )
389     {
390         string new_path=string(path) + *it;
391         new_path += string("/");
392         list_osc_paths(s, t, new_path.c_str());
393     }
394
395 }
396
397 void list_osc_params(lo_server s, lo_address t, const char *path) {
398     vector<string> my_paths;
399     debugOutput(DEBUG_LEVEL_NORMAL, "params for: %s\n", path);
400    
401     osc_params.clear();
402     lo_server_add_method(s, "/response", NULL, osc_param_response_handler, NULL);
403
404     if (lo_send(t, path, "s", "params") == -1) {
405         debugOutput(DEBUG_LEVEL_NORMAL, " OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));
406     }
407    
408     if (lo_server_recv_noblock(s, 1000) == 0) {
409         debugOutput(DEBUG_LEVEL_NORMAL, "timeout\n");
410         return;
411     }
412    
413     lo_server_del_method(s, "/response", NULL);
414    
415     vector<string> my_params=osc_params;
416    
417     for ( vector<string>::iterator it = my_params.begin();
418             it != my_params.end();
419             ++it )
420     {
421         string value=osc_param_get_value(s, t, path, (*it).c_str());
422         debugOutput(DEBUG_LEVEL_NORMAL, "  %20s = %s\n", (*it).c_str(), value.c_str());
423     }
424
425 }
426
427 string osc_param_get_value(lo_server s, lo_address t, const char *path, const char *param) {
428     lo_server_add_method(s, "/response", NULL, osc_data_response_handler, NULL);
429
430     if (lo_send(t, path, "ss", "get", param) == -1) {
431         debugOutput(DEBUG_LEVEL_NORMAL, " OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));
432     }
433    
434     if (lo_server_recv_noblock(s, 1000) == 0) {
435         return string("timeout");
436     }
437    
438     lo_server_del_method(s, "/response", NULL);
439     return osc_value;
440 }
441
442 void osc_error_handler(int num, const char *msg, const char *path)
443 {
444     debugOutput(DEBUG_LEVEL_NORMAL, "liblo server error %d in path %s: %s\n", num, path, msg);
445 }
446
447 int osc_path_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
448         void *data, void *user_data)
449 {
450     for (int i=0; i< argc;i++) {
451         switch (lo_type(types[i])) {
452             /** Standard C, NULL terminated string. */
453             case LO_STRING:
454                 osc_paths.push_back(string(&(argv[i]->s)));
455                 break;
456             default:
457                 debugOutput(DEBUG_LEVEL_NORMAL, "unexpected data type in response message\n");
458         }
459     }
460     return 1;
461 }
462
463 int osc_param_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
464         void *data, void *user_data)
465 {
466     for (int i=0; i< argc;i++) {
467         switch (lo_type(types[i])) {
468             /** Standard C, NULL terminated string. */
469             case LO_STRING:
470                 osc_params.push_back(string(&(argv[i]->s)));
471                 break;
472             default:
473                 debugOutput(DEBUG_LEVEL_NORMAL, "unexpected data type in response message\n");
474         }
475     }
476     return 1;
477 }
478
479 int osc_data_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
480         void *data, void *user_data)
481 {
482     std::ostringstream str;
483    
484     if(argc==1) {
485         switch (lo_type(types[0])) {
486             /* basic OSC types */
487             /** 32 bit signed integer. */
488             case LO_INT32:
489                 str << "0x" << std::hex << argv[0]->i;
490                 osc_value=str.str();
491                 break;
492             case LO_INT64:
493                 str << "0x" << std::hex << argv[0]->h;
494                 osc_value=str.str();
495                 break;
496             /** 32 bit IEEE-754 float. */
497             case LO_FLOAT:
498                 str << argv[0]->f;
499                 osc_value=str.str();
500                 break;
501             /** Standard C, NULL terminated string. */
502             case LO_STRING:
503                 osc_value=string(&argv[0]->s);
504                 break;
505             default:
506                 osc_value="unsupported response datatype";
507         }
508     } else {
509         osc_value="invalid response";
510     }
511     return 1;
512 }
Note: See TracBrowser for help on using the browser.