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

Revision 1146, 17.6 kB (checked in by ppalmers, 13 years ago)

reset errno when parsing arguments. fixes #107.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copyright (C) 2005-2008 by Daniel Wagner
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  * This program 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) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include <libraw1394/raw1394.h>
26 #include <libiec61883/iec61883.h>
27
28 #include "debugmodule/debugmodule.h"
29
30 #include "libieee1394/configrom.h"
31 #include "libieee1394/ieee1394service.h"
32 #include "libutil/cmd_serialize.h"
33 #include "libavc/general/avc_generic.h"
34
35 #include "fireworks/efc/efc_avc_cmd.h"
36 #include "fireworks/efc/efc_cmds_mixer.h"
37 #include "fireworks/efc/efc_cmds_monitor.h"
38 #include "fireworks/efc/efc_cmds_hardware.h"
39 using namespace FireWorks;
40
41 #include <argp.h>
42 #include <stdlib.h>
43 #include <iostream>
44
45 using namespace std;
46 using namespace AVC;
47 using namespace Util;
48
49 DECLARE_GLOBAL_DEBUG_MODULE;
50
51 #define MAX_ARGS 1000
52
53 ////////////////////////////////////////////////
54 // arg parsing
55 ////////////////////////////////////////////////
56 const char *argp_program_version = "test-echomixer 0.1";
57 const char *argp_program_bug_address = "<ffado-devel@lists.sf.net>";
58 static char doc[] = "test-avccmd -- test program to examine the echo audio mixer.";
59 static char args_doc[] = "NODE_ID";
60 static struct argp_option options[] = {
61     {"verbose",   'v', 0,           0,  "Produce verbose output" },
62     {"port",      'p', "PORT",      0,  "Set port" },
63     {"node",      'n', "NODE",      0,  "Set node" },
64    { 0 }
65 };
66
67 struct arguments
68 {
69     arguments()
70         : nargs ( 0 )
71         , verbose( false )
72         , test( false )
73         , port( 0 )
74         {
75             args[0] = 0;
76         }
77
78     char* args[MAX_ARGS];
79     int   nargs;
80     bool  verbose;
81     bool  test;
82     int   port;
83     int   node;
84 } arguments;
85
86 // Parse a single option.
87 static error_t
88 parse_opt( int key, char* arg, struct argp_state* state )
89 {
90     // Get the input argument from `argp_parse', which we
91     // know is a pointer to our arguments structure.
92     struct arguments* arguments = ( struct arguments* ) state->input;
93
94     char* tail;
95     errno = 0;
96     switch (key) {
97     case 'v':
98         arguments->verbose = true;
99         break;
100     case 't':
101         arguments->test = true;
102         break;
103     case 'p':
104         arguments->port = strtol(arg, &tail, 0);
105         if (errno) {
106             perror("argument parsing failed:");
107             return errno;
108         }
109         break;
110     case 'n':
111         arguments->node = strtol(arg, &tail, 0);
112         if (errno) {
113             perror("argument parsing failed:");
114             return errno;
115         }
116         break;
117     case ARGP_KEY_ARG:
118         if (state->arg_num >= MAX_ARGS) {
119             // Too many arguments.
120             argp_usage (state);
121         }
122         arguments->args[state->arg_num] = arg;
123         arguments->nargs++;
124         break;
125     case ARGP_KEY_END:
126         if(arguments->nargs<0) {
127             printf("not enough arguments\n");
128             return -1;
129         }
130        
131         break;
132     default:
133         return ARGP_ERR_UNKNOWN;
134     }
135     return 0;
136 }
137
138 static struct argp argp = { options, parse_opt, args_doc, doc };
139
140 bool doEfcOverAVC(Ieee1394Service& m_1394Service, int node, EfcCmd &c)
141 {
142     EfcOverAVCCmd cmd( m_1394Service );
143     cmd.setCommandType( AVC::AVCCommand::eCT_Control );
144     cmd.setNodeId( node );
145     cmd.setSubunitType( AVC::eST_Unit  );
146     cmd.setSubunitId( 0xff );
147
148     cmd.setVerbose( DEBUG_LEVEL_NORMAL );
149
150     cmd.m_cmd = &c;
151
152     if ( !cmd.fire()) {
153         debugError( "EfcOverAVCCmd command failed\n" );
154         c.showEfcCmd();
155         return false;
156     }
157
158     if (   c.m_header.retval != EfcCmd::eERV_Ok
159         && c.m_header.retval != EfcCmd::eERV_FlashBusy) {
160         debugError( "EFC command failed\n" );
161         c.showEfcCmd();
162         return false;
163     }
164
165     return true;
166 }
167
168 ///////////////////////////
169 // main
170 //////////////////////////
171 int
172 main(int argc, char **argv)
173 {
174     // arg parsing
175     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
176         fprintf( stderr, "Could not parse command line\n" );
177         exit(-1);
178     }
179     errno = 0;
180
181     Ieee1394Service *m_1394Service = new Ieee1394Service();
182     if ( !m_1394Service ) {
183         debugFatal( "Could not create Ieee1349Service object\n" );
184         return false;
185     }
186
187     if ( !m_1394Service->initialize( arguments.port ) ) {
188         debugFatal( "Could not initialize Ieee1349Service object\n" );
189         delete m_1394Service;
190         m_1394Service = 0;
191         return false;
192     }
193
194     EfcHardwareInfoCmd  m_HwInfo;
195    
196     if (!doEfcOverAVC(*m_1394Service, arguments.node, m_HwInfo)) {
197         debugFatal("Could not obtain FireWorks device info\n");
198         return false;
199     }
200     m_HwInfo.showEfcCmd();
201
202     unsigned int ch=0;
203    
204     uint32_t pbk_vol[m_HwInfo.m_nb_1394_playback_channels][5];
205     uint32_t rec_vol[m_HwInfo.m_nb_1394_record_channels][5];
206     uint32_t out_vol[m_HwInfo.m_nb_phys_audio_out][5];
207     uint32_t in_vol[m_HwInfo.m_nb_phys_audio_in][5];
208    
209     memset(pbk_vol, 0, sizeof(uint32_t) * 5 * m_HwInfo.m_nb_1394_playback_channels);
210     memset(rec_vol, 0, sizeof(uint32_t) * 5 * m_HwInfo.m_nb_1394_record_channels);
211     memset(out_vol, 0, sizeof(uint32_t) * 5 * m_HwInfo.m_nb_phys_audio_out);
212     memset(in_vol, 0, sizeof(uint32_t) * 5 * m_HwInfo.m_nb_phys_audio_in);
213    
214     enum eMixerTarget t=eMT_PlaybackMix;
215     enum eMixerCommand c = eMC_Gain;
216     enum eCmdType type = eCT_Get;
217     EfcGenericMixerCmd cmd(t,c);
218     cmd.setType(type);
219
220 #define DO_PLAYBACK_MIX
221 // #define DO_RECORD_MIX
222 #define DO_PHYS_OUT_MIX
223 #define DO_PHYS_IN_MIX
224
225 #ifdef DO_PLAYBACK_MIX
226     cmd.setTarget(eMT_PlaybackMix);
227     for (ch=0;ch<m_HwInfo.m_nb_1394_playback_channels;ch++) {
228 //     for (ch=0;ch<1;ch++) {
229         {
230             cmd.setCommand(eMC_Gain);
231             cmd.m_channel=ch;
232             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
233                 debugFatal("Cmd failed\n");
234             }
235             pbk_vol[ch][0]=cmd.m_value;
236         }
237 //         {
238 //             cmd.setCommand(eMC_Solo);
239 //             cmd.m_channel=ch;
240 //             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
241 //                 debugFatal("Cmd failed\n");
242 //             }
243 //             pbk_vol[ch][1]=cmd.m_value;
244 //         }
245         {
246             cmd.setCommand(eMC_Mute);
247             cmd.m_channel=ch;
248             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
249                 debugFatal("Cmd failed\n");
250             }
251             pbk_vol[ch][2]=cmd.m_value;
252         }
253 //         {
254 //             cmd.setCommand(eMC_Pan);
255 //             cmd.m_channel=ch;
256 //             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
257 //                 debugFatal("Cmd failed\n");
258 //             }
259 //             pbk_vol[ch][3]=cmd.m_value;
260 //         }
261 //         {
262 //             cmd.setCommand(eMC_Nominal);
263 //             cmd.m_channel=ch;
264 //             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
265 //                 debugFatal("Cmd failed\n");
266 //             }
267 //             pbk_vol[ch][4]=cmd.m_value;
268 //         }
269     }
270 #endif
271
272 #ifdef DO_RECORD_MIX
273     cmd.setTarget(eMT_RecordMix);
274     for (ch=0;ch<m_HwInfo.m_nb_1394_record_channels;ch++) {
275 //     for (ch=0;ch<1;ch++) {
276         {
277             cmd.setCommand(eMC_Gain);
278             cmd.m_channel=ch;
279             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
280                 debugFatal("Cmd failed\n");
281             }
282             rec_vol[ch][0]=cmd.m_value;
283         }
284         {
285             cmd.setCommand(eMC_Solo);
286             cmd.m_channel=ch;
287             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
288                 debugFatal("Cmd failed\n");
289             }
290             rec_vol[ch][1]=cmd.m_value;
291         }
292         {
293             cmd.setCommand(eMC_Mute);
294             cmd.m_channel=ch;
295             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
296                 debugFatal("Cmd failed\n");
297             }
298             rec_vol[ch][2]=cmd.m_value;
299         }
300         {
301             cmd.setCommand(eMC_Pan);
302             cmd.m_channel=ch;
303             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
304                 debugFatal("Cmd failed\n");
305             }
306             rec_vol[ch][3]=cmd.m_value;
307         }
308         {
309             cmd.setCommand(eMC_Nominal);
310             cmd.m_channel=ch;
311             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
312                 debugFatal("Cmd failed\n");
313             }
314             rec_vol[ch][4]=cmd.m_value;
315         }
316     }
317 #endif
318
319 #ifdef DO_PHYS_OUT_MIX
320     cmd.setTarget(eMT_PhysicalOutputMix);
321     for (ch=0;ch<m_HwInfo.m_nb_phys_audio_out;ch++) {
322 //     for (ch=0;ch<1;ch++) {
323         {
324             cmd.setCommand(eMC_Gain);
325             cmd.m_channel=ch;
326             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
327                 debugFatal("Cmd failed\n");
328             }
329             out_vol[ch][0]=cmd.m_value;
330         }
331 //         {
332 //             cmd.setCommand(eMC_Solo);
333 //             cmd.m_channel=ch;
334 //             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
335 //                 debugFatal("Cmd failed\n");
336 //             }
337 //             out_vol[ch][1]=cmd.m_value;
338 //         }
339         {
340             cmd.setCommand(eMC_Mute);
341             cmd.m_channel=ch;
342             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
343                 debugFatal("Cmd failed\n");
344             }
345             out_vol[ch][2]=cmd.m_value;
346         }
347 //         {
348 //             cmd.setCommand(eMC_Pan);
349 //             cmd.m_channel=ch;
350 //             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
351 //                 debugFatal("Cmd failed\n");
352 //             }
353 //             out_vol[ch][3]=cmd.m_value;
354 //         }
355         {
356             cmd.setCommand(eMC_Nominal);
357             cmd.m_channel=ch;
358             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
359                 debugFatal("Cmd failed\n");
360             }
361             out_vol[ch][4]=cmd.m_value;
362         }
363     }
364 #endif
365
366 #ifdef DO_PHYS_IN_MIX
367     cmd.setTarget(eMT_PhysicalInputMix);
368     for (ch=0;ch<m_HwInfo.m_nb_phys_audio_in;ch++) {
369 //     for (ch=0;ch<1;ch++) {
370         {
371             cmd.setCommand(eMC_Gain);
372             cmd.m_channel=ch;
373             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
374                 debugFatal("Cmd failed\n");
375             }
376             in_vol[ch][0]=cmd.m_value;
377         }
378         {
379             cmd.setCommand(eMC_Solo);
380             cmd.m_channel=ch;
381             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
382                 debugFatal("Cmd failed\n");
383             }
384             in_vol[ch][1]=cmd.m_value;
385         }
386         {
387             cmd.setCommand(eMC_Mute);
388             cmd.m_channel=ch;
389             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
390                 debugFatal("Cmd failed\n");
391             }
392             in_vol[ch][2]=cmd.m_value;
393         }
394         {
395             cmd.setCommand(eMC_Pan);
396             cmd.m_channel=ch;
397             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
398                 debugFatal("Cmd failed\n");
399             }
400             in_vol[ch][3]=cmd.m_value;
401         }
402         {
403             cmd.setCommand(eMC_Nominal);
404             cmd.m_channel=ch;
405             if (!doEfcOverAVC(*m_1394Service, arguments.node, cmd)) {
406                 debugFatal("Cmd failed\n");
407             }
408             in_vol[ch][4]=cmd.m_value;
409         }
410     }
411 #endif
412
413     uint32_t monitor_gain[m_HwInfo.m_nb_phys_audio_in][m_HwInfo.m_nb_phys_audio_out];
414     for (unsigned int ch_in=0;ch_in<m_HwInfo.m_nb_phys_audio_in;ch_in++) {
415         for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
416             {
417                 EfcGetMonitorGainCmd getCmd;
418                 getCmd.m_input=ch_in;
419                 getCmd.m_output=ch_out;
420                 if (!doEfcOverAVC(*m_1394Service, arguments.node, getCmd)) {
421                     debugFatal("Cmd failed\n");
422                 }
423                 monitor_gain[ch_in][ch_out]=getCmd.m_value;
424             }
425         }
426     }
427     uint32_t monitor_pan[m_HwInfo.m_nb_phys_audio_in][m_HwInfo.m_nb_phys_audio_out];
428     for (unsigned int ch_in=0;ch_in<m_HwInfo.m_nb_phys_audio_in;ch_in++) {
429         for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
430             {
431                 EfcGetMonitorPanCmd getCmd;
432                 getCmd.m_input=ch_in;
433                 getCmd.m_output=ch_out;
434                 if (!doEfcOverAVC(*m_1394Service, arguments.node, getCmd)) {
435                     debugFatal("Cmd failed\n");
436                 }
437                 monitor_pan[ch_in][ch_out]=getCmd.m_value;
438             }
439         }
440     }
441     uint32_t monitor_mute[m_HwInfo.m_nb_phys_audio_in][m_HwInfo.m_nb_phys_audio_out];
442     for (unsigned int ch_in=0;ch_in<m_HwInfo.m_nb_phys_audio_in;ch_in++) {
443         for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
444             {
445                 EfcGetMonitorMuteCmd getCmd;
446                 getCmd.m_input=ch_in;
447                 getCmd.m_output=ch_out;
448                 if (!doEfcOverAVC(*m_1394Service, arguments.node, getCmd)) {
449                     debugFatal("Cmd failed\n");
450                 }
451                 monitor_mute[ch_in][ch_out]=getCmd.m_value;
452             }
453         }
454     }
455
456     uint32_t monitor_solo[m_HwInfo.m_nb_phys_audio_in][m_HwInfo.m_nb_phys_audio_out];
457     for (unsigned int ch_in=0;ch_in<m_HwInfo.m_nb_phys_audio_in;ch_in++) {
458         for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
459             {
460                 EfcGetMonitorSoloCmd getCmd;
461                 getCmd.m_input=ch_in;
462                 getCmd.m_output=ch_out;
463                 if (!doEfcOverAVC(*m_1394Service, arguments.node, getCmd)) {
464                     debugFatal("Cmd failed\n");
465                 }
466                 monitor_solo[ch_in][ch_out]=getCmd.m_value;
467             }
468         }
469     }
470
471     printf("Mixer state info\n");
472     printf("================\n");
473     printf("        %10s %10s %10s %10s %10s\n","GAIN","PAN","SOLO","MUTE","NOMINAL");
474 #ifdef DO_PLAYBACK_MIX
475     printf("Playback mixer state:\n");
476     for (ch=0;ch<m_HwInfo.m_nb_1394_playback_channels;ch++) {
477         printf(" ch %2d: ", ch);
478         int j;
479         for (j=0;j<5;j++) {
480             if (j==0 || j==2)
481                 printf("%10u ", pbk_vol[ch][j]);
482             else
483                 printf("%10s ", "*");
484         }
485         printf("\n");
486     }
487 #endif
488
489 #ifdef DO_RECORD_MIX
490     printf("Record mixer state:\n");
491     for (ch=0;ch<m_HwInfo.m_nb_1394_record_channels;ch++) {
492         printf(" ch %2d: ", ch);
493         int j;
494         for (j=0;j<5;j++) {
495             printf("%10u ", rec_vol[ch][j]);
496         }
497         printf("\n");
498     }   
499 #endif
500
501 #ifdef DO_PHYS_OUT_MIX
502     printf("Output mixer state:\n");
503     for (ch=0;ch<m_HwInfo.m_nb_phys_audio_out;ch++) {
504         printf(" ch %2d: ", ch);
505         int j;
506         for (j=0;j<5;j++) {
507            if (j==0 || j==2 || j==4)
508                 printf("%10u ", out_vol[ch][j]);
509             else
510                 printf("%10s ", "*");
511         }
512         printf("\n");
513     }
514 #endif
515    
516 #ifdef DO_PHYS_IN_MIX
517     printf("Input mixer state:\n");
518     for (ch=0;ch<m_HwInfo.m_nb_phys_audio_in;ch++) {
519         printf(" ch %2d: ", ch);
520         int j;
521         for (j=0;j<5;j++) {
522             printf("%10u ", in_vol[ch][j]);
523         }
524         printf("\n");
525     }
526 #endif
527    
528     printf("\nMonitor state info\n");
529     printf("==================\n");
530    
531     printf("GAIN  ");
532     for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
533         printf("      OUT%02u",ch_out);
534     }
535     printf("\n");
536    
537     for (unsigned int ch_in=0;ch_in<m_HwInfo.m_nb_phys_audio_in;ch_in++) {
538         printf("ch %2u:", ch_in);
539         for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
540             printf(" %10u", monitor_gain[ch_in][ch_out]);
541         }
542         printf("\n");
543     }
544     printf("\n");
545    
546     printf("PAN   ");
547     for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
548         printf("      OUT%02u",ch_out);
549     }
550     printf("\n");
551    
552     for (unsigned int ch_in=0;ch_in<m_HwInfo.m_nb_phys_audio_in;ch_in++) {
553         printf("ch %2u:", ch_in);
554         for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
555             printf(" %10u", monitor_pan[ch_in][ch_out]);
556         }
557         printf("\n");
558     }
559     printf("\n");
560
561     printf("MUTE  ");
562     for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
563         printf("      OUT%02u",ch_out);
564     }
565     printf("\n");
566    
567     for (unsigned int ch_in=0;ch_in<m_HwInfo.m_nb_phys_audio_in;ch_in++) {
568         printf("ch %2u:", ch_in);
569         for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
570             printf(" %10u", monitor_mute[ch_in][ch_out]);
571         }
572         printf("\n");
573     }
574     printf("\n");
575
576     printf("SOLO  ");
577     for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
578         printf("      OUT%02u",ch_out);
579     }
580     printf("\n");
581    
582     for (unsigned int ch_in=0;ch_in<m_HwInfo.m_nb_phys_audio_in;ch_in++) {
583         printf("ch %2u:", ch_in);
584         for (unsigned int ch_out=0;ch_out<m_HwInfo.m_nb_phys_audio_out;ch_out++) {
585             printf(" %10u", monitor_solo[ch_in][ch_out]);
586         }
587         printf("\n");
588     }
589     printf("\n");
590
591     delete m_1394Service;
592
593     return 0;
594 }
595
Note: See TracBrowser for help on using the browser.