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