src/3rdparty/phonon/gstreamer/alsasink2.c
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /* GStreamer
       
     2  * Copyright (C) 2001 CodeFactory AB
       
     3  * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
       
     4  * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
       
     5  * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
       
     6  * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
       
     7  * Copyright (C) 2005, 2006 Tim-Philipp Müller <tim centricular net>
       
     8  * Copyright (C) 2008 Matthias Kretz <kretz@kde.org>
       
     9  *
       
    10  * gstalsasink2.c:
       
    11  *
       
    12  * This library is free software; you can redistribute it and/or
       
    13  * modify it under the terms of the GNU Library General Public
       
    14  * License as published by the Free Software Foundation; either
       
    15  * version 2 of the License, or (at your option) any later version.
       
    16  *
       
    17  * This library is distributed in the hope that it will be useful,
       
    18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    20  * Library General Public License for more details.
       
    21  *
       
    22  *  You should have received a copy of the GNU Lesser General Public 
       
    23  *  License along with this library.  If not, see <http://www.gnu.org/licenses/>.
       
    24  */
       
    25 
       
    26 /**
       
    27  * SECTION:element-alsasink2
       
    28  * @short_description: play audio to an ALSA device
       
    29  * @see_also: alsasrc, alsamixer
       
    30  *
       
    31  * <refsect2>
       
    32  * <para>
       
    33  * This element renders raw audio samples using the ALSA api.
       
    34  * </para>
       
    35  * <title>Example pipelines</title>
       
    36  * <para>
       
    37  * Play an Ogg/Vorbis file.
       
    38  * </para>
       
    39  * <programlisting>
       
    40  * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! alsasink2
       
    41  * </programlisting>
       
    42  * </refsect2>
       
    43  *
       
    44  * Last reviewed on 2006-03-01 (0.10.4)
       
    45  */
       
    46 
       
    47 #define _XOPEN_SOURCE 600
       
    48 
       
    49 #include <sys/ioctl.h>
       
    50 #include <fcntl.h>
       
    51 #include <errno.h>
       
    52 #include <unistd.h>
       
    53 #include <string.h>
       
    54 #include <getopt.h>
       
    55 #include <alsa/asoundlib.h>
       
    56 
       
    57 #include "alsasink2.h"
       
    58 
       
    59 #include <gst/interfaces/propertyprobe.h>
       
    60 #include <gst/audio/multichannel.h>
       
    61 
       
    62 #define _(text) (text)
       
    63 
       
    64 #define GST_CHECK_ALSA_VERSION(major,minor,micro) \
       
    65     (SND_LIB_MAJOR > (major) || \
       
    66      (SND_LIB_MAJOR == (major) && SND_LIB_MINOR > (minor)) || \
       
    67      (SND_LIB_MAJOR == (major) && SND_LIB_MINOR == (minor) && \
       
    68       SND_LIB_SUBMINOR >= (micro)))
       
    69 
       
    70 static const GList *
       
    71 gst_alsa_device_property_probe_get_properties (GstPropertyProbe * probe)
       
    72 {
       
    73   GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
       
    74   static GList *list = NULL;
       
    75 
       
    76   /* well, not perfect, but better than no locking at all.
       
    77    * In the worst case we leak a list node, so who cares? */
       
    78   GST_CLASS_LOCK (GST_OBJECT_CLASS (klass));
       
    79 
       
    80   if (!list) {
       
    81     GParamSpec *pspec;
       
    82 
       
    83     pspec = g_object_class_find_property (klass, "device");
       
    84     list = g_list_append (NULL, pspec);
       
    85   }
       
    86 
       
    87   GST_CLASS_UNLOCK (GST_OBJECT_CLASS (klass));
       
    88 
       
    89   return list;
       
    90 }
       
    91 
       
    92 static GList *
       
    93 gst_alsa_get_device_list (snd_pcm_stream_t stream)
       
    94 {
       
    95   snd_ctl_t *handle;
       
    96   int card, err, dev;
       
    97   snd_ctl_card_info_t *info;
       
    98   snd_pcm_info_t *pcminfo;
       
    99   gboolean mixer = (stream == ~0u);
       
   100   GList *list = NULL;
       
   101 
       
   102   if (stream == ~0u)
       
   103     stream = 0;
       
   104 
       
   105   snd_ctl_card_info_malloc (&info);
       
   106   snd_pcm_info_malloc (&pcminfo);
       
   107   card = -1;
       
   108 
       
   109   if (snd_card_next (&card) < 0 || card < 0) {
       
   110     /* no soundcard found */
       
   111     return NULL;
       
   112   }
       
   113 
       
   114   while (card >= 0) {
       
   115     gchar name[32];
       
   116 
       
   117     g_snprintf (name, sizeof (name), "hw:%d", card);
       
   118     if ((err = snd_ctl_open (&handle, name, 0)) < 0) {
       
   119       goto next_card;
       
   120     }
       
   121     if ((err = snd_ctl_card_info (handle, info)) < 0) {
       
   122       snd_ctl_close (handle);
       
   123       goto next_card;
       
   124     }
       
   125 
       
   126     if (mixer) {
       
   127       list = g_list_append (list, g_strdup (name));
       
   128     } else {
       
   129       g_snprintf (name, sizeof (name), "default:CARD=%d", card);
       
   130       list = g_list_append (list, g_strdup (name));
       
   131       dev = -1;
       
   132       while (1) {
       
   133         gchar *gst_device;
       
   134 
       
   135         snd_ctl_pcm_next_device (handle, &dev);
       
   136 
       
   137         if (dev < 0)
       
   138           break;
       
   139         snd_pcm_info_set_device (pcminfo, dev);
       
   140         snd_pcm_info_set_subdevice (pcminfo, 0);
       
   141         snd_pcm_info_set_stream (pcminfo, stream);
       
   142         if ((err = snd_ctl_pcm_info (handle, pcminfo)) < 0) {
       
   143           continue;
       
   144         }
       
   145 
       
   146         gst_device = g_strdup_printf ("hw:%d,%d", card, dev);
       
   147         list = g_list_append (list, gst_device);
       
   148       }
       
   149     }
       
   150     snd_ctl_close (handle);
       
   151   next_card:
       
   152     if (snd_card_next (&card) < 0) {
       
   153       break;
       
   154     }
       
   155   }
       
   156 
       
   157   snd_ctl_card_info_free (info);
       
   158   snd_pcm_info_free (pcminfo);
       
   159 
       
   160   return list;
       
   161 }
       
   162 
       
   163 static void
       
   164 gst_alsa_device_property_probe_probe_property (GstPropertyProbe * probe,
       
   165     guint prop_id, const GParamSpec * pspec)
       
   166 {
       
   167   if (!g_str_equal (pspec->name, "device")) {
       
   168     G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
       
   169   }
       
   170 }
       
   171 
       
   172 static gboolean
       
   173 gst_alsa_device_property_probe_needs_probe (GstPropertyProbe * probe,
       
   174     guint prop_id, const GParamSpec * pspec)
       
   175 {
       
   176   /* don't cache probed data */
       
   177   return TRUE;
       
   178 }
       
   179 
       
   180 static GValueArray *
       
   181 gst_alsa_device_property_probe_get_values (GstPropertyProbe * probe,
       
   182     guint prop_id, const GParamSpec * pspec)
       
   183 {
       
   184   GstElementClass *klass;
       
   185   const GList *templates;
       
   186   snd_pcm_stream_t mode = -1;
       
   187   GValueArray *array;
       
   188   GValue value = { 0, };
       
   189   GList *l, *list;
       
   190 
       
   191   if (!g_str_equal (pspec->name, "device")) {
       
   192     G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
       
   193     return NULL;
       
   194   }
       
   195 
       
   196   klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (probe));
       
   197 
       
   198   /* I'm pretty sure ALSA has a good way to do this. However, their cool
       
   199    * auto-generated documentation is pretty much useless if you try to
       
   200    * do function-wise look-ups. */
       
   201   /* we assume one pad template at max [zero=mixer] */
       
   202   templates = gst_element_class_get_pad_template_list (klass);
       
   203   if (templates) {
       
   204     if (GST_PAD_TEMPLATE_DIRECTION (templates->data) == GST_PAD_SRC)
       
   205       mode = SND_PCM_STREAM_CAPTURE;
       
   206     else
       
   207       mode = SND_PCM_STREAM_PLAYBACK;
       
   208   }
       
   209 
       
   210   list = gst_alsa_get_device_list (mode);
       
   211 
       
   212   if (list == NULL) {
       
   213     GST_LOG_OBJECT (probe, "No devices found");
       
   214     return NULL;
       
   215   }
       
   216 
       
   217   array = g_value_array_new (g_list_length (list));
       
   218   g_value_init (&value, G_TYPE_STRING);
       
   219   for (l = list; l != NULL; l = l->next) {
       
   220     GST_LOG_OBJECT (probe, "Found device: %s", (gchar *) l->data);
       
   221     g_value_take_string (&value, (gchar *) l->data);
       
   222     l->data = NULL;
       
   223     g_value_array_append (array, &value);
       
   224   }
       
   225   g_value_unset (&value);
       
   226   g_list_free (list);
       
   227 
       
   228   return array;
       
   229 }
       
   230 
       
   231 static void
       
   232 gst_alsa_property_probe_interface_init (GstPropertyProbeInterface * iface)
       
   233 {
       
   234   iface->get_properties = gst_alsa_device_property_probe_get_properties;
       
   235   iface->probe_property = gst_alsa_device_property_probe_probe_property;
       
   236   iface->needs_probe = gst_alsa_device_property_probe_needs_probe;
       
   237   iface->get_values = gst_alsa_device_property_probe_get_values;
       
   238 }
       
   239 
       
   240 static void
       
   241 gst_alsa_type_add_device_property_probe_interface (GType type)
       
   242 {
       
   243   static const GInterfaceInfo probe_iface_info = {
       
   244     (GInterfaceInitFunc) gst_alsa_property_probe_interface_init,
       
   245     NULL,
       
   246     NULL,
       
   247   };
       
   248 
       
   249   g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
       
   250       &probe_iface_info);
       
   251 }
       
   252 
       
   253 static GstCaps *
       
   254 gst_alsa_detect_rates (GstObject * obj, snd_pcm_hw_params_t * hw_params,
       
   255     GstCaps * in_caps)
       
   256 {
       
   257   GstCaps *caps;
       
   258   guint min, max;
       
   259   gint err, dir, min_rate, max_rate;
       
   260   guint i;
       
   261 
       
   262   GST_LOG_OBJECT (obj, "probing sample rates ...");
       
   263 
       
   264   if ((err = snd_pcm_hw_params_get_rate_min (hw_params, &min, &dir)) < 0)
       
   265     goto min_rate_err;
       
   266 
       
   267   if ((err = snd_pcm_hw_params_get_rate_max (hw_params, &max, &dir)) < 0)
       
   268     goto max_rate_err;
       
   269 
       
   270   min_rate = min;
       
   271   max_rate = max;
       
   272 
       
   273   if (min_rate < 4000)
       
   274     min_rate = 4000;            /* random 'sensible minimum' */
       
   275 
       
   276   if (max_rate <= 0)
       
   277     max_rate = G_MAXINT;        /* or maybe just use 192400 or so? */
       
   278   else if (max_rate > 0 && max_rate < 4000)
       
   279     max_rate = MAX (4000, min_rate);
       
   280 
       
   281   GST_DEBUG_OBJECT (obj, "Min. rate = %u (%d)", min_rate, min);
       
   282   GST_DEBUG_OBJECT (obj, "Max. rate = %u (%d)", max_rate, max);
       
   283 
       
   284   caps = gst_caps_make_writable (in_caps);
       
   285 
       
   286   for (i = 0; i < gst_caps_get_size (caps); ++i) {
       
   287     GstStructure *s;
       
   288 
       
   289     s = gst_caps_get_structure (caps, i);
       
   290     if (min_rate == max_rate) {
       
   291       gst_structure_set (s, "rate", G_TYPE_INT, min_rate, NULL);
       
   292     } else {
       
   293       gst_structure_set (s, "rate", GST_TYPE_INT_RANGE,
       
   294           min_rate, max_rate, NULL);
       
   295     }
       
   296   }
       
   297 
       
   298   return caps;
       
   299 
       
   300   /* ERRORS */
       
   301 min_rate_err:
       
   302   {
       
   303     GST_ERROR_OBJECT (obj, "failed to query minimum sample rate: %s",
       
   304         snd_strerror (err));
       
   305     gst_caps_unref (in_caps);
       
   306     return NULL;
       
   307   }
       
   308 max_rate_err:
       
   309   {
       
   310     GST_ERROR_OBJECT (obj, "failed to query maximum sample rate: %s",
       
   311         snd_strerror (err));
       
   312     gst_caps_unref (in_caps);
       
   313     return NULL;
       
   314   }
       
   315 }
       
   316 
       
   317 static const struct
       
   318 {
       
   319   const int width;
       
   320   const int depth;
       
   321   const int sformat;
       
   322   const int uformat;
       
   323 } pcmformats[] = {
       
   324   {
       
   325   8, 8, SND_PCM_FORMAT_S8, SND_PCM_FORMAT_U8}, {
       
   326   16, 16, SND_PCM_FORMAT_S16, SND_PCM_FORMAT_U16}, {
       
   327   32, 24, SND_PCM_FORMAT_S24, SND_PCM_FORMAT_U24}, {
       
   328 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)   /* no endian-unspecific enum available */
       
   329   24, 24, SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_U24_3LE}, {
       
   330 #else
       
   331   24, 24, SND_PCM_FORMAT_S24_3BE, SND_PCM_FORMAT_U24_3BE}, {
       
   332 #endif
       
   333   32, 32, SND_PCM_FORMAT_S32, SND_PCM_FORMAT_U32}
       
   334 };
       
   335 
       
   336 static GstCaps *
       
   337 gst_alsa_detect_formats (GstObject * obj, snd_pcm_hw_params_t * hw_params,
       
   338     GstCaps * in_caps)
       
   339 {
       
   340   snd_pcm_format_mask_t *mask;
       
   341   GstStructure *s;
       
   342   GstCaps *caps;
       
   343   guint i;
       
   344 
       
   345   snd_pcm_format_mask_malloc (&mask);
       
   346   snd_pcm_hw_params_get_format_mask (hw_params, mask);
       
   347 
       
   348   caps = gst_caps_new_empty ();
       
   349 
       
   350   for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
       
   351     GstStructure *scopy;
       
   352     guint w;
       
   353     gint width = 0, depth = 0;
       
   354 
       
   355     s = gst_caps_get_structure (in_caps, i);
       
   356     if (!gst_structure_has_name (s, "audio/x-raw-int")) {
       
   357       GST_WARNING_OBJECT (obj, "skipping non-int format");
       
   358       continue;
       
   359     }
       
   360     if (!gst_structure_get_int (s, "width", &width) ||
       
   361         !gst_structure_get_int (s, "depth", &depth))
       
   362       continue;
       
   363     if (width == 0 || (width % 8) != 0)
       
   364       continue;                 /* Only full byte widths are valid */
       
   365     for (w = 0; w < G_N_ELEMENTS (pcmformats); w++)
       
   366       if (pcmformats[w].width == width && pcmformats[w].depth == depth)
       
   367         break;
       
   368     if (w == G_N_ELEMENTS (pcmformats))
       
   369       continue;                 /* Unknown format */
       
   370 
       
   371     if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat) &&
       
   372         snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
       
   373       /* template contains { true, false } or just one, leave it as it is */
       
   374       scopy = gst_structure_copy (s);
       
   375     } else if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat)) {
       
   376       scopy = gst_structure_copy (s);
       
   377       gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
       
   378     } else if (snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
       
   379       scopy = gst_structure_copy (s);
       
   380       gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
       
   381     } else {
       
   382       scopy = NULL;
       
   383     }
       
   384     if (scopy) {
       
   385       if (width > 8) {
       
   386         /* TODO: proper endianness detection, for now it's CPU endianness only */
       
   387         gst_structure_set (scopy, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
       
   388       }
       
   389       gst_caps_append_structure (caps, scopy);
       
   390     }
       
   391   }
       
   392 
       
   393   snd_pcm_format_mask_free (mask);
       
   394   gst_caps_unref (in_caps);
       
   395   return caps;
       
   396 }
       
   397 
       
   398 /* we don't have channel mappings for more than this many channels */
       
   399 #define GST_ALSA_MAX_CHANNELS 8
       
   400 
       
   401 static GstStructure *
       
   402 get_channel_free_structure (const GstStructure * in_structure)
       
   403 {
       
   404   GstStructure *s = gst_structure_copy (in_structure);
       
   405 
       
   406   gst_structure_remove_field (s, "channels");
       
   407   return s;
       
   408 }
       
   409 
       
   410 static void
       
   411 caps_add_channel_configuration (GstCaps * caps,
       
   412     const GstStructure * in_structure, gint min_chans, gint max_chans)
       
   413 {
       
   414   GstAudioChannelPosition pos[8] = {
       
   415     GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   416     GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   417     GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
       
   418     GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
       
   419     GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
       
   420     GST_AUDIO_CHANNEL_POSITION_LFE,
       
   421     GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
       
   422     GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT
       
   423   };
       
   424   GstStructure *s = NULL;
       
   425   gint c;
       
   426 
       
   427   if (min_chans == max_chans && max_chans <= 2) {
       
   428     s = get_channel_free_structure (in_structure);
       
   429     gst_structure_set (s, "channels", G_TYPE_INT, max_chans, NULL);
       
   430     gst_caps_append_structure (caps, s);
       
   431     return;
       
   432   }
       
   433 
       
   434   g_assert (min_chans >= 1);
       
   435 
       
   436   /* mono and stereo don't need channel configurations */
       
   437   if (min_chans == 2) {
       
   438     s = get_channel_free_structure (in_structure);
       
   439     gst_structure_set (s, "channels", G_TYPE_INT, 2, NULL);
       
   440     gst_caps_append_structure (caps, s);
       
   441   } else if (min_chans == 1 && max_chans >= 2) {
       
   442     s = get_channel_free_structure (in_structure);
       
   443     gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
       
   444     gst_caps_append_structure (caps, s);
       
   445   }
       
   446 
       
   447   /* don't know whether to use 2.1 or 3.0 here - but I suspect
       
   448    * alsa might work around that/fix it somehow. Can we tell alsa
       
   449    * what our channel layout is like? */
       
   450   if (max_chans >= 3 && min_chans <= 3) {
       
   451     GstAudioChannelPosition pos_21[3] = {
       
   452       GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   453       GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   454       GST_AUDIO_CHANNEL_POSITION_LFE
       
   455     };
       
   456 
       
   457     s = get_channel_free_structure (in_structure);
       
   458     gst_structure_set (s, "channels", G_TYPE_INT, 3, NULL);
       
   459     gst_audio_set_channel_positions (s, pos_21);
       
   460     gst_caps_append_structure (caps, s);
       
   461   }
       
   462 
       
   463   /* everything else (4, 6, 8 channels) needs a channel layout */
       
   464   for (c = MAX (4, min_chans); c <= 8; c += 2) {
       
   465     if (max_chans >= c) {
       
   466       s = get_channel_free_structure (in_structure);
       
   467       gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
       
   468       gst_audio_set_channel_positions (s, pos);
       
   469       gst_caps_append_structure (caps, s);
       
   470     }
       
   471   }
       
   472 
       
   473   for (c = MAX (9, min_chans); c <= max_chans; ++c) {
       
   474     GstAudioChannelPosition *ch_layout;
       
   475     gint i;
       
   476 
       
   477     ch_layout = g_new (GstAudioChannelPosition, c);
       
   478     for (i = 0; i < c; ++i) {
       
   479       ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
       
   480     }
       
   481     s = get_channel_free_structure (in_structure);
       
   482     gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
       
   483     gst_audio_set_channel_positions (s, ch_layout);
       
   484     gst_caps_append_structure (caps, s);
       
   485     g_free (ch_layout);
       
   486   }
       
   487 }
       
   488 
       
   489 static GstCaps *
       
   490 gst_alsa_detect_channels (GstObject * obj, snd_pcm_hw_params_t * hw_params,
       
   491     GstCaps * in_caps)
       
   492 {
       
   493   GstCaps *caps;
       
   494   guint min, max;
       
   495   gint min_chans, max_chans;
       
   496   gint err;
       
   497   guint i;
       
   498 
       
   499   GST_LOG_OBJECT (obj, "probing channels ...");
       
   500 
       
   501   if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &min)) < 0)
       
   502     goto min_chan_error;
       
   503 
       
   504   if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &max)) < 0)
       
   505     goto max_chan_error;
       
   506 
       
   507   /* note: the above functions may return (guint) -1 */
       
   508   min_chans = min;
       
   509   max_chans = max;
       
   510 
       
   511   if (min_chans < 0) {
       
   512     min_chans = 1;
       
   513     max_chans = GST_ALSA_MAX_CHANNELS;
       
   514   } else if (max_chans < 0) {
       
   515     max_chans = GST_ALSA_MAX_CHANNELS;
       
   516   }
       
   517 
       
   518   if (min_chans > max_chans) {
       
   519     gint temp;
       
   520 
       
   521     GST_WARNING_OBJECT (obj, "minimum channels > maximum channels (%d > %d), "
       
   522         "please fix your soundcard drivers", min, max);
       
   523     temp = min_chans;
       
   524     min_chans = max_chans;
       
   525     max_chans = temp;
       
   526   }
       
   527 
       
   528   /* pro cards seem to return large numbers for min_channels */
       
   529   if (min_chans > GST_ALSA_MAX_CHANNELS) {
       
   530     GST_DEBUG_OBJECT (obj, "min_chans = %u, looks like a pro card", min_chans);
       
   531     if (max_chans < min_chans) {
       
   532       max_chans = min_chans;
       
   533     } else {
       
   534       /* only support [max_chans; max_chans] for these cards for now
       
   535        * to avoid inflating the source caps with loads of structures ... */
       
   536       min_chans = max_chans;
       
   537     }
       
   538   } else {
       
   539     min_chans = MAX (min_chans, 1);
       
   540     max_chans = MIN (GST_ALSA_MAX_CHANNELS, max_chans);
       
   541   }
       
   542 
       
   543   GST_DEBUG_OBJECT (obj, "Min. channels = %d (%d)", min_chans, min);
       
   544   GST_DEBUG_OBJECT (obj, "Max. channels = %d (%d)", max_chans, max);
       
   545 
       
   546   caps = gst_caps_new_empty ();
       
   547 
       
   548   for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
       
   549     GstStructure *s;
       
   550     GType field_type;
       
   551     gint c_min = min_chans;
       
   552     gint c_max = max_chans;
       
   553 
       
   554     s = gst_caps_get_structure (in_caps, i);
       
   555     /* the template caps might limit the number of channels (like alsasrc),
       
   556      * in which case we don't want to return a superset, so hack around this
       
   557      * for the two common cases where the channels are either a fixed number
       
   558      * or a min/max range). Example: alsasrc template has channels = [1,2] and 
       
   559      * the detection will claim to support 8 channels for device 'plughw:0' */
       
   560     field_type = gst_structure_get_field_type (s, "channels");
       
   561     if (field_type == G_TYPE_INT) {
       
   562       gst_structure_get_int (s, "channels", &c_min);
       
   563       gst_structure_get_int (s, "channels", &c_max);
       
   564     } else if (field_type == GST_TYPE_INT_RANGE) {
       
   565       const GValue *val;
       
   566 
       
   567       val = gst_structure_get_value (s, "channels");
       
   568       c_min = CLAMP (gst_value_get_int_range_min (val), min_chans, max_chans);
       
   569       c_max = CLAMP (gst_value_get_int_range_max (val), min_chans, max_chans);
       
   570     } else {
       
   571       c_min = min_chans;
       
   572       c_max = max_chans;
       
   573     }
       
   574 
       
   575     caps_add_channel_configuration (caps, s, c_min, c_max);
       
   576   }
       
   577 
       
   578   gst_caps_unref (in_caps);
       
   579 
       
   580   return caps;
       
   581 
       
   582   /* ERRORS */
       
   583 min_chan_error:
       
   584   {
       
   585     GST_ERROR_OBJECT (obj, "failed to query minimum channel count: %s",
       
   586         snd_strerror (err));
       
   587     return NULL;
       
   588   }
       
   589 max_chan_error:
       
   590   {
       
   591     GST_ERROR_OBJECT (obj, "failed to query maximum channel count: %s",
       
   592         snd_strerror (err));
       
   593     return NULL;
       
   594   }
       
   595 }
       
   596 
       
   597 #ifndef GST_CHECK_VERSION
       
   598 #define GST_CHECK_VERSION(major,minor,micro) \
       
   599     (GST_VERSION_MAJOR > (major) || \
       
   600      (GST_VERSION_MAJOR == (major) && GST_VERSION_MINOR > (minor)) || \
       
   601      (GST_VERSION_MAJOR == (major) && GST_VERSION_MINOR == (minor) && GST_VERSION_MICRO >= (micro)))
       
   602 #endif
       
   603 
       
   604 #if GST_CHECK_VERSION(0, 10, 18)
       
   605 snd_pcm_t *
       
   606 gst_alsa_open_iec958_pcm (GstObject * obj)
       
   607 {
       
   608   char *iec958_pcm_name = NULL;
       
   609   snd_pcm_t *pcm = NULL;
       
   610   int res;
       
   611   char devstr[256];             /* Storage for local 'default' device string */
       
   612 
       
   613   /*
       
   614    * Try and open our default iec958 device. Fall back to searching on card x
       
   615    * if this fails, which should only happen on older alsa setups
       
   616    */
       
   617 
       
   618   /* The string will be one of these:
       
   619    * SPDIF_CON: Non-audio flag not set:
       
   620    *    spdif:{AES0 0x0 AES1 0x82 AES2 0x0 AES3 0x2}
       
   621    * SPDIF_CON: Non-audio flag set:
       
   622    *    spdif:{AES0 0x2 AES1 0x82 AES2 0x0 AES3 0x2}
       
   623    */
       
   624   sprintf (devstr,
       
   625       "iec958:{AES0 0x%02x AES1 0x%02x AES2 0x%02x AES3 0x%02x}",
       
   626       IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
       
   627       IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
       
   628       0, IEC958_AES3_CON_FS_48000);
       
   629 
       
   630   GST_DEBUG_OBJECT (obj, "Generated device string \"%s\"", devstr);
       
   631   iec958_pcm_name = devstr;
       
   632 
       
   633   res = snd_pcm_open (&pcm, iec958_pcm_name, SND_PCM_STREAM_PLAYBACK, 0);
       
   634   if (G_UNLIKELY (res < 0)) {
       
   635     GST_DEBUG_OBJECT (obj, "failed opening IEC958 device: %s",
       
   636         snd_strerror (res));
       
   637     pcm = NULL;
       
   638   }
       
   639 
       
   640   return pcm;
       
   641 }
       
   642 #endif
       
   643 
       
   644 
       
   645 /*
       
   646  * gst_alsa_probe_supported_formats:
       
   647  *
       
   648  * Takes the template caps and returns the subset which is actually
       
   649  * supported by this device.
       
   650  *
       
   651  */
       
   652 
       
   653 GstCaps *
       
   654 gst_alsa_probe_supported_formats (GstObject * obj, snd_pcm_t * handle,
       
   655     const GstCaps * template_caps)
       
   656 {
       
   657   snd_pcm_hw_params_t *hw_params;
       
   658   snd_pcm_stream_t stream_type;
       
   659   GstCaps *caps;
       
   660   gint err;
       
   661 
       
   662   snd_pcm_hw_params_malloc (&hw_params);
       
   663   if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0)
       
   664     goto error;
       
   665 
       
   666   stream_type = snd_pcm_stream (handle);
       
   667 
       
   668   caps = gst_caps_copy (template_caps);
       
   669 
       
   670   if (!(caps = gst_alsa_detect_formats (obj, hw_params, caps)))
       
   671     goto subroutine_error;
       
   672 
       
   673   if (!(caps = gst_alsa_detect_rates (obj, hw_params, caps)))
       
   674     goto subroutine_error;
       
   675 
       
   676   if (!(caps = gst_alsa_detect_channels (obj, hw_params, caps)))
       
   677     goto subroutine_error;
       
   678 
       
   679 #if GST_CHECK_VERSION(0, 10, 18)
       
   680   /* Try opening IEC958 device to see if we can support that format (playback
       
   681    * only for now but we could add SPDIF capture later) */
       
   682   if (stream_type == SND_PCM_STREAM_PLAYBACK) {
       
   683     snd_pcm_t *pcm = gst_alsa_open_iec958_pcm (obj);
       
   684 
       
   685     if (G_LIKELY (pcm)) {
       
   686       gst_caps_append (caps, gst_caps_new_simple ("audio/x-iec958", NULL));
       
   687       snd_pcm_close (pcm);
       
   688     }
       
   689   }
       
   690 #endif
       
   691 
       
   692   snd_pcm_hw_params_free (hw_params);
       
   693   return caps;
       
   694 
       
   695   /* ERRORS */
       
   696 error:
       
   697   {
       
   698     GST_ERROR_OBJECT (obj, "failed to query formats: %s", snd_strerror (err));
       
   699     snd_pcm_hw_params_free (hw_params);
       
   700     return NULL;
       
   701   }
       
   702 subroutine_error:
       
   703   {
       
   704     GST_ERROR_OBJECT (obj, "failed to query formats");
       
   705     snd_pcm_hw_params_free (hw_params);
       
   706     return NULL;
       
   707   }
       
   708 }
       
   709 
       
   710 static gchar *
       
   711 gst_alsa_find_device_name_no_handle (GstObject * obj, const gchar * devcard,
       
   712     gint device_num, snd_pcm_stream_t stream)
       
   713 {
       
   714   snd_ctl_card_info_t *info = NULL;
       
   715   snd_ctl_t *ctl = NULL;
       
   716   gchar *ret = NULL;
       
   717   gint dev = -1;
       
   718 
       
   719   GST_LOG_OBJECT (obj, "[%s] device=%d", devcard, device_num);
       
   720 
       
   721   if (snd_ctl_open (&ctl, devcard, 0) < 0)
       
   722     return NULL;
       
   723 
       
   724   snd_ctl_card_info_malloc (&info);
       
   725   if (snd_ctl_card_info (ctl, info) < 0)
       
   726     goto done;
       
   727 
       
   728   while (snd_ctl_pcm_next_device (ctl, &dev) == 0 && dev >= 0) {
       
   729     if (dev == device_num) {
       
   730       snd_pcm_info_t *pcminfo;
       
   731 
       
   732       snd_pcm_info_malloc (&pcminfo);
       
   733       snd_pcm_info_set_device (pcminfo, dev);
       
   734       snd_pcm_info_set_subdevice (pcminfo, 0);
       
   735       snd_pcm_info_set_stream (pcminfo, stream);
       
   736       if (snd_ctl_pcm_info (ctl, pcminfo) < 0) {
       
   737         snd_pcm_info_free (pcminfo);
       
   738         break;
       
   739       }
       
   740 
       
   741       ret = g_strdup (snd_pcm_info_get_name (pcminfo));
       
   742       snd_pcm_info_free (pcminfo);
       
   743       GST_LOG_OBJECT (obj, "name from pcminfo: %s", GST_STR_NULL (ret));
       
   744     }
       
   745   }
       
   746 
       
   747   if (ret == NULL) {
       
   748     char *name = NULL;
       
   749     gint card;
       
   750 
       
   751     GST_LOG_OBJECT (obj, "no luck so far, trying backup");
       
   752     card = snd_ctl_card_info_get_card (info);
       
   753     snd_card_get_name (card, &name);
       
   754     ret = g_strdup (name);
       
   755     free (name);
       
   756   }
       
   757 
       
   758 done:
       
   759   snd_ctl_card_info_free (info);
       
   760   snd_ctl_close (ctl);
       
   761 
       
   762   return ret;
       
   763 }
       
   764 
       
   765 gchar *
       
   766 gst_alsa_find_device_name (GstObject * obj, const gchar * device,
       
   767     snd_pcm_t * handle, snd_pcm_stream_t stream)
       
   768 {
       
   769   gchar *ret = NULL;
       
   770 
       
   771   if (device != NULL) {
       
   772     gchar *dev, *comma;
       
   773     gint devnum;
       
   774 
       
   775     GST_LOG_OBJECT (obj, "Trying to get device name from string '%s'", device);
       
   776 
       
   777     /* only want name:card bit, but not devices and subdevices */
       
   778     dev = g_strdup (device);
       
   779     if ((comma = strchr (dev, ','))) {
       
   780       *comma = '\0';
       
   781       devnum = atoi (comma + 1);
       
   782       ret = gst_alsa_find_device_name_no_handle (obj, dev, devnum, stream);
       
   783     }
       
   784     g_free (dev);
       
   785   }
       
   786 
       
   787   if (ret == NULL && handle != NULL) {
       
   788     snd_pcm_info_t *info;
       
   789 
       
   790     GST_LOG_OBJECT (obj, "Trying to get device name from open handle");
       
   791     snd_pcm_info_malloc (&info);
       
   792     snd_pcm_info (handle, info);
       
   793     ret = g_strdup (snd_pcm_info_get_name (info));
       
   794     snd_pcm_info_free (info);
       
   795   }
       
   796 
       
   797   GST_LOG_OBJECT (obj, "Device name for device '%s': %s",
       
   798       GST_STR_NULL (device), GST_STR_NULL (ret));
       
   799 
       
   800   return ret;
       
   801 }
       
   802 
       
   803 /* elementfactory information */
       
   804 static const GstElementDetails gst_alsasink2_details =
       
   805 GST_ELEMENT_DETAILS ("Audio sink (ALSA)",
       
   806     "Sink/Audio",
       
   807     "Output to a sound card via ALSA",
       
   808     "Wim Taymans <wim@fluendo.com>");
       
   809 
       
   810 #define DEFAULT_DEVICE		"default"
       
   811 #define DEFAULT_DEVICE_NAME	""
       
   812 #define SPDIF_PERIOD_SIZE 1536
       
   813 #define SPDIF_BUFFER_SIZE 15360
       
   814 
       
   815 enum
       
   816 {
       
   817   PROP_0,
       
   818   PROP_DEVICE,
       
   819   PROP_DEVICE_NAME
       
   820 };
       
   821 
       
   822 static void gst_alsasink2_init_interfaces (GType type);
       
   823 
       
   824 GST_BOILERPLATE_FULL (_k_GstAlsaSink, gst_alsasink2, GstAudioSink,
       
   825     GST_TYPE_AUDIO_SINK, gst_alsasink2_init_interfaces);
       
   826 
       
   827 static void gst_alsasink2_finalise (GObject * object);
       
   828 static void gst_alsasink2_set_property (GObject * object,
       
   829     guint prop_id, const GValue * value, GParamSpec * pspec);
       
   830 static void gst_alsasink2_get_property (GObject * object,
       
   831     guint prop_id, GValue * value, GParamSpec * pspec);
       
   832 
       
   833 static GstCaps *gst_alsasink2_getcaps (GstBaseSink * bsink);
       
   834 
       
   835 static gboolean gst_alsasink2_open (GstAudioSink * asink);
       
   836 static gboolean gst_alsasink2_prepare (GstAudioSink * asink,
       
   837     GstRingBufferSpec * spec);
       
   838 static gboolean gst_alsasink2_unprepare (GstAudioSink * asink);
       
   839 static gboolean gst_alsasink2_close (GstAudioSink * asink);
       
   840 static guint gst_alsasink2_write (GstAudioSink * asink, gpointer data,
       
   841     guint length);
       
   842 static guint gst_alsasink2_delay (GstAudioSink * asink);
       
   843 static void gst_alsasink2_reset (GstAudioSink * asink);
       
   844 
       
   845 static gint output_ref;         /* 0    */
       
   846 static snd_output_t *output;    /* NULL */
       
   847 static GStaticMutex output_mutex = G_STATIC_MUTEX_INIT;
       
   848 
       
   849 
       
   850 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
       
   851 # define ALSA_SINK2_FACTORY_ENDIANNESS	"LITTLE_ENDIAN, BIG_ENDIAN"
       
   852 #else
       
   853 # define ALSA_SINK2_FACTORY_ENDIANNESS	"BIG_ENDIAN, LITTLE_ENDIAN"
       
   854 #endif
       
   855 
       
   856 static GstStaticPadTemplate alsasink2_sink_factory =
       
   857     GST_STATIC_PAD_TEMPLATE ("sink",
       
   858     GST_PAD_SINK,
       
   859     GST_PAD_ALWAYS,
       
   860     GST_STATIC_CAPS ("audio/x-raw-int, "
       
   861         "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
       
   862         "signed = (boolean) { TRUE, FALSE }, "
       
   863         "width = (int) 32, "
       
   864         "depth = (int) 32, "
       
   865         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
       
   866         "audio/x-raw-int, "
       
   867         "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
       
   868         "signed = (boolean) { TRUE, FALSE }, "
       
   869         "width = (int) 24, "
       
   870         "depth = (int) 24, "
       
   871         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
       
   872         "audio/x-raw-int, "
       
   873         "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
       
   874         "signed = (boolean) { TRUE, FALSE }, "
       
   875         "width = (int) 32, "
       
   876         "depth = (int) 24, "
       
   877         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
       
   878         "audio/x-raw-int, "
       
   879         "endianness = (int) { " ALSA_SINK2_FACTORY_ENDIANNESS " }, "
       
   880         "signed = (boolean) { TRUE, FALSE }, "
       
   881         "width = (int) 16, "
       
   882         "depth = (int) 16, "
       
   883         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
       
   884         "audio/x-raw-int, "
       
   885         "signed = (boolean) { TRUE, FALSE }, "
       
   886         "width = (int) 8, "
       
   887         "depth = (int) 8, "
       
   888         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ];"
       
   889         "audio/x-iec958")
       
   890     );
       
   891 
       
   892 static void
       
   893 gst_alsasink2_finalise (GObject * object)
       
   894 {
       
   895   _k_GstAlsaSink *sink = GST_ALSA_SINK2 (object);
       
   896 
       
   897   g_free (sink->device);
       
   898   g_mutex_free (sink->alsa_lock);
       
   899 
       
   900   g_static_mutex_lock (&output_mutex);
       
   901   --output_ref;
       
   902   if (output_ref == 0) {
       
   903     snd_output_close (output);
       
   904     output = NULL;
       
   905   }
       
   906   g_static_mutex_unlock (&output_mutex);
       
   907 
       
   908   G_OBJECT_CLASS (parent_class)->finalize (object);
       
   909 }
       
   910 
       
   911 static void
       
   912 gst_alsasink2_init_interfaces (GType type)
       
   913 {
       
   914   gst_alsa_type_add_device_property_probe_interface (type);
       
   915 }
       
   916 
       
   917 static void
       
   918 gst_alsasink2_base_init (gpointer g_class)
       
   919 {
       
   920   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
       
   921 
       
   922   gst_element_class_set_details (element_class, &gst_alsasink2_details);
       
   923 
       
   924   gst_element_class_add_pad_template (element_class,
       
   925       gst_static_pad_template_get (&alsasink2_sink_factory));
       
   926 }
       
   927 static void
       
   928 gst_alsasink2_class_init (_k_GstAlsaSinkClass * klass)
       
   929 {
       
   930   GObjectClass *gobject_class;
       
   931   GstElementClass *gstelement_class;
       
   932   GstBaseSinkClass *gstbasesink_class;
       
   933   GstBaseAudioSinkClass *gstbaseaudiosink_class;
       
   934   GstAudioSinkClass *gstaudiosink_class;
       
   935 
       
   936   gobject_class = (GObjectClass *) klass;
       
   937   gstelement_class = (GstElementClass *) klass;
       
   938   gstbasesink_class = (GstBaseSinkClass *) klass;
       
   939   gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
       
   940   gstaudiosink_class = (GstAudioSinkClass *) klass;
       
   941 
       
   942   parent_class = g_type_class_peek_parent (klass);
       
   943 
       
   944   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_alsasink2_finalise);
       
   945   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasink2_get_property);
       
   946   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasink2_set_property);
       
   947 
       
   948   gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasink2_getcaps);
       
   949 
       
   950   gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_alsasink2_open);
       
   951   gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasink2_prepare);
       
   952   gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasink2_unprepare);
       
   953   gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_alsasink2_close);
       
   954   gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_alsasink2_write);
       
   955   gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_alsasink2_delay);
       
   956   gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_alsasink2_reset);
       
   957 
       
   958   g_object_class_install_property (gobject_class, PROP_DEVICE,
       
   959       g_param_spec_string ("device", "Device",
       
   960           "ALSA device, as defined in an asound configuration file",
       
   961           DEFAULT_DEVICE, G_PARAM_READWRITE));
       
   962 
       
   963   g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
       
   964       g_param_spec_string ("device-name", "Device name",
       
   965           "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
       
   966           G_PARAM_READABLE));
       
   967 }
       
   968 
       
   969 static void
       
   970 gst_alsasink2_set_property (GObject * object, guint prop_id,
       
   971     const GValue * value, GParamSpec * pspec)
       
   972 {
       
   973   _k_GstAlsaSink *sink;
       
   974 
       
   975   sink = GST_ALSA_SINK2 (object);
       
   976 
       
   977   switch (prop_id) {
       
   978     case PROP_DEVICE:
       
   979       g_free (sink->device);
       
   980       sink->device = g_value_dup_string (value);
       
   981       /* setting NULL restores the default device */
       
   982       if (sink->device == NULL) {
       
   983         sink->device = g_strdup (DEFAULT_DEVICE);
       
   984       }
       
   985       break;
       
   986     default:
       
   987       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   988       break;
       
   989   }
       
   990 }
       
   991 
       
   992 static void
       
   993 gst_alsasink2_get_property (GObject * object, guint prop_id,
       
   994     GValue * value, GParamSpec * pspec)
       
   995 {
       
   996   _k_GstAlsaSink *sink;
       
   997 
       
   998   sink = GST_ALSA_SINK2 (object);
       
   999 
       
  1000   switch (prop_id) {
       
  1001     case PROP_DEVICE:
       
  1002       g_value_set_string (value, sink->device);
       
  1003       break;
       
  1004     case PROP_DEVICE_NAME:
       
  1005       g_value_take_string (value,
       
  1006           gst_alsa_find_device_name (GST_OBJECT_CAST (sink),
       
  1007               sink->device, sink->handle, SND_PCM_STREAM_PLAYBACK));
       
  1008       break;
       
  1009     default:
       
  1010       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
  1011       break;
       
  1012   }
       
  1013 }
       
  1014 
       
  1015 static void
       
  1016 gst_alsasink2_init (_k_GstAlsaSink * alsasink2, _k_GstAlsaSinkClass * g_class)
       
  1017 {
       
  1018   GST_DEBUG_OBJECT (alsasink2, "initializing alsasink2");
       
  1019 
       
  1020   alsasink2->device = g_strdup (DEFAULT_DEVICE);
       
  1021   alsasink2->handle = NULL;
       
  1022   alsasink2->cached_caps = NULL;
       
  1023   alsasink2->alsa_lock = g_mutex_new ();
       
  1024 
       
  1025   g_static_mutex_lock (&output_mutex);
       
  1026   if (output_ref == 0) {
       
  1027     snd_output_stdio_attach (&output, stdout, 0);
       
  1028     ++output_ref;
       
  1029   }
       
  1030   g_static_mutex_unlock (&output_mutex);
       
  1031 }
       
  1032 
       
  1033 #define CHECK(call, error) \
       
  1034 G_STMT_START {                  \
       
  1035 if ((err = call) < 0)           \
       
  1036   goto error;                   \
       
  1037 } G_STMT_END;
       
  1038 
       
  1039 static GstCaps *
       
  1040 gst_alsasink2_getcaps (GstBaseSink * bsink)
       
  1041 {
       
  1042   GstElementClass *element_class;
       
  1043   GstPadTemplate *pad_template;
       
  1044   _k_GstAlsaSink *sink = GST_ALSA_SINK2 (bsink);
       
  1045   GstCaps *caps;
       
  1046 
       
  1047   if (sink->handle == NULL) {
       
  1048     GST_DEBUG_OBJECT (sink, "device not open, using template caps");
       
  1049     return NULL;                /* base class will get template caps for us */
       
  1050   }
       
  1051 
       
  1052   if (sink->cached_caps) {
       
  1053     GST_LOG_OBJECT (sink, "Returning cached caps");
       
  1054     return gst_caps_ref (sink->cached_caps);
       
  1055   }
       
  1056 
       
  1057   element_class = GST_ELEMENT_GET_CLASS (sink);
       
  1058   pad_template = gst_element_class_get_pad_template (element_class, "sink");
       
  1059   g_return_val_if_fail (pad_template != NULL, NULL);
       
  1060 
       
  1061   caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->handle,
       
  1062       gst_pad_template_get_caps (pad_template));
       
  1063 
       
  1064   if (caps) {
       
  1065     sink->cached_caps = gst_caps_ref (caps);
       
  1066   }
       
  1067 
       
  1068   GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
       
  1069 
       
  1070   return caps;
       
  1071 }
       
  1072 
       
  1073 static int
       
  1074 set_hwparams (_k_GstAlsaSink * alsa)
       
  1075 {
       
  1076   guint rrate;
       
  1077   gint err, dir;
       
  1078   snd_pcm_hw_params_t *params;
       
  1079   guint period_time, buffer_time;
       
  1080 
       
  1081   snd_pcm_hw_params_malloc (&params);
       
  1082 
       
  1083   GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) "
       
  1084       "SPDIF (%d)", alsa->channels, alsa->rate,
       
  1085       snd_pcm_format_name (alsa->format), alsa->iec958);
       
  1086 
       
  1087   /* start with requested values, if we cannot configure alsa for those values,
       
  1088    * we set these values to -1, which will leave the default alsa values */
       
  1089   buffer_time = alsa->buffer_time;
       
  1090   period_time = alsa->period_time;
       
  1091 
       
  1092 retry:
       
  1093   /* choose all parameters */
       
  1094   CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
       
  1095   /* set the interleaved read/write format */
       
  1096   CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
       
  1097       wrong_access);
       
  1098   /* set the sample format */
       
  1099 #if GST_CHECK_VERSION(0, 10, 18)
       
  1100   if (alsa->iec958) {
       
  1101     /* Try to use big endian first else fallback to le and swap bytes */
       
  1102     if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) {
       
  1103       alsa->format = SND_PCM_FORMAT_S16_LE;
       
  1104       alsa->need_swap = TRUE;
       
  1105       GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping");
       
  1106     } else {
       
  1107       alsa->need_swap = FALSE;
       
  1108     }
       
  1109   }
       
  1110 #endif
       
  1111   CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
       
  1112       no_sample_format);
       
  1113   /* set the count of channels */
       
  1114   CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
       
  1115       no_channels);
       
  1116   /* set the stream rate */
       
  1117   rrate = alsa->rate;
       
  1118   CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
       
  1119       no_rate);
       
  1120   if (rrate != alsa->rate)
       
  1121     goto rate_match;
       
  1122 
       
  1123   /* get and dump some limits */
       
  1124   {
       
  1125     guint min, max;
       
  1126 
       
  1127     snd_pcm_hw_params_get_buffer_time_min (params, &min, &dir);
       
  1128     snd_pcm_hw_params_get_buffer_time_max (params, &max, &dir);
       
  1129 
       
  1130     GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
       
  1131         alsa->buffer_time, min, max);
       
  1132 
       
  1133     snd_pcm_hw_params_get_period_time_min (params, &min, &dir);
       
  1134     snd_pcm_hw_params_get_period_time_max (params, &max, &dir);
       
  1135 
       
  1136     GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
       
  1137         alsa->period_time, min, max);
       
  1138 
       
  1139     snd_pcm_hw_params_get_periods_min (params, &min, &dir);
       
  1140     snd_pcm_hw_params_get_periods_max (params, &max, &dir);
       
  1141 
       
  1142     GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
       
  1143   }
       
  1144 
       
  1145   /* now try to configure the buffer time and period time, if one
       
  1146    * of those fail, we fall back to the defaults and emit a warning. */
       
  1147   if (buffer_time != ~0u && !alsa->iec958) {
       
  1148     /* set the buffer time */
       
  1149     if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
       
  1150                 &buffer_time, &dir)) < 0) {
       
  1151       GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
       
  1152           ("Unable to set buffer time %i for playback: %s",
       
  1153               buffer_time, snd_strerror (err)));
       
  1154       /* disable buffer_time the next round */
       
  1155       buffer_time = -1;
       
  1156       goto retry;
       
  1157     }
       
  1158     GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time);
       
  1159   }
       
  1160   if (period_time != ~0u && !alsa->iec958) {
       
  1161     /* set the period time */
       
  1162     if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
       
  1163                 &period_time, &dir)) < 0) {
       
  1164       GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
       
  1165           ("Unable to set period time %i for playback: %s",
       
  1166               period_time, snd_strerror (err)));
       
  1167       /* disable period_time the next round */
       
  1168       period_time = -1;
       
  1169       goto retry;
       
  1170     }
       
  1171     GST_DEBUG_OBJECT (alsa, "period time %u", period_time);
       
  1172   }
       
  1173 
       
  1174   /* Set buffer size and period size manually for SPDIF */
       
  1175   if (G_UNLIKELY (alsa->iec958)) {
       
  1176     snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE;
       
  1177     snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE;
       
  1178 
       
  1179     CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params,
       
  1180             &buffer_size), buffer_size);
       
  1181     CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params,
       
  1182             &period_size, NULL), period_size);
       
  1183   }
       
  1184 
       
  1185   /* write the parameters to device */
       
  1186   CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
       
  1187 
       
  1188   /* now get the configured values */
       
  1189   CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
       
  1190       buffer_size);
       
  1191   CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
       
  1192       period_size);
       
  1193 
       
  1194   GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
       
  1195       alsa->period_size);
       
  1196 
       
  1197   snd_pcm_hw_params_free (params);
       
  1198   return 0;
       
  1199 
       
  1200   /* ERRORS */
       
  1201 no_config:
       
  1202   {
       
  1203     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1204         ("Broken configuration for playback: no configurations available: %s",
       
  1205             snd_strerror (err)));
       
  1206     snd_pcm_hw_params_free (params);
       
  1207     return err;
       
  1208   }
       
  1209 wrong_access:
       
  1210   {
       
  1211     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1212         ("Access type not available for playback: %s", snd_strerror (err)));
       
  1213     snd_pcm_hw_params_free (params);
       
  1214     return err;
       
  1215   }
       
  1216 no_sample_format:
       
  1217   {
       
  1218     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1219         ("Sample format not available for playback: %s", snd_strerror (err)));
       
  1220     snd_pcm_hw_params_free (params);
       
  1221     return err;
       
  1222   }
       
  1223 no_channels:
       
  1224   {
       
  1225     gchar *msg = NULL;
       
  1226 
       
  1227     if ((alsa->channels) == 1)
       
  1228       msg = g_strdup (_("Could not open device for playback in mono mode."));
       
  1229     if ((alsa->channels) == 2)
       
  1230       msg = g_strdup (_("Could not open device for playback in stereo mode."));
       
  1231     if ((alsa->channels) > 2)
       
  1232       msg =
       
  1233           g_strdup_printf (_
       
  1234           ("Could not open device for playback in %d-channel mode."),
       
  1235           alsa->channels);
       
  1236     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (msg), (snd_strerror (err)));
       
  1237     g_free (msg);
       
  1238     snd_pcm_hw_params_free (params);
       
  1239     return err;
       
  1240   }
       
  1241 no_rate:
       
  1242   {
       
  1243     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1244         ("Rate %iHz not available for playback: %s",
       
  1245             alsa->rate, snd_strerror (err)));
       
  1246     return err;
       
  1247   }
       
  1248 rate_match:
       
  1249   {
       
  1250     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1251         ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
       
  1252     snd_pcm_hw_params_free (params);
       
  1253     return -EINVAL;
       
  1254   }
       
  1255 buffer_size:
       
  1256   {
       
  1257     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1258         ("Unable to get buffer size for playback: %s", snd_strerror (err)));
       
  1259     snd_pcm_hw_params_free (params);
       
  1260     return err;
       
  1261   }
       
  1262 period_size:
       
  1263   {
       
  1264     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1265         ("Unable to get period size for playback: %s", snd_strerror (err)));
       
  1266     snd_pcm_hw_params_free (params);
       
  1267     return err;
       
  1268   }
       
  1269 set_hw_params:
       
  1270   {
       
  1271     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1272         ("Unable to set hw params for playback: %s", snd_strerror (err)));
       
  1273     snd_pcm_hw_params_free (params);
       
  1274     return err;
       
  1275   }
       
  1276 }
       
  1277 
       
  1278 static int
       
  1279 set_swparams (_k_GstAlsaSink * alsa)
       
  1280 {
       
  1281   int err;
       
  1282   snd_pcm_sw_params_t *params;
       
  1283 
       
  1284   snd_pcm_sw_params_malloc (&params);
       
  1285 
       
  1286   /* get the current swparams */
       
  1287   CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
       
  1288   /* start the transfer when the buffer is almost full: */
       
  1289   /* (buffer_size / avail_min) * avail_min */
       
  1290   CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
       
  1291           (alsa->buffer_size / alsa->period_size) * alsa->period_size),
       
  1292       start_threshold);
       
  1293 
       
  1294   /* allow the transfer when at least period_size samples can be processed */
       
  1295   CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
       
  1296           alsa->period_size), set_avail);
       
  1297 
       
  1298 #if GST_CHECK_ALSA_VERSION(1,0,16)
       
  1299   /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
       
  1300 #else
       
  1301   /* align all transfers to 1 sample */
       
  1302   CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
       
  1303 #endif
       
  1304 
       
  1305   /* write the parameters to the playback device */
       
  1306   CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
       
  1307 
       
  1308   snd_pcm_sw_params_free (params);
       
  1309   return 0;
       
  1310 
       
  1311   /* ERRORS */
       
  1312 no_config:
       
  1313   {
       
  1314     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1315         ("Unable to determine current swparams for playback: %s",
       
  1316             snd_strerror (err)));
       
  1317     snd_pcm_sw_params_free (params);
       
  1318     return err;
       
  1319   }
       
  1320 start_threshold:
       
  1321   {
       
  1322     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1323         ("Unable to set start threshold mode for playback: %s",
       
  1324             snd_strerror (err)));
       
  1325     snd_pcm_sw_params_free (params);
       
  1326     return err;
       
  1327   }
       
  1328 set_avail:
       
  1329   {
       
  1330     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1331         ("Unable to set avail min for playback: %s", snd_strerror (err)));
       
  1332     snd_pcm_sw_params_free (params);
       
  1333     return err;
       
  1334   }
       
  1335 #if !GST_CHECK_ALSA_VERSION(1,0,16)
       
  1336 set_align:
       
  1337   {
       
  1338     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1339         ("Unable to set transfer align for playback: %s", snd_strerror (err)));
       
  1340     snd_pcm_sw_params_free (params);
       
  1341     return err;
       
  1342   }
       
  1343 #endif
       
  1344 set_sw_params:
       
  1345   {
       
  1346     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1347         ("Unable to set sw params for playback: %s", snd_strerror (err)));
       
  1348     snd_pcm_sw_params_free (params);
       
  1349     return err;
       
  1350   }
       
  1351 }
       
  1352 
       
  1353 static gboolean
       
  1354 alsasink2_parse_spec (_k_GstAlsaSink * alsa, GstRingBufferSpec * spec)
       
  1355 {
       
  1356   /* Initialize our boolean */
       
  1357   alsa->iec958 = FALSE;
       
  1358 
       
  1359   switch (spec->type) {
       
  1360     case GST_BUFTYPE_LINEAR:
       
  1361       GST_DEBUG_OBJECT (alsa,
       
  1362           "Linear format : depth=%d, width=%d, sign=%d, bigend=%d", spec->depth,
       
  1363           spec->width, spec->sign, spec->bigend);
       
  1364 
       
  1365       alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
       
  1366           spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
       
  1367       break;
       
  1368     case GST_BUFTYPE_FLOAT:
       
  1369       switch (spec->format) {
       
  1370         case GST_FLOAT32_LE:
       
  1371           alsa->format = SND_PCM_FORMAT_FLOAT_LE;
       
  1372           break;
       
  1373         case GST_FLOAT32_BE:
       
  1374           alsa->format = SND_PCM_FORMAT_FLOAT_BE;
       
  1375           break;
       
  1376         case GST_FLOAT64_LE:
       
  1377           alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
       
  1378           break;
       
  1379         case GST_FLOAT64_BE:
       
  1380           alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
       
  1381           break;
       
  1382         default:
       
  1383           goto error;
       
  1384       }
       
  1385       break;
       
  1386     case GST_BUFTYPE_A_LAW:
       
  1387       alsa->format = SND_PCM_FORMAT_A_LAW;
       
  1388       break;
       
  1389     case GST_BUFTYPE_MU_LAW:
       
  1390       alsa->format = SND_PCM_FORMAT_MU_LAW;
       
  1391       break;
       
  1392 #if GST_CHECK_VERSION(0, 10, 18)
       
  1393     case GST_BUFTYPE_IEC958:
       
  1394       alsa->format = SND_PCM_FORMAT_S16_BE;
       
  1395       alsa->iec958 = TRUE;
       
  1396       break;
       
  1397 #endif
       
  1398     default:
       
  1399       goto error;
       
  1400 
       
  1401   }
       
  1402   alsa->rate = spec->rate;
       
  1403   alsa->channels = spec->channels;
       
  1404   alsa->buffer_time = spec->buffer_time;
       
  1405   alsa->period_time = spec->latency_time;
       
  1406   alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
       
  1407 
       
  1408   return TRUE;
       
  1409 
       
  1410   /* ERRORS */
       
  1411 error:
       
  1412   {
       
  1413     return FALSE;
       
  1414   }
       
  1415 }
       
  1416 
       
  1417 static gboolean
       
  1418 gst_alsasink2_open (GstAudioSink * asink)
       
  1419 {
       
  1420   _k_GstAlsaSink *alsa;
       
  1421   gint err;
       
  1422 
       
  1423   alsa = GST_ALSA_SINK2 (asink);
       
  1424 
       
  1425   CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_PLAYBACK,
       
  1426           SND_PCM_NONBLOCK), open_error);
       
  1427   GST_LOG_OBJECT (alsa, "Opened device %s", alsa->device);
       
  1428 
       
  1429   return TRUE;
       
  1430 
       
  1431   /* ERRORS */
       
  1432 open_error:
       
  1433   {
       
  1434     if (err == -EBUSY) {
       
  1435       GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
       
  1436           (_("Could not open audio device for playback. "
       
  1437                   "Device is being used by another application.")),
       
  1438           ("Device '%s' is busy", alsa->device));
       
  1439     } else {
       
  1440       GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE,
       
  1441           (_("Could not open audio device for playback.")),
       
  1442           ("Playback open error on device '%s': %s", alsa->device,
       
  1443               snd_strerror (err)));
       
  1444     }
       
  1445     return FALSE;
       
  1446   }
       
  1447 }
       
  1448 
       
  1449 static gboolean
       
  1450 gst_alsasink2_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
       
  1451 {
       
  1452   _k_GstAlsaSink *alsa;
       
  1453   gint err;
       
  1454 
       
  1455   alsa = GST_ALSA_SINK2 (asink);
       
  1456 
       
  1457 #if GST_CHECK_VERSION(0, 10, 18)
       
  1458   if (spec->format == GST_IEC958) {
       
  1459     snd_pcm_close (alsa->handle);
       
  1460     alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa));
       
  1461     if (G_UNLIKELY (!alsa->handle)) {
       
  1462       goto no_iec958;
       
  1463     }
       
  1464   }
       
  1465 #endif
       
  1466 
       
  1467   if (!alsasink2_parse_spec (alsa, spec))
       
  1468     goto spec_parse;
       
  1469 
       
  1470   CHECK (set_hwparams (alsa), hw_params_failed);
       
  1471   CHECK (set_swparams (alsa), sw_params_failed);
       
  1472 
       
  1473   alsa->bytes_per_sample = spec->bytes_per_sample;
       
  1474   spec->segsize = alsa->period_size * spec->bytes_per_sample;
       
  1475   spec->segtotal = alsa->buffer_size / alsa->period_size;
       
  1476 
       
  1477   {
       
  1478     snd_output_t *out_buf = NULL;
       
  1479     char *msg = NULL;
       
  1480 
       
  1481     snd_output_buffer_open (&out_buf);
       
  1482     snd_pcm_dump_hw_setup (alsa->handle, out_buf);
       
  1483     snd_output_buffer_string (out_buf, &msg);
       
  1484     GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg);
       
  1485     snd_output_close (out_buf);
       
  1486     snd_output_buffer_open (&out_buf);
       
  1487     snd_pcm_dump_sw_setup (alsa->handle, out_buf);
       
  1488     snd_output_buffer_string (out_buf, &msg);
       
  1489     GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg);
       
  1490     snd_output_close (out_buf);
       
  1491   }
       
  1492 
       
  1493   return TRUE;
       
  1494 
       
  1495   /* ERRORS */
       
  1496 #if GST_CHECK_VERSION(0, 10, 18)
       
  1497 no_iec958:
       
  1498   {
       
  1499     GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, (NULL),
       
  1500         ("Could not open IEC958 (SPDIF) device for playback"));
       
  1501     return FALSE;
       
  1502   }
       
  1503 #endif
       
  1504 spec_parse:
       
  1505   {
       
  1506     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1507         ("Error parsing spec"));
       
  1508     return FALSE;
       
  1509   }
       
  1510 hw_params_failed:
       
  1511   {
       
  1512     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1513         ("Setting of hwparams failed: %s", snd_strerror (err)));
       
  1514     return FALSE;
       
  1515   }
       
  1516 sw_params_failed:
       
  1517   {
       
  1518     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1519         ("Setting of swparams failed: %s", snd_strerror (err)));
       
  1520     return FALSE;
       
  1521   }
       
  1522 }
       
  1523 
       
  1524 static gboolean
       
  1525 gst_alsasink2_unprepare (GstAudioSink * asink)
       
  1526 {
       
  1527   _k_GstAlsaSink *alsa;
       
  1528   gint err;
       
  1529 
       
  1530   alsa = GST_ALSA_SINK2 (asink);
       
  1531 
       
  1532   CHECK (snd_pcm_drop (alsa->handle), drop);
       
  1533 
       
  1534   CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
       
  1535 
       
  1536   return TRUE;
       
  1537 
       
  1538   /* ERRORS */
       
  1539 drop:
       
  1540   {
       
  1541     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1542         ("Could not drop samples: %s", snd_strerror (err)));
       
  1543     return FALSE;
       
  1544   }
       
  1545 hw_free:
       
  1546   {
       
  1547     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
  1548         ("Could not free hw params: %s", snd_strerror (err)));
       
  1549     return FALSE;
       
  1550   }
       
  1551 }
       
  1552 
       
  1553 static gboolean
       
  1554 gst_alsasink2_close (GstAudioSink * asink)
       
  1555 {
       
  1556   _k_GstAlsaSink *alsa = GST_ALSA_SINK2 (asink);
       
  1557   gint err;
       
  1558 
       
  1559   if (alsa->handle) {
       
  1560     CHECK (snd_pcm_close (alsa->handle), close_error);
       
  1561     alsa->handle = NULL;
       
  1562   }
       
  1563   gst_caps_replace (&alsa->cached_caps, NULL);
       
  1564 
       
  1565   return TRUE;
       
  1566 
       
  1567   /* ERRORS */
       
  1568 close_error:
       
  1569   {
       
  1570     GST_ELEMENT_ERROR (alsa, RESOURCE, CLOSE, (NULL),
       
  1571         ("Playback close error: %s", snd_strerror (err)));
       
  1572     return FALSE;
       
  1573   }
       
  1574 }
       
  1575 
       
  1576 
       
  1577 /*
       
  1578  *   Underrun and suspend recovery
       
  1579  */
       
  1580 static gint
       
  1581 xrun_recovery (_k_GstAlsaSink * alsa, snd_pcm_t * handle, gint err)
       
  1582 {
       
  1583   GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
       
  1584 
       
  1585   if (err == -EPIPE) {          /* under-run */
       
  1586     err = snd_pcm_prepare (handle);
       
  1587     if (err < 0) {
       
  1588       GST_WARNING_OBJECT (alsa,
       
  1589           "Can't recovery from underrun, prepare failed: %s",
       
  1590           snd_strerror (err));
       
  1591     }
       
  1592     return 0;
       
  1593   } else if (err == -ESTRPIPE) {
       
  1594     while ((err = snd_pcm_resume (handle)) == -EAGAIN)
       
  1595       g_usleep (100);           /* wait until the suspend flag is released */
       
  1596 
       
  1597     if (err < 0) {
       
  1598       err = snd_pcm_prepare (handle);
       
  1599       if (err < 0) {
       
  1600         GST_WARNING_OBJECT (alsa,
       
  1601             "Can't recovery from suspend, prepare failed: %s",
       
  1602             snd_strerror (err));
       
  1603       }
       
  1604     }
       
  1605     return 0;
       
  1606   }
       
  1607   return err;
       
  1608 }
       
  1609 
       
  1610 static guint
       
  1611 gst_alsasink2_write (GstAudioSink * asink, gpointer data, guint length)
       
  1612 {
       
  1613   _k_GstAlsaSink *alsa;
       
  1614   gint err;
       
  1615   gint cptr;
       
  1616   gint16 *ptr = data;
       
  1617 
       
  1618   alsa = GST_ALSA_SINK2 (asink);
       
  1619 
       
  1620   if (alsa->iec958 && alsa->need_swap) {
       
  1621     guint i;
       
  1622 
       
  1623     GST_DEBUG_OBJECT (asink, "swapping bytes");
       
  1624     for (i = 0; i < length / 2; i++) {
       
  1625       ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]);
       
  1626     }
       
  1627   }
       
  1628 
       
  1629   GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);
       
  1630 
       
  1631   cptr = length / alsa->bytes_per_sample;
       
  1632 
       
  1633   GST_ALSA_SINK2_LOCK (asink);
       
  1634   while (cptr > 0) {
       
  1635     /* start by doing a blocking wait for free space. Set the timeout
       
  1636      * to 4 times the period time */
       
  1637     err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000));
       
  1638     if (err < 0) {
       
  1639       GST_DEBUG_OBJECT (asink, "wait timeout, %d", err);
       
  1640     } else {
       
  1641       err = snd_pcm_writei (alsa->handle, ptr, cptr);
       
  1642     }
       
  1643 
       
  1644     GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
       
  1645     if (err < 0) {
       
  1646       GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
       
  1647       if (err == -EAGAIN) {
       
  1648         continue;
       
  1649       } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
       
  1650         goto write_error;
       
  1651       }
       
  1652       continue;
       
  1653     }
       
  1654 
       
  1655     ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
       
  1656     cptr -= err;
       
  1657   }
       
  1658   GST_ALSA_SINK2_UNLOCK (asink);
       
  1659 
       
  1660   return length - (cptr * alsa->bytes_per_sample);
       
  1661 
       
  1662 write_error:
       
  1663   {
       
  1664     GST_ALSA_SINK2_UNLOCK (asink);
       
  1665     return length;              /* skip one period */
       
  1666   }
       
  1667 }
       
  1668 
       
  1669 static guint
       
  1670 gst_alsasink2_delay (GstAudioSink * asink)
       
  1671 {
       
  1672   _k_GstAlsaSink *alsa;
       
  1673   snd_pcm_sframes_t delay;
       
  1674   int res;
       
  1675 
       
  1676   alsa = GST_ALSA_SINK2 (asink);
       
  1677 
       
  1678   res = snd_pcm_delay (alsa->handle, &delay);
       
  1679   if (G_UNLIKELY (res < 0)) {
       
  1680     /* on errors, report 0 delay */
       
  1681     GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
       
  1682     delay = 0;
       
  1683   }
       
  1684   if (G_UNLIKELY (delay < 0)) {
       
  1685     /* make sure we never return a negative delay */
       
  1686     GST_WARNING_OBJECT (alsa, "snd_pcm_delay returned negative delay");
       
  1687     delay = 0;
       
  1688   }
       
  1689 
       
  1690   return delay;
       
  1691 }
       
  1692 
       
  1693 static void
       
  1694 gst_alsasink2_reset (GstAudioSink * asink)
       
  1695 {
       
  1696   _k_GstAlsaSink *alsa;
       
  1697   gint err;
       
  1698 
       
  1699   alsa = GST_ALSA_SINK2 (asink);
       
  1700 
       
  1701   GST_ALSA_SINK2_LOCK (asink);
       
  1702   GST_DEBUG_OBJECT (alsa, "drop");
       
  1703   CHECK (snd_pcm_drop (alsa->handle), drop_error);
       
  1704   GST_DEBUG_OBJECT (alsa, "prepare");
       
  1705   CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
       
  1706   GST_DEBUG_OBJECT (alsa, "reset done");
       
  1707   GST_ALSA_SINK2_UNLOCK (asink);
       
  1708 
       
  1709   return;
       
  1710 
       
  1711   /* ERRORS */
       
  1712 drop_error:
       
  1713   {
       
  1714     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
       
  1715         snd_strerror (err));
       
  1716     GST_ALSA_SINK2_UNLOCK (asink);
       
  1717     return;
       
  1718   }
       
  1719 prepare_error:
       
  1720   {
       
  1721     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
       
  1722         snd_strerror (err));
       
  1723     GST_ALSA_SINK2_UNLOCK (asink);
       
  1724     return;
       
  1725   }
       
  1726 }
       
  1727 
       
  1728 static void
       
  1729 gst_alsa_error_wrapper (const char *file, int line, const char *function,
       
  1730     int err, const char *fmt, ...)
       
  1731 {
       
  1732 }
       
  1733 
       
  1734 static gboolean
       
  1735 plugin_init (GstPlugin * plugin)
       
  1736 {
       
  1737   int err;
       
  1738 
       
  1739   if (!gst_element_register (plugin, "_k_alsasink", GST_RANK_PRIMARY,
       
  1740           GST_TYPE_ALSA_SINK2))
       
  1741     return FALSE;
       
  1742 
       
  1743   err = snd_lib_error_set_handler (gst_alsa_error_wrapper);
       
  1744   if (err != 0)
       
  1745     GST_WARNING ("failed to set alsa error handler");
       
  1746 
       
  1747   return TRUE;
       
  1748 }
       
  1749 
       
  1750 #define PACKAGE ""
       
  1751 GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR,
       
  1752     GST_VERSION_MINOR,
       
  1753     "_k_alsa",
       
  1754     "ALSA plugin library (hotfixed)",
       
  1755     plugin_init, "0.1", "LGPL", "Phonon-GStreamer", "")
       
  1756 #undef PACKAGE