[gst-cvs] CVS: gstreamer/plugins/alsa alsa.c,1.2,1.2.4.1 alsa.h,1.11,1.11.4.1
Andy Wingo
wingo at users.sourceforge.net
Sun Sep 23 15:53:02 PDT 2001
Update of /cvsroot/gstreamer/gstreamer/plugins/alsa
In directory usw-pr-cvs1:/tmp/cvs-serv6466/plugins/alsa
Modified Files:
Tag: BRANCH-EVENTS1
alsa.c alsa.h
Log Message:
- if you call gst_element_request_pad_by_name() with, say "sink4" as the pad name
and there is a "sink%d" template, the request_new_pad function will be called.
this is to allow for, for example, requesting a certain channel on a multichannel
device.
- to this end, request_new_pad now has the following prototype:
GstPad* (*request_new_pad) (GstElement *element, GstPadTemplate *templ, const gchar *name)
if request_pad_by_name was called with a name like "sink%d" (i.e. no parsing
was necessary) then NULL is passed as 'name'.
- all plugins that use request pads have been changed to the new api.
also, some incremental (untested) alsa updates, switching to the bytestream api...
Index: alsa.c
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/plugins/alsa/alsa.c,v
retrieving revision 1.2
retrieving revision 1.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- alsa.c 2001/09/10 01:30:18 1.2
+++ alsa.c 2001/09/23 22:52:32 1.2.4.1
@@ -51,6 +51,11 @@
static GstPadTemplate *gst_alsa_sink_pad_factory();
static GstPadTemplate *gst_alsa_sink_request_pad_factory();
+static GstPad* gst_alsa_sink_request_new_pad (GstElement *element, GstPadTemplate *templ, const
+ gchar *name);
+static GstPad* gst_alsa_src_request_new_pad (GstElement *element, GstPadTemplate *templ, const
+ gchar *name);
+
static void gst_alsa_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void gst_alsa_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
static GstElementStateReturn gst_alsa_change_state(GstElement *element);
@@ -64,6 +69,7 @@
static gboolean gst_alsa_set_params(GstAlsa *this);
static void gst_alsa_loop (GstElement *element);
static gboolean gst_alsa_sink_interleaved_process (GstAlsa *this, snd_pcm_uframes_t frames);
+static gboolean gst_alsa_src_interleaved_process (GstAlsa *this, snd_pcm_uframes_t frames);
static gboolean gst_alsa_get_channel_addresses (GstAlsa *this);
static void gst_alsa_release_channel_addresses (GstAlsa *this);
@@ -80,8 +86,8 @@
ARG_FORMAT,
ARG_CHANNELS,
ARG_FREQUENCY,
- ARG_FRAGMENTCOUNT,
- ARG_FRAGMENTSIZE
+ ARG_PERIODCOUNT,
+ ARG_PERIODFRAMES
};
GType
@@ -232,12 +238,12 @@
g_param_spec_int("frequency","frequency","frequency",
8000, 192000, 44100,
G_PARAM_READWRITE));
- g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FRAGMENTCOUNT,
- g_param_spec_int("fragment_count","fragment count","fragment count",
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PERIODCOUNT,
+ g_param_spec_int("period_count","period count","period count",
2, 64, 2,
G_PARAM_READWRITE));
- g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FRAGMENTSIZE,
- g_param_spec_int("fragment_size","fragment size","fragment size",
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PERIODFRAMES,
+ g_param_spec_int("period_frames","period frames","period frames",
64, 4096, 256,
G_PARAM_READWRITE));
@@ -245,6 +251,12 @@
object_class->set_property = gst_alsa_set_property;
element_class->change_state = gst_alsa_change_state;
+
+ if (GST_IS_ALSA_SRC_CLASS(klass)) {
+ element_class->request_new_pad = gst_alsa_src_request_new_pad;
+ } else if (GST_IS_ALSA_SINK_CLASS(klass)) {
+ element_class->request_new_pad = gst_alsa_sink_request_new_pad;
+ }
}
static void
@@ -253,12 +265,14 @@
/* init values */
this->handle = NULL;
- /* set some nice default-values...*/
- this->device = g_strdup("default");
- this->format = SND_PCM_FORMAT_S16;
- this->rate = 44100;
- this->channels = 1;
+ /* we're not going to set default values for things that caps takes care of
+ * because it could be that the device does not support them (eg, my hw:0,0
+ * device does not support mono operation) */
+ this->format = -1;
+ this->rate = 0;
+ this->channels = 0;
+ this->device = g_strdup("default");
this->period_count = 32; /* 'number of fragments' in oss-speak */
this->period_frames = 128;
this->buffer_frames = this->period_count * this->period_frames;
@@ -268,9 +282,11 @@
if (G_OBJECT_TYPE(this) == GST_TYPE_ALSA_SRC) {
this->stream = SND_PCM_STREAM_CAPTURE;
this->pad = gst_pad_new_from_template(gst_alsa_src_pad_factory(), "src");
+ this->process = gst_alsa_src_interleaved_process;
} else if (G_OBJECT_TYPE(this) == GST_TYPE_ALSA_SINK) {
this->stream = SND_PCM_STREAM_PLAYBACK;
this->pad = gst_pad_new_from_template(gst_alsa_sink_pad_factory(), "sink");
+ this->process = gst_alsa_sink_interleaved_process;
} else {
g_print("you cannot instantiate an object of type gstalsa. use alsasink or alsasrc instead.\n");
G_BREAKPOINT();
@@ -284,12 +300,62 @@
// * make request/non-request pads mutually exclusive
// also, if NONINTERLEAVED is all we got, multichannel is mandatory.
- this->process = gst_alsa_sink_interleaved_process;
-
gst_pad_set_negotiate_function(this->pad, gst_alsa_negotiate);
gst_element_set_loop_function(GST_ELEMENT(this), gst_alsa_loop);
}
+static GstPad*
+gst_alsa_sink_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name)
+{
+ GstAlsa *this;
+
+ g_return_val_if_fail (this = GST_ALSA(element), NULL);
+
+ g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL);
+
+ return NULL;
+
+// name = g_strdup_printf ("sink%d",adder->numsinkpads);
+// input_channel->sinkpad = gst_pad_new_from_template (templ, name);
+// gst_element_add_pad (GST_ELEMENT (adder), input_channel->sinkpad);
+// input_channel->bytes_waiting = 0;
+// input_channel->p_input_data = NULL;
+// input_channel->input_buffer = NULL;
+
+ /* add the input_channel to the list of input channels */
+
+// adder->input_channels = g_slist_append (adder->input_channels, input_channel);
+// adder->numsinkpads++;
+
+// return input_channel->sinkpad;
+}
+
+static GstPad*
+gst_alsa_src_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *name)
+{
+ GstAlsa *this;
+
+ g_return_val_if_fail (this = GST_ALSA(element), NULL);
+
+ g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL);
+
+ return NULL;
+
+// name = g_strdup_printf ("sink%d",adder->numsinkpads);
+// input_channel->sinkpad = gst_pad_new_from_template (templ, name);
+// gst_element_add_pad (GST_ELEMENT (adder), input_channel->sinkpad);
+// input_channel->bytes_waiting = 0;
+// input_channel->p_input_data = NULL;
+// input_channel->input_buffer = NULL;
+
+ /* add the input_channel to the list of input channels */
+
+// adder->input_channels = g_slist_append (adder->input_channels, input_channel);
+// adder->numsinkpads++;
+
+// return input_channel->sinkpad;
+}
+
static void
gst_alsa_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
@@ -316,12 +382,12 @@
this->rate = g_value_get_int (value);
prepare_channel = TRUE;
break;
- case ARG_FRAGMENTCOUNT:
+ case ARG_PERIODCOUNT:
this->period_count = g_value_get_int (value);
this->buffer_frames = this->period_count * this->period_frames;
prepare_channel = TRUE;
break;
- case ARG_FRAGMENTSIZE:
+ case ARG_PERIODFRAMES:
this->period_frames = g_value_get_int (value);
this->buffer_frames = this->period_count * this->period_frames;
prepare_channel = TRUE;
@@ -338,9 +404,9 @@
/* if we are playing, we need to do some additional stuff */
if (GST_FLAG_IS_SET(this, GST_ALSA_RUNNING))
snd_pcm_drop(this->handle);
-
+
gst_alsa_set_params(this);
-
+
if (GST_FLAG_IS_SET(this, GST_ALSA_RUNNING))
snd_pcm_prepare(this->handle);
/* ready to play again */
@@ -367,10 +433,10 @@
case ARG_FREQUENCY:
g_value_set_int (value, this->rate);
break;
- case ARG_FRAGMENTCOUNT:
+ case ARG_PERIODCOUNT:
g_value_set_int (value, this->period_count);
break;
- case ARG_FRAGMENTSIZE:
+ case ARG_PERIODFRAMES:
g_value_set_int (value, this->period_frames);
break;
default:
@@ -382,20 +448,27 @@
static GstElementStateReturn
gst_alsa_change_state(GstElement *element)
{
+ GstAlsa *this;
+
g_return_val_if_fail(element != NULL, FALSE);
+ this = GST_ALSA (element);
if (GST_STATE_PENDING(element) == GST_STATE_NULL) {
if (GST_FLAG_IS_SET(element, GST_ALSA_RUNNING))
gst_alsa_stop_audio((GstAlsa *)element);
if (GST_FLAG_IS_SET(element, GST_ALSA_OPEN))
gst_alsa_close_audio((GstAlsa *)element);
- } else {
- if (GST_FLAG_IS_SET(element, GST_ALSA_OPEN) == FALSE)
- if (gst_alsa_open_audio((GstAlsa *)element) == FALSE)
- return GST_STATE_FAILURE;
- if (GST_FLAG_IS_SET(element, GST_ALSA_RUNNING) == FALSE)
- if (gst_alsa_start_audio((GstAlsa *)element) == FALSE)
- return GST_STATE_FAILURE;
+ } else if (GST_STATE_PENDING(element) == GST_STATE_PLAYING) {
+ if (this->format==-1 || this->rate==0 || this->channels==0) {
+ g_print("alsa device not completely configured, awaiting capsnego\n");
+ } else {
+ if (GST_FLAG_IS_SET(element, GST_ALSA_OPEN) == FALSE)
+ if (gst_alsa_open_audio((GstAlsa *)element) == FALSE)
+ return GST_STATE_FAILURE;
+ if (GST_FLAG_IS_SET(element, GST_ALSA_RUNNING) == FALSE)
+ if (gst_alsa_start_audio((GstAlsa *)element) == FALSE)
+ return GST_STATE_FAILURE;
+ }
}
if (GST_ELEMENT_CLASS(parent_class)->change_state)
@@ -404,9 +477,6 @@
return GST_STATE_SUCCESS;
}
-/*
- * Parses the caps-struct, "borrowed" from gstosssink.c
- */
static gboolean
gst_alsa_parse_caps (GstAlsa *this, GstCaps *caps)
{
@@ -648,53 +718,49 @@
gst_alsa_release_channel_addresses(this);
}
} while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
+ // clean up bytestreams
}
static gboolean
gst_alsa_sink_interleaved_process (GstAlsa *this, snd_pcm_uframes_t frames)
{
- GstBuffer *buffer = NULL, *pulled, *temp;
- gint size = 0, wanted_size;
+ GstBuffer *peeked;
+ gint len;
g_return_val_if_fail(this->pad != NULL, FALSE);
- if (this->pad_leftovers) {
- buffer = this->pad_leftovers;
- size = GST_BUFFER_SIZE(buffer);
- }
+ if (!this->pad_bs)
+ this->pad_bs = gst_bytestream_new(this->pad);
- wanted_size = frames * this->sample_bytes * this->channels;
+ len = frames * this->sample_bytes * this->channels;
- /* big hack. */
- while (size < wanted_size) {
- pulled = gst_pad_pull(this->pad);
-
- if (buffer) {
- temp = buffer;
- buffer = gst_buffer_merge(temp, pulled);
- gst_buffer_unref (temp);
- gst_buffer_unref (pulled);
- } else {
- buffer = pulled;
- }
-
- size = GST_BUFFER_SIZE(buffer);
- }
+ peeked = gst_bytestream_peek(this->pad_bs, len);
+ memcpy(this->access_addr[0], GST_BUFFER_DATA(peeked), len);
+ gst_bytestream_flush(this->pad_bs, len);
- if (size == wanted_size) {
- memcpy(this->access_addr[0], GST_BUFFER_DATA(buffer), size);
- } else {
- memcpy(this->access_addr[0], GST_BUFFER_DATA(buffer), frames * this->sample_bytes *
- this->channels);
- this->pad_leftovers = gst_buffer_create_sub(buffer, wanted_size, size-wanted_size);
- }
+ return TRUE;
+}
+
+static gboolean
+gst_alsa_src_interleaved_process (GstAlsa *this, snd_pcm_uframes_t frames)
+{
+ GstBuffer *buf;
+ gint len;
- gst_buffer_unref(buffer);
+ g_return_val_if_fail(this->pad != NULL, FALSE);
+
+ len = frames * this->sample_bytes * this->channels;
+
+ buf = gst_buffer_new();
+ GST_BUFFER_DATA(buf) = g_malloc(len);
+ GST_BUFFER_SIZE(buf) = len;
+ GST_BUFFER_MAXSIZE(buf) = len;
+
+ memcpy(GST_BUFFER_DATA(buf), this->access_addr[0], len);
return TRUE;
}
-
/* taken more or less from pbd's audioengine code */
static gboolean
gst_alsa_set_params (GstAlsa *this)
@@ -755,13 +821,13 @@
ret = snd_pcm_hw_params_set_periods (this->handle, hw_param, this->period_count, 0);
if (ret < 0) {
- g_warning("error setting fragment count minimum (%d): %s", this->period_count, snd_strerror(ret));
+ g_warning("error setting period count minimum (%d): %s", this->period_count, snd_strerror(ret));
return FALSE;
}
ret = snd_pcm_hw_params_set_period_size (this->handle, hw_param, this->period_frames, 0);
if (ret < 0) {
- g_warning("error setting fragment size (%d): %s", this->period_frames, snd_strerror(ret));
+ g_warning("error setting period in frames (%d): %s", this->period_frames, snd_strerror(ret));
return FALSE;
}
@@ -1046,6 +1112,11 @@
{
GstElementFactory *factory;
+ if (!gst_library_load ("gstbytestream")) {
+ gst_info("alsa: could not load support library: 'gstbytestream'\n");
+ return FALSE;
+ }
+
factory = gst_elementfactory_new ("alsasrc", GST_TYPE_ALSA_SRC, &gst_alsa_src_details);
g_return_val_if_fail (factory != NULL, FALSE);
gst_elementfactory_add_padtemplate (factory, gst_alsa_src_pad_factory());
@@ -1069,3 +1140,5 @@
"alsa",
plugin_init
};
+
+
Index: alsa.h
===================================================================
RCS file: /cvsroot/gstreamer/gstreamer/plugins/alsa/alsa.h,v
retrieving revision 1.11
retrieving revision 1.11.4.1
diff -u -d -r1.11 -r1.11.4.1
--- alsa.h 2001/09/10 01:30:18 1.11
+++ alsa.h 2001/09/23 22:52:32 1.11.4.1
@@ -23,6 +23,7 @@
#include <sys/asoundlib.h>
#include <gst/gst.h>
+#include <libs/bytestream/gstbytestream.h>
#include <glib.h>
#define GST_ALSA(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, GST_TYPE_ALSA, GstAlsa)
@@ -67,9 +68,9 @@
GstElement parent;
GstPad *pad;
- GstBuffer *pad_leftovers;
+ GstByteStream *pad_bs;
GstPad **req_pads;
- GstBuffer **req_pad_leftovers;
+ GstByteStream *req_pads_bs;
gchar *device;
snd_pcm_stream_t stream;
More information about the Gstreamer-commits
mailing list