2 * Copyright (C) 2005-2008 by Pieter Palmers
4 * This file is part of FFADO
5 * FFADO = Free Firewire (pro-)audio drivers for linux
7 * FFADO is based upon FreeBoB.
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) version 3 of the License.
14 * This program 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.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "fireworks_device.h"
25 #include "fireworks_control.h"
26 #include "efc/efc_avc_cmd.h"
27 #include "efc/efc_cmd.h"
28 #include "efc/efc_cmds_mixer.h"
29 #include "efc/efc_cmds_monitor.h"
30 #include "efc/efc_cmds_hardware_ctrl.h"
37 // These classes provide support for the controls on the echo devices
40 MonitorControl::MonitorControl(FireWorks::Device
& p
, enum eMonitorControl c
)
41 : Control::MatrixMixer(&p
, "MonitorControl")
47 MonitorControl::MonitorControl(FireWorks::Device
& p
, enum eMonitorControl c
, std::string n
)
48 : Control::MatrixMixer(&p
, n
)
54 void MonitorControl::show()
56 debugOutput(DEBUG_LEVEL_NORMAL
, "MonitorControl\n");
59 std::string
MonitorControl::getRowName( const int row
)
61 std::ostringstream rowname
;
62 rowname
<< "IN" << row
;
63 debugOutput(DEBUG_LEVEL_VERBOSE
, "name for row %d is %s\n",
64 row
, rowname
.str().c_str());
68 std::string
MonitorControl::getColName( const int col
)
70 std::ostringstream colname
;
71 colname
<< "OUT" << col
;
72 debugOutput(DEBUG_LEVEL_VERBOSE
, "name for col %d is %s\n",
73 col
, colname
.str().c_str());
77 int MonitorControl::canWrite( const int row
, const int col
)
79 debugOutput(DEBUG_LEVEL_VERBOSE
, "canWrite for row %d col %d is %d\n",
84 double MonitorControl::setValue( const int row
, const int col
, const double val
)
87 bool did_command
=false;
89 if(row
>= (int)m_ParentDevice
.getHwInfo().m_nb_phys_audio_in
) {
90 debugError("specified row (%u) larger than number of rows (%d)\n",
91 row
, m_ParentDevice
.getHwInfo().m_nb_phys_audio_in
);
94 if(col
>= (int)m_ParentDevice
.getHwInfo().m_nb_phys_audio_out
) {
95 debugError("specified col (%u) larger than number of cols (%d)\n",
96 col
, m_ParentDevice
.getHwInfo().m_nb_phys_audio_out
);
100 // not a switch since we create variables
101 if(m_control
==eMC_Gain
) {
102 EfcSetMonitorGainCmd setCmd
;
103 setCmd
.m_input
= row
;
104 setCmd
.m_output
= col
;
105 setCmd
.m_value
= (uint32_t)val
;
106 if (!m_ParentDevice
.doEfcOverAVC(setCmd
))
108 debugError("Cmd failed\n");
110 // update the session block
111 m_ParentDevice
.m_session
.h
.monitorgains
[row
][col
] = setCmd
.m_value
;
112 retval
= setCmd
.m_value
;
115 if(m_control
==eMC_Pan
) {
116 EfcSetMonitorPanCmd setCmd
;
117 setCmd
.m_input
= row
;
118 setCmd
.m_output
= col
;
119 setCmd
.m_value
= (uint32_t)val
;
120 if (!m_ParentDevice
.doEfcOverAVC(setCmd
))
122 debugError("Cmd failed\n");
124 // update the session block
125 m_ParentDevice
.m_session
.s
.monitorpans
[row
][col
] = setCmd
.m_value
;
126 retval
= setCmd
.m_value
;
129 if(m_control
==eMC_Mute
) {
130 EfcSetMonitorMuteCmd setCmd
;
131 setCmd
.m_input
= row
;
132 setCmd
.m_output
= col
;
133 setCmd
.m_value
= (uint32_t)val
;
134 if (!m_ParentDevice
.doEfcOverAVC(setCmd
))
136 debugError("Cmd failed\n");
138 // update the session block
140 m_ParentDevice
.m_session
.s
.monitorflags
[row
][col
] |= ECHO_SESSION_MUTE_BIT
;
142 m_ParentDevice
.m_session
.s
.monitorflags
[row
][col
] &= ~ECHO_SESSION_MUTE_BIT
;
144 retval
= setCmd
.m_value
;
147 if(m_control
==eMC_Solo
) {
148 EfcSetMonitorSoloCmd setCmd
;
149 setCmd
.m_input
= row
;
150 setCmd
.m_output
= col
;
151 setCmd
.m_value
= (uint32_t)val
;
152 if (!m_ParentDevice
.doEfcOverAVC(setCmd
))
154 debugError("Cmd failed\n");
156 // update the session block
158 m_ParentDevice
.m_session
.s
.monitorflags
[row
][col
] |= ECHO_SESSION_SOLO_BIT
;
160 m_ParentDevice
.m_session
.s
.monitorflags
[row
][col
] &= ~ECHO_SESSION_SOLO_BIT
;
162 retval
= setCmd
.m_value
;
166 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for row %d col %d = %lf\n",
170 debugError("BUG: this should never happen due to enum\n");
175 double MonitorControl::getValue( const int row
, const int col
)
178 bool did_command
=false;
180 if(row
>= (int)m_ParentDevice
.getHwInfo().m_nb_phys_audio_in
) {
181 debugError("specified row (%u) larger than number of rows (%d)\n",
182 row
, m_ParentDevice
.getHwInfo().m_nb_phys_audio_in
);
185 if(col
>= (int)m_ParentDevice
.getHwInfo().m_nb_phys_audio_out
) {
186 debugError("specified col (%u) larger than number of cols (%d)\n",
187 col
, m_ParentDevice
.getHwInfo().m_nb_phys_audio_out
);
191 if(m_control
==eMC_Gain
) {
192 EfcGetMonitorGainCmd getCmd
;
195 if (!m_ParentDevice
.doEfcOverAVC(getCmd
))
197 debugError("Cmd failed\n");
199 retval
=getCmd
.m_value
;
202 if(m_control
==eMC_Pan
) {
203 EfcGetMonitorPanCmd getCmd
;
206 if (!m_ParentDevice
.doEfcOverAVC(getCmd
))
208 debugError("Cmd failed\n");
210 retval
=getCmd
.m_value
;
213 if(m_control
==eMC_Mute
) {
214 EfcGetMonitorMuteCmd getCmd
;
217 if (!m_ParentDevice
.doEfcOverAVC(getCmd
))
219 debugError("Cmd failed\n");
221 retval
=getCmd
.m_value
;
224 if(m_control
==eMC_Solo
) {
225 EfcGetMonitorSoloCmd getCmd
;
228 if (!m_ParentDevice
.doEfcOverAVC(getCmd
))
230 debugError("Cmd failed\n");
232 retval
=getCmd
.m_value
;
236 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for row %d col %d = %lf\n",
240 debugError("BUG: this should never happen due to enum\n");
245 int MonitorControl::getRowCount( )
247 return m_ParentDevice
.getHwInfo().m_nb_phys_audio_in
;
250 int MonitorControl::getColCount( )
252 return m_ParentDevice
.getHwInfo().m_nb_phys_audio_out
;
255 // --- the generic control element for single-value controls
257 SimpleControl::SimpleControl(FireWorks::Device
& p
,
259 enum eMixerCommand c
,
261 : Control::Continuous(&p
, "SimpleControl")
262 , m_Slave(new EfcGenericMixerCmd(t
, c
, channel
))
267 SimpleControl::SimpleControl(FireWorks::Device
& p
,
269 enum eMixerCommand c
,
272 : Control::Continuous(&p
, n
)
273 , m_Slave(new EfcGenericMixerCmd(t
, c
, channel
))
278 SimpleControl::~SimpleControl()
283 void SimpleControl::show()
285 debugOutput(DEBUG_LEVEL_NORMAL
, "SimpleControl\n");
286 if(m_Slave
) m_Slave
->showEfcCmd();
289 bool SimpleControl::setValue( const double val
)
292 m_Slave
->setType(eCT_Set
);
293 m_Slave
->m_value
= (uint32_t)val
;
294 if (!m_ParentDevice
.doEfcOverAVC(*m_Slave
))
296 debugError("Cmd failed\n");
300 // update the session block
301 switch(m_Slave
->getTarget()) {
302 case eMT_PlaybackMix
:
303 switch(m_Slave
->getCommand()) {
305 m_ParentDevice
.m_session
.h
.playbackgains
[m_Slave
->m_channel
] = m_Slave
->m_value
;
311 case eMT_PhysicalOutputMix
:
312 switch(m_Slave
->getCommand()) {
314 m_ParentDevice
.m_session
.h
.outputgains
[m_Slave
->m_channel
] = m_Slave
->m_value
;
323 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for channel %d to %lf = %u\n",
324 m_Slave
->m_channel
, val
, m_Slave
->m_value
);
327 debugError("No slave EFC command present\n");
332 double SimpleControl::getValue( )
335 m_Slave
->setType(eCT_Get
);
336 if (!m_ParentDevice
.doEfcOverAVC(*m_Slave
))
338 debugError("Cmd failed\n");
341 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for channel %d = %u\n",
342 m_Slave
->m_channel
, m_Slave
->m_value
);
343 return m_Slave
->m_value
;
345 debugError("No slave EFC command present\n");
350 // --- the generic control element for on-off controls
352 BinaryControl::BinaryControl(FireWorks::Device
& p
,
354 enum eMixerCommand c
,
355 int channel
, int bit
)
356 : Control::Discrete(&p
, "BinaryControl")
358 , m_Slave(new EfcGenericMixerCmd(t
, c
, channel
))
363 BinaryControl::BinaryControl(FireWorks::Device
& p
,
365 enum eMixerCommand c
,
366 int channel
, int bit
,
368 : Control::Discrete(&p
, n
)
370 , m_Slave(new EfcGenericMixerCmd(t
, c
, channel
))
375 BinaryControl::~BinaryControl()
380 void BinaryControl::show()
382 debugOutput(DEBUG_LEVEL_NORMAL
, "BinaryControl\n");
383 if(m_Slave
) m_Slave
->showEfcCmd();
386 bool BinaryControl::setValue( const int val
)
393 m_Slave
->setType(eCT_Get
);
394 reg
=m_Slave
->m_value
;
403 m_Slave
->setType(eCT_Set
);
404 m_Slave
->m_value
=reg
;
405 if (!m_ParentDevice
.doEfcOverAVC(*m_Slave
))
407 debugError("Cmd failed\n");
411 // update the session block
412 switch(m_Slave
->getTarget()) {
413 case eMT_PlaybackMix
:
414 switch(m_Slave
->getCommand()) {
416 m_ParentDevice
.m_session
.s
.playbacks
[m_Slave
->m_channel
].mute
= m_Slave
->m_value
;
419 m_ParentDevice
.m_session
.s
.playbacks
[m_Slave
->m_channel
].solo
= m_Slave
->m_value
;
425 case eMT_PhysicalOutputMix
:
426 switch(m_Slave
->getCommand()) {
428 m_ParentDevice
.m_session
.s
.outputs
[m_Slave
->m_channel
].mute
= m_Slave
->m_value
;
431 m_ParentDevice
.m_session
.s
.outputs
[m_Slave
->m_channel
].shift
= m_Slave
->m_value
;
437 case eMT_PhysicalInputMix
:
438 switch(m_Slave
->getCommand()) {
440 // m_ParentDevice.m_session.s.inputs[m_Slave->m_channel].pad = m_Slave->m_value;
443 m_ParentDevice
.m_session
.s
.inputs
[m_Slave
->m_channel
].shift
= m_Slave
->m_value
;
453 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue for channel %d to %d (reg: 0x%08X => 0x%08X)\n",
454 m_Slave
->m_channel
, val
, old_reg
, reg
);
457 debugError("No slave EFC command present\n");
462 int BinaryControl::getValue( )
465 // workaround for the failing get nominal command for input channels
466 // get it from the session block
467 if ((m_Slave
->getTarget() == eMT_PhysicalInputMix
)
468 && (m_Slave
->getCommand() == eMC_Nominal
)) {
469 int val
= m_ParentDevice
.m_session
.s
.inputs
[m_Slave
->m_channel
].shift
;
470 debugOutput(DEBUG_LEVEL_VERBOSE
, "input pad workaround: %08X\n", val
);
473 m_Slave
->setType(eCT_Get
);
474 if (!m_ParentDevice
.doEfcOverAVC(*m_Slave
))
476 debugError("Cmd failed\n");
479 bool val
= (m_Slave
->m_value
& (1<<m_bit
)) != 0;
480 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue for channel %d: reg: 0x%08X, result=%d\n",
481 m_Slave
->m_channel
, m_Slave
->m_value
, val
);
484 debugError("No slave EFC command present\n");
489 // --- control element for flags
491 SpdifModeControl::SpdifModeControl(FireWorks::Device
& parent
)
492 : Control::Discrete(&parent
, "SpdifModeControl")
493 , m_ParentDevice(parent
)
497 SpdifModeControl::SpdifModeControl(FireWorks::Device
& parent
,
499 : Control::Discrete(&parent
, n
)
500 , m_ParentDevice(parent
)
504 SpdifModeControl::~SpdifModeControl()
508 void SpdifModeControl::show()
510 debugOutput(DEBUG_LEVEL_NORMAL
, "SpdifModeControl\n");
513 bool SpdifModeControl::setValue( const int val
)
515 EfcChangeFlagsCmd setCmd
;
517 setCmd
.m_setmask
= FIREWORKS_EFC_FLAG_SPDIF_PRO
;
519 setCmd
.m_clearmask
= FIREWORKS_EFC_FLAG_SPDIF_PRO
;
521 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue val: %d setmask: %08X, clear: %08X\n",
522 val
, setCmd
.m_setmask
, setCmd
.m_clearmask
);
523 if (!m_ParentDevice
.doEfcOverAVC(setCmd
))
525 debugError("Cmd failed\n");
531 int SpdifModeControl::getValue( )
533 EfcGetFlagsCmd getCmd
;
534 if (!m_ParentDevice
.doEfcOverAVC(getCmd
))
536 debugError("Cmd failed\n");
539 debugOutput(DEBUG_LEVEL_VERBOSE
, "got flags: %08X\n",
541 if(getCmd
.m_flags
& FIREWORKS_EFC_FLAG_SPDIF_PRO
) return 1;
545 // --- io config controls
547 IOConfigControl::IOConfigControl(FireWorks::Device
& parent
,
548 enum eIOConfigRegister r
)
549 : Control::Discrete(&parent
, "IOConfigControl")
550 , m_Slave(new EfcGenericIOConfigCmd(r
))
551 , m_ParentDevice(parent
)
555 IOConfigControl::IOConfigControl(FireWorks::Device
& parent
,
556 enum eIOConfigRegister r
,
558 : Control::Discrete(&parent
, n
)
559 , m_Slave(new EfcGenericIOConfigCmd(r
))
560 , m_ParentDevice(parent
)
564 IOConfigControl::~IOConfigControl()
569 void IOConfigControl::show()
571 debugOutput(DEBUG_LEVEL_NORMAL
, "IOConfigControl\n");
572 if(m_Slave
) m_Slave
->showEfcCmd();
575 bool IOConfigControl::setValue( const int val
)
578 m_Slave
->setType(eCT_Set
);
579 m_Slave
->m_value
=val
;
580 if (!m_ParentDevice
.doEfcOverAVC(*m_Slave
))
582 debugError("Cmd failed\n");
585 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue to %d \n", val
);
588 debugError("No slave EFC command present\n");
593 int IOConfigControl::getValue( )
596 m_Slave
->setType(eCT_Get
);
597 if (!m_ParentDevice
.doEfcOverAVC(*m_Slave
))
599 debugError("Cmd failed\n");
602 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue: result=%d\n",
604 return m_Slave
->m_value
;
606 debugError("No slave EFC command present\n");
611 // PlaybackRouting controls
613 PlaybackRoutingControl::PlaybackRoutingControl(FireWorks::Device
& parent
)
614 : Control::Discrete(&parent
, "PlaybackRouting")
615 , m_ParentDevice(parent
)
619 PlaybackRoutingControl::PlaybackRoutingControl(FireWorks::Device
& parent
, std::string n
)
620 : Control::Discrete(&parent
, n
)
621 , m_ParentDevice(parent
)
625 PlaybackRoutingControl::~PlaybackRoutingControl()
629 void PlaybackRoutingControl::show()
631 debugOutput(DEBUG_LEVEL_NORMAL
, "PlaybackRouting\n");
634 bool PlaybackRoutingControl::GetState(EfcIsocMapIOConfigCmd
*cmd
)
636 cmd
->m_num_playmap_entries
= 3;
637 cmd
->m_playmap
[0] = 0;
638 cmd
->m_playmap
[1] = 0;
639 cmd
->m_playmap
[2] = 0;
641 cmd
->setType(eCT_Get
);
642 if (!m_ParentDevice
.doEfcOverAVC(*cmd
))
649 bool PlaybackRoutingControl::setValue(int idx
, int v
)
651 EfcIsocMapIOConfigCmd setCmd
;
655 * Playback Stream ch1/2: 0
656 * Playback Stream ch3/4: 2
657 * Playback Stream ch5/6: 4
659 unsigned int value
= v
* 2;
661 if (!GetState(&setCmd
)) {
662 debugError("Cmd failed\n");
666 setCmd
.m_playmap
[idx
] = value
;
668 setCmd
.setType(eCT_Set
);
669 if (!m_ParentDevice
.doEfcOverAVC(setCmd
)) {
670 debugError("Cmd failed\n");
674 debugOutput(DEBUG_LEVEL_VERBOSE
, "setValue: result=%d:%d\n",
676 setCmd
.m_playmap
[idx
]);
681 int PlaybackRoutingControl::getValue(int idx
)
683 EfcIsocMapIOConfigCmd getCmd
;
686 debugOutput(DEBUG_LEVEL_VERBOSE
, "getValue: result=[%d][%d][%d]\n",
689 getCmd
.m_playmap
[2]);
691 return getCmd
.m_playmap
[idx
] / 2;
694 // control to get hardware information
695 HwInfoControl::HwInfoControl(FireWorks::Device
& p
,
697 : Control::Discrete(&p
, "HwInfoControl")
703 HwInfoControl::HwInfoControl(FireWorks::Device
& p
,
706 : Control::Discrete(&p
, n
)
712 HwInfoControl::~HwInfoControl()
716 int HwInfoControl::getValue()
719 case eHIF_PhysicalAudioOutCount
:
720 return m_ParentDevice
.getHwInfo().m_nb_phys_audio_out
;
721 case eHIF_PhysicalAudioInCount
:
722 return m_ParentDevice
.getHwInfo().m_nb_phys_audio_in
;
723 case eHIF_1394PlaybackCount
:
724 return m_ParentDevice
.getHwInfo().m_nb_1394_playback_channels
;
725 case eHIF_1394RecordCount
:
726 return m_ParentDevice
.getHwInfo().m_nb_1394_record_channels
;
727 case eHIF_GroupOutCount
:
728 return m_ParentDevice
.getHwInfo().m_nb_out_groups
;
729 case eHIF_GroupInCount
:
730 return m_ParentDevice
.getHwInfo().m_nb_in_groups
;
731 case eHIF_PhantomPower
:
732 return m_ParentDevice
.getHwInfo().hasSoftwarePhantom();
733 case eHIF_OpticalInterface
:
734 return m_ParentDevice
.getHwInfo().hasOpticalInterface();
735 case eHIF_PlaybackRouting
:
736 return m_ParentDevice
.getHwInfo().hasPlaybackRouting();
738 debugError("Bogus field\n");
743 void HwInfoControl::show()
745 debugOutput(DEBUG_LEVEL_NORMAL
, "HwInfoControl\n");
749 // control to save settings
750 MultiControl::MultiControl(FireWorks::Device
& p
, enum eType t
)
751 : Control::Discrete(&p
, "MultiControl")
757 MultiControl::MultiControl(FireWorks::Device
& p
,
758 enum eType t
, std::string n
)
759 : Control::Discrete(&p
, n
)
765 MultiControl::~MultiControl()
769 bool MultiControl::setValue(const int v
)
773 debugOutput(DEBUG_LEVEL_VERBOSE
, "saving session\n");
774 return m_ParentDevice
.saveSession();
776 debugOutput(DEBUG_LEVEL_VERBOSE
, "indentify device\n");
779 if (!m_ParentDevice
.doEfcOverAVC(cmd
))
781 debugError("Cmd failed\n");
787 debugError("Bad type\n");
792 void MultiControl::show()
794 debugOutput(DEBUG_LEVEL_NORMAL
, "MultiControl\n");
797 debugOutput(DEBUG_LEVEL_NORMAL
, "Type: SaveSession\n");
800 debugOutput(DEBUG_LEVEL_NORMAL
, "Type: Identify\n");
803 debugError("Bad type\n");