summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohns <johns98@gmx.net>2012-02-12 20:14:43 +0100
committerJohns <johns98@gmx.net>2012-02-12 20:14:43 +0100
commit0a2a221fa93bd4177b2a21d2499cef68b47424bd (patch)
tree8a39b18855a487c7830b121abce91bfcc4738734
parent24a065e5de863ab78cd8dc1e9a1ecf5e24ec6176 (diff)
downloadvdr-plugin-softhddevice-0a2a221fa93bd4177b2a21d2499cef68b47424bd.tar.gz
vdr-plugin-softhddevice-0a2a221fa93bd4177b2a21d2499cef68b47424bd.tar.bz2
Add play/pause audio support.
-rw-r--r--ChangeLog1
-rw-r--r--Todo2
-rw-r--r--audio.c105
-rw-r--r--audio.h4
-rw-r--r--softhddev.c24
-rw-r--r--softhddevice.cpp29
6 files changed, 133 insertions, 32 deletions
diff --git a/ChangeLog b/ChangeLog
index 09819e1..a2f6411 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/Todo b/Todo
index 66dbec5..ae6a387 100644
--- a/Todo
+++ b/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.
diff --git a/audio.c b/audio.c
index a65d63d..5d470f6 100644
--- a/audio.c
+++ b/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
@@ -1112,6 +1116,47 @@ static int AlsaSetup(int *freq, int *channels, int use_ac3)
}
/**
+** 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
*/
static void AlsaNoopCallback( __attribute__ ((unused))
@@ -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;
}
@@ -1741,6 +1791,20 @@ static int OssSetup(int *freq, int *channels, int use_ac3)
}
/**
+** Play audio.
+*/
+void OssPlay(void)
+{
+}
+
+/**
+** Pause audio.
+*/
+void OssPause(void)
+{
+}
+
+/**
** Initialize OSS audio output module.
*/
static void OssInit(void)
@@ -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,
};
@@ -2105,6 +2173,32 @@ int AudioSetup(int *freq, int *channels, int 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.
**
** @param device name of pcm device (fe. "hw:0,9" or "/dev/dsp")
@@ -2207,8 +2301,7 @@ void AudioInit(void)
AudioInitThread();
}
#endif
-
- AudioPaused = 1;
+ AudioPaused = 0;
}
/**
diff --git a/audio.h b/audio.h
index f0dedab..677fbcf 100644
--- a/audio.h
+++ b/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
diff --git a/softhddev.c b/softhddev.c
index 5ce146a..882d2c1 100644
--- a/softhddev.c
+++ b/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();
}
/**
diff --git a/softhddevice.cpp b/softhddevice.cpp
index 9854d97..ad9d0cb 100644
--- a/softhddevice.cpp
+++ b/softhddevice.cpp
@@ -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);
+}
+
// ----------------------------------------------------------------------------
/**