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

Revision 668, 17.7 kB (checked in by ppalmers, 16 years ago)

fix small bug in ECHO mixer commands

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