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_wave_channel.h>
21 
22 #include <ags/i18n.h>
23 
24 void ags_play_wave_channel_class_init(AgsPlayWaveChannelClass *play_wave_channel);
25 void ags_play_wave_channel_init(AgsPlayWaveChannel *play_wave_channel);
26 void ags_play_wave_channel_set_property(GObject *gobject,
27 					guint prop_id,
28 					const GValue *value,
29 					GParamSpec *param_spec);
30 void ags_play_wave_channel_get_property(GObject *gobject,
31 					guint prop_id,
32 					GValue *value,
33 					GParamSpec *param_spec);
34 void ags_play_wave_channel_dispose(GObject *gobject);
35 void ags_play_wave_channel_finalize(GObject *gobject);
36 
37 /**
38  * SECTION:ags_play_wave_channel
39  * @short_description: play channel wave
40  * @title: AgsPlayWaveChannel
41  * @section_id:
42  * @include: ags/audio/recall/ags_play_wave_channel.h
43  *
44  * The #AgsPlayWaveChannel class provides ports to the effect processor.
45  */
46 
47 static gpointer ags_play_wave_channel_parent_class = NULL;
48 
49 const gchar *ags_play_wave_channel_plugin_name = "ags-play-wave";
50 const gchar *ags_play_wave_channel_specifier[] = {
51   "./do-playback[0]",
52   "./x-offset[0]",
53 };
54 const gchar *ags_play_wave_channel_control_port[] = {
55   "1/2",
56   "2/2",
57 };
58 
59 enum{
60   PROP_0,
61   PROP_WAVE,
62   PROP_DO_PLAYBACK,
63   PROP_X_OFFSET,
64 };
65 
66 GType
ags_play_wave_channel_get_type()67 ags_play_wave_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_play_wave_channel = 0;
73 
74     static const GTypeInfo ags_play_wave_channel_info = {
75       sizeof (AgsPlayWaveChannelClass),
76       NULL, /* base_init */
77       NULL, /* base_finalize */
78       (GClassInitFunc) ags_play_wave_channel_class_init,
79       NULL, /* class_finalize */
80       NULL, /* class_channel */
81       sizeof (AgsPlayWaveChannel),
82       0,    /* n_preallocs */
83       (GInstanceInitFunc) ags_play_wave_channel_init,
84     };
85 
86     ags_type_play_wave_channel = g_type_register_static(AGS_TYPE_RECALL_CHANNEL,
87 							"AgsPlayWaveChannel",
88 							&ags_play_wave_channel_info,
89 							0);
90 
91     g_once_init_leave(&g_define_type_id__volatile, ags_type_play_wave_channel);
92   }
93 
94   return g_define_type_id__volatile;
95 }
96 
97 void
ags_play_wave_channel_class_init(AgsPlayWaveChannelClass * play_wave_channel)98 ags_play_wave_channel_class_init(AgsPlayWaveChannelClass *play_wave_channel)
99 {
100   GObjectClass *gobject;
101   GParamSpec *param_spec;
102 
103   ags_play_wave_channel_parent_class = g_type_class_peek_parent(play_wave_channel);
104 
105   /* GObjectClass */
106   gobject = (GObjectClass *) play_wave_channel;
107 
108   gobject->set_property = ags_play_wave_channel_set_property;
109   gobject->get_property = ags_play_wave_channel_get_property;
110 
111   gobject->dispose = ags_play_wave_channel_dispose;
112   gobject->finalize = ags_play_wave_channel_finalize;
113 
114   /* properties */
115   /**
116    * AgsPlayWaveChannel:wave:
117    *
118    * The wave containing the notes.
119    *
120    * Since: 3.0.0
121    */
122   param_spec = g_param_spec_object("wave",
123 				   i18n_pspec("assigned AgsWave"),
124 				   i18n_pspec("The AgsWave containing notes"),
125 				   AGS_TYPE_WAVE,
126 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
127   g_object_class_install_property(gobject,
128 				  PROP_WAVE,
129 				  param_spec);
130 
131   /**
132    * AgsPlayWaveChannel:do-playback:
133    *
134    * The do-playback port.
135    *
136    * Since: 3.0.0
137    */
138   param_spec = g_param_spec_object("do-playback",
139 				   i18n_pspec("do playback"),
140 				   i18n_pspec("The do playback control"),
141 				   AGS_TYPE_PORT,
142 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
143   g_object_class_install_property(gobject,
144 				  PROP_DO_PLAYBACK,
145 				  param_spec);
146 
147   /**
148    * AgsPlayWaveChannel:x-offset:
149    *
150    * The x-offset port.
151    *
152    * Since: 3.0.0
153    */
154   param_spec = g_param_spec_object("x-offset",
155 				   i18n_pspec("x offset"),
156 				   i18n_pspec("The x offset control"),
157 				   AGS_TYPE_PORT,
158 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
159   g_object_class_install_property(gobject,
160 				  PROP_X_OFFSET,
161 				  param_spec);
162 }
163 
164 void
ags_play_wave_channel_init(AgsPlayWaveChannel * play_wave_channel)165 ags_play_wave_channel_init(AgsPlayWaveChannel *play_wave_channel)
166 {
167   GList *port;
168 
169   AGS_RECALL(play_wave_channel)->name = "ags-play-wave";
170   AGS_RECALL(play_wave_channel)->version = AGS_RECALL_DEFAULT_VERSION;
171   AGS_RECALL(play_wave_channel)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
172   AGS_RECALL(play_wave_channel)->xml_type = "ags-play-wave-channel";
173 
174   /* fields */
175   play_wave_channel->wave = NULL;
176 
177   /* port */
178   port = NULL;
179 
180   /* do playback */
181   play_wave_channel->do_playback = g_object_new(AGS_TYPE_PORT,
182 						"plugin-name", ags_play_wave_channel_plugin_name,
183 						"specifier", ags_play_wave_channel_specifier[0],
184 						"control-port", ags_play_wave_channel_control_port[0],
185 						"port-value-is-pointer", FALSE,
186 						"port-value-type", G_TYPE_BOOLEAN,
187 						NULL);
188   g_object_ref(play_wave_channel->do_playback);
189 
190   play_wave_channel->do_playback->port_value.ags_port_boolean = TRUE;
191 
192   /* add to port */
193   port = g_list_prepend(port, play_wave_channel->do_playback);
194   g_object_ref(play_wave_channel->do_playback);
195 
196   /* x offset */
197   play_wave_channel->x_offset = g_object_new(AGS_TYPE_PORT,
198 					     "plugin-name", ags_play_wave_channel_plugin_name,
199 					     "specifier", ags_play_wave_channel_specifier[1],
200 					     "control-port", ags_play_wave_channel_control_port[1],
201 					     "port-value-is-pointer", FALSE,
202 					     "port-value-type", G_TYPE_UINT64,
203 					     NULL);
204   g_object_ref(play_wave_channel->x_offset);
205 
206   play_wave_channel->x_offset->port_value.ags_port_boolean = FALSE;
207 
208   /* add to port */
209   port = g_list_prepend(port, play_wave_channel->x_offset);
210   g_object_ref(play_wave_channel->x_offset);
211 
212   /* set port */
213   AGS_RECALL(play_wave_channel)->port = port;
214 }
215 
216 void
ags_play_wave_channel_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)217 ags_play_wave_channel_set_property(GObject *gobject,
218 				   guint prop_id,
219 				   const GValue *value,
220 				   GParamSpec *param_spec)
221 {
222   AgsPlayWaveChannel *play_wave_channel;
223 
224   GRecMutex *recall_mutex;
225 
226   play_wave_channel = AGS_PLAY_WAVE_CHANNEL(gobject);
227 
228   /* get recall mutex */
229   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_wave_channel);
230 
231   switch(prop_id){
232   case PROP_WAVE:
233     {
234       AgsWave *wave;
235 
236       wave = (AgsWave *) g_value_get_object(value);
237 
238       g_rec_mutex_lock(recall_mutex);
239 
240       if(play_wave_channel->wave == wave){
241 	g_rec_mutex_unlock(recall_mutex);
242 
243 	return;
244       }
245 
246       if(play_wave_channel->wave != NULL){
247 	g_object_unref(play_wave_channel->wave);
248       }
249 
250       if(wave != NULL){
251 	g_object_ref(wave);
252       }
253 
254       play_wave_channel->wave = wave;
255 
256       g_rec_mutex_unlock(recall_mutex);
257     }
258     break;
259   case PROP_DO_PLAYBACK:
260     {
261       AgsPort *do_playback;
262 
263       do_playback = (AgsPort *) g_value_get_object(value);
264 
265       g_rec_mutex_lock(recall_mutex);
266 
267       if(play_wave_channel->do_playback == do_playback){
268 	g_rec_mutex_unlock(recall_mutex);
269 
270 	return;
271       }
272 
273       if(play_wave_channel->do_playback != NULL){
274 	g_object_unref(G_OBJECT(play_wave_channel->do_playback));
275       }
276 
277       if(do_playback != NULL){
278 	g_object_ref(G_OBJECT(do_playback));
279       }
280 
281       play_wave_channel->do_playback = do_playback;
282 
283       g_rec_mutex_unlock(recall_mutex);
284     }
285     break;
286   case PROP_X_OFFSET:
287     {
288       AgsPort *x_offset;
289 
290       x_offset = (AgsPort *) g_value_get_object(value);
291 
292       g_rec_mutex_lock(recall_mutex);
293 
294       if(play_wave_channel->x_offset == x_offset){
295 	g_rec_mutex_unlock(recall_mutex);
296 
297 	return;
298       }
299 
300       if(play_wave_channel->x_offset != NULL){
301 	g_object_unref(G_OBJECT(play_wave_channel->x_offset));
302       }
303 
304       if(x_offset != NULL){
305 	g_object_ref(G_OBJECT(x_offset));
306       }
307 
308       play_wave_channel->x_offset = x_offset;
309 
310       g_rec_mutex_unlock(recall_mutex);
311     }
312     break;
313   default:
314     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
315     break;
316   };
317 }
318 
319 void
ags_play_wave_channel_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)320 ags_play_wave_channel_get_property(GObject *gobject,
321 				   guint prop_id,
322 				   GValue *value,
323 				   GParamSpec *param_spec)
324 {
325   AgsPlayWaveChannel *play_wave_channel;
326 
327   GRecMutex *recall_mutex;
328 
329   play_wave_channel = AGS_PLAY_WAVE_CHANNEL(gobject);
330 
331   /* get recall mutex */
332   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_wave_channel);
333 
334   switch(prop_id){
335   case PROP_WAVE:
336     {
337       g_rec_mutex_lock(recall_mutex);
338 
339       g_value_set_object(value, play_wave_channel->wave);
340 
341       g_rec_mutex_unlock(recall_mutex);
342     }
343     break;
344   case PROP_DO_PLAYBACK:
345     {
346       g_rec_mutex_lock(recall_mutex);
347 
348       g_value_set_object(value, play_wave_channel->do_playback);
349 
350       g_rec_mutex_unlock(recall_mutex);
351     }
352     break;
353   case PROP_X_OFFSET:
354     {
355       g_rec_mutex_lock(recall_mutex);
356 
357       g_value_set_object(value, play_wave_channel->x_offset);
358 
359       g_rec_mutex_unlock(recall_mutex);
360     }
361     break;
362   default:
363     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
364     break;
365   };
366 }
367 
368 void
ags_play_wave_channel_dispose(GObject * gobject)369 ags_play_wave_channel_dispose(GObject *gobject)
370 {
371   AgsPlayWaveChannel *play_wave_channel;
372 
373   play_wave_channel = AGS_PLAY_WAVE_CHANNEL(gobject);
374 
375   /* wave */
376   if(play_wave_channel->wave != NULL){
377     g_object_unref(G_OBJECT(play_wave_channel->wave));
378 
379     play_wave_channel->wave = NULL;
380   }
381 
382   /* do playback */
383   if(play_wave_channel->do_playback != NULL){
384     g_object_unref(play_wave_channel->do_playback);
385 
386     play_wave_channel->do_playback = NULL;
387   }
388 
389   /* x-offset */
390   if(play_wave_channel->x_offset != NULL){
391     g_object_unref(play_wave_channel->x_offset);
392 
393     play_wave_channel->x_offset = NULL;
394   }
395 
396   /* call parent */
397   G_OBJECT_CLASS(ags_play_wave_channel_parent_class)->dispose(gobject);
398 }
399 
400 void
ags_play_wave_channel_finalize(GObject * gobject)401 ags_play_wave_channel_finalize(GObject *gobject)
402 {
403   AgsPlayWaveChannel *play_wave_channel;
404 
405   play_wave_channel = AGS_PLAY_WAVE_CHANNEL(gobject);
406 
407   /* wave */
408   if(play_wave_channel->wave != NULL){
409     g_object_unref(G_OBJECT(play_wave_channel->wave));
410   }
411 
412   /* do playback */
413   if(play_wave_channel->do_playback != NULL){
414     g_object_unref(play_wave_channel->do_playback);
415   }
416 
417   /* x-offset */
418   if(play_wave_channel->x_offset != NULL){
419     g_object_unref(play_wave_channel->x_offset);
420   }
421 
422   /* call parent */
423   G_OBJECT_CLASS(ags_play_wave_channel_parent_class)->finalize(gobject);
424 }
425 
426 /**
427  * ags_play_wave_channel_new:
428  * @source: the #AgsChannel
429  *
430  * Create a new instance of #AgsPlayWaveChannel
431  *
432  * Returns: the new #AgsPlayWaveChannel
433  *
434  * Since: 3.0.0
435  */
436 AgsPlayWaveChannel*
ags_play_wave_channel_new(AgsChannel * source)437 ags_play_wave_channel_new(AgsChannel *source)
438 {
439   AgsPlayWaveChannel *play_wave_channel;
440 
441   play_wave_channel = (AgsPlayWaveChannel *) g_object_new(AGS_TYPE_PLAY_WAVE_CHANNEL,
442 							  "source", source,
443 							  NULL);
444 
445   return(play_wave_channel);
446 }
447