• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer Mixer
2  * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
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., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 /**
21  * SECTION:gststreamvolume
22  * @title: GstStreamVolume
23  * @short_description: Interface for elements that provide a stream volume
24  *
25  * This interface is implemented by elements that provide a stream volume. Examples for
26  * such elements are #volume and #playbin.
27  *
28  * Applications can use this interface to get or set the current stream volume. For this
29  * the "volume" #GObject property can be used or the helper functions gst_stream_volume_set_volume()
30  * and gst_stream_volume_get_volume(). This volume is always a linear factor, i.e. 0.0 is muted
31  * 1.0 is 100%. For showing the volume in a GUI it might make sense to convert it to
32  * a different format by using gst_stream_volume_convert_volume(). Volume sliders should usually
33  * use a cubic volume.
34  *
35  * Separate from the volume the stream can also be muted by the "mute" #GObject property or
36  * gst_stream_volume_set_mute() and gst_stream_volume_get_mute().
37  *
38  * Elements that provide some kind of stream volume should implement the "volume" and
39  * "mute" #GObject properties and handle setting and getting of them properly.
40  * The volume property is defined to be a linear volume factor.
41  *
42  */
43 
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47 
48 #include "streamvolume.h"
49 #include <math.h>
50 
51 static void
gst_stream_volume_class_init(GstStreamVolumeInterface * iface)52 gst_stream_volume_class_init (GstStreamVolumeInterface * iface)
53 {
54   g_object_interface_install_property (iface,
55       g_param_spec_double ("volume",
56           "Volume",
57           "Linear volume factor, 1.0=100%",
58           0.0, G_MAXDOUBLE, 1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
59   g_object_interface_install_property (iface,
60       g_param_spec_boolean ("mute",
61           "Mute",
62           "Mute the audio channel without changing the volume",
63           FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
64 }
65 
66 GType
gst_stream_volume_get_type(void)67 gst_stream_volume_get_type (void)
68 {
69   static gsize type = 0;
70   if (g_once_init_enter (&type)) {
71     GType tmp;
72     static const GTypeInfo info = {
73       sizeof (GstStreamVolumeInterface),
74       NULL,                     /* base_init */
75       NULL,                     /* base_finalize */
76       (GClassInitFunc) gst_stream_volume_class_init,    /* class_init */
77       NULL,                     /* class_finalize */
78       NULL,                     /* class_data */
79       0,
80       0,                        /* n_preallocs */
81       NULL                      /* instance_init */
82     };
83     tmp = g_type_register_static (G_TYPE_INTERFACE,
84         "GstStreamVolume", &info, 0);
85     g_type_interface_add_prerequisite (tmp, G_TYPE_OBJECT);
86 
87     g_once_init_leave (&type, tmp);
88   }
89   return type;
90 }
91 
92 /**
93  * gst_stream_volume_get_volume:
94  * @volume: #GstStreamVolume that should be used
95  * @format: #GstStreamVolumeFormat which should be returned
96  *
97  * Returns: The current stream volume as linear factor
98  */
99 gdouble
gst_stream_volume_get_volume(GstStreamVolume * volume,GstStreamVolumeFormat format)100 gst_stream_volume_get_volume (GstStreamVolume * volume,
101     GstStreamVolumeFormat format)
102 {
103   gdouble val;
104 
105   g_return_val_if_fail (GST_IS_STREAM_VOLUME (volume), 1.0);
106 
107   g_object_get (volume, "volume", &val, NULL);
108   if (format != GST_STREAM_VOLUME_FORMAT_LINEAR)
109     val =
110         gst_stream_volume_convert_volume (GST_STREAM_VOLUME_FORMAT_LINEAR,
111         format, val);
112   return val;
113 }
114 
115 /**
116  * gst_stream_volume_set_volume:
117  * @volume: #GstStreamVolume that should be used
118  * @format: #GstStreamVolumeFormat of @val
119  * @val: Linear volume factor that should be set
120  */
121 void
gst_stream_volume_set_volume(GstStreamVolume * volume,GstStreamVolumeFormat format,gdouble val)122 gst_stream_volume_set_volume (GstStreamVolume * volume,
123     GstStreamVolumeFormat format, gdouble val)
124 {
125   g_return_if_fail (GST_IS_STREAM_VOLUME (volume));
126 
127   if (format != GST_STREAM_VOLUME_FORMAT_LINEAR)
128     val =
129         gst_stream_volume_convert_volume (format,
130         GST_STREAM_VOLUME_FORMAT_LINEAR, val);
131   g_object_set (volume, "volume", val, NULL);
132 }
133 
134 /**
135  * gst_stream_volume_get_mute:
136  * @volume: #GstStreamVolume that should be used
137  *
138  * Returns: Returns %TRUE if the stream is muted
139  */
140 gboolean
gst_stream_volume_get_mute(GstStreamVolume * volume)141 gst_stream_volume_get_mute (GstStreamVolume * volume)
142 {
143   gboolean val;
144 
145   g_return_val_if_fail (GST_IS_STREAM_VOLUME (volume), FALSE);
146 
147   g_object_get (volume, "mute", &val, NULL);
148   return val;
149 }
150 
151 /**
152  * gst_stream_volume_set_mute:
153  * @volume: #GstStreamVolume that should be used
154  * @mute: Mute state that should be set
155  */
156 void
gst_stream_volume_set_mute(GstStreamVolume * volume,gboolean mute)157 gst_stream_volume_set_mute (GstStreamVolume * volume, gboolean mute)
158 {
159   g_return_if_fail (GST_IS_STREAM_VOLUME (volume));
160 
161   g_object_set (volume, "mute", mute, NULL);
162 }
163 
164 /**
165  * gst_stream_volume_convert_volume:
166  * @from: #GstStreamVolumeFormat to convert from
167  * @to: #GstStreamVolumeFormat to convert to
168  * @val: Volume in @from format that should be converted
169  *
170  * Returns: the converted volume
171  */
172 gdouble
gst_stream_volume_convert_volume(GstStreamVolumeFormat from,GstStreamVolumeFormat to,gdouble val)173 gst_stream_volume_convert_volume (GstStreamVolumeFormat from,
174     GstStreamVolumeFormat to, gdouble val)
175 {
176   switch (from) {
177     case GST_STREAM_VOLUME_FORMAT_LINEAR:
178       g_return_val_if_fail (val >= 0.0, 0.0);
179       switch (to) {
180         case GST_STREAM_VOLUME_FORMAT_LINEAR:
181           return val;
182         case GST_STREAM_VOLUME_FORMAT_CUBIC:
183           return pow (val, 1 / 3.0);
184         case GST_STREAM_VOLUME_FORMAT_DB:
185           return 20.0 * log10 (val);
186       }
187       break;
188     case GST_STREAM_VOLUME_FORMAT_CUBIC:
189       g_return_val_if_fail (val >= 0.0, 0.0);
190       switch (to) {
191         case GST_STREAM_VOLUME_FORMAT_LINEAR:
192           return val * val * val;
193         case GST_STREAM_VOLUME_FORMAT_CUBIC:
194           return val;
195         case GST_STREAM_VOLUME_FORMAT_DB:
196           return 3.0 * 20.0 * log10 (val);
197       }
198       break;
199     case GST_STREAM_VOLUME_FORMAT_DB:
200       switch (to) {
201         case GST_STREAM_VOLUME_FORMAT_LINEAR:
202           return pow (10.0, val / 20.0);
203         case GST_STREAM_VOLUME_FORMAT_CUBIC:
204           return pow (10.0, val / (3.0 * 20.0));
205         case GST_STREAM_VOLUME_FORMAT_DB:
206           return val;
207       }
208       break;
209   }
210   g_return_val_if_reached (0.0);
211 }
212