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_lv2_audio.h>
21
22 #include <ags/plugin/ags_lv2_manager.h>
23 #include <ags/plugin/ags_lv2_plugin.h>
24 #include <ags/plugin/ags_lv2_conversion.h>
25 #include <ags/plugin/ags_plugin_port.h>
26
27 #include <ags/audio/ags_port.h>
28
29 #if defined(AGS_W32API)
30 #include <windows.h>
31 #else
32 #include <dlfcn.h>
33 #endif
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <unistd.h>
40
41 #include <libxml/tree.h>
42
43 #include <ags/i18n.h>
44
45 void ags_play_lv2_audio_class_init(AgsPlayLv2AudioClass *play_lv2_audio);
46 void ags_play_lv2_audio_init(AgsPlayLv2Audio *play_lv2_audio);
47 void ags_play_lv2_audio_set_property(GObject *gobject,
48 guint prop_id,
49 const GValue *value,
50 GParamSpec *param_spec);
51 void ags_play_lv2_audio_get_property(GObject *gobject,
52 guint prop_id,
53 GValue *value,
54 GParamSpec *param_spec);
55 void ags_play_lv2_audio_dispose(GObject *gobject);
56 void ags_play_lv2_audio_finalize(GObject *gobject);
57
58 /**
59 * SECTION:ags_play_lv2_audio
60 * @short_description: play audio lv2
61 * @title: AgsPlayLv2Audio
62 * @section_id:
63 * @include: ags/audio/recall/ags_play_lv2_audio.h
64 *
65 * The #AgsPlayLv2Audio class provides ports to the effect processor.
66 */
67
68 enum{
69 PROP_0,
70 PROP_TURTLE,
71 PROP_URI,
72 PROP_PLUGIN,
73 PROP_INPUT_LINES,
74 PROP_OUTPUT_LINES,
75 };
76
77 static gpointer ags_play_lv2_audio_parent_class = NULL;
78
79 const gchar *ags_play_lv2_audio_plugin_name = "ags-play-lv2";
80 const gchar *ags_play_lv2_audio_specifier[] = {
81 };
82 const gchar *ags_play_lv2_audio_control_port[] = {
83 };
84
85 GType
ags_play_lv2_audio_get_type()86 ags_play_lv2_audio_get_type()
87 {
88 static volatile gsize g_define_type_id__volatile = 0;
89
90 if(g_once_init_enter (&g_define_type_id__volatile)){
91 GType ags_type_play_lv2_audio;
92
93 static const GTypeInfo ags_play_lv2_audio_info = {
94 sizeof (AgsPlayLv2AudioClass),
95 NULL, /* base_init */
96 NULL, /* base_finalize */
97 (GClassInitFunc) ags_play_lv2_audio_class_init,
98 NULL, /* class_finalize */
99 NULL, /* class_audio */
100 sizeof (AgsPlayLv2Audio),
101 0, /* n_preallocs */
102 (GInstanceInitFunc) ags_play_lv2_audio_init,
103 };
104
105 ags_type_play_lv2_audio = g_type_register_static(AGS_TYPE_RECALL_AUDIO,
106 "AgsPlayLv2Audio",
107 &ags_play_lv2_audio_info,
108 0);
109
110 g_once_init_leave (&g_define_type_id__volatile, ags_type_play_lv2_audio);
111 }
112
113 return g_define_type_id__volatile;
114 }
115
116 void
ags_play_lv2_audio_class_init(AgsPlayLv2AudioClass * play_lv2_audio)117 ags_play_lv2_audio_class_init(AgsPlayLv2AudioClass *play_lv2_audio)
118 {
119 GObjectClass *gobject;
120 GParamSpec *param_spec;
121
122 ags_play_lv2_audio_parent_class = g_type_class_peek_parent(play_lv2_audio);
123
124 /* GObjectClass */
125 gobject = (GObjectClass *) play_lv2_audio;
126
127 gobject->set_property = ags_play_lv2_audio_set_property;
128 gobject->get_property = ags_play_lv2_audio_get_property;
129
130 gobject->dispose = ags_play_lv2_audio_dispose;
131 gobject->finalize = ags_play_lv2_audio_finalize;
132
133 /* properties */
134 /**
135 * AgsPlayLv2Audio:turtle:
136 *
137 * The assigned turtle.
138 *
139 * Since: 3.0.0
140 */
141 param_spec = g_param_spec_object("turtle",
142 i18n_pspec("turtle of recall lv2"),
143 i18n_pspec("The turtle which this recall lv2 is described by"),
144 AGS_TYPE_TURTLE,
145 G_PARAM_READABLE | G_PARAM_WRITABLE);
146 g_object_class_install_property(gobject,
147 PROP_TURTLE,
148 param_spec);
149
150 /**
151 * AgsPlayLv2Audio:uri:
152 *
153 * The uri's name.
154 *
155 * Since: 3.0.0
156 */
157 param_spec = g_param_spec_string("uri",
158 i18n_pspec("the uri"),
159 i18n_pspec("The uri's string representation"),
160 NULL,
161 G_PARAM_READABLE | G_PARAM_WRITABLE);
162 g_object_class_install_property(gobject,
163 PROP_URI,
164 param_spec);
165
166 /**
167 * AgsPlayLv2Audio:plugin:
168 *
169 * The plugin's plugin object.
170 *
171 * Since: 3.0.0
172 */
173 param_spec = g_param_spec_object("plugin",
174 i18n_pspec("the plugin"),
175 i18n_pspec("The plugin as plugin object"),
176 AGS_TYPE_LV2_PLUGIN,
177 G_PARAM_READABLE | G_PARAM_WRITABLE);
178 g_object_class_install_property(gobject,
179 PROP_PLUGIN,
180 param_spec);
181
182 /**
183 * AgsPlayLv2Audio:input-lines:
184 *
185 * The effect's input lines count.
186 *
187 * Since: 3.0.0
188 */
189 param_spec = g_param_spec_ulong("input-lines",
190 i18n_pspec("input lines of effect"),
191 i18n_pspec("The effect's count of input lines"),
192 0,
193 65535,
194 0,
195 G_PARAM_READABLE | G_PARAM_WRITABLE);
196 g_object_class_install_property(gobject,
197 PROP_INPUT_LINES,
198 param_spec);
199
200 /**
201 * AgsPlayLv2Audio:output-lines:
202 *
203 * The effect's output lines count.
204 *
205 * Since: 3.0.0
206 */
207 param_spec = g_param_spec_ulong("output-lines",
208 i18n_pspec("output lines of effect"),
209 i18n_pspec("The effect's count of output lines"),
210 0,
211 65535,
212 0,
213 G_PARAM_READABLE | G_PARAM_WRITABLE);
214 g_object_class_install_property(gobject,
215 PROP_OUTPUT_LINES,
216 param_spec);
217 }
218
219 void
ags_play_lv2_audio_init(AgsPlayLv2Audio * play_lv2_audio)220 ags_play_lv2_audio_init(AgsPlayLv2Audio *play_lv2_audio)
221 {
222 GList *port;
223
224 AGS_RECALL(play_lv2_audio)->name = "ags-play-lv2";
225 AGS_RECALL(play_lv2_audio)->version = AGS_RECALL_DEFAULT_VERSION;
226 AGS_RECALL(play_lv2_audio)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
227 AGS_RECALL(play_lv2_audio)->xml_type = "ags-play-lv2-audio";
228
229 play_lv2_audio->turtle = NULL;
230
231 play_lv2_audio->uri = NULL;
232
233 play_lv2_audio->plugin = NULL;
234 play_lv2_audio->plugin_descriptor = NULL;
235
236 play_lv2_audio->input_port = NULL;
237 play_lv2_audio->input_lines = 0;
238
239 play_lv2_audio->output_port = NULL;
240 play_lv2_audio->output_lines = 0;
241
242 play_lv2_audio->event_port = 0;
243 play_lv2_audio->atom_port = 0;
244
245 play_lv2_audio->bank = 0;
246 play_lv2_audio->program = 0;
247 }
248
249 void
ags_play_lv2_audio_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)250 ags_play_lv2_audio_set_property(GObject *gobject,
251 guint prop_id,
252 const GValue *value,
253 GParamSpec *param_spec)
254 {
255 AgsPlayLv2Audio *play_lv2_audio;
256
257 GRecMutex *recall_mutex;
258
259 play_lv2_audio = AGS_PLAY_LV2_AUDIO(gobject);
260
261 /* get recall mutex */
262 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_lv2_audio);
263
264 switch(prop_id){
265 case PROP_TURTLE:
266 {
267 AgsTurtle *turtle;
268
269 turtle = (AgsTurtle *) g_value_get_object(value);
270
271 g_rec_mutex_lock(recall_mutex);
272
273 if(play_lv2_audio->turtle == turtle){
274 g_rec_mutex_unlock(recall_mutex);
275
276 return;
277 }
278
279 if(play_lv2_audio->turtle != NULL){
280 g_object_unref(play_lv2_audio->turtle);
281 }
282
283 if(turtle != NULL){
284 g_object_ref(turtle);
285 }
286
287 play_lv2_audio->turtle = turtle;
288
289 g_rec_mutex_unlock(recall_mutex);
290 }
291 break;
292 case PROP_URI:
293 {
294 gchar *uri;
295
296 uri = g_value_get_string(value);
297
298 g_rec_mutex_lock(recall_mutex);
299
300 if(uri == play_lv2_audio->uri){
301 g_rec_mutex_unlock(recall_mutex);
302
303 return;
304 }
305
306 if(play_lv2_audio->uri != NULL){
307 g_free(play_lv2_audio->uri);
308 }
309
310 play_lv2_audio->uri = g_strdup(uri);
311
312 g_rec_mutex_unlock(recall_mutex);
313 }
314 break;
315 case PROP_PLUGIN:
316 {
317 AgsLv2Plugin *lv2_plugin;
318
319 lv2_plugin = g_value_get_object(value);
320
321 g_rec_mutex_lock(recall_mutex);
322
323 if(play_lv2_audio->plugin == lv2_plugin){
324 g_rec_mutex_unlock(recall_mutex);
325
326 return;
327 }
328
329 if(play_lv2_audio->plugin != NULL){
330 g_object_unref(play_lv2_audio->plugin);
331 }
332
333 if(lv2_plugin != NULL){
334 g_object_ref(lv2_plugin);
335 }
336
337 play_lv2_audio->plugin = lv2_plugin;
338
339 g_rec_mutex_unlock(recall_mutex);
340 }
341 break;
342 case PROP_INPUT_LINES:
343 {
344 unsigned long effect_input_lines;
345
346 effect_input_lines = g_value_get_ulong(value);
347
348 g_rec_mutex_lock(recall_mutex);
349
350 if(effect_input_lines == play_lv2_audio->input_lines){
351 g_rec_mutex_unlock(recall_mutex);
352
353 return;
354 }
355
356 play_lv2_audio->input_lines = effect_input_lines;
357
358 g_rec_mutex_unlock(recall_mutex);
359 }
360 break;
361 case PROP_OUTPUT_LINES:
362 {
363 unsigned long effect_output_lines;
364
365 effect_output_lines = g_value_get_ulong(value);
366
367 g_rec_mutex_lock(recall_mutex);
368
369 if(effect_output_lines == play_lv2_audio->output_lines){
370 g_rec_mutex_unlock(recall_mutex);
371
372 return;
373 }
374
375 play_lv2_audio->output_lines = effect_output_lines;
376
377 g_rec_mutex_unlock(recall_mutex);
378 }
379 break;
380 default:
381 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
382 break;
383 };
384 }
385
386 void
ags_play_lv2_audio_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)387 ags_play_lv2_audio_get_property(GObject *gobject,
388 guint prop_id,
389 GValue *value,
390 GParamSpec *param_spec)
391 {
392 AgsPlayLv2Audio *play_lv2_audio;
393
394 GRecMutex *recall_mutex;
395
396 play_lv2_audio = AGS_PLAY_LV2_AUDIO(gobject);
397
398 /* get recall mutex */
399 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_lv2_audio);
400
401 switch(prop_id){
402 case PROP_TURTLE:
403 {
404 g_rec_mutex_lock(recall_mutex);
405
406 g_value_set_object(value, play_lv2_audio->turtle);
407
408 g_rec_mutex_unlock(recall_mutex);
409 }
410 break;
411 case PROP_URI:
412 {
413 g_rec_mutex_lock(recall_mutex);
414
415 g_value_set_string(value, play_lv2_audio->uri);
416
417 g_rec_mutex_unlock(recall_mutex);
418 }
419 break;
420 case PROP_PLUGIN:
421 {
422 g_rec_mutex_lock(recall_mutex);
423
424 g_value_set_object(value, play_lv2_audio->plugin);
425
426 g_rec_mutex_unlock(recall_mutex);
427 }
428 break;
429 case PROP_INPUT_LINES:
430 {
431 g_rec_mutex_lock(recall_mutex);
432
433 g_value_set_ulong(value, play_lv2_audio->input_lines);
434
435 g_rec_mutex_unlock(recall_mutex);
436 }
437 break;
438 case PROP_OUTPUT_LINES:
439 {
440 g_rec_mutex_lock(recall_mutex);
441
442 g_value_set_ulong(value, play_lv2_audio->output_lines);
443
444 g_rec_mutex_unlock(recall_mutex);
445 }
446 break;
447 default:
448 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
449 break;
450 }
451 }
452
453 void
ags_play_lv2_audio_dispose(GObject * gobject)454 ags_play_lv2_audio_dispose(GObject *gobject)
455 {
456 AgsPlayLv2Audio *play_lv2_audio;
457
458 play_lv2_audio = AGS_PLAY_LV2_AUDIO(gobject);
459
460 /* turtle */
461 if(play_lv2_audio->turtle != NULL){
462 g_object_unref(play_lv2_audio->turtle);
463
464 play_lv2_audio->turtle = NULL;
465 }
466
467 /* plugin */
468 if(play_lv2_audio->plugin != NULL){
469 g_object_unref(play_lv2_audio->plugin);
470
471 play_lv2_audio->plugin = NULL;
472 }
473
474 /* call parent */
475 G_OBJECT_CLASS(ags_play_lv2_audio_parent_class)->dispose(gobject);
476 }
477
478 void
ags_play_lv2_audio_finalize(GObject * gobject)479 ags_play_lv2_audio_finalize(GObject *gobject)
480 {
481 AgsPlayLv2Audio *play_lv2_audio;
482
483 play_lv2_audio = AGS_PLAY_LV2_AUDIO(gobject);
484
485 /* turtle */
486 if(play_lv2_audio->turtle != NULL){
487 g_object_unref(play_lv2_audio->turtle);
488 }
489
490 /* plugin */
491 if(play_lv2_audio->plugin != NULL){
492 g_object_unref(play_lv2_audio->plugin);
493 }
494
495 /* filename, effect and uri */
496 g_free(play_lv2_audio->uri);
497
498 /* call parent */
499 G_OBJECT_CLASS(ags_play_lv2_audio_parent_class)->finalize(gobject);
500 }
501
502 /**
503 * ags_play_lv2_audio_test_flags:
504 * @play_lv2_audio: the #AgsPlayLv2Audio
505 * @flags: the flags
506 *
507 * Test @flags to be set on @play_lv2_audio.
508 *
509 * Returns: %TRUE if flags are set, else %FALSE
510 *
511 * Since: 3.0.0
512 */
513 gboolean
ags_play_lv2_audio_test_flags(AgsPlayLv2Audio * play_lv2_audio,guint flags)514 ags_play_lv2_audio_test_flags(AgsPlayLv2Audio *play_lv2_audio, guint flags)
515 {
516 gboolean retval;
517
518 GRecMutex *recall_mutex;
519
520 if(!AGS_IS_PLAY_LV2_AUDIO(play_lv2_audio)){
521 return(FALSE);
522 }
523
524 /* get play_lv2_audio mutex */
525 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_lv2_audio);
526
527 /* test */
528 g_rec_mutex_lock(recall_mutex);
529
530 retval = (flags & (play_lv2_audio->flags)) ? TRUE: FALSE;
531
532 g_rec_mutex_unlock(recall_mutex);
533
534 return(retval);
535 }
536
537 /**
538 * ags_play_lv2_audio_set_flags:
539 * @play_lv2_audio: the #AgsPlayLv2Audio
540 * @flags: the flags
541 *
542 * Set flags.
543 *
544 * Since: 3.0.0
545 */
546 void
ags_play_lv2_audio_set_flags(AgsPlayLv2Audio * play_lv2_audio,guint flags)547 ags_play_lv2_audio_set_flags(AgsPlayLv2Audio *play_lv2_audio, guint flags)
548 {
549 GRecMutex *recall_mutex;
550
551 if(!AGS_IS_PLAY_LV2_AUDIO(play_lv2_audio)){
552 return;
553 }
554
555 /* get play_lv2_audio mutex */
556 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_lv2_audio);
557
558 /* set flags */
559 g_rec_mutex_lock(recall_mutex);
560
561 play_lv2_audio->flags |= flags;
562
563 g_rec_mutex_unlock(recall_mutex);
564 }
565
566 /**
567 * ags_play_lv2_audio_unset_flags:
568 * @play_lv2_audio: the #AgsPlayLv2Audio
569 * @flags: the flags
570 *
571 * Unset flags.
572 *
573 * Since: 3.0.0
574 */
575 void
ags_play_lv2_audio_unset_flags(AgsPlayLv2Audio * play_lv2_audio,guint flags)576 ags_play_lv2_audio_unset_flags(AgsPlayLv2Audio *play_lv2_audio, guint flags)
577 {
578 GRecMutex *recall_mutex;
579
580 if(!AGS_IS_PLAY_LV2_AUDIO(play_lv2_audio)){
581 return;
582 }
583
584 /* get play_lv2_audio mutex */
585 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_lv2_audio);
586
587 /* set flags */
588 g_rec_mutex_lock(recall_mutex);
589
590 play_lv2_audio->flags &= (~flags);
591
592 g_rec_mutex_unlock(recall_mutex);
593 }
594
595 /**
596 * ags_play_lv2_audio_load:
597 * @play_lv2_audio: the #AgsPlayLv2Audio
598 *
599 * Set up LV2 handle.
600 *
601 * Since: 3.0.0
602 */
603 void
ags_play_lv2_audio_load(AgsPlayLv2Audio * play_lv2_audio)604 ags_play_lv2_audio_load(AgsPlayLv2Audio *play_lv2_audio)
605 {
606 AgsLv2Plugin *lv2_plugin;
607
608 gchar *filename, *effect;
609
610 guint effect_index;
611 guint i;
612
613 void *plugin_so;
614 LV2_Descriptor_Function lv2_descriptor;
615 LV2_Descriptor *plugin_descriptor;
616
617 GRecMutex *recall_mutex;
618
619 if(!AGS_IS_PLAY_LV2_AUDIO(play_lv2_audio)){
620 return;
621 }
622
623 /* get recall mutex */
624 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_lv2_audio);
625
626 /* get filename and effect */
627 g_rec_mutex_lock(recall_mutex);
628
629 filename = g_strdup(AGS_RECALL(play_lv2_audio)->filename);
630 effect = g_strdup(AGS_RECALL(play_lv2_audio)->effect);
631
632 g_rec_mutex_unlock(recall_mutex);
633
634 /* find AgsLv2Plugin */
635 lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
636 filename, effect);
637
638 g_object_get(lv2_plugin,
639 "plugin-so", &plugin_so,
640 NULL);
641
642 if(plugin_so == NULL){
643 g_message("open %s", filename);
644
645 #ifdef AGS_W32API
646 plugin_so = LoadLibrary(filename);
647 #else
648 plugin_so = dlopen(filename,
649 RTLD_NOW);
650 #endif
651
652 g_object_set(lv2_plugin,
653 "plugin-so", plugin_so,
654 NULL);
655 }
656
657 /* get some fields */
658 play_lv2_audio->plugin = lv2_plugin;
659
660 if(plugin_so != NULL){
661 gboolean success;
662
663 success = FALSE;
664
665 #ifdef AGS_W32API
666 lv2_descriptor = (LV2_Descriptor_Function) GetProcAddress(plugin_so,
667 "lv2_descriptor");
668
669 success = (!lv2_descriptor) ? FALSE: TRUE;
670 #else
671 lv2_descriptor = (LV2_Descriptor_Function) dlsym(plugin_so,
672 "lv2_descriptor");
673
674 success = (dlerror() == NULL) ? TRUE: FALSE;
675 #endif
676
677 if(success && lv2_descriptor){
678 effect_index = 0;
679
680 for(i = 0; (plugin_descriptor = lv2_descriptor((unsigned long) i)) != NULL; i++){
681 if(!g_ascii_strcasecmp(plugin_descriptor->URI,
682 lv2_plugin->uri)){
683 effect_index = i;
684
685 g_object_set(lv2_plugin,
686 "effect-index", effect_index,
687 NULL);
688
689 break;
690 }
691 }
692
693 g_rec_mutex_lock(recall_mutex);
694
695 play_lv2_audio->plugin_descriptor = plugin_descriptor;
696
697 g_rec_mutex_unlock(recall_mutex);
698
699 if(ags_lv2_plugin_test_flags(lv2_plugin, AGS_LV2_PLUGIN_NEEDS_WORKER)){
700 ags_play_lv2_audio_set_flags(play_lv2_audio, AGS_PLAY_LV2_AUDIO_HAS_WORKER);
701 }
702 }
703 }
704
705 /* free */
706 g_free(filename);
707 g_free(effect);
708 }
709
710 /**
711 * ags_play_lv2_audio_load_ports:
712 * @play_lv2_audio: the #AgsPlayLv2Audio
713 *
714 * Set up LV2 ports.
715 *
716 * Returns: (element-type AgsAudio.Port) (transfer full): the #GList-struct containing #AgsPort
717 *
718 * Since: 3.0.0
719 */
720 GList*
ags_play_lv2_audio_load_ports(AgsPlayLv2Audio * play_lv2_audio)721 ags_play_lv2_audio_load_ports(AgsPlayLv2Audio *play_lv2_audio)
722 {
723 AgsPort *current;
724
725 AgsLv2Plugin *lv2_plugin;
726
727 GList *start_port;
728 GList *start_plugin_port, *plugin_port;
729
730 gchar *filename, *effect;
731 gchar *plugin_name;
732
733 uint32_t port_count;
734 uint32_t i;
735
736 GRecMutex *recall_mutex;
737 GRecMutex *base_plugin_mutex;
738
739 if(!AGS_IS_PLAY_LV2_AUDIO(play_lv2_audio)){
740 return(NULL);
741 }
742
743 /* get recall mutex */
744 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_lv2_audio);
745
746 /* get filename and effect */
747 g_rec_mutex_lock(recall_mutex);
748
749 filename = g_strdup(AGS_RECALL(play_lv2_audio)->filename);
750 effect = g_strdup(AGS_RECALL(play_lv2_audio)->effect);
751
752 g_rec_mutex_unlock(recall_mutex);
753
754 /* find AgsLv2Plugin */
755 lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
756 filename, effect);
757
758 play_lv2_audio->plugin = lv2_plugin;
759
760 /* get plugin port */
761 g_object_get(lv2_plugin,
762 "plugin-port", &start_plugin_port,
763 NULL);
764
765 /* get base plugin mutex */
766 base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(lv2_plugin);
767
768 /* get plugin name */
769 g_rec_mutex_lock(base_plugin_mutex);
770
771 plugin_name = g_strdup_printf("lv2-<%s>", lv2_plugin->uri);
772
773 g_rec_mutex_unlock(base_plugin_mutex);
774
775 plugin_port = start_plugin_port;
776 start_port = NULL;
777
778 if(plugin_port != NULL){
779 port_count = g_list_length(plugin_port);
780
781 for(i = 0; i < port_count; i++){
782 gchar *specifier;
783
784 GValue *value;
785
786 GRecMutex *plugin_port_mutex;
787
788 /* get plugin port mutex */
789 plugin_port_mutex = AGS_PLUGIN_PORT_GET_OBJ_MUTEX(plugin_port->data);
790
791 if(ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_INPUT)){
792 if(ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_EVENT)){
793 play_lv2_audio->flags |= AGS_PLAY_LV2_AUDIO_HAS_EVENT_PORT;
794 play_lv2_audio->event_port = AGS_PLUGIN_PORT(plugin_port->data)->port_index;
795 }
796
797 if(ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_ATOM)){
798 play_lv2_audio->flags |= AGS_PLAY_LV2_AUDIO_HAS_ATOM_PORT;
799 play_lv2_audio->atom_port = AGS_PLUGIN_PORT(plugin_port->data)->port_index;
800 }
801 }
802
803 if(ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_CONTROL) &&
804 (ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_INPUT) ||
805 ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_OUTPUT))){
806 gchar *specifier;
807
808 /* get specifier */
809 g_rec_mutex_lock(plugin_port_mutex);
810
811 specifier = g_strdup(AGS_PLUGIN_PORT(plugin_port->data)->port_name);
812
813 g_rec_mutex_unlock(plugin_port_mutex);
814
815 if(specifier == NULL){
816 plugin_port = plugin_port->next;
817
818 continue;
819 }
820
821 current = g_object_new(AGS_TYPE_PORT,
822 "plugin-name", plugin_name,
823 "specifier", specifier,
824 "control-port", g_strdup_printf("%u/%u",
825 i,
826 port_count),
827 "port-value-is-pointer", FALSE,
828 "port-value-type", G_TYPE_FLOAT,
829 NULL);
830 g_object_ref(current);
831
832 if(ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_OUTPUT)){
833 ags_recall_set_flags((AgsRecall *) play_lv2_audio,
834 AGS_RECALL_HAS_OUTPUT_PORT);
835
836 ags_port_set_flags((AgsPort *) current,
837 AGS_PORT_IS_OUTPUT);
838 }else{
839 gint scale_steps;
840
841 g_object_get(plugin_port->data,
842 "scale-steps", &scale_steps,
843 NULL);
844
845 if(!ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_INTEGER) &&
846 !ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_TOGGLED) &&
847 scale_steps == -1){
848 ags_port_set_flags((AgsPort *) current,
849 AGS_PORT_INFINITE_RANGE);
850 }
851 }
852
853 g_object_set(current,
854 "plugin-port", plugin_port->data,
855 NULL);
856
857 ags_play_lv2_audio_load_conversion(play_lv2_audio,
858 (GObject *) current,
859 (GObject *) plugin_port->data);
860
861 g_object_get(plugin_port->data,
862 "default-value", &value,
863 NULL);
864
865 current->port_value.ags_port_ladspa = g_value_get_float(value);
866
867 #ifdef AGS_DEBUG
868 g_message("connecting port: %s %d/%d", specifier, i, port_count);
869 #endif
870
871 start_port = g_list_prepend(start_port,
872 current);
873 }else if(ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_AUDIO)){
874 guint port_index;
875
876 g_object_get(plugin_port->data,
877 "port-index", &port_index,
878 NULL);
879
880 if(ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_INPUT)){
881 g_rec_mutex_lock(recall_mutex);
882
883 if(play_lv2_audio->input_port == NULL){
884 play_lv2_audio->input_port = (uint32_t *) malloc(sizeof(uint32_t));
885 play_lv2_audio->input_port[0] = port_index;
886 }else{
887 play_lv2_audio->input_port = (uint32_t *) realloc(play_lv2_audio->input_port,
888 (play_lv2_audio->input_lines + 1) * sizeof(uint32_t));
889 play_lv2_audio->input_port[play_lv2_audio->input_lines] = port_index;
890 }
891
892 play_lv2_audio->input_lines += 1;
893
894 g_rec_mutex_unlock(recall_mutex);
895 }else if(ags_plugin_port_test_flags((AgsPluginPort *) plugin_port->data, AGS_PLUGIN_PORT_OUTPUT)){
896 g_rec_mutex_lock(recall_mutex);
897
898 if(play_lv2_audio->output_port == NULL){
899 play_lv2_audio->output_port = (uint32_t *) malloc(sizeof(uint32_t));
900 play_lv2_audio->output_port[0] = port_index;
901 }else{
902 play_lv2_audio->output_port = (uint32_t *) realloc(play_lv2_audio->output_port,
903 (play_lv2_audio->output_lines + 1) * sizeof(uint32_t));
904 play_lv2_audio->output_port[play_lv2_audio->output_lines] = port_index;
905 }
906
907 play_lv2_audio->output_lines += 1;
908
909 g_rec_mutex_unlock(recall_mutex);
910 }
911 }
912
913 /* iterate */
914 plugin_port = plugin_port->next;
915 }
916
917 start_port = g_list_reverse(start_port);
918 AGS_RECALL(play_lv2_audio)->port = g_list_copy(start_port);
919 }
920
921 /* unref/free */
922 g_list_free_full(start_plugin_port,
923 g_object_unref);
924
925 g_free(filename);
926 g_free(effect);
927
928 g_free(plugin_name);
929
930 #ifdef AGS_DEBUG
931 g_message("output lines: %d", play_lv2_audio->output_lines);
932 #endif
933
934 return(start_port);
935 }
936
937 /**
938 * ags_play_lv2_audio_load_conversion:
939 * @play_lv2_audio: the #AgsPlayLv2Audio
940 * @port: the #AgsPort
941 * @plugin_port: the #AgsPluginPort
942 *
943 * Loads conversion object by using @plugin_port and sets in on @port.
944 *
945 * Since: 3.0.0
946 */
947 void
ags_play_lv2_audio_load_conversion(AgsPlayLv2Audio * play_lv2_audio,GObject * port,GObject * plugin_port)948 ags_play_lv2_audio_load_conversion(AgsPlayLv2Audio *play_lv2_audio,
949 GObject *port,
950 GObject *plugin_port)
951 {
952 AgsLv2Conversion *lv2_conversion;
953
954 if(!AGS_IS_PLAY_LV2_AUDIO(play_lv2_audio) ||
955 !AGS_IS_PORT(port) ||
956 !AGS_PLUGIN_PORT(plugin_port)){
957 return;
958 }
959
960 lv2_conversion = NULL;
961
962 if(ags_plugin_port_test_flags((AgsPluginPort *) plugin_port, AGS_PLUGIN_PORT_LOGARITHMIC)){
963 lv2_conversion = ags_lv2_conversion_new();
964 lv2_conversion->flags |= AGS_LV2_CONVERSION_LOGARITHMIC;
965
966 g_object_set(port,
967 "conversion", lv2_conversion,
968 NULL);
969 }
970 }
971
972 /**
973 * ags_play_lv2_audio_find:
974 * @recall: (element-type AgsAudio.Recall) (transfer none): the #GList-struct containing #AgsRecall
975 * @filename: plugin's filename
976 * @uri: plugin's uri
977 *
978 * Retrieve LV2 recall.
979 *
980 * Returns: (element-type AgsAudio.Recall) (transfer none): Next match.
981 *
982 * Since: 3.0.0
983 */
984 GList*
ags_play_lv2_audio_find(GList * recall,gchar * filename,gchar * uri)985 ags_play_lv2_audio_find(GList *recall,
986 gchar *filename, gchar *uri)
987 {
988 while(recall != NULL){
989 if(AGS_IS_PLAY_LV2_AUDIO(recall->data)){
990 gboolean success;
991
992 GRecMutex *recall_mutex;
993
994 /* get recall mutex */
995 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(recall->data);
996
997 /* check current filename and effect */
998 g_rec_mutex_lock(recall_mutex);
999
1000 success = (!g_strcmp0(AGS_RECALL(recall->data)->filename,
1001 filename) &&
1002 !g_strcmp0(AGS_PLAY_LV2_AUDIO(recall->data)->uri,
1003 uri)) ? TRUE: FALSE;
1004
1005 g_rec_mutex_unlock(recall_mutex);
1006
1007 if(success){
1008 break;
1009 }
1010 }
1011
1012 /* iterate */
1013 recall = recall->next;
1014 }
1015
1016 return(recall);
1017 }
1018
1019 /**
1020 * ags_play_lv2_audio_new:
1021 * @audio: the #AgsAudio
1022 *
1023 * Create a new instance of #AgsPlayLv2Audio
1024 *
1025 * Returns: the new #AgsPlayLv2Audio
1026 *
1027 * Since: 3.0.0
1028 */
1029 AgsPlayLv2Audio*
ags_play_lv2_audio_new(AgsAudio * audio)1030 ags_play_lv2_audio_new(AgsAudio *audio)
1031 {
1032 AgsPlayLv2Audio *play_lv2_audio;
1033
1034 play_lv2_audio = (AgsPlayLv2Audio *) g_object_new(AGS_TYPE_PLAY_LV2_AUDIO,
1035 "audio", audio,
1036 NULL);
1037
1038 return(play_lv2_audio);
1039 }
1040