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

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

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

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