bugfixes found while testing:
authorBenjamin Otte <otte@gnome.org>
Thu, 27 Feb 2003 22:33:01 +0000 (22:33 +0000)
committerBenjamin Otte <otte@gnome.org>
Thu, 27 Feb 2003 22:33:01 +0000 (22:33 +0000)
Original commit message from CVS:
bugfixes found while testing:
- return after 1 iteration, don't loop for ever
- caps nego: only parse endianness when necessary
- caps nego: make mu law and a law work
- caps nego: make float work
- call right function when going from PAUSED to PLAYING
- stupid error in request_new_pad

ext/alsa/gstalsa.c

index 9aed113c203da8c2f20e6053ad5b9ec1186549e8..ab1cb298c71b7087c5c5f52e1a8179299dc96260 100644 (file)
@@ -453,7 +453,7 @@ gst_alsa_request_new_pad (GstElement *element, GstPadTemplate *templ,
   gint channel = 0;
 
   g_return_val_if_fail ((this = GST_ALSA (element)), NULL);
-  g_return_val_if_fail (GST_FLAG_IS_SET (element, GST_ALSA_RUNNING), NULL);
+  g_return_val_if_fail (!GST_FLAG_IS_SET (element, GST_ALSA_RUNNING), NULL);
 
   /* you can't request a pad if the non-request pad already has more than 1 channel */
   g_return_val_if_fail (this->channels > GST_ELEMENT(this)->numpads, NULL);
@@ -514,23 +514,49 @@ gst_alsa_get_format (GstCaps *caps)
                        "width", &width,
                        "depth", &depth,
                        "law", &law,
-                       "endianness", &endianness,
                        "signed", &sign,
                        NULL))
         return SND_PCM_FORMAT_UNKNOWN;
        
