[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