gst_plugins_base/ext/alsa/gstalsa.c
changeset 0 0e761a78d257
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
       
     2  *
       
     3  * This library is free software; you can redistribute it and/or
       
     4  * modify it under the terms of the GNU Library General Public
       
     5  * License as published by the Free Software Foundation; either
       
     6  * version 2 of the License, or (at your option) any later version.
       
     7  *
       
     8  * This library is distributed in the hope that it will be useful,
       
     9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       
    11  * Library General Public License for more details.
       
    12  *
       
    13  * You should have received a copy of the GNU Library General Public
       
    14  * License along with this library; if not, write to the Free
       
    15  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
       
    16  */
       
    17 
       
    18 #include "gstalsa.h"
       
    19 
       
    20 #include <gst/audio/multichannel.h>
       
    21 
       
    22 static GstCaps *
       
    23 gst_alsa_detect_rates (GstObject * obj, snd_pcm_hw_params_t * hw_params,
       
    24     GstCaps * in_caps)
       
    25 {
       
    26   GstCaps *caps;
       
    27   guint min, max;
       
    28   gint err, dir, min_rate, max_rate, i;
       
    29 
       
    30   GST_LOG_OBJECT (obj, "probing sample rates ...");
       
    31 
       
    32   if ((err = snd_pcm_hw_params_get_rate_min (hw_params, &min, &dir)) < 0)
       
    33     goto min_rate_err;
       
    34 
       
    35   if ((err = snd_pcm_hw_params_get_rate_max (hw_params, &max, &dir)) < 0)
       
    36     goto max_rate_err;
       
    37 
       
    38   min_rate = min;
       
    39   max_rate = max;
       
    40 
       
    41   if (min_rate < 4000)
       
    42     min_rate = 4000;            /* random 'sensible minimum' */
       
    43 
       
    44   if (max_rate <= 0)
       
    45     max_rate = G_MAXINT;        /* or maybe just use 192400 or so? */
       
    46   else if (max_rate > 0 && max_rate < 4000)
       
    47     max_rate = MAX (4000, min_rate);
       
    48 
       
    49   GST_DEBUG_OBJECT (obj, "Min. rate = %u (%d)", min_rate, min);
       
    50   GST_DEBUG_OBJECT (obj, "Max. rate = %u (%d)", max_rate, max);
       
    51 
       
    52   caps = gst_caps_make_writable (in_caps);
       
    53 
       
    54   for (i = 0; i < gst_caps_get_size (caps); ++i) {
       
    55     GstStructure *s;
       
    56 
       
    57     s = gst_caps_get_structure (caps, i);
       
    58     if (min_rate == max_rate) {
       
    59       gst_structure_set (s, "rate", G_TYPE_INT, min_rate, NULL);
       
    60     } else {
       
    61       gst_structure_set (s, "rate", GST_TYPE_INT_RANGE,
       
    62           min_rate, max_rate, NULL);
       
    63     }
       
    64   }
       
    65 
       
    66   return caps;
       
    67 
       
    68   /* ERRORS */
       
    69 min_rate_err:
       
    70   {
       
    71     GST_ERROR_OBJECT (obj, "failed to query minimum sample rate: %s",
       
    72         snd_strerror (err));
       
    73     gst_caps_unref (in_caps);
       
    74     return NULL;
       
    75   }
       
    76 max_rate_err:
       
    77   {
       
    78     GST_ERROR_OBJECT (obj, "failed to query maximum sample rate: %s",
       
    79         snd_strerror (err));
       
    80     gst_caps_unref (in_caps);
       
    81     return NULL;
       
    82   }
       
    83 }
       
    84 
       
    85 static const struct
       
    86 {
       
    87   const int width;
       
    88   const int depth;
       
    89   const int sformat;
       
    90   const int uformat;
       
    91 } pcmformats[] = {
       
    92   {
       
    93   8, 8, SND_PCM_FORMAT_S8, SND_PCM_FORMAT_U8}, {
       
    94   16, 16, SND_PCM_FORMAT_S16, SND_PCM_FORMAT_U16}, {
       
    95   32, 24, SND_PCM_FORMAT_S24, SND_PCM_FORMAT_U24}, {
       
    96 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)   /* no endian-unspecific enum available */
       
    97   24, 24, SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_U24_3LE}, {
       
    98 #else
       
    99   24, 24, SND_PCM_FORMAT_S24_3BE, SND_PCM_FORMAT_U24_3BE}, {
       
   100 #endif
       
   101   32, 32, SND_PCM_FORMAT_S32, SND_PCM_FORMAT_U32}
       
   102 };
       
   103 
       
   104 static GstCaps *
       
   105 gst_alsa_detect_formats (GstObject * obj, snd_pcm_hw_params_t * hw_params,
       
   106     GstCaps * in_caps)
       
   107 {
       
   108   snd_pcm_format_mask_t *mask;
       
   109   GstStructure *s;
       
   110   GstCaps *caps;
       
   111   gint i;
       
   112 
       
   113   snd_pcm_format_mask_malloc (&mask);
       
   114   snd_pcm_hw_params_get_format_mask (hw_params, mask);
       
   115 
       
   116   caps = gst_caps_new_empty ();
       
   117 
       
   118   for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
       
   119     GstStructure *scopy;
       
   120     gint w, width = 0, depth = 0;
       
   121 
       
   122     s = gst_caps_get_structure (in_caps, i);
       
   123     if (!gst_structure_has_name (s, "audio/x-raw-int")) {
       
   124       GST_WARNING_OBJECT (obj, "skipping non-int format");
       
   125       continue;
       
   126     }
       
   127     if (!gst_structure_get_int (s, "width", &width) ||
       
   128         !gst_structure_get_int (s, "depth", &depth))
       
   129       continue;
       
   130     if (width == 0 || (width % 8) != 0)
       
   131       continue;                 /* Only full byte widths are valid */
       
   132     for (w = 0; w < G_N_ELEMENTS (pcmformats); w++)
       
   133       if (pcmformats[w].width == width && pcmformats[w].depth == depth)
       
   134         break;
       
   135     if (w == G_N_ELEMENTS (pcmformats))
       
   136       continue;                 /* Unknown format */
       
   137 
       
   138     if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat) &&
       
   139         snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
       
   140       /* template contains { true, false } or just one, leave it as it is */
       
   141       scopy = gst_structure_copy (s);
       
   142     } else if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat)) {
       
   143       scopy = gst_structure_copy (s);
       
   144       gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
       
   145     } else if (snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
       
   146       scopy = gst_structure_copy (s);
       
   147       gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
       
   148     } else {
       
   149       scopy = NULL;
       
   150     }
       
   151     if (scopy) {
       
   152       if (width > 8) {
       
   153         /* TODO: proper endianness detection, for now it's CPU endianness only */
       
   154         gst_structure_set (scopy, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
       
   155       }
       
   156       gst_caps_append_structure (caps, scopy);
       
   157     }
       
   158   }
       
   159 
       
   160   snd_pcm_format_mask_free (mask);
       
   161   gst_caps_unref (in_caps);
       
   162   return caps;
       
   163 }
       
   164 
       
   165 /* we don't have channel mappings for more than this many channels */
       
   166 #define GST_ALSA_MAX_CHANNELS 8
       
   167 
       
   168 static GstStructure *
       
   169 get_channel_free_structure (const GstStructure * in_structure)
       
   170 {
       
   171   GstStructure *s = gst_structure_copy (in_structure);
       
   172 
       
   173   gst_structure_remove_field (s, "channels");
       
   174   return s;
       
   175 }
       
   176 
       
   177 static void
       
   178 caps_add_channel_configuration (GstCaps * caps,
       
   179     const GstStructure * in_structure, gint min_chans, gint max_chans)
       
   180 {
       
   181   GstAudioChannelPosition pos[8] = {
       
   182     GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   183     GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   184     GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
       
   185     GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
       
   186     GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
       
   187     GST_AUDIO_CHANNEL_POSITION_LFE,
       
   188     GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
       
   189     GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT
       
   190   };
       
   191   GstStructure *s = NULL;
       
   192   gint c;
       
   193 
       
   194   if (min_chans == max_chans && max_chans <= 2) {
       
   195     s = get_channel_free_structure (in_structure);
       
   196     gst_structure_set (s, "channels", G_TYPE_INT, max_chans, NULL);
       
   197     gst_caps_append_structure (caps, s);
       
   198     return;
       
   199   }
       
   200 
       
   201   g_assert (min_chans >= 1);
       
   202 
       
   203   /* mono and stereo don't need channel configurations */
       
   204   if (min_chans == 2) {
       
   205     s = get_channel_free_structure (in_structure);
       
   206     gst_structure_set (s, "channels", G_TYPE_INT, 2, NULL);
       
   207     gst_caps_append_structure (caps, s);
       
   208   } else if (min_chans == 1 && max_chans >= 2) {
       
   209     s = get_channel_free_structure (in_structure);
       
   210     gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
       
   211     gst_caps_append_structure (caps, s);
       
   212   }
       
   213 
       
   214   /* don't know whether to use 2.1 or 3.0 here - but I suspect
       
   215    * alsa might work around that/fix it somehow. Can we tell alsa
       
   216    * what our channel layout is like? */
       
   217   if (max_chans >= 3 && min_chans <= 3) {
       
   218     GstAudioChannelPosition pos_21[3] = {
       
   219       GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       
   220       GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
       
   221       GST_AUDIO_CHANNEL_POSITION_LFE
       
   222     };
       
   223 
       
   224     s = get_channel_free_structure (in_structure);
       
   225     gst_structure_set (s, "channels", G_TYPE_INT, 3, NULL);
       
   226     gst_audio_set_channel_positions (s, pos_21);
       
   227     gst_caps_append_structure (caps, s);
       
   228   }
       
   229 
       
   230   /* everything else (4, 6, 8 channels) needs a channel layout */
       
   231   for (c = MAX (4, min_chans); c <= 8; c += 2) {
       
   232     if (max_chans >= c) {
       
   233       s = get_channel_free_structure (in_structure);
       
   234       gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
       
   235       gst_audio_set_channel_positions (s, pos);
       
   236       gst_caps_append_structure (caps, s);
       
   237     }
       
   238   }
       
   239 
       
   240   for (c = MAX (9, min_chans); c <= max_chans; ++c) {
       
   241     GstAudioChannelPosition *ch_layout;
       
   242     guint i;
       
   243 
       
   244     ch_layout = g_new (GstAudioChannelPosition, c);
       
   245     for (i = 0; i < c; ++i) {
       
   246       ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
       
   247     }
       
   248     s = get_channel_free_structure (in_structure);
       
   249     gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
       
   250     gst_audio_set_channel_positions (s, ch_layout);
       
   251     gst_caps_append_structure (caps, s);
       
   252     g_free (ch_layout);
       
   253   }
       
   254 }
       
   255 
       
   256 static GstCaps *
       
   257 gst_alsa_detect_channels (GstObject * obj, snd_pcm_hw_params_t * hw_params,
       
   258     GstCaps * in_caps)
       
   259 {
       
   260   GstCaps *caps;
       
   261   guint min, max;
       
   262   gint min_chans, max_chans;
       
   263   gint err, i;
       
   264 
       
   265   GST_LOG_OBJECT (obj, "probing channels ...");
       
   266 
       
   267   if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &min)) < 0)
       
   268     goto min_chan_error;
       
   269 
       
   270   if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &max)) < 0)
       
   271     goto max_chan_error;
       
   272 
       
   273   /* note: the above functions may return (guint) -1 */
       
   274   min_chans = min;
       
   275   max_chans = max;
       
   276 
       
   277   if (min_chans < 0) {
       
   278     min_chans = 1;
       
   279     max_chans = GST_ALSA_MAX_CHANNELS;
       
   280   } else if (max_chans < 0) {
       
   281     max_chans = GST_ALSA_MAX_CHANNELS;
       
   282   }
       
   283 
       
   284   if (min_chans > max_chans) {
       
   285     gint temp;
       
   286 
       
   287     GST_WARNING_OBJECT (obj, "minimum channels > maximum channels (%d > %d), "
       
   288         "please fix your soundcard drivers", min, max);
       
   289     temp = min_chans;
       
   290     min_chans = max_chans;
       
   291     max_chans = temp;
       
   292   }
       
   293 
       
   294   /* pro cards seem to return large numbers for min_channels */
       
   295   if (min_chans > GST_ALSA_MAX_CHANNELS) {
       
   296     GST_DEBUG_OBJECT (obj, "min_chans = %u, looks like a pro card", min_chans);
       
   297     if (max_chans < min_chans) {
       
   298       max_chans = min_chans;
       
   299     } else {
       
   300       /* only support [max_chans; max_chans] for these cards for now
       
   301        * to avoid inflating the source caps with loads of structures ... */
       
   302       min_chans = max_chans;
       
   303     }
       
   304   } else {
       
   305     min_chans = MAX (min_chans, 1);
       
   306     max_chans = MIN (GST_ALSA_MAX_CHANNELS, max_chans);
       
   307   }
       
   308 
       
   309   GST_DEBUG_OBJECT (obj, "Min. channels = %d (%d)", min_chans, min);
       
   310   GST_DEBUG_OBJECT (obj, "Max. channels = %d (%d)", max_chans, max);
       
   311 
       
   312   caps = gst_caps_new_empty ();
       
   313 
       
   314   for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
       
   315     GstStructure *s;
       
   316     GType field_type;
       
   317     gint c_min = min_chans;
       
   318     gint c_max = max_chans;
       
   319 
       
   320     s = gst_caps_get_structure (in_caps, i);
       
   321     /* the template caps might limit the number of channels (like alsasrc),
       
   322      * in which case we don't want to return a superset, so hack around this
       
   323      * for the two common cases where the channels are either a fixed number
       
   324      * or a min/max range). Example: alsasrc template has channels = [1,2] and 
       
   325      * the detection will claim to support 8 channels for device 'plughw:0' */
       
   326     field_type = gst_structure_get_field_type (s, "channels");
       
   327     if (field_type == G_TYPE_INT) {
       
   328       gst_structure_get_int (s, "channels", &c_min);
       
   329       gst_structure_get_int (s, "channels", &c_max);
       
   330     } else if (field_type == GST_TYPE_INT_RANGE) {
       
   331       const GValue *val;
       
   332 
       
   333       val = gst_structure_get_value (s, "channels");
       
   334       c_min = CLAMP (gst_value_get_int_range_min (val), min_chans, max_chans);
       
   335       c_max = CLAMP (gst_value_get_int_range_max (val), min_chans, max_chans);
       
   336     } else {
       
   337       c_min = min_chans;
       
   338       c_max = max_chans;
       
   339     }
       
   340 
       
   341     caps_add_channel_configuration (caps, s, c_min, c_max);
       
   342   }
       
   343 
       
   344   gst_caps_unref (in_caps);
       
   345 
       
   346   return caps;
       
   347 
       
   348   /* ERRORS */
       
   349 min_chan_error:
       
   350   {
       
   351     GST_ERROR_OBJECT (obj, "failed to query minimum channel count: %s",
       
   352         snd_strerror (err));
       
   353     return NULL;
       
   354   }
       
   355 max_chan_error:
       
   356   {
       
   357     GST_ERROR_OBJECT (obj, "failed to query maximum channel count: %s",
       
   358         snd_strerror (err));
       
   359     return NULL;
       
   360   }
       
   361 }
       
   362 
       
   363 snd_pcm_t *
       
   364 gst_alsa_open_iec958_pcm (GstObject * obj)
       
   365 {
       
   366   char *iec958_pcm_name = NULL;
       
   367   snd_pcm_t *pcm = NULL;
       
   368   int res;
       
   369   char devstr[256];             /* Storage for local 'default' device string */
       
   370 
       
   371   /*
       
   372    * Try and open our default iec958 device. Fall back to searching on card x
       
   373    * if this fails, which should only happen on older alsa setups
       
   374    */
       
   375 
       
   376   /* The string will be one of these:
       
   377    * SPDIF_CON: Non-audio flag not set:
       
   378    *    spdif:{AES0 0x0 AES1 0x82 AES2 0x0 AES3 0x2}
       
   379    * SPDIF_CON: Non-audio flag set:
       
   380    *    spdif:{AES0 0x2 AES1 0x82 AES2 0x0 AES3 0x2}
       
   381    */
       
   382   sprintf (devstr,
       
   383       "iec958:{AES0 0x%02x AES1 0x%02x AES2 0x%02x AES3 0x%02x}",
       
   384       IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
       
   385       IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
       
   386       0, IEC958_AES3_CON_FS_48000);
       
   387 
       
   388   GST_DEBUG_OBJECT (obj, "Generated device string \"%s\"", devstr);
       
   389   iec958_pcm_name = devstr;
       
   390 
       
   391   res = snd_pcm_open (&pcm, iec958_pcm_name, SND_PCM_STREAM_PLAYBACK, 0);
       
   392   if (G_UNLIKELY (res < 0)) {
       
   393     GST_DEBUG_OBJECT (obj, "failed opening IEC958 device: %s",
       
   394         snd_strerror (res));
       
   395     pcm = NULL;
       
   396   }
       
   397 
       
   398   return pcm;
       
   399 }
       
   400 
       
   401 
       
   402 /*
       
   403  * gst_alsa_probe_supported_formats:
       
   404  *
       
   405  * Takes the template caps and returns the subset which is actually
       
   406  * supported by this device.
       
   407  *
       
   408  */
       
   409 
       
   410 GstCaps *
       
   411 gst_alsa_probe_supported_formats (GstObject * obj, snd_pcm_t * handle,
       
   412     const GstCaps * template_caps)
       
   413 {
       
   414   snd_pcm_hw_params_t *hw_params;
       
   415   snd_pcm_stream_t stream_type;
       
   416   GstCaps *caps;
       
   417   gint err;
       
   418 
       
   419   snd_pcm_hw_params_malloc (&hw_params);
       
   420   if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0)
       
   421     goto error;
       
   422 
       
   423   stream_type = snd_pcm_stream (handle);
       
   424 
       
   425   caps = gst_caps_copy (template_caps);
       
   426 
       
   427   if (!(caps = gst_alsa_detect_formats (obj, hw_params, caps)))
       
   428     goto subroutine_error;
       
   429 
       
   430   if (!(caps = gst_alsa_detect_rates (obj, hw_params, caps)))
       
   431     goto subroutine_error;
       
   432 
       
   433   if (!(caps = gst_alsa_detect_channels (obj, hw_params, caps)))
       
   434     goto subroutine_error;
       
   435 
       
   436   /* Try opening IEC958 device to see if we can support that format (playback
       
   437    * only for now but we could add SPDIF capture later) */
       
   438   if (stream_type == SND_PCM_STREAM_PLAYBACK) {
       
   439     snd_pcm_t *pcm = gst_alsa_open_iec958_pcm (obj);
       
   440 
       
   441     if (G_LIKELY (pcm)) {
       
   442       gst_caps_append (caps, gst_caps_new_simple ("audio/x-iec958", NULL));
       
   443       snd_pcm_close (pcm);
       
   444     }
       
   445   }
       
   446 
       
   447   snd_pcm_hw_params_free (hw_params);
       
   448   return caps;
       
   449 
       
   450   /* ERRORS */
       
   451 error:
       
   452   {
       
   453     GST_ERROR_OBJECT (obj, "failed to query formats: %s", snd_strerror (err));
       
   454     snd_pcm_hw_params_free (hw_params);
       
   455     return NULL;
       
   456   }
       
   457 subroutine_error:
       
   458   {
       
   459     GST_ERROR_OBJECT (obj, "failed to query formats");
       
   460     snd_pcm_hw_params_free (hw_params);
       
   461     return NULL;
       
   462   }
       
   463 }
       
   464 
       
   465 static gchar *
       
   466 gst_alsa_find_device_name_no_handle (GstObject * obj, const gchar * devcard,
       
   467     gint device_num, snd_pcm_stream_t stream)
       
   468 {
       
   469   snd_ctl_card_info_t *info = NULL;
       
   470   snd_ctl_t *ctl = NULL;
       
   471   gchar *ret = NULL;
       
   472   gint dev = -1;
       
   473 
       
   474   GST_LOG_OBJECT (obj, "[%s] device=%d", devcard, device_num);
       
   475 
       
   476   if (snd_ctl_open (&ctl, devcard, 0) < 0)
       
   477     return NULL;
       
   478 
       
   479   snd_ctl_card_info_malloc (&info);
       
   480   if (snd_ctl_card_info (ctl, info) < 0)
       
   481     goto done;
       
   482 
       
   483   while (snd_ctl_pcm_next_device (ctl, &dev) == 0 && dev >= 0) {
       
   484     if (dev == device_num) {
       
   485       snd_pcm_info_t *pcminfo;
       
   486 
       
   487       snd_pcm_info_malloc (&pcminfo);
       
   488       snd_pcm_info_set_device (pcminfo, dev);
       
   489       snd_pcm_info_set_subdevice (pcminfo, 0);
       
   490       snd_pcm_info_set_stream (pcminfo, stream);
       
   491       if (snd_ctl_pcm_info (ctl, pcminfo) < 0) {
       
   492         snd_pcm_info_free (pcminfo);
       
   493         break;
       
   494       }
       
   495 
       
   496       ret = g_strdup (snd_pcm_info_get_name (pcminfo));
       
   497       snd_pcm_info_free (pcminfo);
       
   498       GST_LOG_OBJECT (obj, "name from pcminfo: %s", GST_STR_NULL (ret));
       
   499     }
       
   500   }
       
   501 
       
   502   if (ret == NULL) {
       
   503     char *name = NULL;
       
   504     gint card;
       
   505 
       
   506     GST_LOG_OBJECT (obj, "no luck so far, trying backup");
       
   507     card = snd_ctl_card_info_get_card (info);
       
   508     snd_card_get_name (card, &name);
       
   509     ret = g_strdup (name);
       
   510     free (name);
       
   511   }
       
   512 
       
   513 done:
       
   514   snd_ctl_card_info_free (info);
       
   515   snd_ctl_close (ctl);
       
   516 
       
   517   return ret;
       
   518 }
       
   519 
       
   520 gchar *
       
   521 gst_alsa_find_device_name (GstObject * obj, const gchar * device,
       
   522     snd_pcm_t * handle, snd_pcm_stream_t stream)
       
   523 {
       
   524   gchar *ret = NULL;
       
   525 
       
   526   if (device != NULL) {
       
   527     gchar *dev, *comma;
       
   528     gint devnum;
       
   529 
       
   530     GST_LOG_OBJECT (obj, "Trying to get device name from string '%s'", device);
       
   531 
       
   532     /* only want name:card bit, but not devices and subdevices */
       
   533     dev = g_strdup (device);
       
   534     if ((comma = strchr (dev, ','))) {
       
   535       *comma = '\0';
       
   536       devnum = atoi (comma + 1);
       
   537       ret = gst_alsa_find_device_name_no_handle (obj, dev, devnum, stream);
       
   538     }
       
   539     g_free (dev);
       
   540   }
       
   541 
       
   542   if (ret == NULL && handle != NULL) {
       
   543     snd_pcm_info_t *info;
       
   544 
       
   545     GST_LOG_OBJECT (obj, "Trying to get device name from open handle");
       
   546     snd_pcm_info_malloc (&info);
       
   547     snd_pcm_info (handle, info);
       
   548     ret = g_strdup (snd_pcm_info_get_name (info));
       
   549     snd_pcm_info_free (info);
       
   550   }
       
   551 
       
   552   GST_LOG_OBJECT (obj, "Device name for device '%s': %s",
       
   553       GST_STR_NULL (device), GST_STR_NULL (ret));
       
   554 
       
   555   return ret;
       
   556 }