+    /* extract endianness if needed */
+    if (width > 8) {
+      if (!gst_caps_get (caps,
+                         "endianness", &endianness,
+                         NULL))
+        return SND_PCM_FORMAT_UNKNOWN;      
+    } else {
+      endianness = G_BYTE_ORDER;
+    }
+    
     /* find corresponding alsa format */
     switch (law) {
       case 0: return snd_pcm_build_linear_format (depth, width, sign ? 0 : 1, endianness == G_LITTLE_ENDIAN ? 0 : 1);
-      case 1: return SND_PCM_FORMAT_A_LAW;
-      case 2: return SND_PCM_FORMAT_MU_LAW;
+      case 1: 
+        if (width == 8 && depth == 8 && sign == FALSE) {
+          return SND_PCM_FORMAT_MU_LAW;
+        } else {
+          return SND_PCM_FORMAT_UNKNOWN;
+        }
+      case 2: 
+        if (width == 8 && depth == 8 && sign == FALSE) {
+          return SND_PCM_FORMAT_A_LAW;
+        } else {
+          return SND_PCM_FORMAT_UNKNOWN;
+        }
       default: return SND_PCM_FORMAT_UNKNOWN;
     }
   } else if (strncmp (format_name, "float", 5) == 0) {
     gchar *layout;
+    gfloat intercept, slope;
     /* get layout */
-    if (!gst_caps_get_string (caps, "layout", (const gchar **) &layout))
+    if (!gst_caps_get (caps, "layout", &layout,
+                             "intercept", &intercept,
+                             "slope", &slope,
+                             NULL))
       return SND_PCM_FORMAT_UNKNOWN;
+    if (intercept != 0.0f || slope != 1.0f) {
+      return SND_PCM_FORMAT_UNKNOWN;      
+    }
        /* match layout to format wrt to endianness */
     if (strncmp (layout, "gfloat", 6) == 0) {
       return SND_PCM_FORMAT_FLOAT;
@@ -547,35 +573,42 @@ gst_alsa_get_format (GstCaps *caps)
 static GstProps *
 gst_alsa_get_props (snd_pcm_format_t format)
 {
-  /* int or float */
-  if (snd_pcm_format_linear (format)) {
+  if (format == SND_PCM_FORMAT_A_LAW) {
+    return gst_props_new ("format", GST_PROPS_STRING ("int"),
+                          "law", GST_PROPS_INT(2),
+                          "width", GST_PROPS_INT(8),
+                          "depth", GST_PROPS_INT(8),
+                          "signed", GST_PROPS_BOOLEAN (FALSE),
+                          NULL);
+  } else if (format == SND_PCM_FORMAT_MU_LAW) {
+    return gst_props_new ("format", GST_PROPS_STRING ("int"),
+                          "law", GST_PROPS_INT(1),
+                          "width", GST_PROPS_INT(8),
+                          "depth", GST_PROPS_INT(8),
+                          "signed", GST_PROPS_BOOLEAN (FALSE),
+                          NULL);
+  } else if (snd_pcm_format_linear (format)) {
+    /* int */
     GstProps *props = gst_props_new ("format", GST_PROPS_STRING ("int"),
                           "width", GST_PROPS_INT(snd_pcm_format_physical_width (format)),
                           "depth", GST_PROPS_INT(snd_pcm_format_width (format)),
+                          "law", GST_PROPS_INT(0),
                           "signed", GST_PROPS_BOOLEAN (snd_pcm_format_signed (format) == 1 ? TRUE : FALSE),
                           NULL);
     /* endianness */
-    switch (snd_pcm_format_little_endian (format)) {
-    case 0:
-      gst_props_add_entry (props, gst_props_entry_new ("endianness", GST_PROPS_INT (G_BIG_ENDIAN)));
-      break;
-    case 1:
-      gst_props_add_entry (props, gst_props_entry_new ("endianness", GST_PROPS_INT (G_LITTLE_ENDIAN)));
-      break;
-    default:
-      break;
-    }
-    /* law */
-    switch (format) {
-    case SND_PCM_FORMAT_A_LAW:
-      gst_props_add_entry (props, gst_props_entry_new ("law", GST_PROPS_INT (1)));
-      break;
-    case SND_PCM_FORMAT_MU_LAW:
-      gst_props_add_entry (props, gst_props_entry_new ("law", GST_PROPS_INT (2)));
-      break;
-    default:
-      gst_props_add_entry (props, gst_props_entry_new ("law", GST_PROPS_INT (0)));
-      break;                   
+    if (snd_pcm_format_physical_width (format) > 8) {
+      switch (snd_pcm_format_little_endian (format)) {
+      case 0:
+        gst_props_add_entry (props, gst_props_entry_new ("endianness", GST_PROPS_INT (G_BIG_ENDIAN)));
+        break;
+      case 1:
+        gst_props_add_entry (props, gst_props_entry_new ("endianness", GST_PROPS_INT (G_LITTLE_ENDIAN)));
+        break;
+      default:
+        g_warning("ALSA: Unknown byte order in sound driver. Continuing by assuming system byte order.");
+        gst_props_add_entry (props, gst_props_entry_new ("endianness", GST_PROPS_INT (G_BYTE_ORDER)));
+        break;
+      }
     }
     return props;
   } else if (snd_pcm_format_float (format)) {
@@ -585,6 +618,8 @@ gst_alsa_get_props (snd_pcm_format_t format)
 
     return gst_props_new ("format", GST_PROPS_STRING ("float"),
                           "layout", GST_PROPS_STRING (snd_pcm_format_width (format) == 64 ? "gdouble" : "gfloat"),
+                          "intercept", GST_PROPS_FLOAT (0),
+                          "slope", GST_PROPS_FLOAT (1),
                           NULL);
   }
   return NULL;
@@ -657,11 +692,11 @@ gst_alsa_link (GstPad *pad, GstCaps *caps)
       if (!gst_alsa_open_audio (this))
         return GST_PAD_LINK_REFUSED;
 
-    /* FIXME: allow changing the format here, even by retrying caps on other pads */
     format = gst_alsa_get_format (caps);
     GST_DEBUG (GST_CAT_CAPS, "found format %s\n", snd_pcm_format_name (format));
       
-    if (this->format != SND_PCM_FORMAT_UNKNOWN && this->format != format)
+    /* FIXME: allow changing the format here, even by retrying caps on other pads */
+    if (format == SND_PCM_FORMAT_UNKNOWN || (this->format != SND_PCM_FORMAT_UNKNOWN && this->format != format))
       return GST_PAD_LINK_REFUSED;
     if (!gst_caps_get (caps, "rate", &rate,
                              "channels", &channels,
@@ -710,8 +745,8 @@ gst_alsa_change_state (GstElement *element)
   case GST_STATE_READY_TO_PAUSED:
     break;
   case GST_STATE_PAUSED_TO_PLAYING:
-    if (GST_FLAG_IS_SET (element, GST_ALSA_OPEN) == FALSE)
-      if (!gst_alsa_open_audio (this))
+    if (GST_FLAG_IS_SET (element, GST_ALSA_RUNNING) == FALSE)
+      if (!gst_alsa_start_audio (this))
         return GST_STATE_FAILURE;
 
   case GST_STATE_PLAYING_TO_PAUSED:
@@ -763,18 +798,18 @@ gst_alsa_sink_loop (GstElement *element)
     }
   }
   
-  while (1) {
-    
-    avail = snd_pcm_avail_update (this->handle);
-    if (avail < 0) {
-      if (avail == -EPIPE) {
-        gst_alsa_xrun_recovery (this);
-        continue;
-      } else {
-        g_warning ("unknown ALSA avail_update return value (%d)", (int) avail);
-        return;
-      }
+restart:
+  
+  avail = snd_pcm_avail_update (this->handle);
+  if (avail < 0) {
+    if (avail == -EPIPE) {
+      gst_alsa_xrun_recovery (this);
+      goto restart;
+    } else {
+      g_warning ("unknown ALSA avail_update return value (%d)", (int) avail);
+      return;
     }
+  }
 
     if (avail > 0) {
       /* check how many bytes we still have in all our bytestreams */
@@ -852,15 +887,14 @@ gst_alsa_sink_loop (GstElement *element)
            * under gdb, or when exiting due to a signal */
           GST_DEBUG (GST_CAT_PLUGIN_INFO, "got interrupted while waiting");
           if (gst_element_interrupt (element))
-            break;
+            return;
           else
-            continue;
+            goto restart;
          }
         g_warning ("error waiting for alsa pcm: (%d: %s)", errno, strerror (errno));
         return;
       }
     }
-  }
 }
 
 static void