root/trunk/libffado/tests/test-ffado.cpp

Revision 445, 14.8 kB (checked in by pieterpalmers, 17 years ago)

* name change from FreeBoB to FFADO
* replaced tabs by 4 spaces
* got rid of end-of-line spaces
* made all license and copyrights conform

library becomes LGPL, apps become GPL
explicitly state LGPL v2.1 and GPL v2 (don't like v3 draft)

copyrights are 2005-2007 Daniel & Pieter
except for the MotU stuff (C) Jonathan, Pieter

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