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_route_dssi_audio.h>
21 
22 #include <ags/audio/recall/ags_route_dssi_audio_run.h>
23 
24 #include <ags/i18n.h>
25 
26 void ags_route_dssi_audio_class_init(AgsRouteDssiAudioClass *route_dssi_audio);
27 void ags_route_dssi_audio_init(AgsRouteDssiAudio *route_dssi_audio);
28 void ags_route_dssi_audio_set_property(GObject *gobject,
29 				       guint prop_id,
30 				       const GValue *value,
31 				       GParamSpec *param_spec);
32 void ags_route_dssi_audio_get_property(GObject *gobject,
33 				       guint prop_id,
34 				       GValue *value,
35 				       GParamSpec *param_spec);
36 void ags_route_dssi_audio_dispose(GObject *gobject);
37 void ags_route_dssi_audio_finalize(GObject *gobject);
38 
39 /**
40  * SECTION:ags_route_dssi_audio
41  * @short_description: route MIDI to DSSI
42  * @title: AgsRouteDssiAudio
43  * @section_id:
44  * @include: ags/audio/recall/ags_route_dssi_audio.h
45  *
46  * The #AgsRouteDssiAudio class provides ports to the effect processor.
47  */
48 
49 enum{
50   PROP_0,
51   PROP_NOTATION_INPUT,
52   PROP_SEQUENCER_INPUT,
53 };
54 
55 static gpointer ags_route_dssi_audio_parent_class = NULL;
56 
57 const gchar *ags_route_dssi_audio_plugin_name = "ags-route-dssi";
58 const gchar *ags_route_dssi_audio_specifier[] = {
59   "./notation-input[0]",
60   "./sequencer-input[0]",
61 };
62 const gchar *ags_route_dssi_audio_control_port[] = {
63   "1/2",
64   "2/2",
65 };
66 
67 GType
ags_route_dssi_audio_get_type()68 ags_route_dssi_audio_get_type()
69 {
70   static volatile gsize g_define_type_id__volatile = 0;
71 
72   if(g_once_init_enter (&g_define_type_id__volatile)){
73     GType ags_type_route_dssi_audio;
74 
75     static const GTypeInfo ags_route_dssi_audio_info = {
76       sizeof (AgsRouteDssiAudioClass),
77       NULL, /* base_init */
78       NULL, /* base_finalize */
79       (GClassInitFunc) ags_route_dssi_audio_class_init,
80       NULL, /* class_finalize */
81       NULL, /* class_data */
82       sizeof (AgsRouteDssiAudio),
83       0,    /* n_preallocs */
84       (GInstanceInitFunc) ags_route_dssi_audio_init,
85     };
86 
87     ags_type_route_dssi_audio = g_type_register_static(AGS_TYPE_RECALL_AUDIO,
88 						       "AgsRouteDssiAudio",
89 						       &ags_route_dssi_audio_info,
90 						       0);
91 
92     g_once_init_leave (&g_define_type_id__volatile, ags_type_route_dssi_audio);
93   }
94 
95   return g_define_type_id__volatile;
96 }
97 
98 void
ags_route_dssi_audio_class_init(AgsRouteDssiAudioClass * route_dssi_audio)99 ags_route_dssi_audio_class_init(AgsRouteDssiAudioClass *route_dssi_audio)
100 {
101   GObjectClass *gobject;
102   GParamSpec *param_spec;
103 
104   ags_route_dssi_audio_parent_class = g_type_class_peek_parent(route_dssi_audio);
105 
106   gobject = (GObjectClass *) route_dssi_audio;
107 
108   gobject->set_property = ags_route_dssi_audio_set_property;
109   gobject->get_property = ags_route_dssi_audio_get_property;
110 
111   gobject->dispose = ags_route_dssi_audio_dispose;
112   gobject->finalize = ags_route_dssi_audio_finalize;
113 
114   /* properties */
115   /**
116    * AgsRouteDssiAudio:notation-input:
117    *
118    * If enabled input is taken of #AgsNotation.
119    *
120    * Since: 3.0.0
121    */
122   param_spec = g_param_spec_object("notation-input",
123 				   i18n_pspec("route notation input"),
124 				   i18n_pspec("Route notation as input to the DSSI recall."),
125 				   AGS_TYPE_PORT,
126 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
127   g_object_class_install_property(gobject,
128 				  PROP_NOTATION_INPUT,
129 				  param_spec);
130 
131   /**
132    * AgsRouteDssiAudio:sequencer-input:
133    *
134    * If enabled input is taken of #AgsSequencer.
135    *
136    * Since: 3.0.0
137    */
138   param_spec = g_param_spec_object("sequencer-input",
139 				   i18n_pspec("route sequencer input"),
140 				   i18n_pspec("Route sequencer as input to the DSSI recall."),
141 				   AGS_TYPE_PORT,
142 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
143   g_object_class_install_property(gobject,
144 				  PROP_SEQUENCER_INPUT,
145 				  param_spec);
146 }
147 
148 void
ags_route_dssi_audio_init(AgsRouteDssiAudio * route_dssi_audio)149 ags_route_dssi_audio_init(AgsRouteDssiAudio *route_dssi_audio)
150 {
151   GList *port;
152 
153   AGS_RECALL(route_dssi_audio)->name = "ags-count-beats";
154   AGS_RECALL(route_dssi_audio)->version = AGS_RECALL_DEFAULT_VERSION;
155   AGS_RECALL(route_dssi_audio)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
156   AGS_RECALL(route_dssi_audio)->xml_type = "ags-count-beats-audio";
157 
158   port = NULL;
159 
160   /* notation input */
161   route_dssi_audio->notation_input = g_object_new(AGS_TYPE_PORT,
162 						  "plugin-name", ags_route_dssi_audio_plugin_name,
163 						  "specifier", ags_route_dssi_audio_specifier[0],
164 						  "control-port", ags_route_dssi_audio_control_port[0],
165 						  "port-value-is-pointer", FALSE,
166 						  "port-value-type", G_TYPE_BOOLEAN,
167 						  "port-value-size", sizeof(gboolean),
168 						  "port-value-length", 1,
169 						  NULL);
170   g_object_ref(route_dssi_audio->notation_input);
171 
172   route_dssi_audio->notation_input->port_value.ags_port_boolean = FALSE;
173 
174   /* add to port */
175   port = g_list_prepend(port,
176 			route_dssi_audio->notation_input);
177   g_object_ref(route_dssi_audio->notation_input);
178 
179   /* sequencer input */
180   route_dssi_audio->sequencer_input = g_object_new(AGS_TYPE_PORT,
181 						  "plugin-name", ags_route_dssi_audio_plugin_name,
182 						  "specifier", ags_route_dssi_audio_specifier[1],
183 						  "control-port", ags_route_dssi_audio_control_port[1],
184 						  "port-value-is-pointer", FALSE,
185 						  "port-value-type", G_TYPE_BOOLEAN,
186 						  "port-value-size", sizeof(gboolean),
187 						  "port-value-length", 1,
188 						  NULL);
189   g_object_ref(route_dssi_audio->sequencer_input);
190 
191   route_dssi_audio->sequencer_input->port_value.ags_port_boolean = FALSE;
192 
193   /* add to port */
194   port = g_list_prepend(port,
195 			route_dssi_audio->sequencer_input);
196   g_object_ref(route_dssi_audio->sequencer_input);
197 
198   /* port */
199   AGS_RECALL(route_dssi_audio)->port = port;
200 }
201 
202 void
ags_route_dssi_audio_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)203 ags_route_dssi_audio_set_property(GObject *gobject,
204 				  guint prop_id,
205 				  const GValue *value,
206 				  GParamSpec *param_spec)
207 {
208   AgsRouteDssiAudio *route_dssi_audio;
209 
210   GRecMutex *recall_mutex;
211 
212   route_dssi_audio = AGS_ROUTE_DSSI_AUDIO(gobject);
213 
214   /* get recall mutex */
215   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(route_dssi_audio);
216 
217   switch(prop_id){
218   case PROP_NOTATION_INPUT:
219     {
220       AgsPort *port;
221 
222       port = (AgsPort *) g_value_get_object(value);
223 
224       g_rec_mutex_lock(recall_mutex);
225 
226       if(port == route_dssi_audio->notation_input){
227 	g_rec_mutex_unlock(recall_mutex);
228 
229 	return;
230       }
231 
232       if(route_dssi_audio->notation_input != NULL){
233 	g_object_unref(G_OBJECT(route_dssi_audio->notation_input));
234       }
235 
236       if(port != NULL){
237 	g_object_ref(G_OBJECT(port));
238       }
239 
240       route_dssi_audio->notation_input = port;
241 
242       g_rec_mutex_unlock(recall_mutex);
243     }
244     break;
245   case PROP_SEQUENCER_INPUT:
246     {
247       AgsPort *port;
248 
249       port = (AgsPort *) g_value_get_object(value);
250 
251       g_rec_mutex_lock(recall_mutex);
252 
253       if(port == route_dssi_audio->sequencer_input){
254 	g_rec_mutex_unlock(recall_mutex);
255 
256 	return;
257       }
258 
259       if(route_dssi_audio->sequencer_input != NULL){
260 	g_object_unref(G_OBJECT(route_dssi_audio->sequencer_input));
261       }
262 
263       if(port != NULL){
264 	g_object_ref(G_OBJECT(port));
265       }
266 
267       route_dssi_audio->sequencer_input = port;
268 
269       g_rec_mutex_unlock(recall_mutex);
270     }
271     break;
272   default:
273     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
274     break;
275   };
276 }
277 
278 void
ags_route_dssi_audio_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)279 ags_route_dssi_audio_get_property(GObject *gobject,
280 				  guint prop_id,
281 				  GValue *value,
282 				  GParamSpec *param_spec)
283 {
284   AgsRouteDssiAudio *route_dssi_audio;
285 
286   GRecMutex *recall_mutex;
287 
288   route_dssi_audio = AGS_ROUTE_DSSI_AUDIO(gobject);
289 
290   /* get recall mutex */
291   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(route_dssi_audio);
292 
293   switch(prop_id){
294   case PROP_NOTATION_INPUT:
295     {
296       g_rec_mutex_lock(recall_mutex);
297 
298       g_value_set_object(value, route_dssi_audio->notation_input);
299 
300       g_rec_mutex_unlock(recall_mutex);
301     }
302     break;
303   case PROP_SEQUENCER_INPUT:
304     {
305       g_rec_mutex_lock(recall_mutex);
306 
307       g_value_set_object(value, route_dssi_audio->sequencer_input);
308 
309       g_rec_mutex_unlock(recall_mutex);
310     }
311     break;
312   default:
313     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
314     break;
315   };
316 }
317 
318 void
ags_route_dssi_audio_dispose(GObject * gobject)319 ags_route_dssi_audio_dispose(GObject *gobject)
320 {
321   AgsRouteDssiAudio *route_dssi_audio;
322 
323   route_dssi_audio = AGS_ROUTE_DSSI_AUDIO(gobject);
324 
325   /* notation input */
326   if(route_dssi_audio->notation_input != NULL){
327     g_object_unref(G_OBJECT(route_dssi_audio->notation_input));
328 
329     route_dssi_audio->notation_input = NULL;
330   }
331 
332   /* sequencer input */
333   if(route_dssi_audio->sequencer_input != NULL){
334     g_object_unref(G_OBJECT(route_dssi_audio->sequencer_input));
335 
336     route_dssi_audio->sequencer_input = NULL;
337   }
338 
339   /* call parent */
340   G_OBJECT_CLASS(ags_route_dssi_audio_parent_class)->dispose(gobject);
341 }
342 
343 void
ags_route_dssi_audio_finalize(GObject * gobject)344 ags_route_dssi_audio_finalize(GObject *gobject)
345 {
346   AgsRouteDssiAudio *route_dssi_audio;
347 
348   route_dssi_audio = AGS_ROUTE_DSSI_AUDIO(gobject);
349 
350   if(route_dssi_audio->notation_input != NULL){
351     g_object_unref(G_OBJECT(route_dssi_audio->notation_input));
352   }
353 
354   if(route_dssi_audio->sequencer_input != NULL){
355     g_object_unref(G_OBJECT(route_dssi_audio->sequencer_input));
356   }
357 
358   /* call parent */
359   G_OBJECT_CLASS(ags_route_dssi_audio_parent_class)->finalize(gobject);
360 }
361 
362 /**
363  * ags_route_dssi_audio_new:
364  * @audio: the #AgsAudio
365  *
366  * Create a new instance of #AgsRouteDssiAudio
367  *
368  * Returns: the new #AgsRouteDssiAudio
369  *
370  * Since: 3.0.0
371  */
372 AgsRouteDssiAudio*
ags_route_dssi_audio_new(AgsAudio * audio)373 ags_route_dssi_audio_new(AgsAudio *audio)
374 {
375   AgsRouteDssiAudio *route_dssi_audio;
376 
377   route_dssi_audio = (AgsRouteDssiAudio *) g_object_new(AGS_TYPE_ROUTE_DSSI_AUDIO,
378 							"audio", audio,
379 							NULL);
380 
381   return(route_dssi_audio);
382 }
383