///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Winnov L.P., 1997.  All rights reserved
// set.c: CAsrc class set methods implementation.
//
// Modified : C++ -> C
///////////////////////////////////////////////////////////////////////////////

#include "common.h"
#include "io.h"
#include "wnvasrc.h"
#include "asrc.h"
#include "asrcpriv.h"
        
#undef PUBLIC
#undef PRIVATE
#define PUBLIC
#define PRIVATE
        
        
//////////////////////////////////////////////////////////////////////////////////////////
// When changing the audio source, shadow the input monitor mute

PRIVATE void asrcSetMonitorMuteShadow (PASRC pAsrc, UINT nSource, BOOL fMute)
{
    if (nSource >= NAUDIOSOURCES) return;
    sharedSetMuteShadow (pAsrc->m_pShared, sharedGetMuteShadow (pAsrc->m_pShared) & ~(1 << nSource));
    sharedSetMuteShadow (pAsrc->m_pShared, sharedGetMuteShadow (pAsrc->m_pShared) |((fMute?1:0) << nSource));
}

//////////////////////////////////////////////////////////////////////////////
// The video driver has set the source, set the audio source appropriately.
// returns: TRUE if the audio source was changed

PRIVATE DWORD asrcSetAudioWithVideo (PASRC pAsrc, DWORD dwVideoSource)
{
    UINT nAsrc;
    
    if (dwVideoSource >= NVIDEOSOURCES) return FALSE;	// fail
    if (!sharedGetAsrcForVsrcEnable (pAsrc->m_pShared)) return FALSE;	// disabled
    
    nAsrc = sharedGetAsrcForVsrc (pAsrc->m_pShared, (UINT)dwVideoSource);
    if (nAsrc &&			// 0 means no association
       (nAsrc != (UINT)asrcGetSource (pAsrc)))	// different from current source
    {
    	asrcSetSource (pAsrc, (DWORD)nAsrc);
    	return TRUE;			// source changed
    }
    return FALSE;			// source did not change
}

//////////////////////////////////////////////////////////////////////////////
// A video source has been activated.
// As a side affect, it may change the audio source.
// returns: TRUE if the audio source was changed

PRIVATE DWORD asrcSetVideoSource (PASRC pAsrc, DWORD dwVideoSource)
{
    if (!sharedGetAsrcForVsrcEnable (pAsrc->m_pShared)) return FALSE;	// disabled
    if (halIsVideoTuner (&pAsrc->m_hal, (UINT)dwVideoSource))	// new source
    {
	if (asrcGetSource (pAsrc) == ASRC_CAMERA)		// old source
	{
	    asrcSetSource (pAsrc, ASRC_TUNER);
	    return TRUE;	// source changed
	}
    }
    else
    if (halIsVideoCamera (&pAsrc->m_hal, (UINT)dwVideoSource))	// new source
    {
	if (asrcGetSource (pAsrc) == ASRC_TUNER)			// old source
	{
	    asrcSetSource (pAsrc, ASRC_CAMERA);
	    return TRUE;	// source changed
	}
    }
    return FALSE;	// source did not change
}

