fixups in the prop view/controller compilation fixes in the player add gst-editor...
authorAndy Wingo <wingo@pobox.com>
Mon, 27 May 2002 04:48:57 +0000 (04:48 +0000)
committerAndy Wingo <wingo@pobox.com>
Mon, 27 May 2002 04:48:57 +0000 (04:48 +0000)
Original commit message from CVS:
* fixups in the prop view/controller
* compilation fixes in the player
* add gst-editor to gst-all
* fixes to adder to comply with new osssink sync issues
* alsa fixes, although still 100% cpu is used, yum
* reenable locking of threaded elements, seems to work fine here
* fix a makefile in examples/plugins

ext/alsa/gstalsa.c
gst/adder/gstadder.c

index afe057e72742f0f8b9db70f86ca13683d3c0f64b..a05869ad1392bb6307d7fe262dee2640eadbccc9 100644 (file)
@@ -20,6 +20,7 @@
 */
 
 #include <stdlib.h>
+#include <sys/time.h>
 #include "gstalsa.h"
 
 static GstElementDetails gst_alsa_sink_details = {  
@@ -69,6 +70,7 @@ static void gst_alsa_close_audio(GstAlsa *this);
 
 static gboolean gst_alsa_set_params(GstAlsa *this);
 static void gst_alsa_loop (GstElement *element);
+static void gst_alsa_xrun_recovery (GstAlsa *this);
 static gboolean gst_alsa_sink_process (GstAlsa *this, snd_pcm_uframes_t frames);
 static gboolean gst_alsa_src_process (GstAlsa *this, snd_pcm_uframes_t frames);
 
@@ -80,6 +82,13 @@ static void memset_interleave (char *dst, char val, unsigned int bytes,
                                unsigned int unit_bytes, 
                                unsigned int skip_bytes);
 
+/* #define _DEBUG */
+#ifdef _DEBUG
+#define DEBUG(text, args...) g_message(text, ##args)
+#else
+#define DEBUG(text, args...)
+#endif
+
 
 enum {
     ARG_0,
@@ -785,7 +794,7 @@ gst_alsa_connect(GstPad *pad, GstCaps *caps)
     return GST_PAD_CONNECT_DELAYED;
 }
 
-/* shamelessly stolen from pbd's audioengine. thanks, paul! */
+/* shamelessly stolen from pbd's audioengine and jack alsa_driver. thanks, paul! */
 static void
 gst_alsa_loop (GstElement *element)
 {
@@ -833,11 +842,12 @@ gst_alsa_loop (GstElement *element)
         xrun_detected = FALSE;
         
         this->avail = snd_pcm_avail_update (this->handle);
-//        g_print ("snd_pcm_avail_update() = %d\n", (int)this->avail);
+        DEBUG ("snd_pcm_avail_update() = %d", (int)this->avail);
         
         if (this->avail < 0) {
             if (this->avail == -EPIPE) {
-                xrun_detected = TRUE;
+                gst_alsa_xrun_recovery (this);
+                this->avail = 0;
             } else {
                 g_warning("unknown ALSA avail_update return value (%d)",
                           (int)this->avail);
@@ -848,12 +858,8 @@ gst_alsa_loop (GstElement *element)
         /* round down to nearest period_frames avail */
         this->avail -= this->avail % this->period_frames;
 
-//        g_print ("snd_pcm_avail_update(), rounded down = %d\n", (int)this->avail);
+        DEBUG ("snd_pcm_avail_update(), rounded down = %d", (int)this->avail);
 
-        /* pretty sophisticated eh? */
-        if (xrun_detected)
-            g_warning ("xrun detected"); 
-        
         /* we need to loop here because the available bytes might not be
          * contiguous */
         while (this->avail) {
@@ -1025,6 +1031,36 @@ gst_alsa_sink_process (GstAlsa *this, snd_pcm_uframes_t frames)
     return TRUE;
 }
 
+static void
+gst_alsa_xrun_recovery (GstAlsa *this)
+{
+    snd_pcm_status_t *status;
+    int res;
+
+    snd_pcm_status_alloca(&status);
+
+    if (this->stream == SND_PCM_STREAM_CAPTURE) {
+        if ((res = snd_pcm_status(this->handle, status)) < 0) {
+            g_warning ("status error: %s", snd_strerror(res));
+        }
+    } else {
+        if ((res = snd_pcm_status(this->handle, status)) < 0) {
+            g_warning ("status error: %s", snd_strerror(res));
+        }
+    }
+    
+    if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
+        struct timeval now, diff, tstamp;
+        gettimeofday(&now, 0);
+        snd_pcm_status_get_trigger_tstamp(status, &tstamp);
+        timersub(&now, &tstamp, &diff);
+        g_warning("alsa: xrun of at least %.3f msecs", diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
+    }
+    
+    gst_alsa_stop_audio (this);
+    gst_alsa_start_audio (this);
+}      
+
 /* taken more or less from pbd's audioengine code */
 static gboolean
 gst_alsa_set_params (GstAlsa *this)
@@ -1144,7 +1180,7 @@ gst_alsa_set_params (GstAlsa *this)
         return FALSE;
     }
     
-    ret = snd_pcm_sw_params_set_stop_threshold (this->handle, sw_param, ~0U);
+    ret = snd_pcm_sw_params_set_stop_threshold (this->handle, sw_param, this->buffer_frames);
     if (ret < 0) {
         g_warning("could not set stop mode: %s", snd_strerror(ret));
         return FALSE;
index 2ecb6d7702317a9981fa7422c1ad8b3f9623816d..fd31e0b52cbc5a3f37349c09af0213e57798d47a 100644 (file)
@@ -157,37 +157,43 @@ gst_adder_parse_caps (GstAdder *adder, GstCaps *caps)
       gst_caps_get_int     (caps, "endianness", &adder->endianness);
       gst_caps_get_boolean (caps, "signed",     &adder->is_signed);
       gst_caps_get_int     (caps, "channels",   &adder->channels);
+      gst_caps_get_int     (caps, "rate",      &adder->rate);
     } else if (strcmp (format, "float") == 0) {
       adder->format     = GST_ADDER_FORMAT_FLOAT;
       gst_caps_get_string  (caps, "layout",    &adder->layout);
       gst_caps_get_float   (caps, "intercept", &adder->intercept);
       gst_caps_get_float   (caps, "slope",     &adder->slope);
       gst_caps_get_int     (caps, "channels",  &adder->channels);
+      gst_caps_get_int     (caps, "rate",      &adder->rate);
     }
   } else {
     /* otherwise, a previously-connected pad has set all the values. we should
        barf if some of the attempted new values don't match. */
     if (strcmp (format, "int") == 0) {
-      gint width, channels;
+      gint width, channels, rate;
       gboolean is_signed;
 
       gst_caps_get_int     (caps, "width",     &width);
       gst_caps_get_int     (caps, "channels",  &channels);
       gst_caps_get_boolean (caps, "signed",    &is_signed);
+      gst_caps_get_int     (caps, "rate",      &rate);
 
       if ((adder->format != GST_ADDER_FORMAT_INT) ||
           (adder->width  != width) ||
           (adder->channels != channels) ||
-          (adder->is_signed != is_signed)) {
+          (adder->is_signed != is_signed) ||
+          (adder->rate != rate)) {
         return FALSE;
       }
     } else if (strcmp (format, "float") == 0) {
-      gint channels;
+      gint channels, rate;
 
       gst_caps_get_int     (caps, "channels",  &channels);
+      gst_caps_get_int     (caps, "rate",      &rate);
 
       if ((adder->format != GST_ADDER_FORMAT_FLOAT) ||
-          (adder->channels != channels)) {
+          (adder->channels != channels) ||
+          (adder->rate != rate)) {
         return FALSE;
       }
     } else {
@@ -377,6 +383,8 @@ gst_adder_loop (GstElement *element)
   guint8    *raw_in;
   guint32    waiting;
   guint32    got_bytes;
+  gint64     timestamp = 0;
+  gint64     offset = 0;
   register guint i;
 
   g_return_if_fail (element != NULL);
@@ -474,6 +482,13 @@ gst_adder_loop (GstElement *element)
       inputs = g_slist_next (inputs);
     }
 
+    GST_BUFFER_TIMESTAMP (buf_out) = timestamp;
+    if (adder->format == GST_ADDER_FORMAT_FLOAT)
+      offset += GST_BUFFER_SIZE (buf_out) / sizeof (gfloat) / adder->channels;
+    else
+      offset += GST_BUFFER_SIZE (buf_out) * 8 / adder->width / adder->channels;
+    timestamp = offset * GST_SECOND / adder->rate;
+
     /* send it out */
 
     GST_DEBUG (0, "pushing buf_out");