mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
Add play/pause audio support.
This commit is contained in:
parent
24a065e5de
commit
0a2a221fa9
@ -1,6 +1,7 @@
|
||||
User johns
|
||||
Date:
|
||||
|
||||
Add play/pause audio support.
|
||||
Fix bug: audible glitch when switching AC-3 pass-through <-> none.
|
||||
Fix bug: mpeg stills not displayed.
|
||||
Detect audio stream type only after stream switch.
|
||||
|
2
Todo
2
Todo
@ -80,7 +80,7 @@ audio:
|
||||
Combine alsa+oss ringbuffer code.
|
||||
Make alsa thread/polled and oss thread/polled output module runtime
|
||||
selectable.
|
||||
software volume support
|
||||
software volume support (could be done with asound.conf)
|
||||
add pause support for replay pause
|
||||
Mute should do a real mute and not only set volume to zero.
|
||||
Starting suspended and muted, didn't register the mute.
|
||||
|
105
audio.c
105
audio.c
@ -113,6 +113,8 @@ typedef struct _audio_module_
|
||||
uint64_t(*GetDelay) (void); ///< get current audio delay
|
||||
void (*SetVolume) (int); ///< set output volume
|
||||
int (*Setup) (int *, int *, int); ///< setup channels, samplerate
|
||||
void (*Play) (void); ///< play
|
||||
void (*Pause) (void); ///< pause
|
||||
void (*Init) (void); ///< initialize audio output module
|
||||
void (*Exit) (void); ///< cleanup audio output module
|
||||
} AudioModule;
|
||||
@ -134,7 +136,7 @@ static const char *AudioAC3Device; ///< alsa/OSS AC3 device name
|
||||
static const char *AudioMixerDevice; ///< alsa/OSS mixer device name
|
||||
static const char *AudioMixerChannel; ///< alsa/OSS mixer channel name
|
||||
static volatile char AudioRunning; ///< thread running / stopped
|
||||
static int AudioPaused; ///< audio paused
|
||||
static volatile char AudioPaused; ///< audio paused
|
||||
static unsigned AudioSampleRate; ///< audio sample rate in hz
|
||||
static unsigned AudioChannels; ///< number of audio channels
|
||||
static const int AudioBytesProSample = 2; ///< number of bytes per sample
|
||||
@ -567,7 +569,6 @@ static void AlsaEnqueue(const void *samples, int count)
|
||||
state = snd_pcm_state(AlsaPCMHandle);
|
||||
Debug(3, "audio/alsa: state %s\n", snd_pcm_state_name(state));
|
||||
Debug(3, "audio/alsa: unpaused\n");
|
||||
AudioPaused = 0;
|
||||
}
|
||||
}
|
||||
// Update audio clock
|
||||
@ -626,6 +627,9 @@ static void AlsaThread(void)
|
||||
AlsaFlushBuffer = 0;
|
||||
break;
|
||||
}
|
||||
if (AudioPaused) {
|
||||
break;
|
||||
}
|
||||
// wait for space in kernel buffers
|
||||
if ((err = snd_pcm_wait(AlsaPCMHandle, 100)) < 0) {
|
||||
Error(_("audio/alsa: wait underrun error?\n"));
|
||||
@ -637,7 +641,7 @@ static void AlsaThread(void)
|
||||
usleep(100 * 1000);
|
||||
continue;
|
||||
}
|
||||
if (AlsaFlushBuffer) {
|
||||
if (AlsaFlushBuffer || AudioPaused) {
|
||||
continue;
|
||||
}
|
||||
if ((err = AlsaPlayRingbuffer())) { // empty / error
|
||||
@ -1111,6 +1115,47 @@ static int AlsaSetup(int *freq, int *channels, int use_ac3)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
** Play audio.
|
||||
*/
|
||||
void AlsaPlay(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (AlsaCanPause) {
|
||||
if ((err = snd_pcm_pause(AlsaPCMHandle, 0))) {
|
||||
Error(_("audio/alsa: snd_pcm_pause(): %s\n"), snd_strerror(err));
|
||||
}
|
||||
} else {
|
||||
if ((err = snd_pcm_prepare(AlsaPCMHandle)) < 0) {
|
||||
Error(_("audio/alsa: snd_pcm_prepare(): %s\n"), snd_strerror(err));
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (snd_pcm_state(AlsaPCMHandle) == SND_PCM_STATE_PAUSED) {
|
||||
Error(_("audio/alsa: still paused\n"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
** Pause audio.
|
||||
*/
|
||||
void AlsaPause(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (AlsaCanPause) {
|
||||
if ((err = snd_pcm_pause(AlsaPCMHandle, 1))) {
|
||||
Error(_("snd_pcm_pause(): %s\n"), snd_strerror(err));
|
||||
}
|
||||
} else {
|
||||
if ((err = snd_pcm_drop(AlsaPCMHandle)) < 0) {
|
||||
Error(_("snd_pcm_drop(): %s\n"), snd_strerror(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Empty log callback
|
||||
*/
|
||||
@ -1179,6 +1224,8 @@ static const AudioModule AlsaModule = {
|
||||
.GetDelay = AlsaGetDelay,
|
||||
.SetVolume = AlsaSetVolume,
|
||||
.Setup = AlsaSetup,
|
||||
.Play = AlsaPlay,
|
||||
.Pause = AlsaPause,
|
||||
.Init = AlsaInit,
|
||||
.Exit = AlsaExit,
|
||||
};
|
||||
@ -1388,6 +1435,9 @@ static void OssThread(void)
|
||||
OssFlushBuffer = 0;
|
||||
break;
|
||||
}
|
||||
if (AudioPaused) {
|
||||
break;
|
||||
}
|
||||
|
||||
fds[0].fd = OssPcmFildes;
|
||||
fds[0].events = POLLOUT | POLLERR;
|
||||
@ -1399,7 +1449,7 @@ static void OssThread(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (OssFlushBuffer) {
|
||||
if (OssFlushBuffer || AudioPaused) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1740,6 +1790,20 @@ static int OssSetup(int *freq, int *channels, int use_ac3)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
** Play audio.
|
||||
*/
|
||||
void OssPlay(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
** Pause audio.
|
||||
*/
|
||||
void OssPause(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
** Initialize OSS audio output module.
|
||||
*/
|
||||
@ -1785,6 +1849,8 @@ static const AudioModule OssModule = {
|
||||
.GetDelay = OssGetDelay,
|
||||
.SetVolume = OssSetVolume,
|
||||
.Setup = OssSetup,
|
||||
.Play = OssPlay,
|
||||
.Pause = OssPause,
|
||||
.Init = OssInit,
|
||||
.Exit = OssExit,
|
||||
};
|
||||
@ -1868,6 +1934,8 @@ static const AudioModule NoopModule = {
|
||||
.GetDelay = NoopGetDelay,
|
||||
.SetVolume = NoopSetVolume,
|
||||
.Setup = NoopSetup,
|
||||
.Play = NoopVoid,
|
||||
.Pause = NoopVoid,
|
||||
.Init = NoopVoid,
|
||||
.Exit = NoopVoid,
|
||||
};
|
||||
@ -2104,6 +2172,32 @@ int AudioSetup(int *freq, int *channels, int use_ac3)
|
||||
return AudioUsedModule->Setup(freq, channels, use_ac3);
|
||||
}
|
||||
|
||||
/**
|
||||
** Play audio.
|
||||
*/
|
||||
void AudioPlay(void)
|
||||
{
|
||||
if (!AudioPaused) {
|
||||
Warning("audio: not paused, check the code\n");
|
||||
return;
|
||||
}
|
||||
Debug(3, "audio: resumed\n");
|
||||
AudioPaused = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Pause audio.
|
||||
*/
|
||||
void AudioPause(void)
|
||||
{
|
||||
if (AudioPaused) {
|
||||
Warning("audio: already paused, check the code\n");
|
||||
return;
|
||||
}
|
||||
Debug(3, "audio: paused\n");
|
||||
AudioPaused = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
** Set pcm audio device.
|
||||
**
|
||||
@ -2207,8 +2301,7 @@ void AudioInit(void)
|
||||
AudioInitThread();
|
||||
}
|
||||
#endif
|
||||
|
||||
AudioPaused = 1;
|
||||
AudioPaused = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
4
audio.h
4
audio.h
@ -39,8 +39,8 @@ extern int64_t AudioGetClock(); ///< get current audio clock
|
||||
extern void AudioSetVolume(int); ///< set volume
|
||||
extern int AudioSetup(int *, int *, int); ///< setup audio output
|
||||
|
||||
//extern void AudioPlay(void); ///< play audio
|
||||
//extern void AudioPause(void); ///< pause audio
|
||||
extern void AudioPlay(void); ///< play audio
|
||||
extern void AudioPause(void); ///< pause audio
|
||||
|
||||
extern void AudioSetDevice(const char *); ///< set PCM audio device
|
||||
extern void AudioSetDeviceAC3(const char *); ///< set pass-through device
|
||||
|
24
softhddev.c
24
softhddev.c
@ -66,7 +66,7 @@ static char ConfigStartX11Server; ///< flag start the x11 server
|
||||
|
||||
static pthread_mutex_t SuspendLockMutex; ///< suspend lock mutex
|
||||
|
||||
static volatile char VideoFreezed; ///< video freezed
|
||||
static volatile char StreamFreezed; ///< stream freezed
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Audio
|
||||
@ -211,7 +211,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
|
||||
|
||||
// channel switch: SetAudioChannelDevice: SetDigitalAudioDevice:
|
||||
|
||||
if (VideoFreezed) { // video freezed
|
||||
if (StreamFreezed) { // stream freezed
|
||||
return 0;
|
||||
}
|
||||
if (SkipAudio || !MyAudioDecoder) { // skip audio
|
||||
@ -376,11 +376,12 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
|
||||
}
|
||||
|
||||
/**
|
||||
** Mute audio device.
|
||||
** Turns off audio while replaying.
|
||||
*/
|
||||
void Mute(void)
|
||||
{
|
||||
SkipAudio = 1;
|
||||
AudioFlushBuffers();
|
||||
//AudioSetVolume(0);
|
||||
}
|
||||
|
||||
@ -604,7 +605,7 @@ int VideoDecode(void)
|
||||
int saved_size;
|
||||
static int last_codec_id = CODEC_ID_NONE;
|
||||
|
||||
if (VideoFreezed) {
|
||||
if (StreamFreezed) { // stream freezed
|
||||
return 1;
|
||||
}
|
||||
if (VideoClearBuffers) {
|
||||
@ -822,7 +823,7 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
if (SkipVideo) { // skip video
|
||||
return size;
|
||||
}
|
||||
if (VideoFreezed) { // video freezed
|
||||
if (StreamFreezed) { // stream freezed
|
||||
return 0;
|
||||
}
|
||||
if (NewVideoStream) { // channel switched
|
||||
@ -1123,9 +1124,7 @@ void SetPlayMode(void)
|
||||
NewAudioStream = 1;
|
||||
}
|
||||
}
|
||||
VideoFreezed = 0;
|
||||
// done by Resume: SkipAudio = 0;
|
||||
// done by Resume: SkipVideo = 0;
|
||||
StreamFreezed = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1150,9 +1149,9 @@ void Clear(void)
|
||||
*/
|
||||
void Play(void)
|
||||
{
|
||||
VideoFreezed = 0;
|
||||
StreamFreezed = 0;
|
||||
SkipAudio = 0;
|
||||
// FIXME: restart audio
|
||||
AudioPlay();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1160,9 +1159,8 @@ void Play(void)
|
||||
*/
|
||||
void Freeze(void)
|
||||
{
|
||||
VideoFreezed = 1;
|
||||
// FIXME: freeze audio
|
||||
AudioFlushBuffers();
|
||||
StreamFreezed = 1;
|
||||
AudioPause();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -657,7 +657,6 @@ class cSoftHdDevice:public cDevice
|
||||
virtual void Play(void);
|
||||
virtual void Freeze(void);
|
||||
virtual void Mute(void);
|
||||
virtual void SetVolumeDevice(int);
|
||||
virtual void StillPicture(const uchar *, int);
|
||||
virtual bool Poll(cPoller &, int = 0);
|
||||
virtual bool Flush(int = 0);
|
||||
@ -675,6 +674,7 @@ class cSoftHdDevice:public cDevice
|
||||
virtual int GetAudioChannelDevice(void);
|
||||
virtual void SetDigitalAudioDevice(bool);
|
||||
virtual void SetAudioTrackDevice(eTrackType);
|
||||
virtual void SetVolumeDevice(int);
|
||||
virtual int PlayAudio(const uchar *, int, uchar);
|
||||
|
||||
// Image Grab facilities
|
||||
@ -700,6 +700,7 @@ cSoftHdDevice::cSoftHdDevice(void)
|
||||
#if 0
|
||||
spuDecoder = NULL;
|
||||
#endif
|
||||
SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat));
|
||||
}
|
||||
|
||||
cSoftHdDevice::~cSoftHdDevice(void)
|
||||
@ -826,6 +827,9 @@ void cSoftHdDevice::Freeze(void)
|
||||
::Freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
** Turns off audio while replaying.
|
||||
*/
|
||||
void cSoftHdDevice::Mute(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
@ -834,13 +838,6 @@ void cSoftHdDevice::Mute(void)
|
||||
::Mute();
|
||||
}
|
||||
|
||||
void cSoftHdDevice::SetVolumeDevice(int volume)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, volume);
|
||||
|
||||
::SetVolumeDevice(volume);
|
||||
}
|
||||
|
||||
/**
|
||||
** Display the given I-frame as a still picture.
|
||||
*/
|
||||
@ -891,8 +888,8 @@ bool cSoftHdDevice::Flush(int timeout_ms)
|
||||
**
|
||||
** @note FIXME: this function isn't called on the initial channel
|
||||
*/
|
||||
void cSoftHdDevice:: SetVideoDisplayFormat(eVideoDisplayFormat
|
||||
video_display_format)
|
||||
void cSoftHdDevice::SetVideoDisplayFormat(
|
||||
eVideoDisplayFormat video_display_format)
|
||||
{
|
||||
static int last = -1;
|
||||
|
||||
@ -965,6 +962,18 @@ int cSoftHdDevice::GetAudioChannelDevice(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Sets the audio volume on this device (Volume = 0...255).
|
||||
**
|
||||
** @param volume device volume
|
||||
*/
|
||||
void cSoftHdDevice::SetVolumeDevice(int volume)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, volume);
|
||||
|
||||
::SetVolumeDevice(volume);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user