BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / drivers / audio / echo / generic / CMonitorCtrl.cpp
blobfc6e0d0aa84b4866ae70def495fd1a1583c5165a
1 // ****************************************************************************
2 //
3 // CMonitorCtrl.cpp
4 //
5 // Class to control monitors
6 //
7 // ----------------------------------------------------------------------------
8 //
9 // This file is part of Echo Digital Audio's generic driver library.
10 // Copyright Echo Digital Audio Corporation (c) 1998 - 2005
11 // All rights reserved
12 // www.echoaudio.com
14 // This library is free software; you can redistribute it and/or
15 // modify it under the terms of the GNU Lesser General Public
16 // License as published by the Free Software Foundation; either
17 // version 2.1 of the License, or (at your option) any later version.
19 // This library is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 // Lesser General Public License for more details.
24 // You should have received a copy of the GNU Lesser General Public
25 // License along with this library; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 // ****************************************************************************
30 #include "CEchoGals.h"
31 #include "CMonitorCtrl.h"
33 //*****************************************************************************
35 // Destructor (this class uses the default constructor)
37 //*****************************************************************************
39 CMonitorCtrl::~CMonitorCtrl()
41 Cleanup();
45 //*****************************************************************************
47 // Init
49 //*****************************************************************************
51 ECHOSTATUS CMonitorCtrl::Init(CEchoGals *pEG)
53 DWORD dwBytes;
54 DWORD dwArraySize;
56 m_Gains = NULL;
57 m_Mutes = NULL;
58 m_Pans = NULL;
59 m_PanDbs = NULL;
62 // Cache stuff
64 m_pEG = pEG;
65 m_wNumBussesIn = pEG->GetNumBussesIn();
66 m_wNumBussesOut = pEG->GetNumBussesOut();
69 // Indigo has no inputs; attempting to allocate 0 bytes
70 // causes a BSOD on Windows ME.
72 if ((0 == m_wNumBussesIn) || (0 == m_wNumBussesOut))
74 ECHO_DEBUGPRINTF(("CMonitorCtrl::Init - this card has no inputs!\n"));
75 return ECHOSTATUS_OK;
78 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
80 // Allocate the arrays
82 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
84 dwArraySize = m_wNumBussesIn * (m_wNumBussesOut >> 1);
86 dwBytes = sizeof(INT8) * dwArraySize;
87 OsAllocateNonPaged(dwBytes,(void **) &m_Gains);
88 if (NULL == m_Gains)
90 Cleanup();
91 return ECHOSTATUS_NO_MEM;
94 dwBytes = sizeof(WORD) * dwArraySize;
95 OsAllocateNonPaged(dwBytes,(void **) &m_Pans);
96 if (NULL == m_Pans)
98 Cleanup();
99 return ECHOSTATUS_NO_MEM;
102 dwBytes = sizeof(BYTE) * dwArraySize;
103 OsAllocateNonPaged(dwBytes,(void **) &m_Mutes);
104 if (NULL == m_Mutes)
106 Cleanup();
107 return ECHOSTATUS_NO_MEM;
110 dwBytes = sizeof(PAN_DB) * dwArraySize;
111 OsAllocateNonPaged(dwBytes,(void **) &m_PanDbs );
112 if (NULL == m_PanDbs)
114 Cleanup();
115 return ECHOSTATUS_NO_MEM;
118 //==============================================================
120 // Init the arrays
122 //==============================================================
124 WORD wBusIn,wBusOut,wIndex;
126 for (wBusIn = 0; wBusIn < m_wNumBussesIn; wBusIn++)
127 for (wBusOut = 0; wBusOut < m_wNumBussesOut; wBusOut += 2)
129 wIndex = GetIndex(wBusIn,wBusOut);
132 // Pan hard left for even inputs, hard right for odd
134 if (0 == (wBusIn & 1))
136 m_Pans[wIndex] = 0;
137 m_PanDbs[wIndex].iLeft = 0;
138 m_PanDbs[wIndex].iRight = (INT8) GENERIC_TO_DSP( ECHOGAIN_MUTED );
140 else
142 m_Pans[wIndex] = MAX_MIXER_PAN;
143 m_PanDbs[wIndex].iLeft = (INT8) GENERIC_TO_DSP( ECHOGAIN_MUTED );
144 m_PanDbs[wIndex].iRight = 0;
148 // Mute unless this is not a digital input
149 // and the input is going to the same-numbered output
151 if ( (wBusIn < m_pEG->GetFirstDigitalBusIn()) &&
152 ( (wBusIn & 0xfffe) == wBusOut ) )
154 m_Mutes[wIndex] = FALSE;
156 else
158 m_Mutes[wIndex] = TRUE;
162 // Put stuff in the comm page
164 SetGain(wBusIn,wBusOut,ECHOGAIN_UPDATE,FALSE);
168 // Now actually update the DSP
170 m_pEG->GetDspCommObject()->UpdateAudioOutLineLevel();
173 return ECHOSTATUS_OK;
175 } // Init
178 //*****************************************************************************
180 // Cleanup - free allocated memory
182 //*****************************************************************************
184 void CMonitorCtrl::Cleanup()
186 if (m_Gains)
187 OsFreeNonPaged(m_Gains);
189 if (m_Mutes)
190 OsFreeNonPaged(m_Mutes);
192 if (m_Pans)
193 OsFreeNonPaged(m_Pans);
195 if (m_PanDbs)
196 OsFreeNonPaged(m_PanDbs);
198 } // Cleanup
201 //*****************************************************************************
203 // Set and get gain
205 //*****************************************************************************
207 ECHOSTATUS CMonitorCtrl::SetGain
209 WORD wBusIn,
210 WORD wBusOut,
211 INT32 iGain,
212 BOOL fImmediate
215 ECHOSTATUS Status;
217 if (NULL == m_pEG)
218 return ECHOSTATUS_DSP_DEAD;
220 if ( (NULL == m_Gains) ||
221 (NULL == m_PanDbs) )
222 return ECHOSTATUS_NO_MEM;
224 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) )
226 ECHO_DEBUGPRINTF(("CMonitorCtrl::SetGain - out of range in %d out %d\n",
227 wBusIn,wBusOut));
228 return ECHOSTATUS_INVALID_PARAM;
232 // Round down to the nearest even bus
234 wBusOut &= 0xfffe;
237 // Figure out the index into the array
239 WORD wIndex = GetIndex(wBusIn,wBusOut);
241 if (ECHOGAIN_UPDATE == iGain)
243 iGain = DSP_TO_GENERIC( m_Gains[ wIndex ] );
245 else
247 if (iGain > ECHOGAIN_MAXOUT)
248 iGain = ECHOGAIN_MAXOUT;
249 else if (iGain < ECHOGAIN_MUTED)
250 iGain = ECHOGAIN_MUTED;
252 m_Gains[ wIndex ] = (INT8) GENERIC_TO_DSP( iGain );
255 // Gain has changed; store the notify
257 m_pEG->MixerControlChanged(ECHO_MONITOR,MXN_LEVEL,wBusIn,wBusOut);
261 // Use the gain that was passed in, the pan setting,
262 // and the mute to calculate the left and right gains
264 INT32 iLeft = iGain + DSP_TO_GENERIC( m_PanDbs[wIndex].iLeft );
265 INT32 iRight = iGain + DSP_TO_GENERIC( m_PanDbs[wIndex].iRight );
268 // Adjust left and right by the output bus gain
270 iLeft += m_pEG->m_BusOutLineLevels[wBusOut].GetGain();
271 iRight += m_pEG->m_BusOutLineLevels[wBusOut + 1].GetGain();
274 // Either mute or clamp
276 if (TRUE == m_Mutes[wIndex])
278 iLeft = ECHOGAIN_MUTED;
279 iRight = ECHOGAIN_MUTED;
281 else
283 if ( m_pEG->m_BusOutLineLevels[wBusOut].IsMuteOn() )
285 iLeft = ECHOGAIN_MUTED;
287 else
290 // Clamp left
292 if (iLeft > ECHOGAIN_MAXOUT)
293 iLeft = ECHOGAIN_MAXOUT;
294 else if (iLeft < ECHOGAIN_MUTED)
295 iLeft = ECHOGAIN_MUTED;
298 if ( m_pEG->m_BusOutLineLevels[wBusOut + 1].IsMuteOn() )
300 iRight = ECHOGAIN_MUTED;
302 else
305 // Clamp right
307 if (iRight > ECHOGAIN_MAXOUT)
308 iRight = ECHOGAIN_MAXOUT;
309 else if (iRight < ECHOGAIN_MUTED)
310 iRight = ECHOGAIN_MUTED;
317 // Set the left channel
319 if ( (NULL == m_pEG) ||
320 (NULL == m_pEG->GetDspCommObject() ) )
321 return ECHOSTATUS_DSP_DEAD;
324 Status = m_pEG->
325 GetDspCommObject()->
326 SetAudioMonitor( wBusOut,
327 wBusIn,
328 iLeft,
329 FALSE);
332 // Set the right channel
334 if (ECHOSTATUS_OK == Status)
336 Status = m_pEG->
337 GetDspCommObject()->
338 SetAudioMonitor( wBusOut + 1,
339 wBusIn,
340 iRight,
341 fImmediate);
344 return Status;
348 ECHOSTATUS CMonitorCtrl::GetGain(WORD wBusIn, WORD wBusOut, INT32 &iGain)
350 WORD wIndex = GetIndex(wBusIn,wBusOut);
352 if (NULL == m_Gains)
353 return ECHOSTATUS_NO_MEM;
355 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) )
357 ECHO_DEBUGPRINTF(("CMonitorCtrl::GetGain - out of range in %d out %d\n",
358 wBusIn,wBusOut));
359 return ECHOSTATUS_INVALID_PARAM;
362 iGain = DSP_TO_GENERIC( m_Gains[wIndex] );
364 return ECHOSTATUS_OK;
368 //*****************************************************************************
370 // Set and get mute
372 //*****************************************************************************
374 ECHOSTATUS CMonitorCtrl::SetMute
376 WORD wBusIn,
377 WORD wBusOut,
378 BOOL bMute,
379 BOOL fImmediate
382 if (NULL == m_Mutes)
383 return ECHOSTATUS_NO_MEM;
385 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) )
387 ECHO_DEBUGPRINTF(("CMonitorCtrl::SetMute - out of range in %d out %d\n",
388 wBusIn,wBusOut));
389 return ECHOSTATUS_INVALID_PARAM;
392 wBusOut &= 0xfffe;
394 WORD wIndex = GetIndex(wBusIn,wBusOut);
397 // Store the mute
399 m_Mutes[ wIndex ] = (BYTE) bMute;
402 // Store the notify
404 m_pEG->MixerControlChanged(ECHO_MONITOR,MXN_MUTE,wBusIn,wBusOut);
408 // Call the SetGain function to do all the heavy lifting
409 // Use the ECHOGAIN_UPDATE value to tell the function to
410 // recalculate the gain setting using the currently stored value.
412 return SetGain(wBusIn,wBusOut,ECHOGAIN_UPDATE,fImmediate);
416 ECHOSTATUS CMonitorCtrl::GetMute(WORD wBusIn, WORD wBusOut, BOOL &bMute)
418 wBusOut &= 0xfffe;
420 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) )
422 ECHO_DEBUGPRINTF(("CMonitorCtrl::GetMute - out of range in %d out %d\n",
423 wBusIn,wBusOut));
424 return ECHOSTATUS_INVALID_PARAM;
428 WORD wIndex = GetIndex(wBusIn,wBusOut);
430 if (NULL == m_Mutes)
431 return ECHOSTATUS_NO_MEM;
433 bMute = (BOOL) m_Mutes[ wIndex ];
435 return ECHOSTATUS_OK;
439 //*****************************************************************************
441 // Set and get pan
443 //*****************************************************************************
445 ECHOSTATUS CMonitorCtrl::SetPan(WORD wBusIn, WORD wBusOut, INT32 iPan)
447 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) )
449 ECHO_DEBUGPRINTF(("CMonitorCtrl::SetPan - out of range in %d out %d\n",
450 wBusIn,wBusOut));
451 return ECHOSTATUS_INVALID_PARAM;
454 wBusOut &= 0xfffe;
456 WORD wIndex = GetIndex(wBusIn,wBusOut);
458 if (NULL == m_Pans)
459 return ECHOSTATUS_NO_MEM;
462 // Clamp it and stash it
464 if (iPan < 0)
465 iPan = 0;
466 else if (iPan > MAX_MIXER_PAN)
467 iPan = MAX_MIXER_PAN;
469 m_Pans[wIndex] = (WORD) iPan;
472 // Convert this pan setting into left and right dB values
474 m_PanDbs[wIndex].iLeft = (INT8) GENERIC_TO_DSP( PanToDb(MAX_MIXER_PAN - iPan) );
475 m_PanDbs[wIndex].iRight = (INT8) GENERIC_TO_DSP( PanToDb(iPan) );
478 // Store the notify
480 m_pEG->MixerControlChanged(ECHO_MONITOR,MXN_PAN,wBusIn,wBusOut);
483 // Once again SetGain does all the hard work
485 return SetGain(wBusIn,wBusOut,ECHOGAIN_UPDATE);
489 ECHOSTATUS CMonitorCtrl::GetPan(WORD wBusIn, WORD wBusOut, INT32 &iPan)
491 if ( (wBusIn >= m_wNumBussesIn) || (wBusOut >= m_wNumBussesOut) )
493 ECHO_DEBUGPRINTF(("CMonitorCtrl::GetPan - out of range in %d out %d\n",
494 wBusIn,wBusOut));
495 return ECHOSTATUS_INVALID_PARAM;
499 wBusOut &= 0xfffe;
501 WORD wIndex = GetIndex(wBusIn,wBusOut);
503 if (NULL == m_Pans)
504 return ECHOSTATUS_NO_MEM;
506 iPan = m_Pans[ wIndex ];
508 return ECHOSTATUS_OK;