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

Revision 582, 22.1 kB (checked in by ppalmers, 17 years ago)

see prev commit

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 "ffadodevice.h"
37
38 #include "bebob/focusrite/focusrite.h"
39
40 #include <dbus-c++/dbus.h>
41 #include "controlserver.h"
42 #include "libcontrol/BasicElements.h"
43
44 #include <signal.h>
45
46 #include <argp.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50
51 #include <vector>
52 #include <string>
53 #include <iostream>
54 #include <sstream>
55
56 #include <lo/lo.h>
57
58 using namespace std;
59
60 DECLARE_GLOBAL_DEBUG_MODULE;
61
62 // prototypes & stuff for listing the OSC space
63 void list_osc_paths(lo_server s, lo_address t, const char *path);
64 void list_osc_params(lo_server s, lo_address t, const char *path);
65 string osc_param_get_value(lo_server s, lo_address t, const char *path, const char *param);
66
67 vector<string> osc_paths;
68 vector<string> osc_params;
69 string osc_value;
70
71 int osc_path_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
72     void *data, void *user_data);
73
74 int osc_param_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
75     void *data, void *user_data);
76
77 int osc_data_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
78     void *data, void *user_data);
79
80 void osc_error_handler(int num, const char *msg, const char *path);
81
82 // DBUS stuff
83 DBus::BusDispatcher dispatcher;
84
85 // signal handler
86 int run=1;
87 static void sighandler (int sig)
88 {
89     run = 0;
90     dispatcher.leave();
91 }
92
93 // global's
94 const char *argp_program_version = PACKAGE_STRING;
95 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
96
97 // Program documentation.
98 static char doc[] = "FFADO -- a driver for Firewire Audio devices (test application)\n\n"
99                     "OPERATION: Discover\n"
100                     "           SetSamplerate samplerate\n"
101                     "           ListOscSpace\n"
102                     "           OscServer\n"
103                     "           FocusriteSetPhantom [0=ch1-4, 1=ch5-8] [1=on, 0=off]\n"
104                     "           DBus\n"
105                     ;
106
107 // A description of the arguments we accept.
108 static char args_doc[] = "OPERATION";
109
110 struct arguments
111 {
112     short silent;
113     short verbose;
114     int   port;
115     int   node_id;
116     int   node_id_set;
117     char* args[2];
118 };
119
120 // The options we understand.
121 static struct argp_option options[] = {
122     {"quiet",    'q',       0,    0,  "Don't produce any output" },
123     {"silent",   's',       0,    OPTION_ALIAS },
124
125     {"verbose",  'v', "level",    0,  "Produce verbose output" },
126
127
128     {"node",     'n',    "id",    0,  "Node to use" },
129     {"port",     'p',    "nr",    0,  "IEEE1394 Port to use" },
130     { 0 }
131 };
132
133 //-------------------------------------------------------------
134
135 // Parse a single option.
136 static error_t
137 parse_opt( int key, char* arg, struct argp_state* state )
138 {
139     // Get the input argument from `argp_parse', which we
140     // know is a pointer to our arguments structure.
141     struct arguments* arguments = ( struct arguments* ) state->input;
142     char* tail;
143
144     switch (key) {
145     case 'q': case 's':
146         arguments->silent = 1;
147         break;
148     case 'v':
149         if (arg) {
150             arguments->verbose = strtol( arg, &tail, 0 );
151             if ( errno ) {
152                 fprintf( stderr,  "Could not parse 'verbose' argument\n" );
153                 return ARGP_ERR_UNKNOWN;
154             }
155         }
156         break;
157     case 'p':
158         if (arg) {
159             arguments->port = strtol( arg, &tail, 0 );
160             if ( errno ) {
161                 fprintf( stderr,  "Could not parse 'port' argument\n" );
162                 return ARGP_ERR_UNKNOWN;
163             }
164         } else {
165             if ( errno ) {
166                 fprintf( stderr, "Could not parse 'port' argumen\n" );
167                 return ARGP_ERR_UNKNOWN;
168             }
169         }
170         break;
171     case 'n':
172         if (arg) {
173             arguments->node_id = strtol( arg, &tail, 0 );
174             if ( errno ) {
175                 fprintf( stderr,  "Could not parse 'node' argument\n" );
176                 return ARGP_ERR_UNKNOWN;
177             }
178             arguments->node_id_set=1;
179         } else {
180             if ( errno ) {
181                 fprintf( stderr, "Could not parse 'node' argumen\n" );
182                 return ARGP_ERR_UNKNOWN;
183             }
184         }
185         break;
186     case ARGP_KEY_ARG:
187         if (state->arg_num >= 3) {
188             // Too many arguments.
189             argp_usage( state );
190         }
191         arguments->args[state->arg_num] = arg;
192         break;
193     case ARGP_KEY_END:
194         if (state->arg_num < 1) {
195         // Not enough arguments.
196         argp_usage( state );
197         }
198         break;
199     default:
200         return ARGP_ERR_UNKNOWN;
201     }
202     return 0;
203 }
204
205 // Our argp parser.
206 static struct argp argp = { options, parse_opt, args_doc, doc };
207
208 int exitfunction( int retval ) {
209     debugOutput( DEBUG_LEVEL_NORMAL, "Debug output flushed...\n" );
210     flushDebugOutput();
211    
212     return retval;
213 }
214
215 int
216 main( int argc, char **argv )
217 {
218     struct arguments arguments;
219
220     // Default values.
221     arguments.silent      = 0;
222     arguments.verbose     = 0;
223     arguments.port        = 0;
224     arguments.node_id     = 0;
225     arguments.node_id_set = 0; // if we don't specify a node, discover all
226     arguments.args[0]     = "";
227     arguments.args[1]     = "";
228
229     setDebugLevel(arguments.verbose);
230
231     // Parse our arguments; every option seen by `parse_opt' will
232     // be reflected in `arguments'.
233     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
234         fprintf( stderr, "Could not parse command line\n" );
235         return exitfunction(-1);
236     }
237
238     printf("verbose level = %d\n", arguments.verbose);
239
240     printf( "Using ffado library version: %s\n\n", ffado_get_version() );
241
242     if ( strcmp( arguments.args[0], "Discover" ) == 0 ) {
243         DeviceManager *m_deviceManager = new DeviceManager();
244         if ( !m_deviceManager ) {
245             fprintf( stderr, "Could not allocate device manager\n" );
246             return exitfunction(-1);
247         }
248         if ( arguments.verbose ) {
249             m_deviceManager->setVerboseLevel(arguments.verbose);
250         }
251         if ( !m_deviceManager->initialize( arguments.port ) ) {
252             fprintf( stderr, "Could not initialize device manager\n" );
253             delete m_deviceManager;
254             return exitfunction(-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 exitfunction(-1);
263         }
264         delete m_deviceManager;
265         return exitfunction(0);
266     } else if ( strcmp( arguments.args[0], "SetSamplerate" ) == 0 ) {
267         char* tail;
268         int samplerate = strtol( arguments.args[1], &tail, 0 );
269         if ( errno ) {
270             fprintf( stderr,  "Could not parse samplerate argument\n" );
271             return exitfunction(-1);
272         }
273
274         DeviceManager *m_deviceManager = new DeviceManager();
275         if ( !m_deviceManager ) {
276             fprintf( stderr, "Could not allocate device manager\n" );
277             return exitfunction(-1);
278         }
279         if ( arguments.verbose ) {
280             m_deviceManager->setVerboseLevel(arguments.verbose);
281         }
282         if ( !m_deviceManager->initialize( arguments.port ) ) {
283             fprintf( stderr, "Could not initialize device manager\n" );
284             delete m_deviceManager;
285             return exitfunction(-1);
286         }
287         if ( arguments.verbose ) {
288             m_deviceManager->setVerboseLevel(arguments.verbose);
289         }
290         if ( !m_deviceManager->discover() ) {
291             fprintf( stderr, "Could not discover devices\n" );
292             delete m_deviceManager;
293             return exitfunction(-1);
294         }
295
296         if(arguments.node_id_set) {
297             FFADODevice* avDevice = m_deviceManager->getAvDevice( arguments.node_id );
298             if ( avDevice ) {
299                 if ( avDevice->setSamplingFrequency( samplerate ) ) {
300                     m_deviceManager->discover();
301                 } else {
302                     fprintf( stderr, "Could not set samplerate\n" );
303                 }
304             }
305         } else {
306             int i=0;
307
308             int devices_on_bus = m_deviceManager->getNbDevices();
309             printf("  port = %d, devices_on_bus = %d\n", arguments.port, devices_on_bus);
310
311             for(i=0;i<devices_on_bus;i++) {
312                 int node_id=m_deviceManager->getDeviceNodeId(i);
313                 printf("  set samplerate for device = %d, node = %d\n", i, node_id);
314                 FFADODevice* avDevice = m_deviceManager->getAvDevice( node_id );
315                 if ( avDevice ) {
316                     if ( !avDevice->setSamplingFrequency( samplerate ) ) {
317                         fprintf( stderr, "Could not set samplerate\n" );
318                     }
319                 }
320             }
321         }
322         delete m_deviceManager;
323         return exitfunction(0);
324     } else if ( strcmp( arguments.args[0], "ListOscSpace" ) == 0 ) {
325         // list osc space by using OSC messages
326         // a server is assumed to be present
327
328         /* start a new server.
329         when sending a message from this context, the response
330         address will be set to this server's address.
331         */
332         lo_server s = lo_server_new(NULL, osc_error_handler);
333         lo_address t = lo_address_new(NULL, "17820");
334
335         list_osc_paths(s, t, "/");
336
337         lo_address_free(t);
338         lo_server_free(s);
339
340     } else if ( strcmp( arguments.args[0], "OscServer" ) == 0 ) {
341         DeviceManager *m_deviceManager = new DeviceManager();
342         if ( !m_deviceManager ) {
343             fprintf( stderr, "Could not allocate device manager\n" );
344             return exitfunction(-1);
345         }
346         if ( !m_deviceManager->initialize( arguments.port ) ) {
347             fprintf( stderr, "Could not initialize device manager\n" );
348             delete m_deviceManager;
349             return exitfunction(-1);
350         }
351         if ( arguments.verbose ) {
352             m_deviceManager->setVerboseLevel(arguments.verbose);
353         }
354         if ( !m_deviceManager->discover() ) {
355             fprintf( stderr, "Could not discover devices\n" );
356             delete m_deviceManager;
357             return exitfunction(-1);
358         }
359
360         printf("server started\n");
361         printf("press ctrl-c to stop it & continue\n");
362
363         signal (SIGINT, sighandler);
364
365         run=1;
366         while(run) {
367             sleep(1);
368             fflush(stdout);
369             fflush(stderr);
370         }
371         signal (SIGINT, SIG_DFL);
372
373         printf("server stopped\n");
374         delete m_deviceManager;
375         return exitfunction(0);
376     } else if ( strcmp( arguments.args[0], "FocusriteSetPhantom" ) == 0 ) {
377         char* tail;
378         int inputchannels = strtol( arguments.args[1], &tail, 0 );
379         if ( errno ) {
380             fprintf( stderr,  "Could not parse inputchannels argument\n" );
381             return exitfunction(-1);
382         }
383         int onoff = strtol( arguments.args[2], &tail, 0 );
384         if ( errno ) {
385             fprintf( stderr,  "Could not parse on/off argument\n" );
386             return exitfunction(-1);
387         }
388        
389         DeviceManager *m_deviceManager = new DeviceManager();
390         if ( !m_deviceManager ) {
391             fprintf( stderr, "Could not allocate device manager\n" );
392             return exitfunction(-1);
393         }
394         if ( arguments.verbose ) {
395             m_deviceManager->setVerboseLevel(arguments.verbose);
396         }
397         if ( !m_deviceManager->initialize( arguments.port ) ) {
398             fprintf( stderr, "Could not initialize device manager\n" );
399             delete m_deviceManager;
400             return exitfunction(-1);
401         }
402         if ( arguments.verbose ) {
403             m_deviceManager->setVerboseLevel(arguments.verbose);
404         }
405         if ( !m_deviceManager->discover() ) {
406             fprintf( stderr, "Could not discover devices\n" );
407             delete m_deviceManager;
408             return exitfunction(-1);
409         }
410
411         if(arguments.node_id_set) {
412             FFADODevice* avDevice = m_deviceManager->getAvDevice( arguments.node_id );
413             if ( avDevice ) {
414                 if ( avDevice->getConfigRom().getNodeVendorId() == 0x00130e ) {
415                    
416                     BeBoB::FocusriteVendorDependentCmd cmd( avDevice->get1394Service() );
417                     cmd.setCommandType( AVC::AVCCommand::eCT_Control );
418                     cmd.setNodeId( avDevice->getConfigRom().getNodeId() );
419                     cmd.setVerbose( arguments.verbose );
420                    
421 //                         if (inputchannels) {
422 //                             cmd.m_id=99;
423 //                         } else {
424 //                             cmd.m_id=98;
425 //                         }
426 //                         if (onoff) {
427 //                             cmd.m_value=1;
428 //                         } else {
429 //                             cmd.m_value=0;
430 //                         }
431                         cmd.m_id=inputchannels;
432                         cmd.m_value=onoff;
433                    
434                     if ( !cmd.fire() ) {
435                         debugError( "FocusriteVendorDependentCmd info command failed\n" );
436                         // shouldn't this be an error situation?
437                         return exitfunction(-1);
438                     }
439
440                 } else {
441                     fprintf( stderr, "Not a Focusrite device: id=0x%06X ...\n", avDevice->getConfigRom().getNodeVendorId());
442                 }
443             }
444         } else {
445             int i=0;
446
447             int devices_on_bus = m_deviceManager->getNbDevices();
448             printf("  port = %d, devices_on_bus = %d\n", arguments.port, devices_on_bus);
449
450             for(i=0;i<devices_on_bus;i++) {
451                 int node_id=m_deviceManager->getDeviceNodeId(i);
452                 printf("  set phantom power for device = %d, node = %d\n", i, node_id);
453                 FFADODevice* avDevice = m_deviceManager->getAvDevice( arguments.node_id );
454                 if ( avDevice ) {
455                     if ( avDevice->getConfigRom().getNodeVendorId() == 0x00130e ) {
456                        
457                         BeBoB::FocusriteVendorDependentCmd cmd( avDevice->get1394Service() );
458                         cmd.setCommandType( AVC::AVCCommand::eCT_Control );
459                         cmd.setNodeId( avDevice->getConfigRom().getNodeId() );
460                         cmd.setVerbose( arguments.verbose );
461                        
462 //                         if (inputchannels) {
463 //                             cmd.m_id=99;
464 //                         } else {
465 //                             cmd.m_id=98;
466 //                         }
467 //                         if (onoff) {
468 //                             cmd.m_value=1;
469 //                         } else {
470 //                             cmd.m_value=0;
471 //                         }
472                         cmd.m_id=inputchannels;
473                         cmd.m_value=onoff;
474                        
475                         if ( !cmd.fire() ) {
476                             debugError( "FocusriteVendorDependentCmd info command failed\n" );
477                             // shouldn't this be an error situation?
478                             return exitfunction(-1);
479                         }
480    
481                     } else {
482                         fprintf( stderr, "Not a Focusrite device: id=0x%06X ...\n", avDevice->getConfigRom().getNodeVendorId());
483                     }
484                 }
485
486             }
487         }
488         delete m_deviceManager;
489         return exitfunction(0);
490     } else if ( strcmp( arguments.args[0], "DBus" ) == 0 ) {
491         DeviceManager *m_deviceManager = new DeviceManager();
492         if ( !m_deviceManager ) {
493             fprintf( stderr, "Could not allocate device manager\n" );
494             return exitfunction(-1);
495         }
496         if ( !m_deviceManager->initialize( arguments.port ) ) {
497             fprintf( stderr, "Could not initialize device manager\n" );
498             delete m_deviceManager;
499             return exitfunction(-1);
500         }
501         if ( arguments.verbose ) {
502             m_deviceManager->setVerboseLevel(arguments.verbose);
503         }
504         if ( !m_deviceManager->discover() ) {
505             fprintf( stderr, "Could not discover devices\n" );
506             delete m_deviceManager;
507             return exitfunction(-1);
508         }
509        
510         signal (SIGINT, sighandler);
511        
512         DBus::_init_threading();
513    
514         // test DBUS stuff
515         DBus::default_dispatcher = &dispatcher;
516    
517         DBus::Connection conn = DBus::Connection::SessionBus();
518         conn.request_name("org.ffado.Control");
519        
520         DBusControl::Container *container
521             = new DBusControl::Container(conn, "/org/ffado/Control/DeviceManager", *m_deviceManager);
522        
523         printf("DBUS test service running\n");
524         printf("press ctrl-c to stop it & continue\n");
525        
526         dispatcher.enter();
527    
528         delete container;
529
530         signal (SIGINT, SIG_DFL);
531
532         printf("server stopped\n");
533         delete m_deviceManager;
534         return exitfunction(0);
535     } else {
536         printf( "unknown operation\n" );
537     }
538
539 }
540
541 void list_osc_paths(lo_server s, lo_address t, const char *path) {
542     vector<string> my_paths;
543
544     printf("listing path: %s\n", path);
545
546     osc_paths.clear();
547     lo_server_add_method(s, "/response", NULL, osc_path_response_handler, NULL);
548
549     if (lo_send(t, path, "s", "list") == -1) {
550         printf(" OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));
551     }
552
553     if (lo_server_recv_noblock(s, 1000) == 0) {
554         printf("timeout\n");
555         return;
556     }
557
558     lo_server_del_method(s, "/response", NULL);
559
560     list_osc_params(s, t, path);
561
562     my_paths=osc_paths;
563     for ( vector<string>::iterator it = my_paths.begin();
564             it != my_paths.end();
565             ++it )
566     {
567         string new_path=string(path) + *it;
568         new_path += string("/");
569         list_osc_paths(s, t, new_path.c_str());
570     }
571
572 }
573
574 void list_osc_params(lo_server s, lo_address t, const char *path) {
575     vector<string> my_paths;
576     printf("params for: %s\n", path);
577
578     osc_params.clear();
579     lo_server_add_method(s, "/response", NULL, osc_param_response_handler, NULL);
580
581     if (lo_send(t, path, "s", "params") == -1) {
582         printf(" OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));
583     }
584
585     if (lo_server_recv_noblock(s, 1000) == 0) {
586         printf("timeout\n");
587         return;
588     }
589
590     lo_server_del_method(s, "/response", NULL);
591
592     vector<string> my_params=osc_params;
593
594     for ( vector<string>::iterator it = my_params.begin();
595             it != my_params.end();
596             ++it )
597     {
598         string value=osc_param_get_value(s, t, path, (*it).c_str());
599         printf("  %20s = %s\n", (*it).c_str(), value.c_str());
600     }
601
602 }
603
604 string osc_param_get_value(lo_server s, lo_address t, const char *path, const char *param) {
605     lo_server_add_method(s, "/response", NULL, osc_data_response_handler, NULL);
606
607     if (lo_send(t, path, "ss", "get", param) == -1) {
608         printf(" OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t));
609     }
610
611     if (lo_server_recv_noblock(s, 1000) == 0) {
612         return string("timeout");
613     }
614
615     lo_server_del_method(s, "/response", NULL);
616     return osc_value;
617 }
618
619 void osc_error_handler(int num, const char *msg, const char *path)
620 {
621     printf("liblo server error %d in path %s: %s\n", num, path, msg);
622 }
623
624 int osc_path_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
625         void *data, void *user_data)
626 {
627     for (int i=0; i< argc;i++) {
628         switch (lo_type(types[i])) {
629             /** Standard C, NULL terminated string. */
630             case LO_STRING:
631                 osc_paths.push_back(string(&(argv[i]->s)));
632                 break;
633             default:
634                 printf("unexpected data type in response message\n");
635         }
636     }
637     return 1;
638 }
639
640 int osc_param_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
641         void *data, void *user_data)
642 {
643     for (int i=0; i< argc;i++) {
644         switch (lo_type(types[i])) {
645             /** Standard C, NULL terminated string. */
646             case LO_STRING:
647                 osc_params.push_back(string(&(argv[i]->s)));
648                 break;
649             default:
650                 printf("unexpected data type in response message\n");
651         }
652     }
653     return 1;
654 }
655
656 int osc_data_response_handler(const char *path, const char *types, lo_arg **argv, int argc,
657         void *data, void *user_data)
658 {
659     std::ostringstream str;
660
661     if(argc==1) {
662         switch (lo_type(types[0])) {
663             /* basic OSC types */
664             /** 32 bit signed integer. */
665             case LO_INT32:
666                 str << "0x" << std::hex << argv[0]->i;
667                 osc_value=str.str();
668                 break;
669             case LO_INT64:
670                 str << "0x" << std::hex << argv[0]->h;
671                 osc_value=str.str();
672                 break;
673             /** 32 bit IEEE-754 float. */
674             case LO_FLOAT:
675                 str << argv[0]->f;
676                 osc_value=str.str();
677                 break;
678             /** Standard C, NULL terminated string. */
679             case LO_STRING:
680                 osc_value=string(&argv[0]->s);
681                 break;
682             default:
683                 osc_value="unsupported response datatype";
684         }
685     } else {
686         osc_value="invalid response";
687     }
688     return 1;
689 }
Note: See TracBrowser for help on using the browser.