3ca3abb54106ec9235f52d7953f6b7334d3601a0
[platform/upstream/gst-plugins-good.git] / sys / oss / gstossmixerelement.c
1 /* OSS mixer interface element.
2  * Copyright (C) 2005 Andrew Vander Wingo <wingo@pobox.com>
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  * SECTION:element-ossmixer
22  * @short_description: element to control sound input and output levels with OSS
23  *
24  * <refsect2>
25  * <para>
26  * This element lets you adjust sound input and output levels with the
27  * Open Sound System (OSS). It supports the GstMixer interface, which can be
28  * used to obtain a list of available mixer tracks. Set the mixer element to
29  * READY state before using the GstMixer interface on it.
30  * </para>
31  * <title>Example pipelines</title>
32  * <para>
33  * ossmixer can't be used in a sensible way in gst-launch.
34  * </para>
35  * </refsect2>
36  */
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #include "gstossmixerelement.h"
43
44 GST_DEBUG_CATEGORY_EXTERN (oss_debug);
45 #define GST_CAT_DEFAULT oss_debug
46
47 #define DEFAULT_DEVICE       "/dev/mixer"
48 #define DEFAULT_DEVICE_NAME  NULL
49
50 enum
51 {
52   PROP_0,
53   PROP_DEVICE,
54   PROP_DEVICE_NAME
55 };
56
57
58 static const GstElementDetails gst_oss_mixer_element_details =
59 GST_ELEMENT_DETAILS ("OSS Mixer",
60     "Generic/Audio",
61     "Control sound input and output levels with OSS",
62     "Andrew Vander Wingo <wingo@pobox.com>");
63
64
65 GST_BOILERPLATE_WITH_INTERFACE (GstOssMixerElement, gst_oss_mixer_element,
66     GstElement, GST_TYPE_ELEMENT, GstMixer, GST_TYPE_MIXER,
67     gst_oss_mixer_element);
68
69 GST_IMPLEMENT_OSS_MIXER_METHODS (GstOssMixerElement, gst_oss_mixer_element);
70
71 static GstStateChangeReturn gst_oss_mixer_element_change_state (GstElement *
72     element, GstStateChange transition);
73
74 static void gst_oss_mixer_element_set_property (GObject * object,
75     guint prop_id, const GValue * value, GParamSpec * pspec);
76 static void gst_oss_mixer_element_get_property (GObject * object,
77     guint prop_id, GValue * value, GParamSpec * pspec);
78 static void gst_oss_mixer_element_finalize (GObject * object);
79
80 static void
81 gst_oss_mixer_element_base_init (gpointer klass)
82 {
83   gst_element_class_set_details (GST_ELEMENT_CLASS (klass),
84       &gst_oss_mixer_element_details);
85 }
86
87 static void
88 gst_oss_mixer_element_class_init (GstOssMixerElementClass * klass)
89 {
90   GstElementClass *element_class;
91   GObjectClass *gobject_class;
92
93   element_class = (GstElementClass *) klass;
94   gobject_class = (GObjectClass *) klass;
95
96   gobject_class->finalize = gst_oss_mixer_element_finalize;
97   gobject_class->set_property = gst_oss_mixer_element_set_property;
98   gobject_class->get_property = gst_oss_mixer_element_get_property;
99
100   /**
101    * GstOssMixerElement:device
102    *
103    * OSS mixer device (usually /dev/mixer)
104    *
105    * Since: 0.10.5
106    **/
107   g_object_class_install_property (gobject_class, PROP_DEVICE,
108       g_param_spec_string ("device", "Device",
109           "OSS mixer device (usually /dev/mixer)", DEFAULT_DEVICE,
110           G_PARAM_READWRITE));
111
112   g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
113       g_param_spec_string ("device-name", "Device name",
114           "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
115           G_PARAM_READABLE));
116
117   element_class->change_state =
118       GST_DEBUG_FUNCPTR (gst_oss_mixer_element_change_state);
119 }
120
121 static void
122 gst_oss_mixer_element_finalize (GObject * obj)
123 {
124   GstOssMixerElement *this = GST_OSS_MIXER_ELEMENT (obj);
125
126   g_free (this->device);
127
128   G_OBJECT_CLASS (parent_class)->finalize (obj);
129 }
130
131 static void
132 gst_oss_mixer_element_init (GstOssMixerElement * this,
133     GstOssMixerElementClass * g_class)
134 {
135   this->mixer = NULL;
136   this->device = g_strdup (DEFAULT_DEVICE);
137 }
138
139 static void
140 gst_oss_mixer_element_set_property (GObject * object, guint prop_id,
141     const GValue * value, GParamSpec * pspec)
142 {
143   GstOssMixerElement *this = GST_OSS_MIXER_ELEMENT (object);
144
145   switch (prop_id) {
146     case PROP_DEVICE:
147       g_free (this->device);
148       this->device = g_value_dup_string (value);
149       /* make sure we never set NULL */
150       if (this->device == NULL) {
151         this->device = g_strdup (DEFAULT_DEVICE);
152       }
153       break;
154     default:
155       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
156       break;
157   }
158 }
159
160 static void
161 gst_oss_mixer_element_get_property (GObject * object, guint prop_id,
162     GValue * value, GParamSpec * pspec)
163 {
164   GstOssMixerElement *this = GST_OSS_MIXER_ELEMENT (object);
165
166   switch (prop_id) {
167     case PROP_DEVICE:
168       g_value_set_string (value, this->device);
169       break;
170     case PROP_DEVICE_NAME:
171       if (this->mixer) {
172         g_value_set_string (value, this->mixer->cardname);
173       } else {
174         g_value_set_string (value, NULL);
175       }
176       break;
177     default:
178       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
179       break;
180   }
181 }
182
183 static GstStateChangeReturn
184 gst_oss_mixer_element_change_state (GstElement * element,
185     GstStateChange transition)
186 {
187   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
188   GstOssMixerElement *this = GST_OSS_MIXER_ELEMENT (element);
189
190   switch (transition) {
191     case GST_STATE_CHANGE_NULL_TO_READY:
192       if (!this->mixer) {
193         this->mixer = gst_ossmixer_new (this->device, GST_OSS_MIXER_ALL);
194         if (!this->mixer)
195           goto open_failed;
196       }
197       break;
198       break;
199     default:
200       break;
201   }
202
203   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
204   if (ret == GST_STATE_CHANGE_FAILURE)
205     return ret;
206
207   switch (transition) {
208     case GST_STATE_CHANGE_READY_TO_NULL:
209       if (this->mixer) {
210         gst_ossmixer_free (this->mixer);
211         this->mixer = NULL;
212       }
213       break;
214     default:
215       break;
216   }
217   return ret;
218
219   /* ERRORS */
220 open_failed:
221   {
222     GST_ELEMENT_ERROR (element, RESOURCE, OPEN_READ_WRITE, (NULL),
223         ("Failed to open oss mixer device '%s'", this->device));
224     return GST_STATE_CHANGE_FAILURE;
225   }
226 }