gst_plugins_base/ext/alsa/gstalsasrc.c
branchRCL_3
changeset 30 7e817e7e631c
parent 0 0e761a78d257
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
       
     1 /* GStreamer
       
     2  * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
       
     3  *
       
     4  * gstalsasrc.c:
       
     5  *
       
     6  * This library is free software; you can redistribute it and/or
       
     7  * modify it under the terms of the GNU Library General Public
       
     8  * License as published by the Free Software Foundation; either
       
     9  * version 2 of the License, or (at your option) any later version.
       
    10  *
       
    11  * This library is distributed in the hope that it will be useful,
       
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    14  * Library General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU Library General Public
       
    17  * License along with this library; if not, write to the
       
    18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    19  * Boston, MA 02111-1307, USA.
       
    20  */
       
    21 
       
    22 /**
       
    23  * SECTION:element-alsasrc
       
    24  * @short_description: capture audio from an alsa device
       
    25  * @see_also: alsasink, alsamixer
       
    26  *
       
    27  * <refsect2>
       
    28  * <para>
       
    29  * This element reads data from an audio card using the ALSA API.
       
    30  * </para>
       
    31  * <title>Example pipelines</title>
       
    32  * <para>
       
    33  * Record from a sound card using ALSA and encode to Ogg/Vorbis.
       
    34  * </para>
       
    35  * <programlisting>
       
    36  * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
       
    37  * </programlisting>
       
    38  * </refsect2>
       
    39  *
       
    40  * Last reviewed on 2006-03-01 (0.10.4)
       
    41  */
       
    42 
       
    43 #ifdef HAVE_CONFIG_H
       
    44 #include "config.h"
       
    45 #endif
       
    46 #include <sys/ioctl.h>
       
    47 #include <fcntl.h>
       
    48 #include <errno.h>
       
    49 #include <unistd.h>
       
    50 #include <string.h>
       
    51 #include <getopt.h>
       
    52 #include <alsa/asoundlib.h>
       
    53 
       
    54 #include "gstalsasrc.h"
       
    55 #include "gstalsadeviceprobe.h"
       
    56 
       
    57 #include <gst/gst-i18n-plugin.h>
       
    58 
       
    59 /* elementfactory information */
       
    60 static const GstElementDetails gst_alsasrc_details =
       
    61 GST_ELEMENT_DETAILS ("Audio source (ALSA)",
       
    62     "Source/Audio",
       
    63     "Read from a sound card via ALSA",
       
    64     "Wim Taymans <wim@fluendo.com>");
       
    65 
       
    66 #define DEFAULT_PROP_DEVICE		"default"
       
    67 #define DEFAULT_PROP_DEVICE_NAME	""
       
    68 
       
    69 enum
       
    70 {
       
    71   PROP_0,
       
    72   PROP_DEVICE,
       
    73   PROP_DEVICE_NAME,
       
    74 };
       
    75 
       
    76 static void gst_alsasrc_init_interfaces (GType type);
       
    77 
       
    78 GST_BOILERPLATE_FULL (GstAlsaSrc, gst_alsasrc, GstAudioSrc,
       
    79     GST_TYPE_AUDIO_SRC, gst_alsasrc_init_interfaces);
       
    80 
       
    81 GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaSrc, gst_alsasrc_mixer);
       
    82 
       
    83 static void gst_alsasrc_finalize (GObject * object);
       
    84 static void gst_alsasrc_set_property (GObject * object,
       
    85     guint prop_id, const GValue * value, GParamSpec * pspec);
       
    86 static void gst_alsasrc_get_property (GObject * object,
       
    87     guint prop_id, GValue * value, GParamSpec * pspec);
       
    88 
       
    89 static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc);
       
    90 
       
    91 static gboolean gst_alsasrc_open (GstAudioSrc * asrc);
       
    92 static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc,
       
    93     GstRingBufferSpec * spec);
       
    94 static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc);
       
    95 static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
       
    96 static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
       
    97 static guint gst_alsasrc_delay (GstAudioSrc * asrc);
       
    98 static void gst_alsasrc_reset (GstAudioSrc * asrc);
       
    99 
       
   100 /* AlsaSrc signals and args */
       
   101 enum
       
   102 {
       
   103   LAST_SIGNAL
       
   104 };
       
   105 
       
   106 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
       
   107 # define ALSA_SRC_FACTORY_ENDIANNESS   "LITTLE_ENDIAN, BIG_ENDIAN"
       
   108 #else
       
   109 # define ALSA_SRC_FACTORY_ENDIANNESS   "BIG_ENDIAN, LITTLE_ENDIAN"
       
   110 #endif
       
   111 
       
   112 static GstStaticPadTemplate alsasrc_src_factory =
       
   113     GST_STATIC_PAD_TEMPLATE ("src",
       
   114     GST_PAD_SRC,
       
   115     GST_PAD_ALWAYS,
       
   116     GST_STATIC_CAPS ("audio/x-raw-int, "
       
   117         "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
       
   118         "signed = (boolean) { TRUE, FALSE }, "
       
   119         "width = (int) 32, "
       
   120         "depth = (int) 32, "
       
   121         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
       
   122         "audio/x-raw-int, "
       
   123         "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
       
   124         "signed = (boolean) { TRUE, FALSE }, "
       
   125         "width = (int) 32, "
       
   126         "depth = (int) 24, "
       
   127         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
       
   128         "audio/x-raw-int, "
       
   129         "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
       
   130         "signed = (boolean) { TRUE, FALSE }, "
       
   131         "width = (int) 24, "
       
   132         "depth = (int) 24, "
       
   133         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
       
   134         "audio/x-raw-int, "
       
   135         "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
       
   136         "signed = (boolean) { TRUE, FALSE }, "
       
   137         "width = (int) 16, "
       
   138         "depth = (int) 16, "
       
   139         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
       
   140         "audio/x-raw-int, "
       
   141         "signed = (boolean) { TRUE, FALSE }, "
       
   142         "width = (int) 8, "
       
   143         "depth = (int) 8, "
       
   144         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]")
       
   145     );
       
   146 
       
   147 static void
       
   148 gst_alsasrc_finalize (GObject * object)
       
   149 {
       
   150   GstAlsaSrc *src = GST_ALSA_SRC (object);
       
   151 
       
   152   g_free (src->device);
       
   153   g_mutex_free (src->alsa_lock);
       
   154 
       
   155   G_OBJECT_CLASS (parent_class)->finalize (object);
       
   156 }
       
   157 
       
   158 static gboolean
       
   159 gst_alsasrc_interface_supported (GstAlsaSrc * this, GType interface_type)
       
   160 {
       
   161   /* only support this one interface (wrapped by GstImplementsInterface) */
       
   162   g_assert (interface_type == GST_TYPE_MIXER);
       
   163 
       
   164   return gst_alsasrc_mixer_supported (this, interface_type);
       
   165 }
       
   166 
       
   167 static void
       
   168 gst_implements_interface_init (GstImplementsInterfaceClass * klass)
       
   169 {
       
   170   klass->supported = (gpointer) gst_alsasrc_interface_supported;
       
   171 }
       
   172 
       
   173 static void
       
   174 gst_alsasrc_init_interfaces (GType type)
       
   175 {
       
   176   static const GInterfaceInfo implements_iface_info = {
       
   177     (GInterfaceInitFunc) gst_implements_interface_init,
       
   178     NULL,
       
   179     NULL,
       
   180   };
       
   181   static const GInterfaceInfo mixer_iface_info = {
       
   182     (GInterfaceInitFunc) gst_alsasrc_mixer_interface_init,
       
   183     NULL,
       
   184     NULL,
       
   185   };
       
   186 
       
   187   g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
       
   188       &implements_iface_info);
       
   189   g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
       
   190 
       
   191   gst_alsa_type_add_device_property_probe_interface (type);
       
   192 }
       
   193 
       
   194 static void
       
   195 gst_alsasrc_base_init (gpointer g_class)
       
   196 {
       
   197   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
       
   198 
       
   199   gst_element_class_set_details (element_class, &gst_alsasrc_details);
       
   200 
       
   201   gst_element_class_add_pad_template (element_class,
       
   202       gst_static_pad_template_get (&alsasrc_src_factory));
       
   203 }
       
   204 
       
   205 static void
       
   206 gst_alsasrc_class_init (GstAlsaSrcClass * klass)
       
   207 {
       
   208   GObjectClass *gobject_class;
       
   209   GstElementClass *gstelement_class;
       
   210   GstBaseSrcClass *gstbasesrc_class;
       
   211   GstBaseAudioSrcClass *gstbaseaudiosrc_class;
       
   212   GstAudioSrcClass *gstaudiosrc_class;
       
   213 
       
   214   gobject_class = (GObjectClass *) klass;
       
   215   gstelement_class = (GstElementClass *) klass;
       
   216   gstbasesrc_class = (GstBaseSrcClass *) klass;
       
   217   gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
       
   218   gstaudiosrc_class = (GstAudioSrcClass *) klass;
       
   219 
       
   220   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_alsasrc_finalize);
       
   221   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasrc_get_property);
       
   222   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasrc_set_property);
       
   223 
       
   224   gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps);
       
   225 
       
   226   gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_alsasrc_open);
       
   227   gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasrc_prepare);
       
   228   gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasrc_unprepare);
       
   229   gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_alsasrc_close);
       
   230   gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_alsasrc_read);
       
   231   gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_alsasrc_delay);
       
   232   gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_alsasrc_reset);
       
   233 
       
   234   g_object_class_install_property (gobject_class, PROP_DEVICE,
       
   235       g_param_spec_string ("device", "Device",
       
   236           "ALSA device, as defined in an asound configuration file",
       
   237           DEFAULT_PROP_DEVICE, G_PARAM_READWRITE));
       
   238 
       
   239   g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
       
   240       g_param_spec_string ("device-name", "Device name",
       
   241           "Human-readable name of the sound device",
       
   242           DEFAULT_PROP_DEVICE_NAME, G_PARAM_READABLE));
       
   243 }
       
   244 
       
   245 static void
       
   246 gst_alsasrc_set_property (GObject * object, guint prop_id,
       
   247     const GValue * value, GParamSpec * pspec)
       
   248 {
       
   249   GstAlsaSrc *src;
       
   250 
       
   251   src = GST_ALSA_SRC (object);
       
   252 
       
   253   switch (prop_id) {
       
   254     case PROP_DEVICE:
       
   255       g_free (src->device);
       
   256       src->device = g_value_dup_string (value);
       
   257       if (src->device == NULL) {
       
   258         src->device = g_strdup (DEFAULT_PROP_DEVICE);
       
   259       }
       
   260       break;
       
   261     default:
       
   262       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   263       break;
       
   264   }
       
   265 }
       
   266 
       
   267 static void
       
   268 gst_alsasrc_get_property (GObject * object, guint prop_id,
       
   269     GValue * value, GParamSpec * pspec)
       
   270 {
       
   271   GstAlsaSrc *src;
       
   272 
       
   273   src = GST_ALSA_SRC (object);
       
   274 
       
   275   switch (prop_id) {
       
   276     case PROP_DEVICE:
       
   277       g_value_set_string (value, src->device);
       
   278       break;
       
   279     case PROP_DEVICE_NAME:
       
   280       g_value_take_string (value,
       
   281           gst_alsa_find_device_name (GST_OBJECT_CAST (src),
       
   282               src->device, src->handle, SND_PCM_STREAM_CAPTURE));
       
   283       break;
       
   284     default:
       
   285       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   286       break;
       
   287   }
       
   288 }
       
   289 
       
   290 static void
       
   291 gst_alsasrc_init (GstAlsaSrc * alsasrc, GstAlsaSrcClass * g_class)
       
   292 {
       
   293   GST_DEBUG_OBJECT (alsasrc, "initializing");
       
   294 
       
   295   alsasrc->device = g_strdup (DEFAULT_PROP_DEVICE);
       
   296   alsasrc->cached_caps = NULL;
       
   297 
       
   298   alsasrc->alsa_lock = g_mutex_new ();
       
   299 }
       
   300 
       
   301 #define CHECK(call, error) \
       
   302 G_STMT_START {                  \
       
   303 if ((err = call) < 0)           \
       
   304   goto error;                   \
       
   305 } G_STMT_END;
       
   306 
       
   307 
       
   308 static GstCaps *
       
   309 gst_alsasrc_getcaps (GstBaseSrc * bsrc)
       
   310 {
       
   311   GstElementClass *element_class;
       
   312   GstPadTemplate *pad_template;
       
   313   GstAlsaSrc *src;
       
   314   GstCaps *caps;
       
   315 
       
   316   src = GST_ALSA_SRC (bsrc);
       
   317 
       
   318   if (src->handle == NULL) {
       
   319     GST_DEBUG_OBJECT (src, "device not open, using template caps");
       
   320     return NULL;                /* base class will get template caps for us */
       
   321   }
       
   322 
       
   323   if (src->cached_caps) {
       
   324     GST_LOG_OBJECT (src, "Returning cached caps");
       
   325     return gst_caps_ref (src->cached_caps);
       
   326   }
       
   327 
       
   328   element_class = GST_ELEMENT_GET_CLASS (src);
       
   329   pad_template = gst_element_class_get_pad_template (element_class, "src");
       
   330   g_return_val_if_fail (pad_template != NULL, NULL);
       
   331 
       
   332   caps = gst_alsa_probe_supported_formats (GST_OBJECT (src), src->handle,
       
   333       gst_pad_template_get_caps (pad_template));
       
   334 
       
   335   if (caps) {
       
   336     src->cached_caps = gst_caps_ref (caps);
       
   337   }
       
   338 
       
   339   GST_INFO_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps);
       
   340 
       
   341   return caps;
       
   342 }
       
   343 
       
   344 static int
       
   345 set_hwparams (GstAlsaSrc * alsa)
       
   346 {
       
   347   guint rrate;
       
   348   gint err, dir;
       
   349   snd_pcm_hw_params_t *params;
       
   350 
       
   351   snd_pcm_hw_params_malloc (&params);
       
   352 
       
   353   /* choose all parameters */
       
   354   CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
       
   355   /* set the interleaved read/write format */
       
   356   CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
       
   357       wrong_access);
       
   358   /* set the sample format */
       
   359   CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
       
   360       no_sample_format);
       
   361   /* set the count of channels */
       
   362   CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
       
   363       no_channels);
       
   364   /* set the stream rate */
       
   365   rrate = alsa->rate;
       
   366   CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
       
   367       no_rate);
       
   368   if (rrate != alsa->rate)
       
   369     goto rate_match;
       
   370 
       
   371   if (alsa->buffer_time != -1) {
       
   372     /* set the buffer time */
       
   373     CHECK (snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
       
   374             &alsa->buffer_time, &dir), buffer_time);
       
   375   }
       
   376   if (alsa->period_time != -1) {
       
   377     /* set the period time */
       
   378     CHECK (snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
       
   379             &alsa->period_time, &dir), period_time);
       
   380   }
       
   381 
       
   382   /* write the parameters to device */
       
   383   CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
       
   384 
       
   385   CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
       
   386       buffer_size);
       
   387 
       
   388   CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
       
   389       period_size);
       
   390 
       
   391   snd_pcm_hw_params_free (params);
       
   392   return 0;
       
   393 
       
   394   /* ERRORS */
       
   395 no_config:
       
   396   {
       
   397     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   398         ("Broken configuration for recording: no configurations available: %s",
       
   399             snd_strerror (err)));
       
   400     snd_pcm_hw_params_free (params);
       
   401     return err;
       
   402   }
       
   403 wrong_access:
       
   404   {
       
   405     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   406         ("Access type not available for recording: %s", snd_strerror (err)));
       
   407     snd_pcm_hw_params_free (params);
       
   408     return err;
       
   409   }
       
   410 no_sample_format:
       
   411   {
       
   412     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   413         ("Sample format not available for recording: %s", snd_strerror (err)));
       
   414     snd_pcm_hw_params_free (params);
       
   415     return err;
       
   416   }
       
   417 no_channels:
       
   418   {
       
   419     gchar *msg = NULL;
       
   420 
       
   421     if ((alsa->channels) == 1)
       
   422       msg = g_strdup (_("Could not open device for recording in mono mode."));
       
   423     if ((alsa->channels) == 2)
       
   424       msg = g_strdup (_("Could not open device for recording in stereo mode."));
       
   425     if ((alsa->channels) > 2)
       
   426       msg =
       
   427           g_strdup_printf (_
       
   428           ("Could not open device for recording in %d-channel mode"),
       
   429           alsa->channels);
       
   430     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (msg), (snd_strerror (err)));
       
   431     g_free (msg);
       
   432     snd_pcm_hw_params_free (params);
       
   433     return err;
       
   434   }
       
   435 no_rate:
       
   436   {
       
   437     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   438         ("Rate %iHz not available for recording: %s",
       
   439             alsa->rate, snd_strerror (err)));
       
   440     snd_pcm_hw_params_free (params);
       
   441     return err;
       
   442   }
       
   443 rate_match:
       
   444   {
       
   445     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   446         ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
       
   447     snd_pcm_hw_params_free (params);
       
   448     return -EINVAL;
       
   449   }
       
   450 buffer_time:
       
   451   {
       
   452     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   453         ("Unable to set buffer time %i for recording: %s",
       
   454             alsa->buffer_time, snd_strerror (err)));
       
   455     snd_pcm_hw_params_free (params);
       
   456     return err;
       
   457   }
       
   458 buffer_size:
       
   459   {
       
   460     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   461         ("Unable to get buffer size for recording: %s", snd_strerror (err)));
       
   462     snd_pcm_hw_params_free (params);
       
   463     return err;
       
   464   }
       
   465 period_time:
       
   466   {
       
   467     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   468         ("Unable to set period time %i for recording: %s", alsa->period_time,
       
   469             snd_strerror (err)));
       
   470     snd_pcm_hw_params_free (params);
       
   471     return err;
       
   472   }
       
   473 period_size:
       
   474   {
       
   475     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   476         ("Unable to get period size for recording: %s", snd_strerror (err)));
       
   477     snd_pcm_hw_params_free (params);
       
   478     return err;
       
   479   }
       
   480 set_hw_params:
       
   481   {
       
   482     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   483         ("Unable to set hw params for recording: %s", snd_strerror (err)));
       
   484     snd_pcm_hw_params_free (params);
       
   485     return err;
       
   486   }
       
   487 }
       
   488 
       
   489 static int
       
   490 set_swparams (GstAlsaSrc * alsa)
       
   491 {
       
   492   int err;
       
   493   snd_pcm_sw_params_t *params;
       
   494 
       
   495   snd_pcm_sw_params_malloc (&params);
       
   496 
       
   497   /* get the current swparams */
       
   498   CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
       
   499   /* allow the transfer when at least period_size samples can be processed */
       
   500   CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
       
   501           alsa->period_size), set_avail);
       
   502   /* start the transfer on first read */
       
   503   CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
       
   504           0), start_threshold);
       
   505 
       
   506 #if GST_CHECK_ALSA_VERSION(1,0,16)
       
   507   /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
       
   508 #else
       
   509   /* align all transfers to 1 sample */
       
   510   CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
       
   511 #endif
       
   512 
       
   513   /* write the parameters to the recording device */
       
   514   CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
       
   515 
       
   516   snd_pcm_sw_params_free (params);
       
   517   return 0;
       
   518 
       
   519   /* ERRORS */
       
   520 no_config:
       
   521   {
       
   522     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   523         ("Unable to determine current swparams for playback: %s",
       
   524             snd_strerror (err)));
       
   525     snd_pcm_sw_params_free (params);
       
   526     return err;
       
   527   }
       
   528 start_threshold:
       
   529   {
       
   530     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   531         ("Unable to set start threshold mode for playback: %s",
       
   532             snd_strerror (err)));
       
   533     snd_pcm_sw_params_free (params);
       
   534     return err;
       
   535   }
       
   536 set_avail:
       
   537   {
       
   538     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   539         ("Unable to set avail min for playback: %s", snd_strerror (err)));
       
   540     snd_pcm_sw_params_free (params);
       
   541     return err;
       
   542   }
       
   543 #if !GST_CHECK_ALSA_VERSION(1,0,16)
       
   544 set_align:
       
   545   {
       
   546     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   547         ("Unable to set transfer align for playback: %s", snd_strerror (err)));
       
   548     snd_pcm_sw_params_free (params);
       
   549     return err;
       
   550   }
       
   551 #endif
       
   552 set_sw_params:
       
   553   {
       
   554     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   555         ("Unable to set sw params for playback: %s", snd_strerror (err)));
       
   556     snd_pcm_sw_params_free (params);
       
   557     return err;
       
   558   }
       
   559 }
       
   560 
       
   561 static gboolean
       
   562 alsasrc_parse_spec (GstAlsaSrc * alsa, GstRingBufferSpec * spec)
       
   563 {
       
   564   switch (spec->type) {
       
   565     case GST_BUFTYPE_LINEAR:
       
   566       alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
       
   567           spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
       
   568       break;
       
   569     case GST_BUFTYPE_FLOAT:
       
   570       switch (spec->format) {
       
   571         case GST_FLOAT32_LE:
       
   572           alsa->format = SND_PCM_FORMAT_FLOAT_LE;
       
   573           break;
       
   574         case GST_FLOAT32_BE:
       
   575           alsa->format = SND_PCM_FORMAT_FLOAT_BE;
       
   576           break;
       
   577         case GST_FLOAT64_LE:
       
   578           alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
       
   579           break;
       
   580         case GST_FLOAT64_BE:
       
   581           alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
       
   582           break;
       
   583         default:
       
   584           goto error;
       
   585       }
       
   586       break;
       
   587     case GST_BUFTYPE_A_LAW:
       
   588       alsa->format = SND_PCM_FORMAT_A_LAW;
       
   589       break;
       
   590     case GST_BUFTYPE_MU_LAW:
       
   591       alsa->format = SND_PCM_FORMAT_MU_LAW;
       
   592       break;
       
   593     default:
       
   594       goto error;
       
   595 
       
   596   }
       
   597   alsa->rate = spec->rate;
       
   598   alsa->channels = spec->channels;
       
   599   alsa->buffer_time = spec->buffer_time;
       
   600   alsa->period_time = spec->latency_time;
       
   601   alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
       
   602 
       
   603   return TRUE;
       
   604 
       
   605   /* ERRORS */
       
   606 error:
       
   607   {
       
   608     return FALSE;
       
   609   }
       
   610 }
       
   611 
       
   612 static gboolean
       
   613 gst_alsasrc_open (GstAudioSrc * asrc)
       
   614 {
       
   615   GstAlsaSrc *alsa;
       
   616   gint err;
       
   617 
       
   618   alsa = GST_ALSA_SRC (asrc);
       
   619 
       
   620   CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_CAPTURE,
       
   621           SND_PCM_NONBLOCK), open_error);
       
   622 
       
   623   if (!alsa->mixer)
       
   624     alsa->mixer = gst_alsa_mixer_new (alsa->device, GST_ALSA_MIXER_CAPTURE);
       
   625 
       
   626   return TRUE;
       
   627 
       
   628   /* ERRORS */
       
   629 open_error:
       
   630   {
       
   631     if (err == -EBUSY) {
       
   632       GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
       
   633           (_("Could not open audio device for recording. "
       
   634                   "Device is being used by another application.")),
       
   635           ("Device '%s' is busy", alsa->device));
       
   636     } else {
       
   637       GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
       
   638           (_("Could not open audio device for recording.")),
       
   639           ("Recording open error on device '%s': %s", alsa->device,
       
   640               snd_strerror (err)));
       
   641     }
       
   642     return FALSE;
       
   643   }
       
   644 }
       
   645 
       
   646 static gboolean
       
   647 gst_alsasrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
       
   648 {
       
   649   GstAlsaSrc *alsa;
       
   650   gint err;
       
   651 
       
   652   alsa = GST_ALSA_SRC (asrc);
       
   653 
       
   654   if (!alsasrc_parse_spec (alsa, spec))
       
   655     goto spec_parse;
       
   656 
       
   657   CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);
       
   658 
       
   659   CHECK (set_hwparams (alsa), hw_params_failed);
       
   660   CHECK (set_swparams (alsa), sw_params_failed);
       
   661   CHECK (snd_pcm_prepare (alsa->handle), prepare_failed);
       
   662 
       
   663   alsa->bytes_per_sample = spec->bytes_per_sample;
       
   664   spec->segsize = alsa->period_size * spec->bytes_per_sample;
       
   665   spec->segtotal = alsa->buffer_size / alsa->period_size;
       
   666   spec->silence_sample[0] = 0;
       
   667   spec->silence_sample[1] = 0;
       
   668   spec->silence_sample[2] = 0;
       
   669   spec->silence_sample[3] = 0;
       
   670 
       
   671   return TRUE;
       
   672 
       
   673   /* ERRORS */
       
   674 spec_parse:
       
   675   {
       
   676     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   677         ("Error parsing spec"));
       
   678     return FALSE;
       
   679   }
       
   680 non_block:
       
   681   {
       
   682     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   683         ("Could not set device to blocking: %s", snd_strerror (err)));
       
   684     return FALSE;
       
   685   }
       
   686 hw_params_failed:
       
   687   {
       
   688     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   689         ("Setting of hwparams failed: %s", snd_strerror (err)));
       
   690     return FALSE;
       
   691   }
       
   692 sw_params_failed:
       
   693   {
       
   694     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   695         ("Setting of swparams failed: %s", snd_strerror (err)));
       
   696     return FALSE;
       
   697   }
       
   698 prepare_failed:
       
   699   {
       
   700     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   701         ("Prepare failed: %s", snd_strerror (err)));
       
   702     return FALSE;
       
   703   }
       
   704 }
       
   705 
       
   706 static gboolean
       
   707 gst_alsasrc_unprepare (GstAudioSrc * asrc)
       
   708 {
       
   709   GstAlsaSrc *alsa;
       
   710   gint err;
       
   711 
       
   712   alsa = GST_ALSA_SRC (asrc);
       
   713 
       
   714   CHECK (snd_pcm_drop (alsa->handle), drop);
       
   715 
       
   716   CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
       
   717 
       
   718   CHECK (snd_pcm_nonblock (alsa->handle, 1), non_block);
       
   719 
       
   720   return TRUE;
       
   721 
       
   722   /* ERRORS */
       
   723 drop:
       
   724   {
       
   725     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   726         ("Could not drop samples: %s", snd_strerror (err)));
       
   727     return FALSE;
       
   728   }
       
   729 hw_free:
       
   730   {
       
   731     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   732         ("Could not free hw params: %s", snd_strerror (err)));
       
   733     return FALSE;
       
   734   }
       
   735 non_block:
       
   736   {
       
   737     GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
       
   738         ("Could not set device to nonblocking: %s", snd_strerror (err)));
       
   739     return FALSE;
       
   740   }
       
   741 }
       
   742 
       
   743 static gboolean
       
   744 gst_alsasrc_close (GstAudioSrc * asrc)
       
   745 {
       
   746   GstAlsaSrc *alsa = GST_ALSA_SRC (asrc);
       
   747 
       
   748   snd_pcm_close (alsa->handle);
       
   749 
       
   750   if (alsa->mixer) {
       
   751     gst_alsa_mixer_free (alsa->mixer);
       
   752     alsa->mixer = NULL;
       
   753   }
       
   754 
       
   755   gst_caps_replace (&alsa->cached_caps, NULL);
       
   756 
       
   757   return TRUE;
       
   758 }
       
   759 
       
   760 /*
       
   761  *   Underrun and suspend recovery
       
   762  */
       
   763 static gint
       
   764 xrun_recovery (GstAlsaSrc * alsa, snd_pcm_t * handle, gint err)
       
   765 {
       
   766   GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
       
   767 
       
   768   if (err == -EPIPE) {          /* under-run */
       
   769     err = snd_pcm_prepare (handle);
       
   770     if (err < 0)
       
   771       GST_WARNING_OBJECT (alsa,
       
   772           "Can't recovery from underrun, prepare failed: %s",
       
   773           snd_strerror (err));
       
   774     return 0;
       
   775   } else if (err == -ESTRPIPE) {
       
   776     while ((err = snd_pcm_resume (handle)) == -EAGAIN)
       
   777       g_usleep (100);           /* wait until the suspend flag is released */
       
   778 
       
   779     if (err < 0) {
       
   780       err = snd_pcm_prepare (handle);
       
   781       if (err < 0)
       
   782         GST_WARNING_OBJECT (alsa,
       
   783             "Can't recovery from suspend, prepare failed: %s",
       
   784             snd_strerror (err));
       
   785     }
       
   786     return 0;
       
   787   }
       
   788   return err;
       
   789 }
       
   790 
       
   791 static guint
       
   792 gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length)
       
   793 {
       
   794   GstAlsaSrc *alsa;
       
   795   gint err;
       
   796   gint cptr;
       
   797   gint16 *ptr;
       
   798 
       
   799   alsa = GST_ALSA_SRC (asrc);
       
   800 
       
   801   cptr = length / alsa->bytes_per_sample;
       
   802   ptr = data;
       
   803 
       
   804   GST_ALSA_SRC_LOCK (asrc);
       
   805   while (cptr > 0) {
       
   806     if ((err = snd_pcm_readi (alsa->handle, ptr, cptr)) < 0) {
       
   807       if (err == -EAGAIN) {
       
   808         GST_DEBUG_OBJECT (asrc, "Read error: %s", snd_strerror (err));
       
   809         continue;
       
   810       } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
       
   811         goto read_error;
       
   812       }
       
   813       continue;
       
   814     }
       
   815 
       
   816     ptr += err * alsa->channels;
       
   817     cptr -= err;
       
   818   }
       
   819   GST_ALSA_SRC_UNLOCK (asrc);
       
   820 
       
   821   return length - cptr;
       
   822 
       
   823 read_error:
       
   824   {
       
   825     GST_ALSA_SRC_UNLOCK (asrc);
       
   826     return length;              /* skip one period */
       
   827   }
       
   828 }
       
   829 
       
   830 static guint
       
   831 gst_alsasrc_delay (GstAudioSrc * asrc)
       
   832 {
       
   833   GstAlsaSrc *alsa;
       
   834   snd_pcm_sframes_t delay;
       
   835   int res;
       
   836 
       
   837   alsa = GST_ALSA_SRC (asrc);
       
   838 
       
   839   res = snd_pcm_delay (alsa->handle, &delay);
       
   840   if (G_UNLIKELY (res < 0)) {
       
   841     GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
       
   842     delay = 0;
       
   843   }
       
   844 
       
   845   return CLAMP (delay, 0, alsa->buffer_size);
       
   846 }
       
   847 
       
   848 static void
       
   849 gst_alsasrc_reset (GstAudioSrc * asrc)
       
   850 {
       
   851   GstAlsaSrc *alsa;
       
   852   gint err;
       
   853 
       
   854   alsa = GST_ALSA_SRC (asrc);
       
   855 
       
   856   GST_ALSA_SRC_LOCK (asrc);
       
   857   GST_DEBUG_OBJECT (alsa, "drop");
       
   858   CHECK (snd_pcm_drop (alsa->handle), drop_error);
       
   859   GST_DEBUG_OBJECT (alsa, "prepare");
       
   860   CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
       
   861   GST_DEBUG_OBJECT (alsa, "reset done");
       
   862   GST_ALSA_SRC_UNLOCK (asrc);
       
   863 
       
   864   return;
       
   865 
       
   866   /* ERRORS */
       
   867 drop_error:
       
   868   {
       
   869     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
       
   870         snd_strerror (err));
       
   871     GST_ALSA_SRC_UNLOCK (asrc);
       
   872     return;
       
   873   }
       
   874 prepare_error:
       
   875   {
       
   876     GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
       
   877         snd_strerror (err));
       
   878     GST_ALSA_SRC_UNLOCK (asrc);
       
   879     return;
       
   880   }
       
   881 }