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

Revision 435, 14.7 kB (checked in by pieterpalmers, 15 years ago)

src/devicemanager:
- start OSC server for the device manager

src/devicemanager,
src/iavdevice,
src/libieee1394/configrom:
- inherit from OscNode? to become Osc'able

src/bounce,
src/libstreaming/AmdtpStreamProcessor,
src/libstreaming/AmdtpSlaveStreamProcessor:
- fixed bounce device implementation, now working

src/bebob:
- fixed midi bug

General:
- removed 'intermediate XML'
- removed obsolete tests
- removed obsolete files
- removed obsolete API calls

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