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_play_audio.h>
21 
22 #include <ags/plugin/ags_plugin_port.h>
23 
24 #include <ags/i18n.h>
25 
26 void ags_play_audio_class_init(AgsPlayAudioClass *play_audio);
27 void ags_play_audio_mutable_interface_init(AgsMutableInterface *mutable);
28 void ags_play_audio_init(AgsPlayAudio *play_audio);
29 void ags_play_audio_set_property(GObject *gobject,
30 				 guint prop_id,
31 				 const GValue *value,
32 				 GParamSpec *param_spec);
33 void ags_play_audio_get_property(GObject *gobject,
34 				 guint prop_id,
35 				 GValue *value,
36 				 GParamSpec *param_spec);
37 void ags_play_audio_dispose(GObject *gobject);
38 void ags_play_audio_finalize(GObject *gobject);
39 
40 void ags_play_audio_set_muted(AgsMutable *mutable, gboolean muted);
41 
42 static AgsPluginPort* ags_play_audio_get_muted_plugin_port();
43 
44 /**
45  * SECTION:ags_play_audio
46  * @short_description: play audio
47  * @title: AgsPlayAudio
48  * @section_id:
49  * @include: ags/audio/recall/ags_play_audio.h
50  *
51  * The #AgsPlayAudio class provides ports to the effect processor.
52  */
53 
54 enum{
55   PROP_0,
56   PROP_MUTED,
57 };
58 
59 static gpointer ags_play_audio_parent_class = NULL;
60 
61 const gchar *ags_play_audio_plugin_name = "ags-play";
62 const gchar *ags_play_audio_specifier[] = {
63   "./muted[0]",
64 };
65 const gchar *ags_play_audio_control_port[] = {
66   "1/1",
67 };
68 
69 GType
ags_play_audio_get_type()70 ags_play_audio_get_type()
71 {
72   static volatile gsize g_define_type_id__volatile = 0;
73 
74   if(g_once_init_enter (&g_define_type_id__volatile)){
75     GType ags_type_play_audio = 0;
76 
77     static const GTypeInfo ags_play_audio_info = {
78       sizeof (AgsPlayAudioClass),
79       NULL, /* base_init */
80       NULL, /* base_finalize */
81       (GClassInitFunc) ags_play_audio_class_init,
82       NULL, /* class_finalize */
83       NULL, /* class_audio */
84       sizeof (AgsPlayAudio),
85       0,    /* n_preallocs */
86       (GInstanceInitFunc) ags_play_audio_init,
87     };
88 
89     static const GInterfaceInfo ags_mutable_interface_info = {
90       (GInterfaceInitFunc) ags_play_audio_mutable_interface_init,
91       NULL, /* interface_finalize */
92       NULL, /* interface_data */
93     };
94 
95     ags_type_play_audio = g_type_register_static(AGS_TYPE_RECALL_AUDIO,
96 						 "AgsPlayAudio",
97 						 &ags_play_audio_info,
98 						 0);
99 
100     g_type_add_interface_static(ags_type_play_audio,
101 				AGS_TYPE_MUTABLE,
102 				&ags_mutable_interface_info);
103 
104     g_once_init_leave(&g_define_type_id__volatile, ags_type_play_audio);
105   }
106 
107   return g_define_type_id__volatile;
108 }
109 
110 void
ags_play_audio_mutable_interface_init(AgsMutableInterface * mutable)111 ags_play_audio_mutable_interface_init(AgsMutableInterface *mutable)
112 {
113   mutable->set_muted = ags_play_audio_set_muted;
114 }
115 
116 void
ags_play_audio_class_init(AgsPlayAudioClass * play_audio)117 ags_play_audio_class_init(AgsPlayAudioClass *play_audio)
118 {
119   GObjectClass *gobject;
120 
121   GParamSpec *param_spec;
122 
123   ags_play_audio_parent_class = g_type_class_peek_parent(play_audio);
124 
125   /* GObjectClass */
126   gobject = (GObjectClass *) play_audio;
127 
128   gobject->set_property = ags_play_audio_set_property;
129   gobject->get_property = ags_play_audio_get_property;
130 
131   gobject->dispose = ags_play_audio_dispose;
132   gobject->finalize = ags_play_audio_finalize;
133 
134   /* properties */
135   /**
136    * AgsPlayAudio: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 audio"),
144 				   i18n_pspec("Mute the audio"),
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_play_audio_init(AgsPlayAudio * play_audio)153 ags_play_audio_init(AgsPlayAudio *play_audio)
154 {
155   GList *port;
156 
157   AGS_RECALL(play_audio)->name = "ags-play";
158   AGS_RECALL(play_audio)->version = AGS_RECALL_DEFAULT_VERSION;
159   AGS_RECALL(play_audio)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
160   AGS_RECALL(play_audio)->xml_type = "ags-play-audio";
161 
162   port = NULL;
163 
164   /* muted */
165   play_audio->muted = g_object_new(AGS_TYPE_PORT,
166 				   "plugin-name", ags_play_audio_plugin_name,
167 				   "specifier", ags_play_audio_specifier[0],
168 				   "control-port", ags_play_audio_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(play_audio->muted);
175 
176   play_audio->muted->port_value.ags_port_float = (float) 0.0;
177 
178   /* plugin port */
179   g_object_set(play_audio->muted,
180 	       "plugin-port", ags_play_audio_get_muted_plugin_port(),
181 	       NULL);
182 
183   /* add to port */
184   port = g_list_prepend(port, play_audio->muted);
185   g_object_ref(play_audio->muted);
186 
187   /* set port */
188   AGS_RECALL(play_audio)->port = port;
189 }
190 
191 void
ags_play_audio_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)192 ags_play_audio_set_property(GObject *gobject,
193 			      guint prop_id,
194 			      const GValue *value,
195 			      GParamSpec *param_spec)
196 {
197   AgsPlayAudio *play_audio;
198 
199   GRecMutex *recall_mutex;
200 
201   play_audio = AGS_PLAY_AUDIO(gobject);
202 
203   /* get recall mutex */
204   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_audio);
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 == play_audio->muted){
216 	g_rec_mutex_unlock(recall_mutex);
217 
218 	return;
219       }
220 
221       if(play_audio->muted != NULL){
222 	g_object_unref(G_OBJECT(play_audio->muted));
223       }
224 
225       if(port != NULL){
226 	g_object_ref(G_OBJECT(port));
227       }
228 
229       play_audio->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_play_audio_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)241 ags_play_audio_get_property(GObject *gobject,
242 			      guint prop_id,
243 			      GValue *value,
244 			      GParamSpec *param_spec)
245 {
246   AgsPlayAudio *play_audio;
247 
248   GRecMutex *recall_mutex;
249 
250   play_audio = AGS_PLAY_AUDIO(gobject);
251 
252   /* get recall mutex */
253   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_audio);
254 
255   switch(prop_id){
256   case PROP_MUTED:
257     {
258       g_rec_mutex_lock(recall_mutex);
259 
260       g_value_set_object(value, play_audio->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_play_audio_dispose(GObject * gobject)272 ags_play_audio_dispose(GObject *gobject)
273 {
274   AgsPlayAudio *play_audio;
275 
276   play_audio = AGS_PLAY_AUDIO(gobject);
277 
278   /* muted */
279   if(play_audio->muted != NULL){
280     g_object_unref(G_OBJECT(play_audio->muted));
281 
282     play_audio->muted = NULL;
283   }
284 
285   /* call parent */
286   G_OBJECT_CLASS(ags_play_audio_parent_class)->dispose(gobject);
287 }
288 
289 void
ags_play_audio_finalize(GObject * gobject)290 ags_play_audio_finalize(GObject *gobject)
291 {
292   AgsPlayAudio *play_audio;
293 
294   play_audio = AGS_PLAY_AUDIO(gobject);
295 
296   /* muted */
297   if(play_audio->muted != NULL){
298     g_object_unref(G_OBJECT(play_audio->muted));
299   }
300 
301   /* call parent */
302   G_OBJECT_CLASS(ags_play_audio_parent_class)->finalize(gobject);
303 }
304 
305 void
ags_play_audio_set_muted(AgsMutable * mutable,gboolean muted)306 ags_play_audio_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 
327   g_object_unref(port);
328 }
329 
330 static AgsPluginPort*
ags_play_audio_get_muted_plugin_port()331 ags_play_audio_get_muted_plugin_port()
332 {
333   static AgsPluginPort *plugin_port = NULL;
334 
335   static GMutex mutex;
336 
337   g_mutex_lock(&mutex);
338 
339   if(plugin_port == NULL){
340     plugin_port = ags_plugin_port_new();
341     g_object_ref(plugin_port);
342 
343     plugin_port->flags |= (AGS_PLUGIN_PORT_INPUT |
344 			   AGS_PLUGIN_PORT_CONTROL |
345 			   AGS_PLUGIN_PORT_TOGGLED);
346 
347     plugin_port->port_index = 0;
348 
349     /* range */
350     g_value_init(plugin_port->default_value,
351 		 G_TYPE_FLOAT);
352     g_value_init(plugin_port->lower_value,
353 		 G_TYPE_FLOAT);
354     g_value_init(plugin_port->upper_value,
355 		 G_TYPE_FLOAT);
356 
357     g_value_set_float(plugin_port->default_value,
358 		      0.0);
359     g_value_set_float(plugin_port->lower_value,
360 		      0.0);
361     g_value_set_float(plugin_port->upper_value,
362 		      1.0);
363   }
364 
365   g_mutex_unlock(&mutex);
366 
367   return(plugin_port);
368 }
369 
370 /**
371  * ags_play_audio_new:
372  * @audio: the #AgsAudio
373  *
374  * Creates an #AgsPlayAudio
375  *
376  * Returns: a new #AgsPlayAudio
377  *
378  * Since: 3.0.0
379  */
380 AgsPlayAudio*
ags_play_audio_new(AgsAudio * audio)381 ags_play_audio_new(AgsAudio *audio)
382 {
383   AgsPlayAudio *play_audio;
384 
385   play_audio = (AgsPlayAudio *) g_object_new(AGS_TYPE_PLAY_AUDIO,
386 					     "audio", audio,
387 					     NULL);
388 
389   return(play_audio);
390 }
391