xref: /haiku/src/add-ons/kernel/drivers/audio/echo/generic/CPipeOutCtrl.cpp (revision d3503944f052536d75afff2b89c0a9f0fdc9e83e)
13895766dSshatty // ****************************************************************************
23895766dSshatty //
33895766dSshatty //		CPipeOutCtrl.cpp
43895766dSshatty //
53895766dSshatty //		Class to control output pipes on cards with or without vmixers.
63895766dSshatty //
7c2ddc71cSJérôme Duval // ----------------------------------------------------------------------------
8c2ddc71cSJérôme Duval //
9626bc4beSJérôme Duval // This file is part of Echo Digital Audio's generic driver library.
10626bc4beSJérôme Duval // Copyright Echo Digital Audio Corporation (c) 1998 - 2005
113895766dSshatty // All rights reserved
123895766dSshatty // www.echoaudio.com
133895766dSshatty //
14626bc4beSJérôme Duval // This library is free software; you can redistribute it and/or
15626bc4beSJérôme Duval // modify it under the terms of the GNU Lesser General Public
16626bc4beSJérôme Duval // License as published by the Free Software Foundation; either
17626bc4beSJérôme Duval // version 2.1 of the License, or (at your option) any later version.
183895766dSshatty //
19626bc4beSJérôme Duval // This library is distributed in the hope that it will be useful,
20c2ddc71cSJérôme Duval // but WITHOUT ANY WARRANTY; without even the implied warranty of
21626bc4beSJérôme Duval // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22626bc4beSJérôme Duval // Lesser General Public License for more details.
233895766dSshatty //
24626bc4beSJérôme Duval // You should have received a copy of the GNU Lesser General Public
25626bc4beSJérôme Duval // License along with this library; if not, write to the Free Software
26626bc4beSJérôme Duval // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
273895766dSshatty //
283895766dSshatty // ****************************************************************************
293895766dSshatty 
303895766dSshatty #include "CEchoGals.h"
313895766dSshatty #include "CPipeOutCtrl.h"
323895766dSshatty 
333895766dSshatty extern INT32 PanToDb( INT32 iPan );
343895766dSshatty 
35c2ddc71cSJérôme Duval 
36c2ddc71cSJérôme Duval //*****************************************************************************
37c2ddc71cSJérôme Duval //
38c2ddc71cSJérôme Duval // Destructor (this class uses the default constructor)
39c2ddc71cSJérôme Duval //
40c2ddc71cSJérôme Duval //*****************************************************************************
41c2ddc71cSJérôme Duval 
~CPipeOutCtrl()42c2ddc71cSJérôme Duval CPipeOutCtrl::~CPipeOutCtrl()
43c2ddc71cSJérôme Duval {
44c2ddc71cSJérôme Duval 	Cleanup();
45c2ddc71cSJérôme Duval }
46c2ddc71cSJérôme Duval 
47c2ddc71cSJérôme Duval 
483895766dSshatty //*****************************************************************************
493895766dSshatty //
503895766dSshatty // Init
513895766dSshatty //
523895766dSshatty //*****************************************************************************
533895766dSshatty 
Init(CEchoGals * pEG)543895766dSshatty ECHOSTATUS CPipeOutCtrl::Init(CEchoGals *pEG)
553895766dSshatty {
563895766dSshatty 	DWORD	dwBytes;
573895766dSshatty 	WORD	wPipe,wStereoBus;
583895766dSshatty 
593895766dSshatty 	m_Gains = NULL;
603895766dSshatty 	m_Mutes = NULL;
613895766dSshatty 	m_Pans = NULL;
623895766dSshatty 	m_PanDbs = NULL;
633895766dSshatty 
643895766dSshatty 	//
653895766dSshatty 	// Cache stuff
663895766dSshatty 	//
673895766dSshatty 	m_pEG = pEG;
683895766dSshatty 	m_wNumPipesOut = pEG->GetNumPipesOut();
693895766dSshatty 	m_wNumBussesOut = pEG->GetNumBussesOut();
703895766dSshatty 	m_fHasVmixer = pEG->HasVmixer();
713895766dSshatty 
723895766dSshatty 	//
733895766dSshatty 	// Allocate the arrays
743895766dSshatty 	//
753895766dSshatty 	if (m_fHasVmixer)
763895766dSshatty 	{
773895766dSshatty 		WORD wNumStereoBusses = m_wNumBussesOut >> 1;
783895766dSshatty 
793895766dSshatty 		//
803895766dSshatty 		// Allocate arrays for vmixer support
813895766dSshatty 		//
823895766dSshatty 		dwBytes = sizeof(INT8) * m_wNumPipesOut * wNumStereoBusses;
833895766dSshatty 		OsAllocateNonPaged(dwBytes,(void **) &m_Gains);
843895766dSshatty 		if (NULL == m_Gains)
853895766dSshatty 		{
863895766dSshatty 			return ECHOSTATUS_NO_MEM;
873895766dSshatty 		}
883895766dSshatty 
893895766dSshatty 		dwBytes = sizeof(BYTE) * m_wNumPipesOut * wNumStereoBusses;
903895766dSshatty 		OsAllocateNonPaged(dwBytes,(void **) &m_Mutes);
913895766dSshatty 		if (NULL == m_Mutes)
923895766dSshatty 		{
933895766dSshatty 			Cleanup();
943895766dSshatty 			return ECHOSTATUS_NO_MEM;
953895766dSshatty 		}
963895766dSshatty 
973895766dSshatty 		dwBytes = sizeof(WORD) * m_wNumPipesOut * wNumStereoBusses;
983895766dSshatty 		OsAllocateNonPaged(dwBytes,(void **) &m_Pans);
993895766dSshatty 		if (NULL == m_Pans)
1003895766dSshatty 		{
1013895766dSshatty 			Cleanup();
1023895766dSshatty 			return ECHOSTATUS_NO_MEM;
1033895766dSshatty 		}
1043895766dSshatty 
1053895766dSshatty 		dwBytes = sizeof(PAN_DB) * m_wNumPipesOut * wNumStereoBusses;
1063895766dSshatty 		OsAllocateNonPaged(dwBytes,(void **) &m_PanDbs);
1073895766dSshatty 		if (NULL == m_PanDbs)
1083895766dSshatty 		{
1093895766dSshatty 			Cleanup();
1103895766dSshatty 			return ECHOSTATUS_NO_MEM;
1113895766dSshatty 		}
1123895766dSshatty 
1133895766dSshatty 		//
1143895766dSshatty 		// Initialize pans and mutes
1153895766dSshatty 		//
1163895766dSshatty 		for (wPipe = 0; wPipe < m_wNumPipesOut; wPipe++)
117*d3503944SPulkoMandy 		{
1183895766dSshatty 			for (wStereoBus = 0; wStereoBus < wNumStereoBusses; wStereoBus++)
1193895766dSshatty 			{
1203895766dSshatty 				WORD wIndex;
1213895766dSshatty 
1223895766dSshatty 				wIndex = GetIndex(wPipe,wStereoBus << 1);
1233895766dSshatty 
1243895766dSshatty 				//
1253895766dSshatty 				//	Pans
1263895766dSshatty 				//
1273895766dSshatty 				if (0 == (wPipe & 1))
1283895766dSshatty 				{
1293895766dSshatty 					//
1303895766dSshatty 					// Even channel - pan hard left
1313895766dSshatty 					//
1323895766dSshatty 					m_Pans[wIndex] = 0;
1333895766dSshatty 					m_PanDbs[wIndex].iLeft = 0;
1343895766dSshatty 					m_PanDbs[wIndex].iRight = GENERIC_TO_DSP( ECHOGAIN_MUTED );
1353895766dSshatty 				}
1363895766dSshatty 				else
1373895766dSshatty 				{
1383895766dSshatty 					//
1393895766dSshatty 					// Odd channel - pan hard right
1403895766dSshatty 					//
1413895766dSshatty 					m_Pans[wIndex] = MAX_MIXER_PAN;
1423895766dSshatty 					m_PanDbs[wIndex].iLeft = GENERIC_TO_DSP( ECHOGAIN_MUTED );
1433895766dSshatty 					m_PanDbs[wIndex].iRight = 0;
1443895766dSshatty 				}
1453895766dSshatty 
1463895766dSshatty 				//
1473895766dSshatty 				// Mutes
1483895766dSshatty 				//
1493895766dSshatty 				if ((wPipe >> 1) == wStereoBus)
1503895766dSshatty 				{
1513895766dSshatty 					m_Mutes[wIndex] = FALSE;
1523895766dSshatty 				}
1533895766dSshatty 				else
1543895766dSshatty 				{
1553895766dSshatty 					m_Mutes[wIndex] = TRUE;
1563895766dSshatty 				}
1573895766dSshatty 
1583895766dSshatty 				//
1593895766dSshatty 				// Set the gain to the DSP; use fImmedate = FALSE here
1603895766dSshatty 				// to make this faster
1613895766dSshatty 				//
1623895766dSshatty 				SetGain(wPipe,wStereoBus << 1,ECHOGAIN_UPDATE,FALSE);
1633895766dSshatty 
1643895766dSshatty 			}
165*d3503944SPulkoMandy 		}
1663895766dSshatty 
1673895766dSshatty 		//
1683895766dSshatty 		// Set the gain one more time with the immediate flag set to
1693895766dSshatty 		// make sure the DSP gets the message
1703895766dSshatty 		//
1713895766dSshatty 		SetGain(0,0,ECHOGAIN_UPDATE,TRUE);
1723895766dSshatty 	}
1733895766dSshatty 	else
1743895766dSshatty 	{
1753895766dSshatty 		//
1763895766dSshatty 		// Allocate arrays for no vmixer support - don't need pans
1773895766dSshatty 		//
1783895766dSshatty 		dwBytes = sizeof(INT8) * m_wNumPipesOut;
1793895766dSshatty 		OsAllocateNonPaged(dwBytes,(void **) &m_Gains);
1803895766dSshatty 		if (NULL == m_Gains)
1813895766dSshatty 		{
1823895766dSshatty 			return ECHOSTATUS_NO_MEM;
1833895766dSshatty 		}
1843895766dSshatty 
1853895766dSshatty 		dwBytes = sizeof(BYTE) * m_wNumPipesOut;
1863895766dSshatty 		OsAllocateNonPaged(dwBytes,(void **) &m_Mutes);
1873895766dSshatty 		if (NULL == m_Mutes)
1883895766dSshatty 		{
1893895766dSshatty 			OsFreeNonPaged(m_Gains);
1903895766dSshatty 			return ECHOSTATUS_NO_MEM;
1913895766dSshatty 		}
1923895766dSshatty 
1933895766dSshatty 	}
1943895766dSshatty 
1953895766dSshatty 	return ECHOSTATUS_OK;
1963895766dSshatty 
1973895766dSshatty }	// Init
1983895766dSshatty 
1993895766dSshatty 
2003895766dSshatty //*****************************************************************************
2013895766dSshatty //
2023895766dSshatty // Cleanup - free allocated memory
2033895766dSshatty //
2043895766dSshatty //*****************************************************************************
2053895766dSshatty 
Cleanup()2063895766dSshatty void CPipeOutCtrl::Cleanup()
2073895766dSshatty {
2083895766dSshatty 	if (m_Gains)
2093895766dSshatty 		OsFreeNonPaged(m_Gains);
2103895766dSshatty 
2113895766dSshatty 	if (m_Mutes)
2123895766dSshatty 		OsFreeNonPaged(m_Mutes);
2133895766dSshatty 
2143895766dSshatty 	if (m_Pans)
2153895766dSshatty 		OsFreeNonPaged(m_Pans);
2163895766dSshatty 
2173895766dSshatty 	if (m_PanDbs)
2183895766dSshatty 		OsFreeNonPaged(m_PanDbs);
2193895766dSshatty 
2203895766dSshatty }	// Cleanup
2213895766dSshatty 
2223895766dSshatty 
2233895766dSshatty //*****************************************************************************
2243895766dSshatty //
2253895766dSshatty // Set and get gain
2263895766dSshatty //
2273895766dSshatty // For cards without vmixers, output bus gain is not handled by the DSP.
2283895766dSshatty // Instead, the driver adjusts the output pipe volumes by the output bus gain
2293895766dSshatty // and sends that value to the DSP.
2303895766dSshatty //
2313895766dSshatty // For cards with vmixers, the output bus gain is handled by the DSP, so
2323895766dSshatty // the gain setting does not need to take into account the output bus gain
2333895766dSshatty // stored by the driver.
2343895766dSshatty //
2353895766dSshatty //*****************************************************************************
2363895766dSshatty 
SetGain(WORD wPipeOut,WORD wBusOut,INT32 iGain,BOOL fImmediate)2373895766dSshatty ECHOSTATUS CPipeOutCtrl::SetGain
2383895766dSshatty (
2393895766dSshatty 	WORD 	wPipeOut,
2403895766dSshatty 	WORD 	wBusOut,
2413895766dSshatty 	INT32 iGain,
2423895766dSshatty 	BOOL 	fImmediate
2433895766dSshatty )
2443895766dSshatty {
245c2ddc71cSJérôme Duval 	INT32 iBusOutGain;
2463895766dSshatty 	ECHOSTATUS Status;
2473895766dSshatty 
2483895766dSshatty 	if ( NULL == m_pEG)
2493895766dSshatty 		return ECHOSTATUS_DSP_DEAD;
2503895766dSshatty 
2513895766dSshatty 	if (!m_fHasVmixer && (wPipeOut != wBusOut))
2523895766dSshatty 		return ECHOSTATUS_OK;
2533895766dSshatty 
2543895766dSshatty 	if ((NULL == m_Gains) || (NULL == m_Mutes))
2553895766dSshatty 		return ECHOSTATUS_NO_MEM;
2563895766dSshatty 
257c2ddc71cSJérôme Duval 	if ((wPipeOut >= m_wNumPipesOut) || (wBusOut >= m_wNumBussesOut))
258c2ddc71cSJérôme Duval 	{
259c2ddc71cSJérôme Duval 		ECHO_DEBUGPRINTF(("CPipeOutCtrl::SetGain - out of range pipe %d bus %d\n",
260c2ddc71cSJérôme Duval 								wPipeOut,wBusOut));
261c2ddc71cSJérôme Duval 		return ECHOSTATUS_INVALID_PARAM;
262c2ddc71cSJérôme Duval 	}
263c2ddc71cSJérôme Duval 
2643895766dSshatty 	WORD wIndex = GetIndex(wPipeOut,wBusOut);
2653895766dSshatty 
2663895766dSshatty 	/*
2673895766dSshatty 	ECHO_DEBUGPRINTF(("CPipeOutCtrl::SetGain pipe %d  bus %d  gain 0x%lx  index %d\n",
2683895766dSshatty 							wPipeOut,wBusOut,iGain,wIndex));
2693895766dSshatty 	*/
2703895766dSshatty 
2713895766dSshatty 	if (ECHOGAIN_UPDATE == iGain)
2723895766dSshatty 	{
2733895766dSshatty 		iGain = DSP_TO_GENERIC( m_Gains[ wIndex ] );
2743895766dSshatty 	}
2753895766dSshatty 	else
2763895766dSshatty 	{
2773895766dSshatty 		if (iGain > ECHOGAIN_MAXOUT)
2783895766dSshatty 			iGain = ECHOGAIN_MAXOUT;
2793895766dSshatty 		else if (iGain < ECHOGAIN_MUTED)
2803895766dSshatty 			iGain = ECHOGAIN_MUTED;
2813895766dSshatty 
282be188ae1SJérôme Duval 		m_Gains[ wIndex ] = (INT8) GENERIC_TO_DSP( iGain );
2833895766dSshatty 
2843895766dSshatty 		//
2853895766dSshatty 		// Store the notify
2863895766dSshatty 		//
2873895766dSshatty 		m_pEG->MixerControlChanged(ECHO_PIPE_OUT,MXN_LEVEL,wPipeOut,wBusOut);
2883895766dSshatty 	}
2893895766dSshatty 
2903895766dSshatty 	if (m_fHasVmixer)
2913895766dSshatty 	{
2923895766dSshatty 		wBusOut &= 0xfffe;
2933895766dSshatty 
2943895766dSshatty 		if (NULL == m_Pans)
2953895766dSshatty 			return ECHOSTATUS_NO_MEM;
2963895766dSshatty 
2973895766dSshatty 		//
2983895766dSshatty 		// For vmixer cards, the DSP handles the output bus gain,
2993895766dSshatty 		// so no need to account for it here.  Vmixer output pipes
3003895766dSshatty 		// do have to handle panning.
3013895766dSshatty 		//
302c2ddc71cSJérôme Duval 		INT32 iLeft = iGain + DSP_TO_GENERIC( m_PanDbs[wIndex].iLeft );
303c2ddc71cSJérôme Duval 		INT32 iRight = iGain + DSP_TO_GENERIC( m_PanDbs[wIndex].iRight );
3043895766dSshatty 
305c2ddc71cSJérôme Duval 		//
306c2ddc71cSJérôme Duval 		// Add master gain values
307c2ddc71cSJérôme Duval 		//
308c2ddc71cSJérôme Duval 		iBusOutGain = m_pEG->m_BusOutLineLevels[wBusOut].GetGain();
309c2ddc71cSJérôme Duval 		iLeft += iBusOutGain;
310c2ddc71cSJérôme Duval 		iBusOutGain = m_pEG->m_BusOutLineLevels[wBusOut+1].GetGain();
311c2ddc71cSJérôme Duval 		iRight += iBusOutGain;
312c2ddc71cSJérôme Duval 
313c2ddc71cSJérôme Duval 		//
314c2ddc71cSJérôme Duval 		// Muting and clamping
315c2ddc71cSJérôme Duval 		//
3163895766dSshatty 		if (m_Mutes[wIndex])
3173895766dSshatty 		{
3183895766dSshatty 			iLeft = ECHOGAIN_MUTED;
3193895766dSshatty 			iRight = ECHOGAIN_MUTED;
3203895766dSshatty 		}
3213895766dSshatty 		else
3223895766dSshatty 		{
323c2ddc71cSJérôme Duval 			if (  (m_pEG->m_BusOutLineLevels[wBusOut].IsMuteOn()) ||
324c2ddc71cSJérôme Duval 					(iLeft < ECHOGAIN_MUTED))
325c2ddc71cSJérôme Duval 			{
3263895766dSshatty 				iLeft = ECHOGAIN_MUTED;
327c2ddc71cSJérôme Duval 			}
3283895766dSshatty 			else if (iLeft > ECHOGAIN_MAXOUT)
329c2ddc71cSJérôme Duval 			{
3303895766dSshatty 				iLeft = ECHOGAIN_MAXOUT;
331c2ddc71cSJérôme Duval 			}
3323895766dSshatty 
333c2ddc71cSJérôme Duval 			if (  (m_pEG->m_BusOutLineLevels[wBusOut + 1].IsMuteOn()) ||
334c2ddc71cSJérôme Duval 					(iRight < ECHOGAIN_MUTED))
335c2ddc71cSJérôme Duval 			{
3363895766dSshatty 				iRight = ECHOGAIN_MUTED;
337c2ddc71cSJérôme Duval 			}
3383895766dSshatty 			else if (iRight > ECHOGAIN_MAXOUT)
339c2ddc71cSJérôme Duval 			{
3403895766dSshatty 				iRight = ECHOGAIN_MAXOUT;
3413895766dSshatty 			}
342c2ddc71cSJérôme Duval 		}
3433895766dSshatty 
3443895766dSshatty 		//
3453895766dSshatty 		// Set the left channel gain
3463895766dSshatty 		//
3473895766dSshatty 		Status = m_pEG->GetDspCommObject()->SetPipeOutGain(wPipeOut,
3483895766dSshatty 																			wBusOut,
3493895766dSshatty 																			iLeft,
3503895766dSshatty 																			FALSE);
3513895766dSshatty 		if (ECHOSTATUS_OK == Status)
3523895766dSshatty 		{
353c2ddc71cSJérôme Duval 			//
354c2ddc71cSJérôme Duval 			// And the right channel
355c2ddc71cSJérôme Duval 			//
3563895766dSshatty 			Status = m_pEG->GetDspCommObject()->SetPipeOutGain(wPipeOut,
3573895766dSshatty 																				wBusOut + 1,
3583895766dSshatty 																				iRight,
3593895766dSshatty 																				fImmediate);
3603895766dSshatty 		}
3613895766dSshatty 
3623895766dSshatty 	}
3633895766dSshatty 	else
3643895766dSshatty 	{
3653895766dSshatty 		//
3663895766dSshatty 		// Add this output pipe gain to the output bus gain
3673895766dSshatty 		// Since these gains are in decibels, it's OK to just add them
3683895766dSshatty 		//
3693895766dSshatty 		iBusOutGain = m_pEG->m_BusOutLineLevels[wBusOut].GetGain();
3703895766dSshatty 		iGain += iBusOutGain;
3713895766dSshatty 
3723895766dSshatty 		//
3733895766dSshatty 		// Mute this output pipe if this output bus is muted
3743895766dSshatty 		//
3753895766dSshatty 		if (m_Mutes[ wIndex ] ||
3763895766dSshatty 			 (m_pEG->m_BusOutLineLevels[wBusOut].IsMuteOn()) )
3773895766dSshatty 		{
3783895766dSshatty 			iGain = ECHOGAIN_MUTED;
3793895766dSshatty 		}
3803895766dSshatty 		else
3813895766dSshatty 		{
3823895766dSshatty 			//
3833895766dSshatty 			// Clamp the output pipe gain if necessary
3843895766dSshatty 			//
3853895766dSshatty 			if (iGain < ECHOGAIN_MUTED)
3863895766dSshatty 				iGain = ECHOGAIN_MUTED;
3873895766dSshatty 			else if (iGain > ECHOGAIN_MAXOUT)
3883895766dSshatty 				iGain = ECHOGAIN_MAXOUT;
3893895766dSshatty 
3903895766dSshatty 		}
3913895766dSshatty 
3923895766dSshatty 		//
3933895766dSshatty 		// Set the gain
3943895766dSshatty 		//
3953895766dSshatty 		Status = m_pEG->GetDspCommObject()->SetPipeOutGain(wPipeOut,
3963895766dSshatty 																			wBusOut,
3973895766dSshatty 																			iGain,
3983895766dSshatty 																			fImmediate);
3993895766dSshatty 
4003895766dSshatty 	}
4013895766dSshatty 
4023895766dSshatty 	return Status;
4033895766dSshatty }
4043895766dSshatty 
4053895766dSshatty 
GetGain(WORD wPipeOut,WORD wBusOut,INT32 & iGain)4063895766dSshatty ECHOSTATUS CPipeOutCtrl::GetGain(WORD wPipeOut, WORD wBusOut, INT32 &iGain)
4073895766dSshatty {
4083895766dSshatty 	WORD	wIndex = GetIndex(wPipeOut,wBusOut);
4093895766dSshatty 
4103895766dSshatty 	if (NULL == m_Gains)
4113895766dSshatty 		return ECHOSTATUS_NO_MEM;
4123895766dSshatty 
413c2ddc71cSJérôme Duval 	if ((wPipeOut >= m_wNumPipesOut) || (wBusOut >= m_wNumBussesOut))
414c2ddc71cSJérôme Duval 	{
415c2ddc71cSJérôme Duval 		ECHO_DEBUGPRINTF(("CPipeOutCtrl::GetGain - out of range pipe %d bus %d\n",
416c2ddc71cSJérôme Duval 								wPipeOut,wBusOut));
417c2ddc71cSJérôme Duval 		return ECHOSTATUS_INVALID_PARAM;
418c2ddc71cSJérôme Duval 	}
419c2ddc71cSJérôme Duval 
4203895766dSshatty 	iGain = DSP_TO_GENERIC( m_Gains[wIndex] );
4213895766dSshatty 
4223895766dSshatty 	/*
4233895766dSshatty 	ECHO_DEBUGPRINTF(("CPipeOutCtrl::GetGain pipe %d  bus %d  gain 0x%lx  index %d\n",
4243895766dSshatty 							wPipeOut,wBusOut,iGain,wIndex));
4253895766dSshatty 	*/
4263895766dSshatty 
4273895766dSshatty 	return ECHOSTATUS_OK;
4283895766dSshatty }
4293895766dSshatty 
4303895766dSshatty 
4313895766dSshatty //*****************************************************************************
4323895766dSshatty //
4333895766dSshatty // Set and get mute
4343895766dSshatty //
4353895766dSshatty //*****************************************************************************
4363895766dSshatty 
SetMute(WORD wPipeOut,WORD wBusOut,BOOL bMute,BOOL fImmediate)4373895766dSshatty ECHOSTATUS CPipeOutCtrl::SetMute
4383895766dSshatty (
4393895766dSshatty 	WORD wPipeOut,
4403895766dSshatty 	WORD wBusOut,
4413895766dSshatty 	BOOL bMute,
4423895766dSshatty 	BOOL fImmediate
4433895766dSshatty )
4443895766dSshatty {
4453895766dSshatty 	if (!m_fHasVmixer && (wPipeOut != wBusOut))
4463895766dSshatty 		return ECHOSTATUS_OK;
4473895766dSshatty 
4483895766dSshatty 	if (NULL == m_Mutes)
4493895766dSshatty 		return ECHOSTATUS_NO_MEM;
4503895766dSshatty 
451c2ddc71cSJérôme Duval 	if ((wPipeOut >= m_wNumPipesOut) || (wBusOut >= m_wNumBussesOut))
452c2ddc71cSJérôme Duval 	{
453c2ddc71cSJérôme Duval 		ECHO_DEBUGPRINTF(("CPipeOutCtrl::SetMute - out of range pipe %d bus %d\n",
454c2ddc71cSJérôme Duval 								wPipeOut,wBusOut));
455c2ddc71cSJérôme Duval 		return ECHOSTATUS_INVALID_PARAM;
456c2ddc71cSJérôme Duval 	}
457c2ddc71cSJérôme Duval 
4583895766dSshatty 	WORD wIndex = GetIndex(wPipeOut,wBusOut);
4593895766dSshatty 
4603895766dSshatty 	/*
4613895766dSshatty 	ECHO_DEBUGPRINTF(("CPipeOutCtrl::SetMute wPipeOut %d  wBusOut %d  bMute %ld\n",
4623895766dSshatty 							wPipeOut,wBusOut,bMute));
4633895766dSshatty 	*/
4643895766dSshatty 
4653895766dSshatty 	//
4663895766dSshatty 	// Store the mute
4673895766dSshatty 	//
4683895766dSshatty  	m_Mutes[ wIndex ] = (BYTE) bMute;
4693895766dSshatty 
4703895766dSshatty 	//
4713895766dSshatty 	// Store the notify
4723895766dSshatty 	//
4733895766dSshatty 	m_pEG->MixerControlChanged(ECHO_PIPE_OUT,MXN_MUTE,wPipeOut,wBusOut);
4743895766dSshatty 
4753895766dSshatty 	//
4763895766dSshatty 	// Call the SetGain function to do all the heavy lifting
4773895766dSshatty 	// Use the ECHOGAIN_UPDATE value to tell the function to
4783895766dSshatty 	// recalculate the gain setting using the currently stored value.
4793895766dSshatty 	//
4803895766dSshatty 	return SetGain(wPipeOut,wBusOut,ECHOGAIN_UPDATE,fImmediate);
4813895766dSshatty }
4823895766dSshatty 
4833895766dSshatty 
GetMute(WORD wPipeOut,WORD wBusOut,BOOL & bMute)4843895766dSshatty ECHOSTATUS CPipeOutCtrl::GetMute(WORD wPipeOut, WORD wBusOut, BOOL &bMute)
4853895766dSshatty {
4863895766dSshatty 	WORD	wIndex = GetIndex(wPipeOut,wBusOut);
4873895766dSshatty 
4883895766dSshatty 	if (NULL == m_Mutes)
4893895766dSshatty 		return ECHOSTATUS_NO_MEM;
4903895766dSshatty 
491c2ddc71cSJérôme Duval 	if ((wPipeOut >= m_wNumPipesOut) || (wBusOut >= m_wNumBussesOut))
492c2ddc71cSJérôme Duval 	{
493c2ddc71cSJérôme Duval 		ECHO_DEBUGPRINTF(("CPipeOutCtrl::GetMute - out of range pipe %d bus %d\n",
494c2ddc71cSJérôme Duval 								wPipeOut,wBusOut));
495c2ddc71cSJérôme Duval 		return ECHOSTATUS_INVALID_PARAM;
496c2ddc71cSJérôme Duval 	}
497c2ddc71cSJérôme Duval 
4983895766dSshatty 	bMute = (BOOL) m_Mutes[ wIndex ];
4993895766dSshatty 
5003895766dSshatty 	/*
5013895766dSshatty 	ECHO_DEBUGPRINTF(("CPipeOutCtrl::GetMute wPipeOut %d  wBusOut %d  bMute %ld\n",
5023895766dSshatty 							wPipeOut,wBusOut,bMute));
5033895766dSshatty 	*/
5043895766dSshatty 
5053895766dSshatty 	return ECHOSTATUS_OK;
5063895766dSshatty }
5073895766dSshatty 
5083895766dSshatty 
5093895766dSshatty //*****************************************************************************
5103895766dSshatty //
5113895766dSshatty // Set and get pan (vmixer only)
5123895766dSshatty //
5133895766dSshatty //*****************************************************************************
5143895766dSshatty 
SetPan(WORD wPipeOut,WORD wBusOut,INT32 iPan)5153895766dSshatty ECHOSTATUS CPipeOutCtrl::SetPan(WORD wPipeOut, WORD wBusOut, INT32 iPan)
5163895766dSshatty {
5173895766dSshatty 	if (!m_fHasVmixer)
5183895766dSshatty 		return ECHOSTATUS_OK;
5193895766dSshatty 
5203895766dSshatty 	if (NULL == m_Pans)
5213895766dSshatty 		return ECHOSTATUS_NO_MEM;
5223895766dSshatty 
523c2ddc71cSJérôme Duval 	if ((wPipeOut >= m_wNumPipesOut) || (wBusOut >= m_wNumBussesOut))
524c2ddc71cSJérôme Duval 	{
525c2ddc71cSJérôme Duval 		ECHO_DEBUGPRINTF(("CPipeOutCtrl::SetPan - out of range pipe %d bus %d\n",
526c2ddc71cSJérôme Duval 								wPipeOut,wBusOut));
527c2ddc71cSJérôme Duval 		return ECHOSTATUS_INVALID_PARAM;
528c2ddc71cSJérôme Duval 	}
529c2ddc71cSJérôme Duval 
530c2ddc71cSJérôme Duval 
5313895766dSshatty 	WORD	wIndex = GetIndex(wPipeOut,wBusOut);
5323895766dSshatty 
5333895766dSshatty 	//
5343895766dSshatty 	// Clamp it and stash it
5353895766dSshatty 	//
5363895766dSshatty 	if (iPan < 0)
5373895766dSshatty 		iPan = 0;
5383895766dSshatty 	else if (iPan > MAX_MIXER_PAN)
5393895766dSshatty 		iPan = MAX_MIXER_PAN;
5403895766dSshatty 
5413895766dSshatty 	m_Pans[wIndex] = (WORD) iPan;
5423895766dSshatty 
5433895766dSshatty 	//
5443895766dSshatty 	// Store the notify
5453895766dSshatty 	//
5463895766dSshatty 	m_pEG->MixerControlChanged(ECHO_PIPE_OUT,MXN_PAN,wPipeOut,wBusOut);
5473895766dSshatty 
5483895766dSshatty 	//
5493895766dSshatty 	//	Convert this pan setting into left and right dB values
5503895766dSshatty 	//
551be188ae1SJérôme Duval 	m_PanDbs[wIndex].iLeft = (INT8) GENERIC_TO_DSP( PanToDb(MAX_MIXER_PAN - iPan) );
552be188ae1SJérôme Duval 	m_PanDbs[wIndex].iRight = (INT8) GENERIC_TO_DSP( PanToDb(iPan) );
5533895766dSshatty 
5543895766dSshatty 	//
5553895766dSshatty 	// Again, SetGain does all the hard work
5563895766dSshatty 	//
5573895766dSshatty 	return SetGain(wPipeOut,wBusOut,ECHOGAIN_UPDATE);
5583895766dSshatty }
5593895766dSshatty 
5603895766dSshatty 
GetPan(WORD wPipeOut,WORD wBusOut,INT32 & iPan)5613895766dSshatty ECHOSTATUS CPipeOutCtrl::GetPan(WORD wPipeOut, WORD wBusOut, INT32 &iPan)
5623895766dSshatty {
5633895766dSshatty 	WORD	wIndex = GetIndex(wPipeOut,wBusOut);
5643895766dSshatty 
5653895766dSshatty 	if (NULL == m_Pans)
5663895766dSshatty 		return ECHOSTATUS_NO_MEM;
5673895766dSshatty 
568c2ddc71cSJérôme Duval 	if ((wPipeOut >= m_wNumPipesOut) || (wBusOut >= m_wNumBussesOut))
569c2ddc71cSJérôme Duval 	{
570c2ddc71cSJérôme Duval 		ECHO_DEBUGPRINTF(("CPipeOutCtrl::GetPan - out of range pipe %d bus %d\n",
571c2ddc71cSJérôme Duval 								wPipeOut,wBusOut));
572c2ddc71cSJérôme Duval 		return ECHOSTATUS_INVALID_PARAM;
573c2ddc71cSJérôme Duval 	}
574c2ddc71cSJérôme Duval 
5753895766dSshatty 	iPan = m_Pans[ wIndex ];
5763895766dSshatty 
5773895766dSshatty 	return ECHOSTATUS_OK;
5783895766dSshatty }
579