PRIVATE DWORD asrcSetSourceAssociationEnable (PASRC pAsrc, DWORD dwEnable)
{
    sharedSetAsrcForVsrcEnable (pAsrc->m_pShared, (BOOL)dwEnable);
    return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////
// process a message which creates the association

PRIVATE DWORD asrcSetSourceAssociation (PASRC pAsrc, DWORD dwValue)
{
    int nVsrc;
    
    nVsrc = (UINT)dwValue & 255;
    
    if (nVsrc >= NVIDEOSOURCES) return 1;	// fail
    sharedSetAsrcForVsrc (pAsrc->m_pShared, nVsrc, ((UINT)dwValue >> 8) & 255);
    
    return 0;	// pass
}

////////////////////////////////////////////////////////////////////////////////////////////////

PRIVATE DWORD asrcSetSampleRate (PASRC pAsrc, DWORD dwVal)
{
    return halSetSampleRate (&pAsrc->m_hal, (UINT)dwVal);	// return is actual sample rate
}

PRIVATE DWORD asrcSetACE (PASRC pAsrc, DWORD dwVal)
{
    halSetACE (&pAsrc->m_hal, (BOOL)dwVal);
    return 0;
}

PRIVATE DWORD asrcSetAMS (PASRC pAsrc, DWORD dwVal)
{
    UINT old;
    
    old = asrcReadReg (pAsrc, HW_PORT_FREQ);
    if (dwVal)
	asrcWriteReg (pAsrc, HW_PORT_FREQ, old | HW_AMSBIT);
    else
	asrcWriteReg (pAsrc, HW_PORT_FREQ, old & ~HW_AMSBIT);

    sharedSetAMSShadow (pAsrc->m_pShared, (BOOL)dwVal);
    
    return 0;
}

PRIVATE DWORD asrcSetAPE (PASRC pAsrc, DWORD dwVal)
{
    return 0;	// is read only
}

PRIVATE DWORD asrcSetPtr (PASRC pAsrc, DWORD dwVal)
{
    BOOL fACE;
    
    fACE = (BOOL)asrcGetACE (pAsrc);
    asrcSetACE (pAsrc, FALSE);		    	// disable while changing
    asrcWriteReg (pAsrc, HW_PORT_AUDPTR, (UINT)(dwVal >> 4));
    asrcSetACE (pAsrc, fACE);	  		// restore enable audio when done

    return 0;
}

PRIVATE DWORD asrcSetIsPlaying (PASRC pAsrc, DWORD dwVal)
{
    return 0;	// is read-only
}

PRIVATE DWORD asrcSetWaveOutState (PASRC pAsrc, DWORD dwVal)
{
    codecSetWaveOutState (&pAsrc->m_codec, !!dwVal);
    return 0;
}

PRIVATE DWORD asrcSetLeftGainCurrentSource (PASRC pAsrc, DWORD dwVal)
{
    return asrcSetLeftGainPerSource (pAsrc, (UINT)asrcGetSource (pAsrc), dwVal);
}

PRIVATE DWORD asrcSetRightGainCurrentSource (PASRC pAsrc, DWORD dwVal)
{
    return asrcSetRightGainPerSource (pAsrc, (UINT)asrcGetSource (pAsrc), dwVal);
}

PRIVATE DWORD asrcSetLeftGainPerSource (PASRC pAsrc, UINT nSource, DWORD dwVal)
{
    UINT nGain;
    
    nGain = (UINT)dwVal & 0xff;
    sharedSetLeftGain (pAsrc->m_pShared, nSource, nGain);
    if (asrcGetSource (pAsrc) != nSource) return 0;	// not the current source

    codecSetLeftGain (&pAsrc->m_codec, nGain);
    halUpdateVolume (&pAsrc->m_hal);
    return 0;
}
    
PRIVATE DWORD asrcSetRightGainPerSource (PASRC pAsrc, UINT nSource, DWORD dwVal)
{
    UINT nGain;
    
    nGain = (UINT)dwVal & 0xff;
    sharedSetRightGain (pAsrc->m_pShared, nSource, nGain);
    if (asrcGetSource (pAsrc) != nSource) return 0;	// not the current source
    
    codecSetRightGain (&pAsrc->m_codec, nGain);
    halUpdateVolume (&pAsrc->m_hal);
    return 0;
}

PRIVATE DWORD asrcSetSource (PASRC pAsrc, DWORD dwSource)
{
    UINT nOldsrc;
    BOOL fNewMute;

    if (dwSource >= NAUDIOSOURCES) return 0;

    nOldsrc = (UINT)asrcGetSource (pAsrc) & (NAUDIOSOURCES-1);
    fNewMute = asrcGetMonitorMuteShadow (pAsrc, (UINT)dwSource);

    // save (possibly changed) input mute for the current source    
    asrcSetMonitorMuteShadow (pAsrc, 
        nOldsrc,
        (BOOL)asrcGetMonitorMute (pAsrc));

    // avoid noise when switching from unmuted source to muted source by muting before switch
    if (fNewMute)
        halSetMonitorMute (&pAsrc->m_hal, TRUE);
    // restore input gain for source
    asrcSetLeftGainPerSource (pAsrc, (UINT)dwSource, sharedGetLeftGain(pAsrc->m_pShared, (UINT)dwSource));
    asrcSetRightGainPerSource (pAsrc, (UINT)dwSource, sharedGetRightGain(pAsrc->m_pShared, (UINT)dwSource));
    // set the source
    halSetSource (&pAsrc->m_hal, nOldsrc, (UINT)dwSource);
    // avoid noise when switching from muted source to unmuted source by unmuting after switch
    if (!fNewMute)
    	halSetMonitorMute (&pAsrc->m_hal, FALSE);
    
    return 0;
}

PRIVATE DWORD asrcSetLine2Source (PASRC pAsrc, DWORD dwVal)
{
    return asrcSetSource (pAsrc, dwVal?1:0);
}

PRIVATE DWORD asrcSetOutputSource (PASRC pAsrc, DWORD dwVal)
{
	UINT old;
        UINT nCurrent;
        UINT nSaveVolume;
	UINT nVal;
	        
	nCurrent = (halReadAttnReg (&pAsrc->m_hal) & HW_ASS2FIELD_VID2)?1:0;
	nVal = dwVal?1:0;
	
	if (nCurrent == nVal)
	    return 0;	// same output will be selected

	// kill amplifier output
	nSaveVolume = (UINT)asrcGetVolume (pAsrc);	    
	asrcSetVolume (pAsrc, 0);

   	old = halReadAttnReg (&pAsrc->m_hal);
	old &= ~HW_ASS2FIELD_VID2;
	if (nVal) old |= HW_ASS2FIELD_VID2;
	halWriteAttnReg (&pAsrc->m_hal, old);

	// restore amplifier volume
	asrcSetVolume (pAsrc, nSaveVolume);

	sharedSetOutSource (pAsrc->m_pShared, nVal);
	
	return 0;
}

PRIVATE DWORD asrcSetMuteOut (PASRC pAsrc, DWORD dwVal)
{
    halSetMuteOut (&pAsrc->m_hal, dwVal?TRUE:FALSE);
    return 0;
}

PRIVATE DWORD asrcSetMuteIn (PASRC pAsrc, DWORD dwVal)
{
    codecSetMuteIn (&pAsrc->m_codec, dwVal?TRUE:FALSE);
    return 0;
}

PRIVATE DWORD asrcSetAuxMute (PASRC pAsrc, DWORD dwVal)
{
    halSetAuxMute (&pAsrc->m_hal, dwVal?TRUE:FALSE);
    return 0;
}

PRIVATE DWORD asrcSetWaveOutMute (PASRC pAsrc, DWORD dwVal)
{
    halSetWaveOutMute (&pAsrc->m_hal, dwVal?TRUE:FALSE);
    return 0;
}

PRIVATE DWORD asrcSetMonitorMute (PASRC pAsrc, DWORD dwVal)
{
    halSetMonitorMute (&pAsrc->m_hal, dwVal?TRUE:FALSE);
    asrcSetMonitorMuteShadow (pAsrc, (UINT)asrcGetSource (pAsrc), dwVal?TRUE:FALSE);
    return 0;
}

PRIVATE DWORD asrcSetVolume (PASRC pAsrc, DWORD dwVal)
{
    halSetVolume (&pAsrc->m_hal, HAL_MASTER_VOLUME, (UINT)dwVal);
    return 0;
}

PRIVATE DWORD asrcSetBalance (PASRC pAsrc, DWORD dwVal)
{
    halSetVolume (&pAsrc->m_hal, HAL_MASTER_BALANCE, (UINT)dwVal);
    return 0;
}

PRIVATE DWORD asrcSetLeftVolume (PASRC pAsrc, DWORD dwVal)
{
    halSetVolume (&pAsrc->m_hal, HAL_LEFTVOLUME, (UINT)dwVal);
    return 0;
}

PRIVATE DWORD asrcSetRightVolume (PASRC pAsrc, DWORD dwVal)
{
    halSetVolume (&pAsrc->m_hal, HAL_RIGHTVOLUME, (UINT)dwVal);
    return 0;
}

PRIVATE DWORD asrcSetWaveVolume (PASRC pAsrc, DWORD dwVal)
{
    halSetVolume (&pAsrc->m_hal, HAL_WAVEOUT_VOLUME, (UINT)dwVal);
    return 0;
}

PRIVATE DWORD asrcSetAuxVolume (PASRC pAsrc, DWORD dwVal)
{
    if (sharedGetType (pAsrc->m_pShared) == TYPE_ALARIS) return 0;
    halSetVolume (&pAsrc->m_hal, HAL_AUX_VOLUME, (UINT)dwVal);
    return 0;
}

PRIVATE DWORD asrcSetMonitorVolume (PASRC pAsrc, DWORD dwVal)
{
    halSetVolume (&pAsrc->m_hal, HAL_MONITOR_VOLUME, (UINT)dwVal);
    return 0;
}

PRIVATE DWORD asrcSetLine1Volume (PASRC pAsrc, DWORD dwVal)
{
    if (sharedGetType (pAsrc->m_pShared) != TYPE_ALARIS) return 0;
    halSetMixer (&pAsrc->m_hal, HAL_LINE1_VOLUME, (UINT)dwVal);
    return 0;
}

PRIVATE DWORD asrcSetLine2Volume (PASRC pAsrc, DWORD dwVal)
{
    if (sharedGetType (pAsrc->m_pShared) != TYPE_ALARIS) return 0;
    halSetMixer (&pAsrc->m_hal, HAL_LINE2_VOLUME, (UINT)dwVal);
    return 0;
}

PRIVATE DWORD asrcSetMicVolume (PASRC pAsrc, DWORD dwVal)
{
    if (sharedGetType (pAsrc->m_pShared) != TYPE_ALARIS) return 0;
    halSetMixer (&pAsrc->m_hal, HAL_MIC_VOLUME, (UINT)dwVal);
    return 0;
}

PRIVATE DWORD asrcCodecSetSpeakerMute (PASRC pAsrc, BOOL fMute)
{
    codecSetSpeakerMute (&pAsrc->m_codec, fMute);
    return 0;
}

PRIVATE DWORD asrcCodecSetWaveOutMute (PASRC pAsrc, BOOL fMute)
{
    codecSetWaveOutMute (&pAsrc->m_codec, fMute);
    return 0;
}

///////////////////////////////////////////////////////////////////////////////

PRIVATE void asrcSetPower (PASRC pAsrc, BOOL fState)
{
    if (fState)
    	sharedSetPower (pAsrc->m_pShared, sharedGetPower (pAsrc->m_pShared) + 1);
    else
    	sharedSetPower (pAsrc->m_pShared, sharedGetPower (pAsrc->m_pShared) - 1);
    	
    switch (sharedGetPower (pAsrc->m_pShared))
    {
case 0:
	halSetPower (&pAsrc->m_hal, FALSE);
	break;
case 1:    
	halSetPower (&pAsrc->m_hal, TRUE);
    	break;
    }
}

PRIVATE DWORD asrcSetWaveOutPower (PASRC pAsrc, DWORD dwVal)
{
    asrcSetPower (pAsrc, dwVal?TRUE:FALSE);
    return 0;
}

PRIVATE DWORD asrcSetWaveInPower (PASRC pAsrc, DWORD dwVal)
{
    asrcSetPower (pAsrc, dwVal?TRUE:FALSE);
    return 0;
}

PRIVATE DWORD asrcSetMixerPower (PASRC pAsrc, DWORD dwVal)
{
    asrcSetPower (pAsrc, dwVal?TRUE:FALSE);
    return 0;
}

PRIVATE DWORD asrcSetBlockDCEnabled (PASRC pAsrc, DWORD dwVal)
{
    sharedSetBlockDCEnabled (pAsrc->m_pShared, (BOOL)dwVal);
    return 0;
}

PRIVATE DWORD asrcSetCodecMute (PASRC pAsrc, DWORD dwVal)
{
	sharedSetCodecMute (pAsrc->m_pShared, (UINT)dwVal);
	return 0;
}


