gst_plugins_base/ext/alsa/gstalsamixerelement.c
branchRCL_3
changeset 30 7e817e7e631c
parent 0 0e761a78d257
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
       
     1 /* ALSA mixer implementation.
       
     2  * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.net>
       
     3  *
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Library General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12  * Library General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Library General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 
       
    20 
       
    21 #ifdef HAVE_CONFIG_H
       
    22 #include "config.h"
       
    23 #endif
       
    24 
       
    25 #include "gstalsamixerelement.h"
       
    26 #include "gstalsadeviceprobe.h"
       
    27 
       
    28 #define DEFAULT_PROP_DEVICE          "default"
       
    29 #define DEFAULT_PROP_DEVICE_NAME     ""
       
    30 
       
    31 enum
       
    32 {
       
    33   PROP_0,
       
    34   PROP_DEVICE,
       
    35   PROP_DEVICE_NAME
       
    36 };
       
    37 
       
    38 static const GstElementDetails gst_alsa_mixer_element_details =
       
    39 GST_ELEMENT_DETAILS ("Alsa mixer",
       
    40     "Generic/Audio",
       
    41     "Control sound input and output levels with ALSA",
       
    42     "Leif Johnson <leif@ambient.2y.net>");
       
    43 
       
    44 static void gst_alsa_mixer_element_init_interfaces (GType type);
       
    45 
       
    46 GST_BOILERPLATE_FULL (GstAlsaMixerElement, gst_alsa_mixer_element,
       
    47     GstElement, GST_TYPE_ELEMENT, gst_alsa_mixer_element_init_interfaces);
       
    48 
       
    49 /* massive macro that takes care of all the GstMixer stuff */
       
    50 GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaMixerElement, gst_alsa_mixer_element);
       
    51 
       
    52 static void gst_alsa_mixer_element_get_property (GObject * object,
       
    53     guint prop_id, GValue * value, GParamSpec * pspec);
       
    54 static void gst_alsa_mixer_element_set_property (GObject * object,
       
    55     guint prop_id, const GValue * value, GParamSpec * pspec);
       
    56 static void gst_alsa_mixer_element_finalize (GObject * object);
       
    57 
       
    58 static GstStateChangeReturn gst_alsa_mixer_element_change_state (GstElement
       
    59     * element, GstStateChange transition);
       
    60 
       
    61 static gboolean
       
    62 gst_alsa_mixer_element_interface_supported (GstAlsaMixerElement * this,
       
    63     GType interface_type)
       
    64 {
       
    65   if (interface_type == GST_TYPE_MIXER) {
       
    66     return gst_alsa_mixer_element_supported (this, interface_type);
       
    67   }
       
    68 
       
    69   g_return_val_if_reached (FALSE);
       
    70 }
       
    71 
       
    72 static void
       
    73 gst_implements_interface_init (GstImplementsInterfaceClass * klass)
       
    74 {
       
    75   klass->supported = (gpointer) gst_alsa_mixer_element_interface_supported;
       
    76 }
       
    77 
       
    78 static void
       
    79 gst_alsa_mixer_element_init_interfaces (GType type)
       
    80 {
       
    81   static const GInterfaceInfo implements_iface_info = {
       
    82     (GInterfaceInitFunc) gst_implements_interface_init,
       
    83     NULL,
       
    84     NULL,
       
    85   };
       
    86   static const GInterfaceInfo mixer_iface_info = {
       
    87     (GInterfaceInitFunc) gst_alsa_mixer_element_interface_init,
       
    88     NULL,
       
    89     NULL,
       
    90   };
       
    91 
       
    92   g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
       
    93       &implements_iface_info);
       
    94   g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
       
    95 
       
    96   gst_alsa_type_add_device_property_probe_interface (type);
       
    97 }
       
    98 
       
    99 static void
       
   100 gst_alsa_mixer_element_base_init (gpointer klass)
       
   101 {
       
   102   gst_element_class_set_details (GST_ELEMENT_CLASS (klass),
       
   103       &gst_alsa_mixer_element_details);
       
   104 }
       
   105 
       
   106 static void
       
   107 gst_alsa_mixer_element_class_init (GstAlsaMixerElementClass * klass)
       
   108 {
       
   109   GstElementClass *element_class;
       
   110   GObjectClass *gobject_class;
       
   111 
       
   112   element_class = (GstElementClass *) klass;
       
   113   gobject_class = (GObjectClass *) klass;
       
   114 
       
   115   gobject_class->finalize = gst_alsa_mixer_element_finalize;
       
   116   gobject_class->get_property = gst_alsa_mixer_element_get_property;
       
   117   gobject_class->set_property = gst_alsa_mixer_element_set_property;
       
   118 
       
   119   g_object_class_install_property (gobject_class, PROP_DEVICE,
       
   120       g_param_spec_string ("device", "Device",
       
   121           "ALSA device, as defined in an asound configuration file",
       
   122           DEFAULT_PROP_DEVICE, G_PARAM_READWRITE));
       
   123 
       
   124   g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
       
   125       g_param_spec_string ("device-name", "Device name",
       
   126           "Human-readable name of the sound device",
       
   127           DEFAULT_PROP_DEVICE_NAME, G_PARAM_READABLE));
       
   128 
       
   129   element_class->change_state =
       
   130       GST_DEBUG_FUNCPTR (gst_alsa_mixer_element_change_state);
       
   131 }
       
   132 
       
   133 static void
       
   134 gst_alsa_mixer_element_finalize (GObject * obj)
       
   135 {
       
   136   GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (obj);
       
   137 
       
   138   g_free (this->device);
       
   139 
       
   140   G_OBJECT_CLASS (parent_class)->finalize (obj);
       
   141 }
       
   142 
       
   143 static void
       
   144 gst_alsa_mixer_element_init (GstAlsaMixerElement * this,
       
   145     GstAlsaMixerElementClass * klass)
       
   146 {
       
   147   this->mixer = NULL;
       
   148   this->device = g_strdup (DEFAULT_PROP_DEVICE);
       
   149 }
       
   150 
       
   151 static void
       
   152 gst_alsa_mixer_element_set_property (GObject * object, guint prop_id,
       
   153     const GValue * value, GParamSpec * pspec)
       
   154 {
       
   155   GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (object);
       
   156 
       
   157   switch (prop_id) {
       
   158     case PROP_DEVICE:{
       
   159       GST_OBJECT_LOCK (this);
       
   160       g_free (this->device);
       
   161       this->device = g_value_dup_string (value);
       
   162       /* make sure we never set NULL, this is nice when we want to open the
       
   163        * device. */
       
   164       if (this->device == NULL)
       
   165         this->device = g_strdup (DEFAULT_PROP_DEVICE);
       
   166       GST_OBJECT_UNLOCK (this);
       
   167       break;
       
   168     }
       
   169     default:
       
   170       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   171       break;
       
   172   }
       
   173 }
       
   174 
       
   175 static void
       
   176 gst_alsa_mixer_element_get_property (GObject * object, guint prop_id,
       
   177     GValue * value, GParamSpec * pspec)
       
   178 {
       
   179   GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (object);
       
   180 
       
   181   switch (prop_id) {
       
   182     case PROP_DEVICE:{
       
   183       GST_OBJECT_LOCK (this);
       
   184       g_value_set_string (value, this->device);
       
   185       GST_OBJECT_UNLOCK (this);
       
   186       break;
       
   187     }
       
   188     case PROP_DEVICE_NAME:{
       
   189       GST_OBJECT_LOCK (this);
       
   190       if (this->mixer) {
       
   191         g_value_set_string (value, this->mixer->cardname);
       
   192       } else {
       
   193         g_value_set_string (value, NULL);
       
   194       }
       
   195       GST_OBJECT_UNLOCK (this);
       
   196       break;
       
   197     }
       
   198     default:
       
   199       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   200       break;
       
   201   }
       
   202 }
       
   203 
       
   204 static GstStateChangeReturn
       
   205 gst_alsa_mixer_element_change_state (GstElement * element,
       
   206     GstStateChange transition)
       
   207 {
       
   208   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
       
   209   GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (element);
       
   210 
       
   211   switch (transition) {
       
   212     case GST_STATE_CHANGE_NULL_TO_READY:
       
   213       if (!this->mixer) {
       
   214         this->mixer = gst_alsa_mixer_new (this->device, GST_ALSA_MIXER_ALL);
       
   215         if (!this->mixer)
       
   216           goto open_failed;
       
   217         _gst_alsa_mixer_set_interface (this->mixer, GST_MIXER (element));
       
   218       }
       
   219       break;
       
   220     default:
       
   221       break;
       
   222   }
       
   223 
       
   224   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
       
   225   if (ret == GST_STATE_CHANGE_FAILURE)
       
   226     return ret;
       
   227 
       
   228   switch (transition) {
       
   229     case GST_STATE_CHANGE_READY_TO_NULL:
       
   230       if (this->mixer) {
       
   231         gst_alsa_mixer_free (this->mixer);
       
   232         this->mixer = NULL;
       
   233       }
       
   234       break;
       
   235     default:
       
   236       break;
       
   237   }
       
   238 
       
   239   return ret;
       
   240 
       
   241   /* ERRORS */
       
   242 open_failed:
       
   243   {
       
   244     GST_ELEMENT_ERROR (element, RESOURCE, OPEN_READ_WRITE, (NULL),
       
   245         ("Failed to open alsa mixer device '%s'", this->device));
       
   246     return GST_STATE_CHANGE_FAILURE;
       
   247   }
       
   248 }