1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2019 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GSequencer 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ags/audio/recall/ags_volume_channel.h>
21
22 #include <ags/plugin/ags_plugin_port.h>
23
24 #include <ags/i18n.h>
25
26 void ags_volume_channel_class_init(AgsVolumeChannelClass *volume_channel);
27 void ags_volume_channel_init(AgsVolumeChannel *volume_channel);
28 void ags_volume_channel_set_property(GObject *gobject,
29 guint prop_id,
30 const GValue *value,
31 GParamSpec *param_spec);
32 void ags_volume_channel_get_property(GObject *gobject,
33 guint prop_id,
34 GValue *value,
35 GParamSpec *param_spec);
36 void ags_volume_channel_dispose(GObject *gobject);
37 void ags_volume_channel_finalize(GObject *gobject);
38
39 static AgsPluginPort* ags_volume_channel_get_volume_plugin_port();
40
41 /**
42 * SECTION:ags_volume_channel
43 * @short_description: volumes channel
44 * @title: AgsVolumeChannel
45 * @section_id:
46 * @include: ags/audio/recall/ags_volume_channel.h
47 *
48 * The #AgsVolumeChannel class provides ports to the effect processor.
49 */
50
51 enum{
52 PROP_0,
53 PROP_VOLUME,
54 };
55
56 static gpointer ags_volume_channel_parent_class = NULL;
57
58 const gchar *ags_volume_channel_plugin_name = "ags-volume";
59 const gchar *ags_volume_channel_specifier[] = {
60 "./volume[0]"
61 };
62 const gchar *ags_volume_channel_control_port[] = {
63 "1/1"
64 };
65
66 GType
ags_volume_channel_get_type()67 ags_volume_channel_get_type()
68 {
69 static volatile gsize g_define_type_id__volatile = 0;
70
71 if(g_once_init_enter (&g_define_type_id__volatile)){
72 GType ags_type_volume_channel = 0;
73
74 static const GTypeInfo ags_volume_channel_info = {
75 sizeof (AgsVolumeChannelClass),
76 NULL, /* base_init */
77 NULL, /* base_finalize */
78 (GClassInitFunc) ags_volume_channel_class_init,
79 NULL, /* class_finalize */
80 NULL, /* class_data */
81 sizeof (AgsVolumeChannel),
82 0, /* n_preallocs */
83 (GInstanceInitFunc) ags_volume_channel_init,
84 };
85
86 ags_type_volume_channel = g_type_register_static(AGS_TYPE_RECALL_CHANNEL,
87 "AgsVolumeChannel",
88 &ags_volume_channel_info,
89 0);
90
91 g_once_init_leave(&g_define_type_id__volatile, ags_type_volume_channel);
92 }
93
94 return g_define_type_id__volatile;
95 }
96
97 void
ags_volume_channel_class_init(AgsVolumeChannelClass * volume_channel)98 ags_volume_channel_class_init(AgsVolumeChannelClass *volume_channel)
99 {
100 GObjectClass *gobject;
101 AgsRecallClass *recall;
102 GParamSpec *param_spec;
103
104 ags_volume_channel_parent_class = g_type_class_peek_parent(volume_channel);
105
106 /* GObjectClass */
107 gobject = (GObjectClass *) volume_channel;
108
109 gobject->set_property = ags_volume_channel_set_property;
110 gobject->get_property = ags_volume_channel_get_property;
111
112 gobject->dispose = ags_volume_channel_dispose;
113 gobject->finalize = ags_volume_channel_finalize;
114
115 /* properties */
116 /**
117 * AgsVolumeChannel:volume:
118 *
119 * The volume port.
120 *
121 * Since: 3.0.0
122 */
123 param_spec = g_param_spec_object("volume",
124 i18n_pspec("volume to apply"),
125 i18n_pspec("The volume to apply on the channel"),
126 AGS_TYPE_PORT,
127 G_PARAM_READABLE | G_PARAM_WRITABLE);
128 g_object_class_install_property(gobject,
129 PROP_VOLUME,
130 param_spec);
131 }
132
133 void
ags_volume_channel_init(AgsVolumeChannel * volume_channel)134 ags_volume_channel_init(AgsVolumeChannel *volume_channel)
135 {
136 GList *port;
137
138 AGS_RECALL(volume_channel)->name = "ags-volume";
139 AGS_RECALL(volume_channel)->version = AGS_RECALL_DEFAULT_VERSION;
140 AGS_RECALL(volume_channel)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
141 AGS_RECALL(volume_channel)->xml_type = "ags-volume-channel";
142
143 /* initialize the port */
144 port = NULL;
145
146 /* volume */
147 volume_channel->volume = g_object_new(AGS_TYPE_PORT,
148 "plugin-name", "ags-volume",
149 "specifier", "./volume[0]",
150 "control-port", "1/1",
151 "port-value-is-pointer", FALSE,
152 "port-value-type", G_TYPE_FLOAT,
153 "port-value-size", sizeof(gfloat),
154 "port-value-length", 1,
155 NULL);
156 g_object_ref(volume_channel->volume);
157
158 volume_channel->volume->port_value.ags_port_float = 1.0;
159
160 /* port descriptor */
161 g_object_set(volume_channel->volume,
162 "plugin-port", ags_volume_channel_get_volume_plugin_port(),
163 NULL);
164
165 /* add to port */
166 port = g_list_prepend(port, volume_channel->volume);
167 g_object_ref(volume_channel->volume);
168
169 /* set port */
170 AGS_RECALL(volume_channel)->port = port;
171 }
172
173 void
ags_volume_channel_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)174 ags_volume_channel_set_property(GObject *gobject,
175 guint prop_id,
176 const GValue *value,
177 GParamSpec *param_spec)
178 {
179 AgsVolumeChannel *volume_channel;
180
181 GRecMutex *recall_mutex;
182
183 volume_channel = AGS_VOLUME_CHANNEL(gobject);
184
185 /* get recall mutex */
186 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(volume_channel);
187
188 switch(prop_id){
189 case PROP_VOLUME:
190 {
191 AgsPort *port;
192
193 port = (AgsPort *) g_value_get_object(value);
194
195 g_rec_mutex_lock(recall_mutex);
196
197 if(port == volume_channel->volume){
198 g_rec_mutex_unlock(recall_mutex);
199
200 return;
201 }
202
203 if(volume_channel->volume != NULL){
204 g_object_unref(G_OBJECT(volume_channel->volume));
205 }
206
207 if(port != NULL){
208 g_object_ref(G_OBJECT(port));
209 }
210
211 volume_channel->volume = port;
212
213 g_rec_mutex_unlock(recall_mutex);
214 }
215 break;
216 default:
217 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
218 break;
219 }
220 }
221
222 void
ags_volume_channel_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)223 ags_volume_channel_get_property(GObject *gobject,
224 guint prop_id,
225 GValue *value,
226 GParamSpec *param_spec)
227 {
228 AgsVolumeChannel *volume_channel;
229
230 GRecMutex *recall_mutex;
231
232 volume_channel = AGS_VOLUME_CHANNEL(gobject);
233
234 /* get recall mutex */
235 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(volume_channel);
236
237 switch(prop_id){
238 case PROP_VOLUME:
239 {
240 g_rec_mutex_lock(recall_mutex);
241
242 g_value_set_object(value, volume_channel->volume);
243
244 g_rec_mutex_unlock(recall_mutex);
245 }
246 break;
247 default:
248 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
249 break;
250 }
251 }
252
253 void
ags_volume_channel_dispose(GObject * gobject)254 ags_volume_channel_dispose(GObject *gobject)
255 {
256 AgsVolumeChannel *volume_channel;
257
258 volume_channel = AGS_VOLUME_CHANNEL(gobject);
259
260 /* volume */
261 if(volume_channel->volume != NULL){
262 g_object_unref(G_OBJECT(volume_channel->volume));
263 }
264
265 /* call parent */
266 G_OBJECT_CLASS(ags_volume_channel_parent_class)->dispose(gobject);
267 }
268
269 void
ags_volume_channel_finalize(GObject * gobject)270 ags_volume_channel_finalize(GObject *gobject)
271 {
272 AgsVolumeChannel *volume_channel;
273
274 volume_channel = AGS_VOLUME_CHANNEL(gobject);
275
276 /* volume */
277 if(volume_channel->volume != NULL){
278 g_object_unref(G_OBJECT(volume_channel->volume));
279 }
280
281 /* call parent */
282 G_OBJECT_CLASS(ags_volume_channel_parent_class)->finalize(gobject);
283 }
284
285 static AgsPluginPort*
ags_volume_channel_get_volume_plugin_port()286 ags_volume_channel_get_volume_plugin_port()
287 {
288 static AgsPluginPort *plugin_port = NULL;
289
290 static GMutex mutex;
291
292 g_mutex_lock(&mutex);
293
294 if(plugin_port == NULL){
295 plugin_port = ags_plugin_port_new();
296 g_object_ref(plugin_port);
297
298 plugin_port->flags |= (AGS_PLUGIN_PORT_INPUT |
299 AGS_PLUGIN_PORT_CONTROL);
300
301 plugin_port->port_index = 0;
302
303 /* range */
304 g_value_init(plugin_port->default_value,
305 G_TYPE_FLOAT);
306 g_value_init(plugin_port->lower_value,
307 G_TYPE_FLOAT);
308 g_value_init(plugin_port->upper_value,
309 G_TYPE_FLOAT);
310
311 g_value_set_float(plugin_port->default_value,
312 1.0);
313 g_value_set_float(plugin_port->lower_value,
314 0.0);
315 g_value_set_float(plugin_port->upper_value,
316 2.0);
317 }
318
319 g_mutex_unlock(&mutex);
320
321 return(plugin_port);
322 }
323
324 /**
325 * ags_volume_channel_new:
326 * @source: the #AgsAudioSignal
327 *
328 * Create a new instance of #AgsVolumeChannel
329 *
330 * Returns: the new #AgsVolumeChannel
331 *
332 * Since: 3.0.0
333 */
334 AgsVolumeChannel*
ags_volume_channel_new(AgsChannel * source)335 ags_volume_channel_new(AgsChannel *source)
336 {
337 AgsVolumeChannel *volume_channel;
338
339 volume_channel = (AgsVolumeChannel *) g_object_new(AGS_TYPE_VOLUME_CHANNEL,
340 "source", source,
341 NULL);
342
343 return(volume_channel);
344 }
345