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_buffer_channel.h>
21
22 #include <ags/plugin/ags_plugin_port.h>
23
24 #include <ags/i18n.h>
25
26 void ags_buffer_channel_class_init(AgsBufferChannelClass *buffer_channel);
27 void ags_buffer_channel_mutable_interface_init(AgsMutableInterface *mutable);
28 void ags_buffer_channel_init(AgsBufferChannel *buffer_channel);
29 void ags_buffer_channel_set_property(GObject *gobject,
30 guint prop_id,
31 const GValue *value,
32 GParamSpec *param_spec);
33 void ags_buffer_channel_get_property(GObject *gobject,
34 guint prop_id,
35 GValue *value,
36 GParamSpec *param_spec);
37 void ags_buffer_channel_dispose(GObject *gobject);
38 void ags_buffer_channel_finalize(GObject *gobject);
39
40 void ags_buffer_channel_set_muted(AgsMutable *mutable, gboolean muted);
41
42 static AgsPluginPort* ags_buffer_channel_get_muted_plugin_port();
43
44 /**
45 * SECTION:ags_buffer_channel
46 * @short_description: buffers channel
47 * @title: AgsBufferChannel
48 * @section_id:
49 * @include: ags/audio/recall/ags_buffer_channel.h
50 *
51 * The #AgsBufferChannel class provides ports to the effect processor.
52 */
53
54 enum{
55 PROP_0,
56 PROP_MUTED,
57 };
58
59 static gpointer ags_buffer_channel_parent_class = NULL;
60 static AgsMutableInterface *ags_buffer_channel_parent_mutable_interface;
61
62 const gchar *ags_buffer_channel_plugin_name = "ags-buffer";
63 const gchar *ags_buffer_channel_plugin_specifier[] = {
64 "./muted[0]",
65 };
66 const gchar *ags_buffer_channel_plugin_control_port[] = {
67 "1/1",
68 };
69
70 GType
ags_buffer_channel_get_type()71 ags_buffer_channel_get_type()
72 {
73 static volatile gsize g_define_type_id__volatile = 0;
74
75 if(g_once_init_enter (&g_define_type_id__volatile)){
76 GType ags_type_buffer_channel = 0;
77
78 static const GTypeInfo ags_buffer_channel_info = {
79 sizeof (AgsBufferChannelClass),
80 NULL, /* base_init */
81 NULL, /* base_finalize */
82 (GClassInitFunc) ags_buffer_channel_class_init,
83 NULL, /* class_finalize */
84 NULL, /* class_data */
85 sizeof (AgsBufferChannel),
86 0, /* n_preallocs */
87 (GInstanceInitFunc) ags_buffer_channel_init,
88 };
89
90 static const GInterfaceInfo ags_mutable_interface_info = {
91 (GInterfaceInitFunc) ags_buffer_channel_mutable_interface_init,
92 NULL, /* interface_finalize */
93 NULL, /* interface_data */
94 };
95
96 ags_type_buffer_channel = g_type_register_static(AGS_TYPE_RECALL_CHANNEL,
97 "AgsBufferChannel",
98 &ags_buffer_channel_info,
99 0);
100
101 g_type_add_interface_static(ags_type_buffer_channel,
102 AGS_TYPE_MUTABLE,
103 &ags_mutable_interface_info);
104
105 g_once_init_leave(&g_define_type_id__volatile, ags_type_buffer_channel);
106 }
107
108 return g_define_type_id__volatile;
109 }
110
111 void
ags_buffer_channel_mutable_interface_init(AgsMutableInterface * mutable)112 ags_buffer_channel_mutable_interface_init(AgsMutableInterface *mutable)
113 {
114 ags_buffer_channel_parent_mutable_interface = g_type_interface_peek_parent(mutable);
115
116 mutable->set_muted = ags_buffer_channel_set_muted;
117 }
118
119 void
ags_buffer_channel_class_init(AgsBufferChannelClass * buffer_channel)120 ags_buffer_channel_class_init(AgsBufferChannelClass *buffer_channel)
121 {
122 GObjectClass *gobject;
123 AgsRecallClass *recall;
124 GParamSpec *param_spec;
125
126 ags_buffer_channel_parent_class = g_type_class_peek_parent(buffer_channel);
127
128 /* GObjectClass */
129 gobject = (GObjectClass *) buffer_channel;
130
131 gobject->set_property = ags_buffer_channel_set_property;
132 gobject->get_property = ags_buffer_channel_get_property;
133
134 gobject->dispose = ags_buffer_channel_dispose;
135 gobject->finalize = ags_buffer_channel_finalize;
136
137 /* properties */
138 /**
139 * AgsBufferChannel:muted:
140 *
141 * The mute port.
142 *
143 * Since: 3.0.0
144 */
145 param_spec = g_param_spec_object("muted",
146 i18n_pspec("mute channel"),
147 i18n_pspec("Mute the channel"),
148 AGS_TYPE_PORT,
149 G_PARAM_READABLE | G_PARAM_WRITABLE);
150 g_object_class_install_property(gobject,
151 PROP_MUTED,
152 param_spec);
153 }
154
155 void
ags_buffer_channel_init(AgsBufferChannel * buffer_channel)156 ags_buffer_channel_init(AgsBufferChannel *buffer_channel)
157 {
158 GList *port;
159
160 AGS_RECALL(buffer_channel)->name = "ags-buffer";
161 AGS_RECALL(buffer_channel)->version = AGS_RECALL_DEFAULT_VERSION;
162 AGS_RECALL(buffer_channel)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
163 AGS_RECALL(buffer_channel)->xml_type = "ags-buffer-channel";
164
165 port = NULL;
166
167 buffer_channel->muted = g_object_new(AGS_TYPE_PORT,
168 "plugin-name", ags_buffer_channel_plugin_name,
169 "specifier", ags_buffer_channel_plugin_specifier[0],
170 "control-port", ags_buffer_channel_plugin_control_port[0],
171 "port-value-is-pointer", FALSE,
172 "port-value-type", G_TYPE_FLOAT,
173 "port-value-size", sizeof(gfloat),
174 "port-value-length", 1,
175 NULL);
176 g_object_ref(buffer_channel->muted);
177 buffer_channel->muted->port_value.ags_port_float = (float) FALSE;
178
179 /* plugin port */
180 g_object_set(buffer_channel->muted,
181 "plugin-port", ags_buffer_channel_get_muted_plugin_port(),
182 NULL);
183
184 /* add to port */
185 port = g_list_prepend(port, buffer_channel->muted);
186 g_object_ref(buffer_channel->muted);
187
188 /* set port */
189 AGS_RECALL(buffer_channel)->port = port;
190
191 }
192
193
194 void
ags_buffer_channel_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)195 ags_buffer_channel_set_property(GObject *gobject,
196 guint prop_id,
197 const GValue *value,
198 GParamSpec *param_spec)
199 {
200 AgsBufferChannel *buffer_channel;
201
202 GRecMutex *recall_mutex;
203
204 buffer_channel = AGS_BUFFER_CHANNEL(gobject);
205
206 /* get recall mutex */
207 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(buffer_channel);
208
209 switch(prop_id){
210 case PROP_MUTED:
211 {
212 AgsPort *port;
213
214 port = (AgsPort *) g_value_get_object(value);
215
216 g_rec_mutex_lock(recall_mutex);
217
218 if(port == buffer_channel->muted){
219 g_rec_mutex_unlock(recall_mutex);
220
221 return;
222 }
223
224 if(buffer_channel->muted != NULL){
225 g_object_unref(G_OBJECT(buffer_channel->muted));
226 }
227
228 if(port != NULL){
229 g_object_ref(G_OBJECT(port));
230 }
231
232 buffer_channel->muted = port;
233
234 g_rec_mutex_unlock(recall_mutex);
235 }
236 break;
237 default:
238 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
239 break;
240 }
241 }
242
243 void
ags_buffer_channel_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)244 ags_buffer_channel_get_property(GObject *gobject,
245 guint prop_id,
246 GValue *value,
247 GParamSpec *param_spec)
248 {
249 AgsBufferChannel *buffer_channel;
250
251 GRecMutex *recall_mutex;
252
253 buffer_channel = AGS_BUFFER_CHANNEL(gobject);
254
255 /* get recall mutex */
256 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(buffer_channel);
257
258 switch(prop_id){
259 case PROP_MUTED:
260 {
261 g_rec_mutex_lock(recall_mutex);
262
263 g_value_set_object(value, buffer_channel->muted);
264
265 g_rec_mutex_unlock(recall_mutex);
266 }
267 break;
268 default:
269 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
270 break;
271 }
272 }
273
274 void
ags_buffer_channel_dispose(GObject * gobject)275 ags_buffer_channel_dispose(GObject *gobject)
276 {
277 AgsBufferChannel *buffer_channel;
278
279 buffer_channel = AGS_BUFFER_CHANNEL(gobject);
280
281 if(buffer_channel->muted != NULL){
282 g_object_unref(G_OBJECT(buffer_channel->muted));
283
284 buffer_channel->muted = NULL;
285 }
286
287 /* call parent */
288 G_OBJECT_CLASS(ags_buffer_channel_parent_class)->dispose(gobject);
289 }
290
291 void
ags_buffer_channel_finalize(GObject * gobject)292 ags_buffer_channel_finalize(GObject *gobject)
293 {
294 AgsBufferChannel *buffer_channel;
295
296 buffer_channel = AGS_BUFFER_CHANNEL(gobject);
297
298 if(buffer_channel->muted != NULL){
299 g_object_unref(G_OBJECT(buffer_channel->muted));
300 }
301
302 /* call parent */
303 G_OBJECT_CLASS(ags_buffer_channel_parent_class)->finalize(gobject);
304 }
305
306 void
ags_buffer_channel_set_muted(AgsMutable * mutable,gboolean is_muted)307 ags_buffer_channel_set_muted(AgsMutable *mutable, gboolean is_muted)
308 {
309 AgsPort *muted;
310
311 GValue value = {0,};
312
313 g_object_get(G_OBJECT(mutable),
314 "muted", &muted,
315 NULL);
316
317 g_value_init(&value, G_TYPE_FLOAT);
318 g_value_set_float(&value, (float) is_muted);
319
320 ags_port_safe_write(muted, &value);
321
322 g_value_unset(&value);
323 g_object_unref(muted);
324 }
325
326 static AgsPluginPort*
ags_buffer_channel_get_muted_plugin_port()327 ags_buffer_channel_get_muted_plugin_port()
328 {
329 static AgsPluginPort *plugin_port = NULL;
330
331 static GMutex mutex;
332
333 g_mutex_lock(&mutex);
334
335 if(plugin_port == NULL){
336 plugin_port = ags_plugin_port_new();
337 g_object_ref(plugin_port);
338
339 plugin_port->flags |= (AGS_PLUGIN_PORT_INPUT |
340 AGS_PLUGIN_PORT_CONTROL |
341 AGS_PLUGIN_PORT_TOGGLED);
342
343 plugin_port->port_index = 0;
344
345 /* range */
346 g_value_init(plugin_port->default_value,
347 G_TYPE_FLOAT);
348 g_value_init(plugin_port->lower_value,
349 G_TYPE_FLOAT);
350 g_value_init(plugin_port->upper_value,
351 G_TYPE_FLOAT);
352
353 g_value_set_float(plugin_port->default_value,
354 0.0);
355 g_value_set_float(plugin_port->lower_value,
356 0.0);
357 g_value_set_float(plugin_port->upper_value,
358 1.0);
359 }
360
361 g_mutex_unlock(&mutex);
362
363 return(plugin_port);
364 }
365
366 /**
367 * ags_buffer_channel_new:
368 * @destination: the destination #AgsChannel
369 * @source: the source #AgsChannel
370 *
371 * Create a new instance of #AgsBufferChannel
372 *
373 * Returns: the new #AgsBufferChannel
374 *
375 * Since: 3.0.0
376 */
377 AgsBufferChannel*
ags_buffer_channel_new(AgsChannel * destination,AgsChannel * source)378 ags_buffer_channel_new(AgsChannel *destination,
379 AgsChannel *source)
380 {
381 AgsBufferChannel *buffer_channel;
382
383 buffer_channel = (AgsBufferChannel *) g_object_new(AGS_TYPE_BUFFER_CHANNEL,
384 "destination", destination,
385 "source", source,
386 NULL);
387
388 return(buffer_channel);
389 }
390