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