ext/alsa/gstalsasink.*: Add lock to protect alsa calls.

Original commit message from CVS:
* ext/alsa/gstalsasink.c: (gst_alsasink_finalise),
(gst_alsasink_class_init), (gst_alsasink_init),
(gst_alsasink_write), (gst_alsasink_reset):
* ext/alsa/gstalsasink.h:
Add lock to protect alsa calls.
Implement reset to flush samples ASAP, does not work
with dmix though.
This commit is contained in:
Wim Taymans 2006-02-03 12:51:47 +00:00
parent 260b5295c9
commit 7aeb1d4587
3 changed files with 40 additions and 6 deletions

View file

@ -1,3 +1,13 @@
2006-02-03 Wim Taymans <wim@fluendo.com>
* ext/alsa/gstalsasink.c: (gst_alsasink_finalise),
(gst_alsasink_class_init), (gst_alsasink_init),
(gst_alsasink_write), (gst_alsasink_reset):
* ext/alsa/gstalsasink.h:
Add lock to protect alsa calls.
Implement reset to flush samples ASAP, does not work
with dmix though.
2006-02-02 Wim Taymans <wim@fluendo.com> 2006-02-02 Wim Taymans <wim@fluendo.com>
* gst-libs/gst/audio/gstbaseaudiosink.c: * gst-libs/gst/audio/gstbaseaudiosink.c:

View file

@ -42,6 +42,9 @@ GST_ELEMENT_DETAILS ("Audio Sink (ALSA)",
"Output to a sound card via ALSA", "Output to a sound card via ALSA",
"Wim Taymans <wim@fluendo.com>"); "Wim Taymans <wim@fluendo.com>");
#define DEFAULT_DEVICE "default"
#define DEFAULT_DEVICE_NAME ""
enum enum
{ {
PROP_0, PROP_0,
@ -142,6 +145,7 @@ gst_alsasink_finalise (GObject * object)
GstAlsaSink *sink = GST_ALSA_SINK (object); GstAlsaSink *sink = GST_ALSA_SINK (object);
g_free (sink->device); g_free (sink->device);
g_mutex_free (sink->alsa_lock);
} }
static void static void
@ -189,11 +193,12 @@ gst_alsasink_class_init (GstAlsaSinkClass * klass)
g_object_class_install_property (gobject_class, PROP_DEVICE, g_object_class_install_property (gobject_class, PROP_DEVICE,
g_param_spec_string ("device", "Device", g_param_spec_string ("device", "Device",
"ALSA device, as defined in an asound configuration file", "ALSA device, as defined in an asound configuration file",
"default", G_PARAM_READWRITE)); DEFAULT_DEVICE, G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
g_param_spec_string ("device-name", "Device name", g_param_spec_string ("device-name", "Device name",
"Human-readable name of the sound device", "", G_PARAM_READABLE)); "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
G_PARAM_READABLE));
} }
static void static void
@ -246,13 +251,18 @@ gst_alsasink_get_property (GObject * object, guint prop_id,
} }
} }
static snd_output_t *output = NULL;
static void static void
gst_alsasink_init (GstAlsaSink * alsasink) gst_alsasink_init (GstAlsaSink * alsasink)
{ {
GST_DEBUG_OBJECT (alsasink, "initializing alsasink"); GST_DEBUG_OBJECT (alsasink, "initializing alsasink");
alsasink->device = g_strdup ("default"); alsasink->device = g_strdup (DEFAULT_DEVICE);
alsasink->handle = NULL; alsasink->handle = NULL;
alsasink->alsa_lock = g_mutex_new ();
snd_output_stdio_attach (&output, stdout, 0);
} }
static GstCaps * static GstCaps *
@ -695,12 +705,14 @@ gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
cptr = length / alsa->bytes_per_sample; cptr = length / alsa->bytes_per_sample;
ptr = data; ptr = data;
GST_ALSA_LOCK (asink);
while (cptr > 0) { while (cptr > 0) {
err = snd_pcm_writei (alsa->handle, ptr, cptr); err = snd_pcm_writei (alsa->handle, ptr, cptr);
GST_DEBUG_OBJECT (asink, "written %d result %d", cptr, err);
if (err < 0) { if (err < 0) {
GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
if (err == -EAGAIN) { if (err == -EAGAIN) {
GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
continue; continue;
} else if (xrun_recovery (alsa->handle, err) < 0) { } else if (xrun_recovery (alsa->handle, err) < 0) {
goto write_error; goto write_error;
@ -711,11 +723,13 @@ gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
ptr += err * alsa->channels; ptr += err * alsa->channels;
cptr -= err; cptr -= err;
} }
GST_ALSA_UNLOCK (asink);
return length - cptr; return length - cptr;
write_error: write_error:
{ {
GST_ALSA_UNLOCK (asink);
return length; /* skip one period */ return length; /* skip one period */
} }
} }
@ -736,14 +750,18 @@ gst_alsasink_delay (GstAudioSink * asink)
static void static void
gst_alsasink_reset (GstAudioSink * asink) gst_alsasink_reset (GstAudioSink * asink)
{ {
#if 0
GstAlsaSink *alsa; GstAlsaSink *alsa;
gint err; gint err;
alsa = GST_ALSA_SINK (asink); alsa = GST_ALSA_SINK (asink);
GST_ALSA_LOCK (asink);
GST_DEBUG_OBJECT (alsa, "drop");
CHECK (snd_pcm_drop (alsa->handle), drop_error); CHECK (snd_pcm_drop (alsa->handle), drop_error);
GST_DEBUG_OBJECT (alsa, "prepare");
CHECK (snd_pcm_prepare (alsa->handle), prepare_error); CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
GST_DEBUG_OBJECT (alsa, "reset done");
GST_ALSA_UNLOCK (asink);
return; return;
@ -760,5 +778,4 @@ prepare_error:
("alsa-reset: pcm prepare error: %s", snd_strerror (err)), (NULL)); ("alsa-reset: pcm prepare error: %s", snd_strerror (err)), (NULL));
return; return;
} }
#endif
} }

View file

@ -36,10 +36,15 @@ G_BEGIN_DECLS
#define GST_ALSA_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_SINK,GstAlsaSinkClass)) #define GST_ALSA_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_SINK,GstAlsaSinkClass))
#define GST_IS_ALSA_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_SINK)) #define GST_IS_ALSA_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_SINK))
#define GST_IS_ALSA_SINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_SINK)) #define GST_IS_ALSA_SINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_SINK))
#define GST_ALSA_SINK_CAST(obj) ((GstAlsaSink *) (obj))
typedef struct _GstAlsaSink GstAlsaSink; typedef struct _GstAlsaSink GstAlsaSink;
typedef struct _GstAlsaSinkClass GstAlsaSinkClass; typedef struct _GstAlsaSinkClass GstAlsaSinkClass;
#define GST_ALSA_GET_LOCK(obj) (GST_ALSA_SINK_CAST (obj)->alsa_lock)
#define GST_ALSA_LOCK(obj) (g_mutex_lock (GST_ALSA_GET_LOCK (obj)))
#define GST_ALSA_UNLOCK(obj) (g_mutex_unlock (GST_ALSA_GET_LOCK (obj)))
struct _GstAlsaSink { struct _GstAlsaSink {
GstAudioSink sink; GstAudioSink sink;
@ -59,6 +64,8 @@ struct _GstAlsaSink {
guint period_time; guint period_time;
snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t buffer_size;
snd_pcm_uframes_t period_size; snd_pcm_uframes_t period_size;
GMutex *alsa_lock;
}; };
struct _GstAlsaSinkClass { struct _GstAlsaSinkClass {