1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2020 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/fx/ags_fx_dssi_channel.h>
21 
22 #include <ags/plugin/ags_dssi_manager.h>
23 #include <ags/plugin/ags_dssi_plugin.h>
24 #include <ags/plugin/ags_base_plugin.h>
25 #include <ags/plugin/ags_plugin_port.h>
26 
27 #include <ags/audio/ags_port_util.h>
28 
29 #include <ags/audio/fx/ags_fx_dssi_audio.h>
30 
31 void ags_fx_dssi_channel_class_init(AgsFxDssiChannelClass *fx_dssi_channel);
32 void ags_fx_dssi_channel_init(AgsFxDssiChannel *fx_dssi_channel);
33 void ags_fx_dssi_channel_dispose(GObject *gobject);
34 void ags_fx_dssi_channel_finalize(GObject *gobject);
35 
36 /**
37  * SECTION:ags_fx_dssi_channel
38  * @short_description: fx dssi channel
39  * @title: AgsFxDssiChannel
40  * @section_id:
41  * @include: ags/audio/fx/ags_fx_dssi_channel.h
42  *
43  * The #AgsFxDssiChannel class provides ports to the effect processor.
44  */
45 
46 static gpointer ags_fx_dssi_channel_parent_class = NULL;
47 
48 const gchar *ags_fx_dssi_channel_plugin_name = "ags-fx-dssi";
49 
50 GType
ags_fx_dssi_channel_get_type()51 ags_fx_dssi_channel_get_type()
52 {
53   static volatile gsize g_define_type_id__volatile = 0;
54 
55   if(g_once_init_enter (&g_define_type_id__volatile)){
56     GType ags_type_fx_dssi_channel = 0;
57 
58     static const GTypeInfo ags_fx_dssi_channel_info = {
59       sizeof (AgsFxDssiChannelClass),
60       NULL, /* base_init */
61       NULL, /* base_finalize */
62       (GClassInitFunc) ags_fx_dssi_channel_class_init,
63       NULL, /* class_finalize */
64       NULL, /* class_channel */
65       sizeof (AgsFxDssiChannel),
66       0,    /* n_preallocs */
67       (GInstanceInitFunc) ags_fx_dssi_channel_init,
68     };
69 
70     ags_type_fx_dssi_channel = g_type_register_static(AGS_TYPE_FX_NOTATION_CHANNEL,
71 						      "AgsFxDssiChannel",
72 						      &ags_fx_dssi_channel_info,
73 						      0);
74 
75     g_once_init_leave(&g_define_type_id__volatile, ags_type_fx_dssi_channel);
76   }
77 
78   return g_define_type_id__volatile;
79 }
80 
81 void
ags_fx_dssi_channel_class_init(AgsFxDssiChannelClass * fx_dssi_channel)82 ags_fx_dssi_channel_class_init(AgsFxDssiChannelClass *fx_dssi_channel)
83 {
84   GObjectClass *gobject;
85 
86   ags_fx_dssi_channel_parent_class = g_type_class_peek_parent(fx_dssi_channel);
87 
88   /* GObjectClass */
89   gobject = (GObjectClass *) fx_dssi_channel;
90 
91   gobject->dispose = ags_fx_dssi_channel_dispose;
92   gobject->finalize = ags_fx_dssi_channel_finalize;
93 }
94 
95 void
ags_fx_dssi_channel_init(AgsFxDssiChannel * fx_dssi_channel)96 ags_fx_dssi_channel_init(AgsFxDssiChannel *fx_dssi_channel)
97 {
98   AGS_RECALL(fx_dssi_channel)->name = "ags-fx-dssi";
99   AGS_RECALL(fx_dssi_channel)->version = AGS_RECALL_DEFAULT_VERSION;
100   AGS_RECALL(fx_dssi_channel)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
101   AGS_RECALL(fx_dssi_channel)->xml_type = "ags-fx-dssi-channel";
102 
103   fx_dssi_channel->dssi_port = NULL;
104 }
105 
106 void
ags_fx_dssi_channel_dispose(GObject * gobject)107 ags_fx_dssi_channel_dispose(GObject *gobject)
108 {
109   AgsFxDssiChannel *fx_dssi_channel;
110 
111   fx_dssi_channel = AGS_FX_DSSI_CHANNEL(gobject);
112 
113   /* call parent */
114   G_OBJECT_CLASS(ags_fx_dssi_channel_parent_class)->dispose(gobject);
115 }
116 
117 void
ags_fx_dssi_channel_finalize(GObject * gobject)118 ags_fx_dssi_channel_finalize(GObject *gobject)
119 {
120   AgsPort **iter;
121   AgsFxDssiChannel *fx_dssi_channel;
122 
123   fx_dssi_channel = AGS_FX_DSSI_CHANNEL(gobject);
124 
125   if(fx_dssi_channel->dssi_port == NULL){
126     for(iter = fx_dssi_channel->dssi_port; iter[0] != NULL; iter++){
127       g_object_unref(iter[0]);
128     }
129 
130     g_free(fx_dssi_channel->dssi_port);
131   }
132 
133   /* call parent */
134   G_OBJECT_CLASS(ags_fx_dssi_channel_parent_class)->finalize(gobject);
135 }
136 
137 /**
138  * ags_fx_dssi_channel_load_port:
139  * @fx_dssi_channel: the #AgsFxDssiChannel
140  *
141  * Load port of @fx_dssi_channel.
142  *
143  * Since: 3.3.0
144  */
145 void
ags_fx_dssi_channel_load_port(AgsFxDssiChannel * fx_dssi_channel)146 ags_fx_dssi_channel_load_port(AgsFxDssiChannel *fx_dssi_channel)
147 {
148   AgsChannel *input;
149   AgsFxDssiAudio *fx_dssi_audio;
150   AgsPort **dssi_port;
151 
152   AgsDssiPlugin *dssi_plugin;
153 
154   GList *start_plugin_port, *plugin_port;
155 
156   guint *output_port;
157   guint *input_port;
158 
159   guint audio_channel;
160   guint pad;
161   guint output_port_count, input_port_count;
162   guint control_port_count;
163   guint buffer_size;
164   guint nth;
165   guint i, j;
166   gboolean is_live_instrument;
167 
168   GRecMutex *fx_dssi_audio_mutex;
169   GRecMutex *fx_dssi_channel_mutex;
170 
171   if(!AGS_IS_FX_DSSI_CHANNEL(fx_dssi_channel)){
172     return;
173   }
174 
175   fx_dssi_channel_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_dssi_channel);
176 
177   g_rec_mutex_lock(fx_dssi_channel_mutex);
178 
179   if(fx_dssi_channel->dssi_port != NULL){
180     g_rec_mutex_unlock(fx_dssi_channel_mutex);
181 
182     return;
183   }
184 
185   g_rec_mutex_unlock(fx_dssi_channel_mutex);
186 
187   fx_dssi_audio = NULL;
188 
189   g_object_get(fx_dssi_channel,
190 	       "recall-audio", &fx_dssi_audio,
191 	       NULL);
192 
193   if(fx_dssi_audio == NULL){
194     return;
195   }
196 
197   is_live_instrument = ags_fx_dssi_audio_test_flags(fx_dssi_audio, AGS_FX_DSSI_AUDIO_LIVE_INSTRUMENT);
198 
199   if(is_live_instrument){
200     if(fx_dssi_audio != NULL){
201       g_object_unref(fx_dssi_audio);
202     }
203 
204     return;
205   }
206 
207   /* get recall mutex */
208   fx_dssi_audio_mutex = AGS_RECALL_GET_OBJ_MUTEX(fx_dssi_audio);
209 
210   input = NULL;
211 
212   buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
213 
214   g_object_get(fx_dssi_channel,
215 	       "source", &input,
216 	       "buffer-size", &buffer_size,
217 	       NULL);
218 
219   audio_channel = 0;
220   pad = 0;
221 
222   g_object_get(input,
223 	       "audio-channel", &audio_channel,
224 	       "pad", &pad,
225 	       NULL);
226 
227   /* get DSSI plugin */
228   g_rec_mutex_lock(fx_dssi_audio_mutex);
229 
230   dssi_plugin = fx_dssi_audio->dssi_plugin;
231 
232   output_port_count = fx_dssi_audio->output_port_count;
233   output_port = fx_dssi_audio->output_port;
234 
235   input_port_count = fx_dssi_audio->input_port_count;
236   input_port = fx_dssi_audio->input_port;
237 
238   g_rec_mutex_unlock(fx_dssi_audio_mutex);
239 
240   /* get DSSI port */
241   g_rec_mutex_lock(fx_dssi_channel_mutex);
242 
243   dssi_port = fx_dssi_channel->dssi_port;
244 
245   g_rec_mutex_unlock(fx_dssi_channel_mutex);
246 
247   g_object_get(dssi_plugin,
248 	       "plugin-port", &start_plugin_port,
249 	       NULL);
250 
251   /* get control port count */
252   plugin_port = start_plugin_port;
253 
254   control_port_count = 0;
255 
256   while(plugin_port != NULL){
257     if(ags_plugin_port_test_flags(plugin_port->data,
258 				  AGS_PLUGIN_PORT_CONTROL)){
259       control_port_count++;
260     }
261 
262     plugin_port = plugin_port->next;
263   }
264 
265   /*  */
266   if(control_port_count > 0){
267     dssi_port = (AgsPort **) g_malloc((control_port_count + 1) * sizeof(AgsPort *));
268 
269     plugin_port = start_plugin_port;
270 
271     for(nth = 0; nth < control_port_count && plugin_port != NULL;){
272       if(ags_plugin_port_test_flags(plugin_port->data,
273 				    AGS_PLUGIN_PORT_CONTROL)){
274 	AgsPluginPort *current_plugin_port;
275 
276 	gchar *plugin_name;
277 	gchar *specifier;
278 	gchar *control_port;
279 
280 	guint port_index;
281 
282 	GValue default_value = {0,};
283 
284 	GRecMutex *plugin_port_mutex;
285 
286 	current_plugin_port = AGS_PLUGIN_PORT(plugin_port->data);
287 
288 	/* get plugin port mutex */
289 	plugin_port_mutex = AGS_PLUGIN_PORT_GET_OBJ_MUTEX(current_plugin_port);
290 
291 	/* plugin name, specifier and control port */
292 	plugin_name = g_strdup_printf("dssi-%u", dssi_plugin->unique_id);
293 
294 	specifier = NULL;
295 
296 	port_index = 0;
297 
298 	g_object_get(current_plugin_port,
299 		     "port-name", &specifier,
300 		     "port-index", &port_index,
301 		     NULL);
302 
303 	control_port = g_strdup_printf("%u/%u",
304 				       nth,
305 				       control_port_count);
306 
307 	/* default value */
308 	g_value_init(&default_value,
309 		     G_TYPE_FLOAT);
310 
311 	g_rec_mutex_lock(plugin_port_mutex);
312 
313 	g_value_copy(current_plugin_port->default_value,
314 		     &default_value);
315 
316 	g_rec_mutex_unlock(plugin_port_mutex);
317 
318 	/* dssi port */
319 	dssi_port[nth] = g_object_new(AGS_TYPE_PORT,
320 				      "plugin-name", plugin_name,
321 				      "specifier", specifier,
322 				      "control-port", control_port,
323 				      "port-value-is-pointer", FALSE,
324 				      "port-value-type", G_TYPE_FLOAT,
325 				      NULL);
326 	ags_port_set_flags(dssi_port[nth], AGS_PORT_USE_LADSPA_FLOAT);
327 
328 	if(ags_plugin_port_test_flags(current_plugin_port,
329 				      AGS_PLUGIN_PORT_OUTPUT)){
330 	  ags_port_set_flags(dssi_port[nth], AGS_PORT_IS_OUTPUT);
331 
332 	  ags_recall_set_flags((AgsRecall *) fx_dssi_channel,
333 			       AGS_RECALL_HAS_OUTPUT_PORT);
334 
335 	}else{
336 	  if(!ags_plugin_port_test_flags(current_plugin_port,
337 					 AGS_PLUGIN_PORT_INTEGER) &&
338 	     !ags_plugin_port_test_flags(current_plugin_port,
339 					 AGS_PLUGIN_PORT_TOGGLED)){
340 	    ags_port_set_flags(dssi_port[nth], AGS_PORT_INFINITE_RANGE);
341 	  }
342 	}
343 
344 	g_object_set(dssi_port[nth],
345 		     "plugin-port", current_plugin_port,
346 		     NULL);
347 
348 	ags_port_util_load_ladspa_conversion(dssi_port[nth],
349 					     current_plugin_port);
350 
351 	ags_port_safe_write_raw(dssi_port[nth],
352 				&default_value);
353 
354 	ags_recall_add_port((AgsRecall *) fx_dssi_channel,
355 			    dssi_port[nth]);
356 
357 	/* connect port */
358 	for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
359 	  AgsFxDssiAudioScopeData *scope_data;
360 
361 	  scope_data = fx_dssi_audio->scope_data[i];
362 
363 	  if(i == AGS_SOUND_SCOPE_PLAYBACK ||
364 	     i == AGS_SOUND_SCOPE_NOTATION ||
365 	     i == AGS_SOUND_SCOPE_MIDI){
366 	    for(j = 0; j < scope_data->audio_channels; j++){
367 	      AgsFxDssiAudioChannelData *channel_data;
368 
369 	      channel_data = scope_data->channel_data[j];
370 
371 	      if(pad < 128){
372 		AgsFxDssiAudioInputData *input_data;
373 
374 		input_data = channel_data->input_data[pad];
375 
376 		ags_base_plugin_connect_port((AgsBasePlugin *) dssi_plugin,
377 					     input_data->ladspa_handle,
378 					     port_index,
379 					     &(dssi_port[nth]->port_value.ags_port_ladspa));
380 	      }
381 	    }
382 	  }
383 	}
384 
385 	g_free(plugin_name);
386 	g_free(specifier);
387 	g_free(control_port);
388 
389 	g_value_unset(&default_value);
390 
391 	nth++;
392       }
393 
394       plugin_port = plugin_port->next;
395     }
396 
397     dssi_port[nth] = NULL;
398   }
399 
400   /* set DSSI output */
401   g_rec_mutex_lock(fx_dssi_channel_mutex);
402 
403   for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
404     AgsFxDssiAudioScopeData *scope_data;
405 
406     scope_data = fx_dssi_audio->scope_data[i];
407 
408     if(i == AGS_SOUND_SCOPE_PLAYBACK ||
409        i == AGS_SOUND_SCOPE_NOTATION ||
410        i == AGS_SOUND_SCOPE_MIDI){
411       AgsFxDssiAudioChannelData *channel_data;
412       AgsFxDssiAudioInputData *input_data;
413 
414       guint nth;
415 
416       channel_data = scope_data->channel_data[audio_channel];
417 
418       input_data = channel_data->input_data[pad];
419 
420       if(input_data->output == NULL &&
421 	 output_port_count > 0 &&
422 	 buffer_size > 0){
423 	input_data->output = (LADSPA_Data *) g_malloc(output_port_count * buffer_size * sizeof(LADSPA_Data));
424       }
425 
426       if(input_data->input == NULL &&
427 	 input_port_count > 0 &&
428 	 buffer_size > 0){
429 	input_data->input = (LADSPA_Data *) g_malloc(input_port_count * buffer_size * sizeof(LADSPA_Data));
430       }
431 
432       for(nth = 0; nth < output_port_count; nth++){
433 	ags_base_plugin_connect_port((AgsBasePlugin *) dssi_plugin,
434 				     input_data->ladspa_handle,
435 				     output_port[nth],
436 				     &(input_data->output[nth]));
437       }
438 
439       for(nth = 0; nth < input_port_count; nth++){
440 	ags_base_plugin_connect_port((AgsBasePlugin *) dssi_plugin,
441 				     input_data->ladspa_handle,
442 				     input_port[nth],
443 				     &(input_data->input[nth]));
444       }
445 
446       ags_base_plugin_activate((AgsBasePlugin *) dssi_plugin,
447 			       input_data->ladspa_handle);
448     }
449   }
450 
451   fx_dssi_channel->dssi_port = dssi_port;
452 
453   g_rec_mutex_unlock(fx_dssi_channel_mutex);
454 
455   /* unref */
456   if(fx_dssi_audio != NULL){
457     g_object_unref(fx_dssi_audio);
458   }
459 
460   g_list_free_full(start_plugin_port,
461 		   (GDestroyNotify) g_object_unref);
462 }
463 
464 /**
465  * ags_fx_dssi_channel_new:
466  * @channel: the #AgsChannel
467  *
468  * Create a new instance of #AgsFxDssiChannel
469  *
470  * Returns: the new #AgsFxDssiChannel
471  *
472  * Since: 3.3.0
473  */
474 AgsFxDssiChannel*
ags_fx_dssi_channel_new(AgsChannel * channel)475 ags_fx_dssi_channel_new(AgsChannel *channel)
476 {
477   AgsFxDssiChannel *fx_dssi_channel;
478 
479   fx_dssi_channel = (AgsFxDssiChannel *) g_object_new(AGS_TYPE_FX_DSSI_CHANNEL,
480 						      "source", channel,
481 						      NULL);
482 
483   return(fx_dssi_channel);
484 }
485