📄 audlinux_alsa.cpp
字号:
// // frontCenterVolume = 0;
// // if( snd_mixer_selem_get_playback_volume( mixer_elements2,
// // SND_MIXER_SCHN_REAR_RIGHT, &rearRightVolume) < 0)
// // rearRightVolume = 0;
// // if( snd_mixer_selem_get_playback_volume( mixer_elements2,
// // SND_MIXER_SCHN_REAR_LEFT, &rearLeftVolume) < 0)
// // rearLeftVolume = 0;
// // if( snd_mixer_selem_get_playback_volume( mixer_elements2,
// // SND_MIXER_SCHN_WOOFER, &wooferVolume) < 0)
// // wooferVolume = 0;
// long range = pmax - pmin;
// long val = frontLeftVolume;
// frontRightVolume = frontLeftVolume;
// val -= pmin;
// percentage = (long)rint(val / range * 100);
// // printf("min %d, max %d, range %d\n", pmin, pmax, range);
// printf("fleft %ld, fright %ld, center %ld, rleft %ld, rright %ld, woofer %ld, percent %d\n",
// frontLeftVolume, frontRightVolume, frontCenterVolume, rearLeftVolume,
// rearRightVolume, percentage);
// }
// // snd_mixer_selem_get_playback_volume_range( mixer_elements2, &pmin, &pmax);
// }
// }
// nLeftVolume = (nVolume & 0x000000ff);
// nRightVolume = (nVolume & 0x0000ff00) >> 8;
nRetVolume = (UINT16)frontLeftVolume;
// printf("nRetVolume is %ld\n",nRetVolume);
return nRetVolume;
}
HX_RESULT CAudioOutLinuxAlsa::_SetVolume(UINT16 unVolume)
{
HX_RESULT retCode = RA_AOE_NOERR;
///////////////////////// FIXME:
long pmin = 0, pmax = 0;
long percentage = 0;
long frontLeftVolume = 0;
long frontRightVolume = 0;
/* long frontCenterVolume = 0;
long rearLeftVolume = 0;
long rearRightVolume = 0;
long wooferVolume = 0;
snd_mixer_selem_id_t *sid;
snd_mixer_selem_id_alloca(&sid);
*/
snd_mixer_elem_t *mixer_elements;
frontLeftVolume = frontRightVolume = unVolume;
// nNewVolume = (unVolume & 0xff) | ((unVolume &0xff) << 8);
mixer_elements = snd_mixer_first_elem( mixer_handle); //just grab first elem for now
if (snd_mixer_selem_has_playback_volume( mixer_elements)) {
// do this as the volume range in alsa might be more or less than 100
// act like its a percentage, the vol range for rmedigi96 is 16383, and my pci128 is 16
snd_mixer_selem_get_playback_volume_range( mixer_elements, &pmin, &pmax);
int range = pmax - pmin;
int val = frontLeftVolume;
//percent to volume
frontLeftVolume = rint((double)range * ((double)val*.01)) + pmin;
frontRightVolume = frontLeftVolume;
if( snd_mixer_selem_set_playback_volume( mixer_elements,
SND_MIXER_SCHN_FRONT_LEFT,
frontLeftVolume) < 0)
frontLeftVolume = 0;
if( snd_mixer_selem_set_playback_volume( mixer_elements,
SND_MIXER_SCHN_FRONT_RIGHT,
frontRightVolume) < 0)
frontRightVolume = 0;
}
#ifdef _DEBUG
printf("setting volume left %ld, right %ld %ld\%\n", frontLeftVolume, frontRightVolume, unVolume );
#endif
// Save for future use, demonstrates multichannel mixer access.
// for ( mixer_elements = snd_mixer_first_elem( mixer_handle); //ramble through elems
// mixer_elements;
// mixer_elements = snd_mixer_elem_next( mixer_elements) )
// {
// snd_mixer_selem_get_id( mixer_elements, sid);
// printf("mixer control '%s',%i\n",
// snd_mixer_selem_id_get_name( sid),
// snd_mixer_selem_id_get_index( sid));
// if ( snd_mixer_selem_has_common_volume( mixer_elements)) //is mono
// {
// // // check for playback vol mixer
// if (snd_mixer_selem_has_playback_volume( mixer_elements)) {
// snd_mixer_selem_get_playback_volume_range( mixer_elements, &pmin, &pmax);
// int range = pmax - pmin;
// int val = frontLeftVolume;
// val -= pmin;
// frontLeftVolume = rint((double)range * ((double)val*.01)) + pmin; //percent to volume
// //frontLeftVolume = rint((double)val/(double)range * 100);
// // frontLeftVolume = (long) ( unVolume & 0x000000ff);
// frontRightVolume = frontLeftVolume;
// // frontRightVolume = (long) ( unVolume & 0x0000ff00);
// //score!
// if( snd_mixer_selem_set_playback_volume( mixer_elements,
// SND_MIXER_SCHN_MONO,
// frontLeftVolume) < 0)
// frontLeftVolume = 0;
// val -= pmin;
// percentage = (long)rint((double)val/(double)range * 100);
// }
// }
// else //is stereo
// {
// // if (snd_mixer_selem_has_playback_volume( mixer_elements)) {
// snd_mixer_selem_get_playback_volume_range( mixer_elements, &pmin, &pmax);
// printf("vol min %d, max %d\n", pmin, pmax);
// int range = pmax - pmin;
// int tmp;
// int val = frontLeftVolume;
// frontLeftVolume = rint((double)range * ((double)val*.01)) + pmin; //percent to volume
// //rint((double)val/(double)range * 100);
// // frontLeftVolume = (long) ( unVolume & 0x000000ff);
// frontRightVolume = frontLeftVolume;
// // frontRightVolume = (long) ( unVolume & 0x0000ff00);
// if( snd_mixer_selem_set_playback_volume( mixer_elements,
// SND_MIXER_SCHN_FRONT_LEFT,
// frontLeftVolume) < 0)
// frontLeftVolume = 0;
// if( snd_mixer_selem_set_playback_volume( mixer_elements,
// SND_MIXER_SCHN_FRONT_RIGHT,
// frontRightVolume) < 0)
// frontRightVolume = 0;
// // if( snd_mixer_selem_set_playback_volume( mixer_elements,
// // SND_MIXER_SCHN_FRONT_CENTER, &frontCenterVolume) < 0)
// // frontCenterVolume = 0;
// // if( snd_mixer_selem_set_playback_volume( mixer_elements,
// // SND_MIXER_SCHN_REAR_RIGHT, &rearRightVolume) < 0)
// // rearRightVolume = 0;
// // if( snd_mixer_selem_set_playback_volume( mixer_elements,
// // SND_MIXER_SCHN_REAR_LEFT, &rearLeftVolume) < 0)
// // rearLeftVolume = 0;
// // if( snd_mixer_selem_set_playback_volume( mixer_elements,
// // SND_MIXER_SCHN_WOOFER, &wooferVolume) < 0)
// // wooferVolume = 0;
// // }
// int range2 = pmax - pmin;
// int val2 = frontLeftVolume;
// val2 -= pmin;
// percentage = (long)rint((double)val2/(double)range2 * 100);
// }
// }
// printf("fleft %d, fright %d, center %d, rleft %d, rright %d, woofer %d, percent %d\n",
// frontLeftVolume, frontRightVolume, frontCenterVolume, rearLeftVolume,
// rearRightVolume, percentage);
m_wLastError = retCode;
return m_wLastError;
}
//Device specific method to drain a device. This should play the remaining
//bytes in the devices buffer and then return.
HX_RESULT CAudioOutLinuxAlsa::_Drain()
{
HX_RESULT retCode = RA_AOE_NOERR;
if ( pcm_handle < 0 )
{
retCode = RA_AOE_DEVNOTOPEN;
}
// Stop PCM device after pending frames have been played
if( snd_pcm_drain( pcm_handle) < 0)
retCode = RA_AOE_GENERAL;
m_wLastError = retCode;
return m_wLastError;
}
//Device specific method to reset device and return it to a state that it
//can accept new sample rates, num channels, etc.
HX_RESULT CAudioOutLinuxAlsa::_Reset()
{
HX_RESULT retCode = RA_AOE_NOERR;
m_ulPausePosition = 0;
if( pcm_handle > 0 )
// if (snd_pcm_state( pcm_handle) == SND_PCM_STATE_OPEN)
{
if( snd_pcm_reset( pcm_handle) < 0)
{
retCode = RA_AOE_GENERAL;
}
}
else
{
retCode = RA_AOE_DEVNOTOPEN;
}
m_wLastError = retCode;
return m_wLastError;
}
HX_RESULT CAudioOutLinuxAlsa::_CheckFormat( const HXAudioFormat* pFormat )
{
int nBitsPerSample = pFormat->uBitsPerSample;
int ulTmp = pFormat->ulSamplesPerSec;
int nNumChannels = pFormat->uChannels;
float fTmp = 0.0;
int err=0;
snd_pcm_format_t m_format;
HX_RESULT retCode = RA_AOE_NOERR;
if( nBitsPerSample = 16)
{
m_format = SND_PCM_FORMAT_S16;
}
else
{
m_format = SND_PCM_FORMAT_U8;
}
//Is the device already open?
if( pcm_handle > 0 || RA_AOE_NOERR != _OpenAudio() )
{
retCode = RA_AOE_DEVBUSY;
return retCode;
}
//See if the sample rate is supported.
if( snd_pcm_hw_params_test_rate ( pcm_handle, hwparams, ulTmp ,0) < 0)
{
#ifdef _DEBUG
fprintf (stderr, "cannot set sample rate (%s)\n",
snd_strerror (err));
#endif
//Not quite the real error, but it is what we need to return.
retCode = RA_AOE_BADFORMAT;
goto donechecking;
}
//Check num channels.
if(snd_pcm_hw_params_test_channels ( pcm_handle, hwparams, nNumChannels) < 0)
{
retCode = RA_AOE_BADFORMAT;
goto donechecking;
}
if ( snd_pcm_hw_params_test_format( pcm_handle, hwparams, m_format /*SND_PCM_FORMAT_S16*/ ) < 0)
{
retCode = RA_AOE_BADFORMAT;
goto donechecking;
}
//Close the audio device.
donechecking:
_CloseAudio();
m_wLastError = retCode;
return retCode;
}
HX_RESULT CAudioOutLinuxAlsa::_CheckSampleRate( ULONG32 ulSampleRate )
{
ULONG32 ulTmp = ulSampleRate;
m_wLastError = RA_AOE_NOERR;
//Is the device already open?
if( pcm_handle > 0 || RA_AOE_NOERR != _OpenAudio() )
{
m_wLastError = RA_AOE_DEVBUSY;
}
else
{
//See if the sample rate is supported.
if( snd_pcm_hw_params_test_rate ( pcm_handle, hwparams, (uint)ulTmp, 0) != 1)
{
//Not quite the real error, but it is what we need to return.
m_wLastError = RA_AOE_DEVBUSY;
}
else if( ulSampleRate != ulTmp )
{
//It is NOT supported
m_wLastError = RA_AOE_BADFORMAT;
}
_CloseAudio();
}
return m_wLastError;
}
HX_RESULT CAudioOutLinuxAlsa::_Pause()
{
m_wLastError = HXR_OK;
m_ulPausePosition = m_ulTotalWritten;
m_ulTickCount = 0;
m_ulLastTimeStamp = 0;
int err=0;
if( m_bHasHardwarePause)
{
if((err = snd_pcm_pause( pcm_handle, 1)) < 0)
{
#ifdef _DEBUG
fprintf(stderr, "Error : cannot pause (%s)\n", snd_strerror (err));
#endif
m_wLastError = RA_AOE_NOTSUPPORTED;
}
}
else
{
m_wLastError = RA_AOE_NOTSUPPORTED;
}
return m_wLastError;
}
HX_RESULT CAudioOutLinuxAlsa::_Resume()
{
m_wLastError = HXR_OK;
if( m_ulTotalWritten > 0 )
{
m_ulTickCount = GetTickCount();
m_ulLastTimeStamp = m_ulTickCount;
}
if( m_bHasHardwarePause && m_bHasHardwareResume)
{
int err=0;
if((err = snd_pcm_resume( pcm_handle)) < 0)
{
#ifdef _DEBUG
fprintf (stderr, "Error: cannot resume (%s)\n",
snd_strerror (err));
#endif
m_wLastError = RA_AOE_NOTSUPPORTED;
}
}
else
{
m_wLastError = RA_AOE_NOTSUPPORTED;
}
return m_wLastError;
}
BOOL CAudioOutLinuxAlsa::_HardwarePauseSupported() const
{
if( snd_pcm_hw_params_can_resume( hwparams) == 1)
{
m_bHasHardwareResume = true;
}
else
{
m_bHasHardwareResume = false;
}
if( snd_pcm_hw_params_can_pause( hwparams) == 1)
{
m_bHasHardwarePause = true;
return TRUE;
}
else
{
m_bHasHardwarePause = false;
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -