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

Revision 436, 14.9 kB (checked in by pieterpalmers, 17 years ago)

- fixed verbose level setting
- debugged DICE code, works with EVM

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                 fprintf( stderr,  "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                 fprintf( stderr,  "Could not parse 'port' argument\n" );
146                 return ARGP_ERR_UNKNOWN;
147             }
148         } else {
149             if ( errno ) {
150                 fprintf( stderr, "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                 fprintf( stderr,  "Could not parse 'node' argument\n" );
160                 return ARGP_ERR_UNKNOWN;
161             }
162             arguments->node_id_set=1;
163         } else {
164             if ( errno ) {
165                 fprintf( stderr, "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     = 0;
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         fprintf( stderr, "Could not parse command line\n" );
210         return -1;
211     }
212
213     printf("verbose level = %d\n", arguments.verbose);
214
215     printf( "Using freebob library version: %s\n\n", freebob_get_version() );
216    
217     if ( strcmp( arguments.args[0], "Discover" ) == 0 ) {
218         DeviceManager *m_deviceManager = new DeviceManager();
219         if ( !m_deviceManager ) {
220             fprintf( stderr, "Could not allocate device manager\n" );
221             return -1;
222         }
223         if ( !m_deviceManager->initialize( arguments.port ) ) {
224             fprintf( stderr, "Could not initialize device manager\n" );
225             delete m_deviceManager;
226             return -1;
227         }
228         if ( arguments.verbose ) {
229             m_deviceManager->setVerboseLevel(arguments.verbose);
230         }
231         if ( !m_deviceManager->discover() ) {
232             fprintf( stderr, "Could not discover devices\n" );
233             delete m_deviceManager;
234             return -1;
235         }
236         delete m_deviceManager;
237         return 0;
238     } else if ( strcmp( arguments.args[0], "SetSamplerate" ) == 0 ) {
239         char* tail;
240         int samplerate = strtol( arguments.args[1], &tail, 0 );
241         if ( errno ) {
242             fprintf( stderr,  "Could not parse samplerate argument\n" );
243             return -1;
244         }
245        
246         DeviceManager *m_deviceManager = new DeviceManager();
247         if ( !m_deviceManager ) {
248             fprintf( stderr, "Could not allocate device manager\n" );
249             return -1;
250         }
251         if ( !m_deviceManager->initialize( arguments.port ) ) {
252             fprintf( stderr, "Could not initialize device manager\n" );
253             delete m_deviceManager;
254             return -1;
255         }
256         if ( arguments.verbose ) {
257             m_deviceManager->setVerboseLevel(arguments.verbose);
258         }
259         if ( !m_deviceManager->discover() ) {
260             fprintf( stderr, "Could not discover devices\n" );
261             delete m_deviceManager;
262             return -1;
263         }
264    
265         if(arguments.node_id_set) {
266             IAvDevice* avDevice = m_deviceManager->getAvDevice( arguments.node_id );
267             if ( avDevice ) {
268                 if ( avDevice->setSamplingFrequency( parseSampleRate( samplerate ) ) ) {
269                     m_deviceManager->discover();
270                 } else {
271                     fprintf( stderr, "Could not set samplerate\n" );
272                 }
273             }
274         } else {
275             int i=0;
276                
277             int devices_on_bus = m_deviceManager->getNbDevices();
278             printf("  port = %d, devices_on_bus = %d\n", arguments.port, devices_on_bus);
279    
280             for(i=0;i<devices_on_bus;i++) {
281                 int node_id=m_deviceManager->getDeviceNodeId(i);
282                 printf("  set samplerate for device = %d, node = %d\n", i, node_id);
283                 IAvDevice* avDevice = m_deviceManager->getAvDevice( node_id );
284                 if ( avDevice ) {
285                     if ( !avDevice->setSamplingFrequency( parseSampleRate( samplerate ) ) ) {
286                         fprintf( stderr, "Could not set samplerate\n" );
287                     }
288                 }
289             }
290         }
291         delete m_deviceManager;
292         return 0;
293     } else if ( strcmp( arguments.args[0], "ListOscSpace" ) == 0 ) {
294         // list osc space by using OSC messages
295         // a server is assumed to be present
296        
297         /* start a new server.
298         when sending a message from this context, the response
299         address will be set to this server's address.
300         */
301         lo_server s = lo_server_new(NULL, osc_error_handler);
302         lo_address t = lo_address_new(NULL, "17820");
303        
304         list_osc_paths(s, t, "/");
305        
306         lo_address_free(t);
307         lo_server_free(s);
308        
309     } else if ( strcmp( arguments.args[0], "OscServer" ) == 0 ) {
310         DeviceManager *m_deviceManager = new DeviceManager();
311         if ( !m_deviceManager ) {
312             fprintf( stderr, "Could not allocate device manager\n" );
313             return -1;
314         }
315         if ( !m_deviceManager->initialize( arguments.port ) ) {
316             fprintf( stderr, "Could not initialize device manager\n" );
317             delete m_deviceManager;
318             return -1;
319         }
320         if ( arguments.verbose ) {
321             m_deviceManager->setVerboseLevel(arguments.verbose);
322         }
323         if ( !m_deviceManager->discover() ) {
324             fprintf( stderr, "Could not discover devices\n" );
325             delete m_deviceManager;
326             return -1;
327         }
328
329         printf("server started\n");
330         printf("press ctrl-c to stop it & continue\n");
331        
332         signal (SIGINT, sighandler);
333        
334         run=1;
335         while(run) {
336             sleep(1);
337             fflush(stdout);
338             fflush(stderr);
339         }
340         signal (SIGINT, SIG_DFL);
341        
342         printf("server stopped\n");
343         delete m_deviceManager;
344         return 0;
345        
346     } else {
347         printf( "unknown operation\n" );
348     }
349
350 }
351
352 void list_osc_paths(lo_server s, lo_address t, const char *path) {
353     vector<string> my_paths;
354    
355     printf("listing path: %s\n", path);
356    
357     osc_paths.clear();
358     lo_server_add_method(s, "/response", NULL, osc_path_response_handler, NULL);
359
360     if (lo_send(t, path, "s", "list") == -1) {
361         printf(" OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));
362     }
363
364     if (lo_server_recv_noblock(s, 1000) == 0) {
365         printf("timeout\n");
366         return;
367     }
368    
369     lo_server_del_method(s, "/response", NULL);
370    
371     list_osc_params(s, t, path);
372    
373     my_paths=osc_paths;
374     for ( vector<string>::iterator it = my_paths.begin();
375             it != my_paths.end();
376             ++it )
377     {
378         string new_path=string(path) + *it;
379         new_path += string("/");
380         list_osc_paths(s, t, new_path.c_str());
381     }
382
383 }
384
385 void list_osc_params(lo_server s, lo_address t, const char *path) {
386     vector<string> my_paths;
387     printf("params for: %s\n", path);
388    
389     osc_params.clear();
390     lo_server_add_method(s, "/response", NULL, osc_param_response_handler, NULL);
391
392     if (lo_send(t, path, "s", "params") == -1) {
393         printf(" OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));
394     }
395    
396     if (lo_server_recv_noblock(s, 1000) == 0) {
397         printf("timeout\n");
398         return;
399     }
400    
401     lo_server_del_method(s, "/response", NULL);
402    
403     vector<string> my_params=osc_params;
404    
405     for ( vector<string>::iterator it = my_params.begin();
406             it != my_params.end();
407             ++it )
408     {
409         string value=osc_param_get_value(s, t, path, (*it).c_str());
410         printf("  %20s = %s\n", (*it).c_str(), value.c_str());
411     }
412
413 }
414
415 string osc_param_get_value(lo_server s, lo_address t, const char *path, const char *param) {
416     lo_server_add_method(s, "/response", NULL, osc_data_response_handler, NULL);
417
418     if (lo_send(t, path, "ss", "get", param) == -1) {
419         printf(" OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));
420     }
421    
422     if (lo_server_recv_noblock(s, 1000) == 0) {
423         return string("timeout");
424     }
425    
426     lo_server_del_method(s, "/response", NULL);
427     return osc_value;
428 }
429
430 void osc_error_handler(int num, const char *msg, const char *path)
431 {
432     printf("liblo server error %d in path %s: %s\n", num, path, msg);
433 }
434
435 int osc_path_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
436         void *data, void *user_data)
437 {
438     for (int i=0; i< argc;i++) {
439         switch (lo_type(types[i])) {
440             /** Standard C, NULL terminated string. */
441             case LO_STRING:
442                 osc_paths.push_back(string(&(argv[i]->s)));
443                 break;
444             default:
445                 printf("unexpected data type in response message\n");
446         }
447     }
448     return 1;
449 }
450
451 int osc_param_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
452         void *data, void *user_data)
453 {
454     for (int i=0; i< argc;i++) {
455         switch (lo_type(types[i])) {
456             /** Standard C, NULL terminated string. */
457             case LO_STRING:
458                 osc_params.push_back(string(&(argv[i]->s)));
459                 break;
460             default:
461                 printf("unexpected data type in response message\n");
462         }
463     }
464     return 1;
465 }
466
467 int osc_data_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
468         void *data, void *user_data)
469 {
470     std::ostringstream str;
471    
472     if(argc==1) {
473         switch (lo_type(types[0])) {
474             /* basic OSC types */
475             /** 32 bit signed integer. */
476             case LO_INT32:
477                 str << "0x" << std::hex << argv[0]->i;
478                 osc_value=str.str();
479                 break;
480             case LO_INT64:
481                 str << "0x" << std::hex << argv[0]->h;
482                 osc_value=str.str();
483                 break;
484             /** 32 bit IEEE-754 float. */
485             case LO_FLOAT:
486                 str << argv[0]->f;
487                 osc_value=str.str();
488                 break;
489             /** Standard C, NULL terminated string. */
490             case LO_STRING:
491                 osc_value=string(&argv[0]->s);
492                 break;
493             default:
494                 osc_value="unsupported response datatype";
495         }
496     } else {
497         osc_value="invalid response";
498     }
499     return 1;
500 }
Note: See TracBrowser for help on using the browser.