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/recall/ags_play_dssi_audio_run.h>
21
22 #include <ags/plugin/ags_dssi_manager.h>
23 #include <ags/plugin/ags_ladspa_conversion.h>
24 #include <ags/plugin/ags_dssi_plugin.h>
25 #include <ags/plugin/ags_plugin_port.h>
26
27 #include <ags/audio/ags_sound_enums.h>
28 #include <ags/audio/ags_audio.h>
29 #include <ags/audio/ags_recall_id.h>
30 #include <ags/audio/ags_recall_container.h>
31 #include <ags/audio/ags_port.h>
32 #include <ags/audio/ags_audio_buffer_util.h>
33
34 #include <ags/audio/recall/ags_play_dssi_audio.h>
35 #include <ags/audio/recall/ags_delay_audio.h>
36 #include <ags/audio/recall/ags_delay_audio_run.h>
37
38 #include <ags/audio/thread/ags_audio_loop.h>
39 #include <ags/audio/thread/ags_soundcard_thread.h>
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sys/types.h>
45 #include <unistd.h>
46
47 #include <ladspa.h>
48
49 #include <ags/i18n.h>
50
51 void ags_play_dssi_audio_run_class_init(AgsPlayDssiAudioRunClass *play_dssi_audio_run);
52 void ags_play_dssi_audio_run_connectable_interface_init(AgsConnectableInterface *connectable);
53 void ags_play_dssi_audio_run_init(AgsPlayDssiAudioRun *play_dssi_audio_run);
54 void ags_play_dssi_audio_run_set_property(GObject *gobject,
55 guint prop_id,
56 const GValue *value,
57 GParamSpec *param_spec);
58 void ags_play_dssi_audio_run_get_property(GObject *gobject,
59 guint prop_id,
60 GValue *value,
61 GParamSpec *param_spec);
62 void ags_play_dssi_audio_run_dispose(GObject *gobject);
63 void ags_play_dssi_audio_run_finalize(GObject *gobject);
64
65 void ags_play_dssi_audio_run_connect(AgsConnectable *connectable);
66 void ags_play_dssi_audio_run_disconnect(AgsConnectable *connectable);
67 void ags_play_dssi_audio_run_connect_connection(AgsConnectable *connectable,
68 GObject *connection);
69 void ags_play_dssi_audio_run_disconnect_connection(AgsConnectable *connectable,
70 GObject *connection);
71
72 void ags_play_dssi_audio_run_read(AgsFile *file, xmlNode *node, AgsPlugin *plugin);
73 xmlNode* ags_play_dssi_audio_run_write(AgsFile *file, xmlNode *parent, AgsPlugin *plugin);
74
75 void ags_play_dssi_audio_run_run_init_pre(AgsRecall *recall);
76 void ags_play_dssi_audio_run_run_pre(AgsRecall *recall);
77
78 void ags_play_dssi_audio_run_resolve_dependency(AgsRecall *recall);
79
80 void ags_play_dssi_audio_run_alloc_input_callback(AgsDelayAudioRun *delay_audio_run,
81 guint nth_run,
82 gdouble delay, guint attack,
83 AgsPlayDssiAudioRun *play_dssi_audio_run);
84
85 /**
86 * SECTION:ags_play_dssi_audio_run
87 * @short_description: play dssi
88 * @title: AgsPlayDssiAudioRun
89 * @section_id:
90 * @include: ags/audio/recall/ags_play_dssi_audio_run.h
91 *
92 * The #AgsPlayDssiAudioRun class play dssi.
93 */
94
95 enum{
96 PROP_0,
97 PROP_DELAY_AUDIO_RUN,
98 PROP_COUNT_BEATS_AUDIO_RUN,
99 PROP_DESTINATION,
100 PROP_NOTATION,
101 };
102
103 static gpointer ags_play_dssi_audio_run_parent_class = NULL;
104 static AgsConnectableInterface* ags_play_dssi_audio_run_parent_connectable_interface;
105
106 GType
ags_play_dssi_audio_run_get_type()107 ags_play_dssi_audio_run_get_type()
108 {
109 static volatile gsize g_define_type_id__volatile = 0;
110
111 if(g_once_init_enter (&g_define_type_id__volatile)){
112 GType ags_type_play_dssi_audio_run;
113
114 static const GTypeInfo ags_play_dssi_audio_run_info = {
115 sizeof (AgsPlayDssiAudioRunClass),
116 NULL, /* base_init */
117 NULL, /* base_finalize */
118 (GClassInitFunc) ags_play_dssi_audio_run_class_init,
119 NULL, /* class_finalize */
120 NULL, /* class_data */
121 sizeof (AgsPlayDssiAudioRun),
122 0, /* n_preallocs */
123 (GInstanceInitFunc) ags_play_dssi_audio_run_init,
124 };
125
126 static const GInterfaceInfo ags_connectable_interface_info = {
127 (GInterfaceInitFunc) ags_play_dssi_audio_run_connectable_interface_init,
128 NULL, /* interface_finalize */
129 NULL, /* interface_data */
130 };
131
132 ags_type_play_dssi_audio_run = g_type_register_static(AGS_TYPE_RECALL_AUDIO_RUN,
133 "AgsPlayDssiAudioRun",
134 &ags_play_dssi_audio_run_info,
135 0);
136
137 g_type_add_interface_static(ags_type_play_dssi_audio_run,
138 AGS_TYPE_CONNECTABLE,
139 &ags_connectable_interface_info);
140
141 g_once_init_leave (&g_define_type_id__volatile, ags_type_play_dssi_audio_run);
142 }
143
144 return g_define_type_id__volatile;
145 }
146
147 void
ags_play_dssi_audio_run_class_init(AgsPlayDssiAudioRunClass * play_dssi_audio_run)148 ags_play_dssi_audio_run_class_init(AgsPlayDssiAudioRunClass *play_dssi_audio_run)
149 {
150 GObjectClass *gobject;
151 AgsRecallClass *recall;
152
153 GParamSpec *param_spec;
154
155 ags_play_dssi_audio_run_parent_class = g_type_class_peek_parent(play_dssi_audio_run);
156
157 /* GObjectClass */
158 gobject = (GObjectClass *) play_dssi_audio_run;
159
160 gobject->set_property = ags_play_dssi_audio_run_set_property;
161 gobject->get_property = ags_play_dssi_audio_run_get_property;
162
163 gobject->dispose = ags_play_dssi_audio_run_dispose;
164 gobject->finalize = ags_play_dssi_audio_run_finalize;
165
166 /* properties */
167 /**
168 * AgsPlayDssiAudioRun:delay-audio-run:
169 *
170 * The delay audio run dependency.
171 *
172 * Since: 3.0.0
173 */
174 param_spec = g_param_spec_object("delay-audio-run",
175 i18n_pspec("assigned AgsDelayAudioRun"),
176 i18n_pspec("the AgsDelayAudioRun which emits ::notation-alloc-input() signal"),
177 AGS_TYPE_DELAY_AUDIO_RUN,
178 G_PARAM_READABLE | G_PARAM_WRITABLE);
179 g_object_class_install_property(gobject,
180 PROP_DELAY_AUDIO_RUN,
181 param_spec);
182
183 /**
184 * AgsPlayDssiAudioRun:count-beats-audio-run:
185 *
186 * The count beats audio run dependency.
187 *
188 * Since: 3.0.0
189 */
190 param_spec = g_param_spec_object("count-beats-audio-run",
191 i18n_pspec("assigned AgsCountBeatsAudioRun"),
192 i18n_pspec("the AgsCountBeatsAudioRun which just counts"),
193 AGS_TYPE_COUNT_BEATS_AUDIO_RUN,
194 G_PARAM_READABLE | G_PARAM_WRITABLE);
195 g_object_class_install_property(gobject,
196 PROP_COUNT_BEATS_AUDIO_RUN,
197 param_spec);
198
199 /**
200 * AgsPlayDssiAudioRun:destination:
201 *
202 * The destination's audio signal.
203 *
204 * Since: 3.0.0
205 */
206 param_spec = g_param_spec_object("destination",
207 i18n_pspec("destination"),
208 i18n_pspec("The destination audio signal"),
209 AGS_TYPE_AUDIO_SIGNAL,
210 G_PARAM_READABLE | G_PARAM_WRITABLE);
211 g_object_class_install_property(gobject,
212 PROP_DESTINATION,
213 param_spec);
214
215 /**
216 * AgsPlayDssiAudioRun:notation:
217 *
218 * The notation containing the notes.
219 *
220 * Since: 3.0.0
221 */
222 param_spec = g_param_spec_object("notation",
223 i18n_pspec("assigned AgsNotation"),
224 i18n_pspec("The AgsNotation containing notes"),
225 AGS_TYPE_NOTATION,
226 G_PARAM_READABLE | G_PARAM_WRITABLE);
227 g_object_class_install_property(gobject,
228 PROP_NOTATION,
229 param_spec);
230
231 /* AgsRecallClass */
232 recall = (AgsRecallClass *) play_dssi_audio_run;
233
234 recall->resolve_dependency = ags_play_dssi_audio_run_resolve_dependency;
235 recall->run_init_pre = ags_play_dssi_audio_run_run_init_pre;
236 recall->run_pre = ags_play_dssi_audio_run_run_pre;
237 }
238
239 void
ags_play_dssi_audio_run_connectable_interface_init(AgsConnectableInterface * connectable)240 ags_play_dssi_audio_run_connectable_interface_init(AgsConnectableInterface *connectable)
241 {
242 ags_play_dssi_audio_run_parent_connectable_interface = g_type_interface_peek_parent(connectable);
243
244 connectable->connect = ags_play_dssi_audio_run_connect;
245 connectable->disconnect = ags_play_dssi_audio_run_disconnect;
246
247 connectable->connect_connection = ags_play_dssi_audio_run_connect_connection;
248 connectable->disconnect_connection = ags_play_dssi_audio_run_disconnect_connection;
249 }
250
251 void
ags_play_dssi_audio_run_init(AgsPlayDssiAudioRun * play_dssi_audio_run)252 ags_play_dssi_audio_run_init(AgsPlayDssiAudioRun *play_dssi_audio_run)
253 {
254 guint i;
255
256 ags_recall_set_ability_flags((AgsRecall *) play_dssi_audio_run, (AGS_SOUND_ABILITY_SEQUENCER |
257 AGS_SOUND_ABILITY_NOTATION |
258 AGS_SOUND_ABILITY_WAVE |
259 AGS_SOUND_ABILITY_MIDI));
260
261 AGS_RECALL(play_dssi_audio_run)->name = "ags-play-dssi";
262 AGS_RECALL(play_dssi_audio_run)->version = AGS_RECALL_DEFAULT_VERSION;
263 AGS_RECALL(play_dssi_audio_run)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
264 AGS_RECALL(play_dssi_audio_run)->xml_type = "ags-play-dssi-audio-run";
265 AGS_RECALL(play_dssi_audio_run)->port = NULL;
266
267 play_dssi_audio_run->audio_channels = 0;
268
269 play_dssi_audio_run->ladspa_handle = NULL;
270
271 play_dssi_audio_run->port_data = NULL;
272
273 play_dssi_audio_run->input = NULL;
274 play_dssi_audio_run->output = NULL;
275
276 play_dssi_audio_run->delta_time = 0;
277
278 play_dssi_audio_run->event_buffer = (snd_seq_event_t **) malloc(AGS_PLAY_DSSI_AUDIO_RUN_DEFAULT_MIDI_LENGHT * sizeof(snd_seq_event_t *));
279
280 for(i = 0; i < AGS_PLAY_DSSI_AUDIO_RUN_DEFAULT_MIDI_LENGHT; i++){
281 play_dssi_audio_run->event_buffer[i] = NULL;
282 }
283
284 play_dssi_audio_run->event_count = (unsigned long *) malloc(AGS_PLAY_DSSI_AUDIO_RUN_DEFAULT_MIDI_LENGHT * sizeof(unsigned long));
285
286 for(i = 0; i < AGS_PLAY_DSSI_AUDIO_RUN_DEFAULT_MIDI_LENGHT; i++){
287 play_dssi_audio_run->event_count[i] = 0;
288 }
289
290 play_dssi_audio_run->key_on = 0;
291
292 play_dssi_audio_run->delay_audio_run = NULL;
293 play_dssi_audio_run->count_beats_audio_run = NULL;
294
295 play_dssi_audio_run->destination = NULL;
296
297 play_dssi_audio_run->notation = NULL;
298
299 play_dssi_audio_run->timestamp = ags_timestamp_new();
300 g_object_ref(play_dssi_audio_run->timestamp);
301
302 play_dssi_audio_run->timestamp->flags &= (~AGS_TIMESTAMP_UNIX);
303 play_dssi_audio_run->timestamp->flags |= AGS_TIMESTAMP_OFFSET;
304
305 play_dssi_audio_run->timestamp->timer.ags_offset.offset = 0;
306 }
307
308 void
ags_play_dssi_audio_run_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)309 ags_play_dssi_audio_run_set_property(GObject *gobject,
310 guint prop_id,
311 const GValue *value,
312 GParamSpec *param_spec)
313 {
314 AgsPlayDssiAudioRun *play_dssi_audio_run;
315
316 GRecMutex *recall_mutex;
317
318 play_dssi_audio_run = AGS_PLAY_DSSI_AUDIO_RUN(gobject);
319
320 /* get recall mutex */
321 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(gobject);
322
323 switch(prop_id){
324 case PROP_DELAY_AUDIO_RUN:
325 {
326 AgsDelayAudioRun *delay_audio_run, *old_delay_audio_run;
327
328 gboolean is_template;
329
330 delay_audio_run = g_value_get_object(value);
331 old_delay_audio_run = NULL;
332
333 g_rec_mutex_lock(recall_mutex);
334
335 if(delay_audio_run == play_dssi_audio_run->delay_audio_run){
336 g_rec_mutex_unlock(recall_mutex);
337
338 return;
339 }
340
341 if(play_dssi_audio_run->delay_audio_run != NULL){
342 old_delay_audio_run = play_dssi_audio_run->delay_audio_run;
343
344 g_object_unref(G_OBJECT(play_dssi_audio_run->delay_audio_run));
345 }
346
347 if(delay_audio_run != NULL){
348 g_object_ref(delay_audio_run);
349 }
350
351 g_rec_mutex_unlock(recall_mutex);
352
353 /* check template */
354 if(delay_audio_run != NULL &&
355 ags_recall_test_flags((AgsRecall *) play_dssi_audio_run, AGS_RECALL_TEMPLATE)){
356 is_template = TRUE;
357 }else{
358 is_template = FALSE;
359 }
360
361 /* old - dependency/connection */
362 if(is_template){
363 if(old_delay_audio_run != NULL){
364 AgsRecallDependency *recall_dependency;
365
366 GList *list;
367
368 recall_dependency = NULL;
369 list = ags_recall_dependency_find_dependency(AGS_RECALL(play_dssi_audio_run)->recall_dependency,
370 old_delay_audio_run);
371
372 if(list != NULL){
373 recall_dependency = list->data;
374 }
375
376 ags_recall_remove_recall_dependency(AGS_RECALL(play_dssi_audio_run),
377 (GObject *) recall_dependency);
378 }
379 }else{
380 if(ags_connectable_is_connected(AGS_CONNECTABLE(play_dssi_audio_run))){
381 ags_connectable_disconnect_connection(AGS_CONNECTABLE(play_dssi_audio_run),
382 (GObject *) old_delay_audio_run);
383 }
384 }
385
386 /* new - dependency/connection */
387 g_rec_mutex_lock(recall_mutex);
388
389 play_dssi_audio_run->delay_audio_run = delay_audio_run;
390
391 g_rec_mutex_unlock(recall_mutex);
392
393 if(delay_audio_run != NULL){
394 if(is_template){
395 ags_recall_add_recall_dependency(AGS_RECALL(play_dssi_audio_run),
396 ags_recall_dependency_new((GObject *) delay_audio_run));
397 }else{
398 if(ags_connectable_is_connected(AGS_CONNECTABLE(play_dssi_audio_run))){
399 ags_connectable_connect_connection(AGS_CONNECTABLE(play_dssi_audio_run),
400 (GObject *) delay_audio_run);
401 }
402 }
403 }
404 }
405 break;
406 case PROP_COUNT_BEATS_AUDIO_RUN:
407 {
408 AgsCountBeatsAudioRun *count_beats_audio_run, *old_count_beats_audio_run;
409
410 gboolean is_template;
411
412 count_beats_audio_run = g_value_get_object(value);
413 old_count_beats_audio_run = NULL;
414
415 g_rec_mutex_lock(recall_mutex);
416
417 if(count_beats_audio_run == play_dssi_audio_run->count_beats_audio_run){
418 g_rec_mutex_unlock(recall_mutex);
419
420 return;
421 }
422
423 if((AGS_RECALL_TEMPLATE & (AGS_RECALL(play_dssi_audio_run)->flags)) != 0){
424 is_template = TRUE;
425 }else{
426 is_template = FALSE;
427 }
428
429 if(play_dssi_audio_run->count_beats_audio_run != NULL){
430 g_object_unref(G_OBJECT(play_dssi_audio_run->count_beats_audio_run));
431 }
432
433 if(count_beats_audio_run != NULL){
434 g_object_ref(count_beats_audio_run);
435 }
436
437 play_dssi_audio_run->count_beats_audio_run = count_beats_audio_run;
438
439 g_rec_mutex_unlock(recall_mutex);
440
441 /* check template */
442 if(count_beats_audio_run != NULL &&
443 ags_recall_test_flags((AgsRecall *) play_dssi_audio_run, AGS_RECALL_TEMPLATE)){
444 is_template = TRUE;
445 }else{
446 is_template = FALSE;
447 }
448
449 /* dependency - remove */
450 if(is_template){
451 if(old_count_beats_audio_run != NULL){
452 AgsRecallDependency *recall_dependency;
453
454 GList *list;
455
456 recall_dependency = NULL;
457 list = ags_recall_dependency_find_dependency(AGS_RECALL(play_dssi_audio_run)->recall_dependency,
458 old_count_beats_audio_run);
459
460 if(list != NULL){
461 recall_dependency = list->data;
462 }
463
464 ags_recall_remove_recall_dependency(AGS_RECALL(play_dssi_audio_run),
465 (GObject *) recall_dependency);
466 }
467 }
468
469 /* dependency - add */
470 if(is_template &&
471 count_beats_audio_run != NULL){
472 ags_recall_add_recall_dependency(AGS_RECALL(play_dssi_audio_run),
473 ags_recall_dependency_new((GObject *) count_beats_audio_run));
474 }
475 }
476 break;
477 case PROP_DESTINATION:
478 {
479 AgsAudioSignal *destination;
480
481 destination = (AgsAudioSignal *) g_value_get_object(value);
482
483 g_rec_mutex_lock(recall_mutex);
484
485 if(play_dssi_audio_run->destination == (GObject *) destination){
486 g_rec_mutex_unlock(recall_mutex);
487
488 return;
489 }
490
491 if(play_dssi_audio_run->destination != NULL){
492 g_object_unref(play_dssi_audio_run->destination);
493 }
494
495 if(destination != NULL){
496 g_object_ref(destination);
497 }
498
499 play_dssi_audio_run->destination = (GObject *) destination;
500
501 g_rec_mutex_unlock(recall_mutex);
502 }
503 break;
504 case PROP_NOTATION:
505 {
506 AgsNotation *notation;
507
508 notation = (AgsNotation *) g_value_get_object(value);
509
510 g_rec_mutex_lock(recall_mutex);
511
512 if(play_dssi_audio_run->notation == notation){
513 g_rec_mutex_unlock(recall_mutex);
514
515 return;
516 }
517
518 if(play_dssi_audio_run->notation != NULL){
519 g_object_unref(play_dssi_audio_run->notation);
520 }
521
522 if(notation != NULL){
523 g_object_ref(notation);
524 }
525
526 play_dssi_audio_run->notation = notation;
527
528 g_rec_mutex_unlock(recall_mutex);
529 }
530 break;
531 default:
532 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
533 break;
534 };
535 }
536
537 void
ags_play_dssi_audio_run_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)538 ags_play_dssi_audio_run_get_property(GObject *gobject,
539 guint prop_id,
540 GValue *value,
541 GParamSpec *param_spec)
542 {
543 AgsPlayDssiAudioRun *play_dssi_audio_run;
544
545 GRecMutex *recall_mutex;
546
547 play_dssi_audio_run = AGS_PLAY_DSSI_AUDIO_RUN(gobject);
548
549 /* get recall mutex */
550 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(gobject);
551
552 switch(prop_id){
553 case PROP_DELAY_AUDIO_RUN:
554 {
555 g_rec_mutex_lock(recall_mutex);
556
557 g_value_set_object(value, G_OBJECT(play_dssi_audio_run->delay_audio_run));
558
559 g_rec_mutex_unlock(recall_mutex);
560 }
561 break;
562 case PROP_COUNT_BEATS_AUDIO_RUN:
563 {
564 g_rec_mutex_lock(recall_mutex);
565
566 g_value_set_object(value, G_OBJECT(play_dssi_audio_run->count_beats_audio_run));
567
568 g_rec_mutex_unlock(recall_mutex);
569 }
570 break;
571 case PROP_DESTINATION:
572 {
573 g_rec_mutex_lock(recall_mutex);
574
575 g_value_set_object(value, play_dssi_audio_run->destination);
576
577 g_rec_mutex_unlock(recall_mutex);
578 }
579 break;
580 case PROP_NOTATION:
581 {
582 g_rec_mutex_lock(recall_mutex);
583
584 g_value_set_object(value, play_dssi_audio_run->notation);
585
586 g_rec_mutex_unlock(recall_mutex);
587 }
588 break;
589 default:
590 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
591 break;
592 };
593 }
594
595 void
ags_play_dssi_audio_run_dispose(GObject * gobject)596 ags_play_dssi_audio_run_dispose(GObject *gobject)
597 {
598 AgsPlayDssiAudioRun *play_dssi_audio_run;
599
600 play_dssi_audio_run = AGS_PLAY_DSSI_AUDIO_RUN(gobject);
601
602 /* delay audio run */
603 if(play_dssi_audio_run->delay_audio_run != NULL){
604 g_object_unref(G_OBJECT(play_dssi_audio_run->delay_audio_run));
605
606 play_dssi_audio_run->delay_audio_run = NULL;
607 }
608
609 /* count beats audio run */
610 if(play_dssi_audio_run->count_beats_audio_run != NULL){
611 g_object_unref(G_OBJECT(play_dssi_audio_run->count_beats_audio_run));
612
613 play_dssi_audio_run->count_beats_audio_run = NULL;
614 }
615
616 /* notation */
617 if(play_dssi_audio_run->notation != NULL){
618 g_object_unref(G_OBJECT(play_dssi_audio_run->notation));
619
620 play_dssi_audio_run->notation = NULL;
621 }
622
623 /* call parent */
624 G_OBJECT_CLASS(ags_play_dssi_audio_run_parent_class)->dispose(gobject);
625 }
626
627 void
ags_play_dssi_audio_run_finalize(GObject * gobject)628 ags_play_dssi_audio_run_finalize(GObject *gobject)
629 {
630 AgsPlayDssiAudioRun *play_dssi_audio_run;
631
632 play_dssi_audio_run = AGS_PLAY_DSSI_AUDIO_RUN(gobject);
633
634 g_free(play_dssi_audio_run->port_data);
635
636 g_free(play_dssi_audio_run->input);
637 g_free(play_dssi_audio_run->output);
638
639 //FIXME:JK: memory leak
640 g_free(play_dssi_audio_run->event_buffer);
641 g_free(play_dssi_audio_run->event_count);
642
643 /* delay audio run */
644 if(play_dssi_audio_run->delay_audio_run != NULL){
645 g_object_unref(G_OBJECT(play_dssi_audio_run->delay_audio_run));
646 }
647
648 /* count beats audio run */
649 if(play_dssi_audio_run->count_beats_audio_run != NULL){
650 g_object_unref(G_OBJECT(play_dssi_audio_run->count_beats_audio_run));
651 }
652
653 /* notation */
654 if(play_dssi_audio_run->notation != NULL){
655 g_object_unref(G_OBJECT(play_dssi_audio_run->notation));
656 }
657
658 /* timestamp */
659 if(play_dssi_audio_run->timestamp != NULL){
660 g_object_unref(G_OBJECT(play_dssi_audio_run->timestamp));
661 }
662
663 /* call parent */
664 G_OBJECT_CLASS(ags_play_dssi_audio_run_parent_class)->finalize(gobject);
665 }
666
667 void
ags_play_dssi_audio_run_connect(AgsConnectable * connectable)668 ags_play_dssi_audio_run_connect(AgsConnectable *connectable)
669 {
670 AgsPlayDssiAudioRun *play_dssi_audio_run;
671 AgsDelayAudioRun *delay_audio_run;
672
673 if(ags_connectable_is_connected(connectable)){
674 return;
675 }
676
677 /* call parent */
678 ags_play_dssi_audio_run_parent_connectable_interface->connect(connectable);
679
680 play_dssi_audio_run = AGS_PLAY_DSSI_AUDIO_RUN(connectable);
681
682 g_object_get(play_dssi_audio_run,
683 "delay-audio-run", &delay_audio_run,
684 NULL);
685
686 ags_connectable_connect_connection(connectable, (GObject *) delay_audio_run);
687
688 if(delay_audio_run != NULL){
689 g_object_unref(delay_audio_run);
690 }
691 }
692
693 void
ags_play_dssi_audio_run_disconnect(AgsConnectable * connectable)694 ags_play_dssi_audio_run_disconnect(AgsConnectable *connectable)
695 {
696 AgsPlayDssiAudioRun *play_dssi_audio_run;
697 AgsDelayAudioRun *delay_audio_run;
698
699 if(!ags_connectable_is_connected(connectable)){
700 return;
701 }
702
703 play_dssi_audio_run = AGS_PLAY_DSSI_AUDIO_RUN(connectable);
704
705 g_object_get(play_dssi_audio_run,
706 "delay-audio-run", &delay_audio_run,
707 NULL);
708
709 ags_connectable_disconnect_connection(connectable, (GObject *) delay_audio_run);
710
711 /* call parent */
712 ags_play_dssi_audio_run_parent_connectable_interface->disconnect(connectable);
713
714 if(delay_audio_run != NULL){
715 g_object_unref(delay_audio_run);
716 }
717 }
718
719 void
ags_play_dssi_audio_run_connect_connection(AgsConnectable * connectable,GObject * connection)720 ags_play_dssi_audio_run_connect_connection(AgsConnectable *connectable, GObject *connection)
721 {
722 AgsPlayDssiAudioRun *play_dssi_audio_run;
723 AgsDelayAudioRun *delay_audio_run;
724
725 if(connection == NULL){
726 return;
727 }
728
729 play_dssi_audio_run = AGS_PLAY_DSSI_AUDIO_RUN(connectable);
730
731 g_object_get(play_dssi_audio_run,
732 "delay-audio-run", &delay_audio_run,
733 NULL);
734
735 if(connection == (GObject *) delay_audio_run){
736 g_signal_connect(G_OBJECT(delay_audio_run), "notation-alloc-input",
737 G_CALLBACK(ags_play_dssi_audio_run_alloc_input_callback), play_dssi_audio_run);
738 }
739
740 if(delay_audio_run != NULL){
741 g_object_unref(delay_audio_run);
742 }
743 }
744
745 void
ags_play_dssi_audio_run_disconnect_connection(AgsConnectable * connectable,GObject * connection)746 ags_play_dssi_audio_run_disconnect_connection(AgsConnectable *connectable, GObject *connection)
747 {
748 AgsPlayDssiAudioRun *play_dssi_audio_run;
749 AgsDelayAudioRun *delay_audio_run;
750
751 if(connection == NULL){
752 return;
753 }
754
755 play_dssi_audio_run = AGS_PLAY_DSSI_AUDIO_RUN(connectable);
756
757 g_object_get(play_dssi_audio_run,
758 "delay-audio-run", &delay_audio_run,
759 NULL);
760
761 if(connection == (GObject *) delay_audio_run){
762 g_object_disconnect(G_OBJECT(delay_audio_run),
763 "any_signal::notation-alloc-input",
764 G_CALLBACK(ags_play_dssi_audio_run_alloc_input_callback),
765 play_dssi_audio_run,
766 NULL);
767 }
768
769 if(delay_audio_run != NULL){
770 g_object_unref(delay_audio_run);
771 }
772 }
773
774 void
ags_play_dssi_audio_run_resolve_dependency(AgsRecall * recall)775 ags_play_dssi_audio_run_resolve_dependency(AgsRecall *recall)
776 {
777 AgsRecall *template;
778 AgsRecallID *recall_id;
779 AgsRecallContainer *recall_container;
780 AgsRecallDependency *recall_dependency;
781 AgsDelayAudioRun *delay_audio_run;
782 AgsCountBeatsAudioRun *count_beats_audio_run;
783
784 GList *list_start, *list;
785
786 guint i, i_stop;
787
788 g_object_get(recall,
789 "recall-id", &recall_id,
790 "recall-container", &recall_container,
791 NULL);
792
793 g_object_get(recall_container,
794 "recall-audio-run", &list_start,
795 NULL);
796
797 template = NULL;
798 list = ags_recall_find_template(list_start);
799
800 if(list != NULL){
801 template = AGS_RECALL(list->data);
802 }
803
804 g_list_free_full(list_start,
805 g_object_unref);
806
807 g_object_get(template,
808 "recall-dependency", &list_start,
809 NULL);
810
811 list = list_start;
812
813 delay_audio_run = NULL;
814 count_beats_audio_run = NULL;
815
816 i_stop = 2;
817
818 for(i = 0; i < i_stop && list != NULL;){
819 GObject *dependency;
820
821 recall_dependency = AGS_RECALL_DEPENDENCY(list->data);
822
823 g_object_get(recall_dependency,
824 "dependency", &dependency,
825 NULL);
826
827 if(AGS_IS_DELAY_AUDIO_RUN(dependency)){
828 delay_audio_run = (AgsDelayAudioRun *) ags_recall_dependency_resolve(recall_dependency,
829 recall_id);
830
831 i++;
832 }else if(AGS_IS_COUNT_BEATS_AUDIO_RUN(dependency)){
833 count_beats_audio_run = (AgsCountBeatsAudioRun *) ags_recall_dependency_resolve(recall_dependency,
834 recall_id);
835
836 i++;
837 }
838
839 g_object_unref(dependency);
840
841 /* iterate */
842 list = list->next;
843 }
844
845 g_list_free_full(list_start,
846 g_object_unref);
847
848 g_object_set(G_OBJECT(recall),
849 "delay-audio-run", delay_audio_run,
850 "count-beats-audio-run", count_beats_audio_run,
851 NULL);
852
853 g_object_unref(recall_id);
854
855 g_object_unref(recall_container);
856 }
857
858 void
ags_play_dssi_audio_run_run_init_pre(AgsRecall * recall)859 ags_play_dssi_audio_run_run_init_pre(AgsRecall *recall)
860 {
861 AgsPlayDssiAudio *play_dssi_audio;
862 AgsPlayDssiAudioRun *play_dssi_audio_run;
863
864 AgsDssiPlugin *dssi_plugin;
865
866 GObject *output_soundcard;
867
868 LADSPA_Handle *ladspa_handle;
869
870 LADSPA_Data *output, *input;
871 LADSPA_Data *port_data;
872
873 guint port_count;
874 guint output_lines, input_lines;
875 guint samplerate;
876 guint buffer_size;
877 unsigned long i, i_stop;
878
879 void (*parent_class_run_init_pre)(AgsRecall *recall);
880
881 LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor,
882 unsigned long SampleRate);
883 void (*activate)(LADSPA_Handle Instance);
884
885 GRecMutex *play_dssi_audio_mutex;
886
887 /* get parent class */
888 parent_class_run_init_pre = AGS_RECALL_CLASS(ags_play_dssi_audio_run_parent_class)->run_init_pre;
889
890 /* call parent */
891 parent_class_run_init_pre(recall);
892
893 /* get some fields */
894 play_dssi_audio_run = AGS_PLAY_DSSI_AUDIO_RUN(recall);
895
896 g_object_get(recall,
897 "output-soundcard", &output_soundcard,
898 "recall-audio", &play_dssi_audio,
899 NULL);
900
901 /* get presets */
902 ags_soundcard_get_presets(AGS_SOUNDCARD(output_soundcard),
903 NULL,
904 &samplerate,
905 &buffer_size,
906 NULL);
907
908 /* recall mutex */
909 play_dssi_audio_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_dssi_audio);
910
911 /* get some fields */
912 g_rec_mutex_lock(play_dssi_audio_mutex);
913
914 dssi_plugin = play_dssi_audio->plugin;
915
916 output_lines = play_dssi_audio->output_lines;
917 input_lines = play_dssi_audio->input_lines;
918
919 port_count = play_dssi_audio->plugin_descriptor->LADSPA_Plugin->PortCount;
920
921 instantiate = play_dssi_audio->plugin_descriptor->LADSPA_Plugin->instantiate;
922 activate = play_dssi_audio->plugin_descriptor->LADSPA_Plugin->activate;
923
924 g_rec_mutex_unlock(play_dssi_audio_mutex);
925
926 play_dssi_audio_run->port_data = (LADSPA_Data *) malloc(port_count * sizeof(LADSPA_Data));
927
928 output = NULL;
929 input = NULL;
930
931 if(input_lines > 0){
932 input = (LADSPA_Data *) malloc(input_lines *
933 buffer_size *
934 sizeof(LADSPA_Data));
935 }
936
937 output = (LADSPA_Data *) malloc(output_lines *
938 buffer_size *
939 sizeof(LADSPA_Data));
940
941 play_dssi_audio_run->output = output;
942 play_dssi_audio_run->input = input;
943
944 if(input_lines < output_lines){
945 i_stop = output_lines;
946 }else{
947 i_stop = input_lines;
948 }
949
950 ladspa_handle = NULL;
951
952 if(i_stop > 0){
953 ladspa_handle = (LADSPA_Handle *) malloc(i_stop *
954 sizeof(LADSPA_Handle));
955 }
956
957 play_dssi_audio_run->audio_channels = i_stop;
958
959
960 /* instantiate dssi */
961 g_rec_mutex_lock(play_dssi_audio_mutex);
962
963 for(i = 0; i < i_stop; i++){
964 /* instantiate dssi */
965 ladspa_handle[i] = instantiate(play_dssi_audio->plugin_descriptor->LADSPA_Plugin,
966 (unsigned long) samplerate);
967
968 #ifdef AGS_DEBUG
969 g_message("instantiate DSSI handle %d %d",
970 play_dssi_audio->bank,
971 play_dssi_audio->program);
972 #endif
973 }
974
975 g_rec_mutex_unlock(play_dssi_audio_mutex);
976
977 port_data = NULL;
978
979 if(port_count > 0){
980 port_data = (LADSPA_Data *) malloc(port_count * sizeof(LADSPA_Data));
981 }
982
983 /* */
984 play_dssi_audio_run->ladspa_handle = ladspa_handle;
985
986 play_dssi_audio_run->port_data = port_data;
987
988 /* */
989 ags_play_dssi_audio_run_load_ports(play_dssi_audio_run);
990
991 for(i = 0; i < i_stop; i++){
992 if(activate != NULL){
993 activate(play_dssi_audio_run->ladspa_handle[i]);
994 }
995
996 #ifdef AGS_DEBUG
997 g_message("instantiate DSSI handle");
998 #endif
999
1000 }
1001
1002 g_object_unref(output_soundcard);
1003
1004 g_object_unref(play_dssi_audio);
1005 }
1006
1007 void
ags_play_dssi_audio_run_run_pre(AgsRecall * recall)1008 ags_play_dssi_audio_run_run_pre(AgsRecall *recall)
1009 {
1010 AgsPlayDssiAudio *play_dssi_audio;
1011 AgsPlayDssiAudioRun *play_dssi_audio_run;
1012 AgsAudio *audio;
1013 AgsChannel *start_output, *start_input;
1014 AgsChannel *channel;
1015 AgsChannel *selected_channel;
1016 AgsRecycling *recycling;
1017 AgsRecyclingContext *recycling_context;
1018 AgsAudioSignal *destination;
1019 AgsPort *current_port;
1020 AgsRecallID *recall_id;
1021
1022 AgsDssiPlugin *dssi_plugin;
1023
1024 GObject *output_soundcard;
1025
1026 GList *list_start, *list;
1027 GList *port;
1028
1029 snd_seq_event_t *seq_event;
1030 snd_seq_event_t **event_buffer;
1031 unsigned long *event_count;
1032
1033 gchar *specifier, *current_specifier;
1034
1035 LADSPA_Data port_data;
1036
1037 guint bank, program;
1038 guint output_lines, input_lines;
1039 guint port_count;
1040 guint audio_channel;
1041 guint samplerate;
1042 guint buffer_size;
1043 guint format;
1044 guint copy_mode_in, copy_mode_out;
1045 unsigned long i, i_stop;
1046
1047 void (*parent_class_run_pre)(AgsRecall *recall);
1048
1049 void (*select_program)(LADSPA_Handle Instance,
1050 unsigned long Bank,
1051 unsigned long Program);
1052 void (*run_synth)(LADSPA_Handle Instance,
1053 unsigned long SampleCount,
1054 snd_seq_event_t *Events,
1055 unsigned long EventCount);
1056 void (*run)(LADSPA_Handle Instance,
1057 unsigned long SampleCount);
1058
1059 GRecMutex *audio_mutex;
1060 GRecMutex *play_dssi_audio_mutex;
1061 GRecMutex *port_mutex;
1062
1063 /* get parent class */
1064 parent_class_run_pre = AGS_RECALL_CLASS(ags_play_dssi_audio_run_parent_class)->run_pre;
1065
1066 /* call parent */
1067 parent_class_run_pre(recall);
1068
1069 /* get some fields */
1070 play_dssi_audio_run = AGS_PLAY_DSSI_AUDIO_RUN(recall);
1071
1072 g_object_get(recall,
1073 "output-soundcard", &output_soundcard,
1074 "audio-channel", &audio_channel,
1075 "recall-id", &recall_id,
1076 "audio", &audio,
1077 "recall-audio", &play_dssi_audio,
1078 "destination", &destination,
1079 NULL);
1080
1081 /* get presets */
1082 ags_soundcard_get_presets(AGS_SOUNDCARD(output_soundcard),
1083 NULL,
1084 NULL,
1085 &buffer_size,
1086 NULL);
1087
1088 /* recall mutex */
1089 play_dssi_audio_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_dssi_audio);
1090
1091 /* get some fields */
1092 g_rec_mutex_lock(play_dssi_audio_mutex);
1093
1094 dssi_plugin = play_dssi_audio->plugin;
1095
1096 input_lines = play_dssi_audio->input_lines;
1097 output_lines = play_dssi_audio->output_lines;
1098
1099 g_rec_mutex_unlock(play_dssi_audio_mutex);
1100
1101 /* audio mutex */
1102 audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
1103
1104 /* get some fields */
1105 g_rec_mutex_lock(audio_mutex);
1106
1107 start_output = audio->output;
1108
1109 if(start_output != NULL){
1110 g_object_ref(start_output);
1111 }
1112
1113 start_input = audio->input;
1114
1115 if(start_input != NULL){
1116 g_object_ref(start_input);
1117 }
1118
1119 g_rec_mutex_unlock(audio_mutex);
1120
1121 /* get channel */
1122 selected_channel = ags_channel_nth(start_output,
1123 audio_channel);
1124
1125 #if 0
1126 if(ags_audio_test_behaviour_flags(audio, AGS_SOUND_BEHAVIOUR_DEFAULTS_TO_INPUT)){
1127 selected_channel = ags_channel_nth(start_input,
1128 audio_channel);
1129 }else{
1130 selected_channel = ags_channel_nth(start_output,
1131 audio_channel);
1132 }
1133 #endif
1134
1135 /* recycling */
1136 g_object_get(selected_channel,
1137 "first-recycling", &recycling,
1138 NULL);
1139
1140 ags_recall_unset_behaviour_flags((AgsRecall *) recall, AGS_SOUND_BEHAVIOUR_PERSISTENT);
1141
1142 if(destination == NULL){
1143 gdouble delay;
1144 guint attack;
1145 guint length;
1146
1147 //TODO:JK: unclear
1148 attack = 0;
1149 delay = 0.0;
1150
1151 /* create new audio signal */
1152 destination = ags_audio_signal_new((GObject *) output_soundcard,
1153 (GObject *) recycling,
1154 (GObject *) recall_id);
1155
1156 g_object_set(play_dssi_audio_run,
1157 "destination", destination,
1158 NULL);
1159
1160 ags_recycling_create_audio_signal_with_defaults(recycling,
1161 destination,
1162 delay, attack);
1163 length = 1; // (guint) (2.0 * soundcard->delay[soundcard->tic_counter]) + 1;
1164 ags_audio_signal_stream_resize(destination,
1165 length);
1166
1167 ags_connectable_connect(AGS_CONNECTABLE(destination));
1168
1169 destination->stream_current = destination->stream;
1170
1171 ags_recycling_add_audio_signal(recycling,
1172 destination);
1173
1174 #ifdef AGS_DEBUG
1175 g_message("play %x to %x", destination, recall_id);
1176 g_message("creating destination");
1177 #endif
1178 }
1179
1180 g_object_get(destination,
1181 "buffer-size", &buffer_size,
1182 "format", &format,
1183 NULL);
1184
1185 /* select program */
1186 copy_mode_in = ags_audio_buffer_util_get_copy_mode(AGS_AUDIO_BUFFER_UTIL_FLOAT,
1187 ags_audio_buffer_util_format_from_soundcard(format));
1188
1189
1190 if(play_dssi_audio_run->input != NULL){
1191 ags_audio_buffer_util_clear_float(play_dssi_audio_run->input, input_lines,
1192 buffer_size);
1193 }
1194
1195 /* copy data */
1196 if(play_dssi_audio_run->input != NULL){
1197 ags_audio_buffer_util_copy_buffer_to_buffer(play_dssi_audio_run->input, (guint) input_lines, 0,
1198 destination->stream_current->data, 1, 0,
1199 (guint) buffer_size, copy_mode_in);
1200 }
1201
1202 if(play_dssi_audio_run->output != NULL){
1203 ags_audio_buffer_util_clear_float(play_dssi_audio_run->output, output_lines,
1204 buffer_size);
1205 }
1206
1207 /* select program */
1208 g_rec_mutex_lock(play_dssi_audio_mutex);
1209
1210 port_count = play_dssi_audio->plugin_descriptor->LADSPA_Plugin->PortCount;
1211
1212 select_program = play_dssi_audio->plugin_descriptor->select_program;
1213
1214 g_rec_mutex_unlock(play_dssi_audio_mutex);
1215
1216 /* retrieve port data */
1217 g_object_get(play_dssi_audio,
1218 "port", &list_start,
1219 NULL);
1220
1221 for(i = 0; i < port_count; i++){
1222 g_rec_mutex_lock(play_dssi_audio_mutex);
1223
1224 specifier = g_strdup(play_dssi_audio->plugin_descriptor->LADSPA_Plugin->PortNames[i]);
1225
1226 g_rec_mutex_unlock(play_dssi_audio_mutex);
1227
1228 list = list_start;
1229
1230 while(list != NULL){
1231 gboolean success;
1232
1233 current_port = list->data;
1234
1235 /* get port mutex */
1236 port_mutex = AGS_PORT_GET_OBJ_MUTEX(current_port);
1237
1238 /* check specifier */
1239 g_rec_mutex_lock(port_mutex);
1240
1241 current_specifier = g_strdup(current_port->specifier);
1242
1243 g_rec_mutex_unlock(port_mutex);
1244
1245 success = (!g_strcmp0(specifier,
1246 current_specifier)) ? TRUE: FALSE;
1247 g_free(current_specifier);
1248
1249 if(success){
1250 GValue value = {0,};
1251
1252 g_value_init(&value,
1253 G_TYPE_FLOAT);
1254 ags_port_safe_read(current_port,
1255 &value);
1256
1257 play_dssi_audio_run->port_data[i] = g_value_get_float(&value);
1258
1259 g_value_unset(&value);
1260
1261 break;
1262 }
1263
1264 list = list->next;
1265 }
1266
1267 g_free(specifier);
1268 }
1269
1270 g_object_get(play_dssi_audio,
1271 "bank", &bank,
1272 "program", &program,
1273 NULL);
1274
1275 if(select_program != NULL){
1276 if(input_lines < output_lines){
1277 i_stop = output_lines;
1278 }else{
1279 i_stop = input_lines;
1280 }
1281
1282 for(i = 0; i < i_stop; i++){
1283 select_program(play_dssi_audio_run->ladspa_handle[i],
1284 (unsigned long) bank,
1285 (unsigned long) program);
1286
1287 // g_message("b p %u %u", bank, program);
1288 }
1289 }
1290
1291 /* reset port data */
1292 for(i = 0; i < port_count; i++){
1293 g_rec_mutex_lock(play_dssi_audio_mutex);
1294
1295 specifier = g_strdup(play_dssi_audio->plugin_descriptor->LADSPA_Plugin->PortNames[i]);
1296
1297 g_rec_mutex_unlock(play_dssi_audio_mutex);
1298
1299 list = list_start;
1300 current_port = NULL;
1301
1302 while(list != NULL){
1303 gboolean success;
1304
1305 current_port = list->data;
1306
1307 /* get port mutex */
1308 port_mutex = AGS_PORT_GET_OBJ_MUTEX(current_port);
1309
1310 /* check specifier */
1311 g_rec_mutex_lock(port_mutex);
1312
1313 current_specifier = g_strdup(current_port->specifier);
1314
1315 g_rec_mutex_unlock(port_mutex);
1316
1317 success = (!g_strcmp0(specifier,
1318 current_specifier)) ? TRUE: FALSE;
1319 g_free(current_specifier);
1320
1321 if(success){
1322 break;
1323 }
1324
1325 list = list->next;
1326 }
1327
1328 g_free(specifier);
1329
1330 if(list != NULL){
1331 GValue value = {0,};
1332
1333 g_value_init(&value,
1334 G_TYPE_FLOAT);
1335 port_data = play_dssi_audio_run->port_data[i];
1336
1337 g_value_set_float(&value,
1338 port_data);
1339 ags_port_safe_write(current_port,
1340 &value);
1341
1342 g_value_unset(&value);
1343 }
1344 }
1345
1346 g_list_free_full(list_start,
1347 g_object_unref);
1348
1349 /* process data */
1350 g_rec_mutex_lock(play_dssi_audio_mutex);
1351
1352 run_synth = play_dssi_audio->plugin_descriptor->run_synth;
1353 run = play_dssi_audio->plugin_descriptor->LADSPA_Plugin->run;
1354
1355 g_rec_mutex_unlock(play_dssi_audio_mutex);
1356
1357 if(play_dssi_audio_run->event_buffer != NULL &&
1358 play_dssi_audio_run->key_on != 0){
1359 event_buffer = play_dssi_audio_run->event_buffer;
1360 event_count = play_dssi_audio_run->event_count;
1361
1362 while(event_buffer[0] != NULL){
1363 seq_event = event_buffer[0];
1364
1365 if(run_synth != NULL){
1366 if(event_buffer[0]->type == SND_SEQ_EVENT_NOTEON){
1367 run_synth(play_dssi_audio_run->ladspa_handle[0],
1368 (unsigned long) (output_lines * buffer_size),
1369 event_buffer[0],
1370 event_count[0]);
1371 }
1372 }else if(run != NULL){
1373 run(play_dssi_audio_run->ladspa_handle[0],
1374 (unsigned long) buffer_size);
1375 }
1376
1377 event_buffer++;
1378 event_count++;
1379 }
1380 }
1381
1382 /* create audio data */
1383 ags_audio_buffer_util_clear_buffer(destination->stream_current->data, 1,
1384 buffer_size, ags_audio_buffer_util_format_from_soundcard(format));
1385
1386 /* get copy mode and clear buffer */
1387 copy_mode_out = ags_audio_buffer_util_get_copy_mode(ags_audio_buffer_util_format_from_soundcard(format),
1388 AGS_AUDIO_BUFFER_UTIL_FLOAT);
1389
1390 /* copy data */
1391 if(play_dssi_audio_run->output != NULL){
1392 ags_audio_buffer_util_copy_buffer_to_buffer(destination->stream_current->data, 1, 0,
1393 play_dssi_audio_run->output, (guint) output_lines, 0,
1394 (guint) buffer_size, copy_mode_out);
1395 }
1396
1397 /* unref */
1398 g_object_unref(output_soundcard);
1399
1400 g_object_unref(recall_id);
1401
1402 g_object_unref(audio);
1403
1404 g_object_unref(play_dssi_audio);
1405
1406 g_object_unref(destination);
1407
1408 if(start_output != NULL){
1409 g_object_unref(start_output);
1410 }
1411
1412 if(start_input != NULL){
1413 g_object_unref(start_input);
1414 }
1415
1416 if(selected_channel != NULL){
1417 g_object_unref(selected_channel);
1418 }
1419
1420 if(recycling != NULL){
1421 g_object_unref(recycling);
1422 }
1423 }
1424
1425 void
ags_play_dssi_audio_run_alloc_input_callback(AgsDelayAudioRun * delay_audio_run,guint nth_run,gdouble delay,guint attack,AgsPlayDssiAudioRun * play_dssi_audio_run)1426 ags_play_dssi_audio_run_alloc_input_callback(AgsDelayAudioRun *delay_audio_run,
1427 guint nth_run,
1428 gdouble delay, guint attack,
1429 AgsPlayDssiAudioRun *play_dssi_audio_run)
1430 {
1431 AgsAudio *audio;
1432 AgsNotation *notation;
1433 AgsNote *note;
1434 AgsPlayDssiAudio *play_dssi_audio;
1435 AgsDelayAudio *delay_audio;
1436
1437 GObject *output_soundcard;
1438
1439 snd_seq_event_t *seq_event;
1440 snd_seq_event_t **event_buffer;
1441 unsigned long *event_count;
1442
1443 GList *start_list, *list;
1444 GList *start_current_position, *current_position;
1445 GList *start_feed_note, *feed_note;
1446 GList *start_append_note, *append_note;
1447 GList *start_remove_note, *remove_note;
1448
1449 guint audio_start_mapping;
1450 guint midi_start_mapping, midi_end_mapping;
1451 guint notation_counter;
1452 guint note_x0, note_x1;
1453 guint note_y;
1454 guint input_pads;
1455 guint selected_key;
1456 guint audio_channel;
1457 guint i;
1458
1459 GRecMutex *audio_mutex;
1460
1461 if(delay != 0.0){
1462 return;
1463 }
1464
1465 g_object_get(play_dssi_audio_run,
1466 "audio", &audio,
1467 "audio-channel", &audio_channel,
1468 "output-soundcard", &output_soundcard,
1469 "recall-audio", &play_dssi_audio,
1470 NULL);
1471
1472 g_object_get(delay_audio_run,
1473 "recall-audio", &delay_audio,
1474 NULL);
1475
1476 /* audio mutex */
1477 audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
1478
1479 /* get audio fields */
1480 g_rec_mutex_lock(audio_mutex);
1481
1482 start_list = g_list_copy_deep(audio->notation,
1483 (GCopyFunc) g_object_ref,
1484 NULL);
1485
1486 g_rec_mutex_unlock(audio_mutex);
1487
1488 if(start_list == NULL){
1489 g_object_unref(audio);
1490
1491 g_object_unref(output_soundcard);
1492
1493 g_object_unref(play_dssi_audio);
1494
1495 g_object_unref(delay_audio);
1496
1497 return;
1498 }
1499
1500 /* get notation */
1501 notation = NULL;
1502 current_position = NULL;
1503
1504 start_feed_note = NULL;
1505 start_append_note = NULL;
1506 start_remove_note = NULL;
1507
1508 /* get some fields */
1509 g_rec_mutex_lock(audio_mutex);
1510
1511 notation_counter = play_dssi_audio_run->count_beats_audio_run->notation_counter;
1512
1513 input_pads = audio->input_pads;
1514
1515 audio_start_mapping = audio->audio_start_mapping;
1516
1517 midi_start_mapping = audio->midi_start_mapping;
1518 midi_end_mapping = audio->midi_end_mapping;
1519
1520 g_rec_mutex_unlock(audio_mutex);
1521
1522 /* */
1523 play_dssi_audio_run->timestamp->timer.ags_offset.offset = AGS_NOTATION_DEFAULT_OFFSET * floor(notation_counter / AGS_NOTATION_DEFAULT_OFFSET);
1524
1525 list = ags_notation_find_near_timestamp(start_list, audio_channel,
1526 play_dssi_audio_run->timestamp);
1527
1528 start_current_position = NULL;
1529
1530 if(list != NULL){
1531 notation = list->data;
1532
1533 g_object_get(notation,
1534 "note", &start_current_position,
1535 NULL);
1536
1537 current_position = start_current_position;
1538 }
1539
1540 /*
1541 * feed midi
1542 */
1543 while(current_position != NULL){
1544 gboolean do_feed;
1545 gboolean success;
1546
1547 note = AGS_NOTE(current_position->data);
1548
1549 do_feed = ags_note_test_flags(note,
1550 AGS_NOTE_FEED);
1551 g_object_get(note,
1552 "x0", ¬e_x0,
1553 "x1", ¬e_x1,
1554 "y", ¬e_y,
1555 NULL);
1556
1557 if(note_x0 == notation_counter){
1558 start_append_note = g_list_prepend(start_append_note,
1559 note);
1560 g_object_ref(note);
1561 }else if((do_feed &&
1562 (note_x1 == notation_counter ||
1563 note_x1 + 1 == notation_counter)) ||
1564 (!do_feed &&
1565 note_x0 <= notation_counter &&
1566 note_x1 > notation_counter)){
1567 start_feed_note = g_list_prepend(start_feed_note,
1568 note);
1569 g_object_ref(note);
1570 }else if((do_feed &&
1571 note_x1 + 1 == notation_counter) ||
1572 (!do_feed &&
1573 note_x1 == notation_counter)){
1574 start_remove_note = g_list_prepend(start_remove_note,
1575 note);
1576 g_object_ref(note);
1577 }else if(note_x0 > notation_counter){
1578 break;
1579 }
1580
1581 /* iterate */
1582 current_position = current_position->next;
1583 }
1584
1585 feed_note =
1586 start_feed_note = g_list_reverse(start_feed_note);
1587
1588 append_note =
1589 start_append_note = g_list_reverse(start_append_note);
1590
1591 remove_note =
1592 start_remove_note = g_list_reverse(start_remove_note);
1593
1594 /* feed/append */
1595 if(start_feed_note != NULL){
1596 if(start_append_note != NULL){
1597 start_feed_note = g_list_concat(start_feed_note,
1598 start_append_note);
1599 }
1600 }else{
1601 start_feed_note = start_append_note;
1602 }
1603
1604 feed_note = start_feed_note;
1605
1606 for(i = 0; feed_note != NULL && i < AGS_PLAY_DSSI_AUDIO_RUN_DEFAULT_MIDI_LENGHT; i++){
1607 note = feed_note->data;
1608
1609 g_object_get(note,
1610 "y", ¬e_y,
1611 NULL);
1612
1613 /* send key-on */
1614 if(ags_audio_test_behaviour_flags(audio, AGS_SOUND_BEHAVIOUR_REVERSE_MAPPING)){
1615 selected_key = input_pads - note_y - 1;
1616 }else{
1617 selected_key = note_y;
1618 }
1619
1620 if(play_dssi_audio_run->event_buffer[i] == NULL){
1621 play_dssi_audio_run->event_buffer[i] = (snd_seq_event_t *) g_malloc(sizeof(snd_seq_event_t));
1622 }
1623
1624 seq_event = play_dssi_audio_run->event_buffer[i];
1625
1626 play_dssi_audio_run->event_count[i] = 1;
1627
1628 /* key on */
1629 memset(seq_event, 0, sizeof(snd_seq_event_t));
1630
1631 seq_event->type = SND_SEQ_EVENT_NOTEON;
1632
1633 seq_event->data.note.channel = 0;
1634 seq_event->data.note.note = 0x7f & (selected_key - audio_start_mapping + midi_start_mapping);
1635 seq_event->data.note.velocity = 127;
1636
1637 play_dssi_audio_run->key_on += 1;
1638
1639 /* iterate */
1640 feed_note = feed_note->next;
1641 }
1642
1643 for(; remove_note != NULL && i < AGS_PLAY_DSSI_AUDIO_RUN_DEFAULT_MIDI_LENGHT; i++){
1644 g_free(play_dssi_audio_run->event_buffer[i]);
1645
1646 play_dssi_audio_run->event_buffer[i] = NULL;
1647 play_dssi_audio_run->event_count[i] = 0;
1648
1649 play_dssi_audio_run->key_on -= 1;
1650
1651 /* iterate */
1652 remove_note = remove_note->next;
1653 }
1654
1655 g_list_free_full(start_list,
1656 g_object_unref);
1657 g_list_free_full(start_current_position,
1658 g_object_unref);
1659
1660 g_list_free_full(start_feed_note,
1661 g_object_unref);
1662 g_list_free_full(start_remove_note,
1663 g_object_unref);
1664
1665 /* unref */
1666 g_object_unref(audio);
1667
1668 g_object_unref(output_soundcard);
1669
1670 g_object_unref(play_dssi_audio);
1671
1672 g_object_unref(delay_audio);
1673 }
1674
1675 /**
1676 * ags_play_dssi_audio_run_load_ports:
1677 * @play_dssi_audio_run: the #AgsPlayDssiAudioRun
1678 *
1679 * Set up DSSI ports.
1680 *
1681 * Since: 3.0.0
1682 */
1683 void
ags_play_dssi_audio_run_load_ports(AgsPlayDssiAudioRun * play_dssi_audio_run)1684 ags_play_dssi_audio_run_load_ports(AgsPlayDssiAudioRun *play_dssi_audio_run)
1685 {
1686 AgsPlayDssiAudio *play_dssi_audio;
1687 AgsPort *current_port;
1688
1689 AgsDssiPlugin *dssi_plugin;
1690
1691 GList *list_start, *list;
1692
1693 gchar *plugin_name;
1694 gchar *specifier;
1695 gchar *path;
1696
1697 guint output_lines, input_lines;
1698 unsigned long port_count;
1699 unsigned long i, j, j_stop;
1700
1701 DSSI_Descriptor *plugin_descriptor;
1702 LADSPA_PortDescriptor *port_descriptor;
1703 LADSPA_PortDescriptor current_port_descriptor;
1704
1705 void (*connect_port)(LADSPA_Handle Instance,
1706 unsigned long Port,
1707 LADSPA_Data * DataLocation);
1708
1709 GRecMutex *play_dssi_audio_mutex;
1710 GRecMutex *base_plugin_mutex;
1711
1712 if(!AGS_IS_PLAY_DSSI_AUDIO_RUN(play_dssi_audio_run)){
1713 return;
1714 }
1715
1716 g_object_get(play_dssi_audio_run,
1717 "recall-audio", &play_dssi_audio,
1718 NULL);
1719
1720 /* recall mutex */
1721 play_dssi_audio_mutex = AGS_RECALL_GET_OBJ_MUTEX(play_dssi_audio);
1722
1723 /* get some fields */
1724 g_rec_mutex_lock(play_dssi_audio_mutex);
1725
1726 list_start = g_list_copy(AGS_RECALL(play_dssi_audio)->port);
1727
1728 dssi_plugin = play_dssi_audio->plugin;
1729
1730 plugin_descriptor = play_dssi_audio->plugin_descriptor;
1731
1732 input_lines = play_dssi_audio->input_lines;
1733 output_lines = play_dssi_audio->output_lines;
1734
1735 g_rec_mutex_unlock(play_dssi_audio_mutex);
1736
1737 /* base plugin mutex */
1738 base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(dssi_plugin);
1739
1740 /* get some fields */
1741 g_rec_mutex_lock(base_plugin_mutex);
1742
1743 port_count = plugin_descriptor->LADSPA_Plugin->PortCount;
1744
1745 port_descriptor = plugin_descriptor->LADSPA_Plugin->PortDescriptors;
1746 connect_port = plugin_descriptor->LADSPA_Plugin->connect_port;
1747
1748 g_rec_mutex_unlock(base_plugin_mutex);
1749
1750 if(input_lines < output_lines){
1751 j_stop = output_lines;
1752 }else{
1753 j_stop = input_lines;
1754 }
1755
1756 for(i = 0; i < port_count; i++){
1757 AgsPluginPort *plugin_port;
1758
1759 GRecMutex *port_mutex;
1760
1761 g_rec_mutex_lock(base_plugin_mutex);
1762
1763 current_port_descriptor = port_descriptor[i];
1764
1765 g_rec_mutex_unlock(base_plugin_mutex);
1766
1767 if(LADSPA_IS_PORT_CONTROL(current_port_descriptor)){
1768 if(LADSPA_IS_PORT_INPUT(current_port_descriptor) ||
1769 LADSPA_IS_PORT_OUTPUT(current_port_descriptor)){
1770 LADSPA_Data *port_pointer;
1771
1772 g_rec_mutex_lock(base_plugin_mutex);
1773
1774 specifier = g_strdup(plugin_descriptor->LADSPA_Plugin->PortNames[i]);
1775
1776 g_rec_mutex_unlock(base_plugin_mutex);
1777
1778 list = ags_port_find_specifier(list_start, specifier);
1779 g_free(specifier);
1780
1781 if(list != NULL){
1782 current_port = list->data;
1783
1784 /* get port mutex */
1785 port_mutex = AGS_PORT_GET_OBJ_MUTEX(current_port);
1786
1787 /* get port pointer */
1788 g_rec_mutex_lock(port_mutex);
1789
1790 port_pointer = (LADSPA_Data *) &(current_port->port_value.ags_port_ladspa);
1791
1792 g_rec_mutex_unlock(port_mutex);
1793
1794 for(j = 0; j < j_stop; j++){
1795 #ifdef AGS_DEBUG
1796 g_message("connecting port[%d]: %d/%d - %f", j, i, port_count, current->port_value.ags_port_ladspa);
1797 #endif
1798 connect_port(play_dssi_audio_run->ladspa_handle[j],
1799 (unsigned long) i,
1800 port_pointer);
1801 }
1802 }
1803 }
1804 }
1805 }
1806
1807 g_list_free(list_start);
1808
1809 /* connect audio port */
1810 for(j = 0; j < input_lines; j++){
1811 connect_port(play_dssi_audio_run->ladspa_handle[j],
1812 (unsigned long) (play_dssi_audio->input_port[j]),
1813 &(play_dssi_audio_run->input[j]));
1814 }
1815
1816 for(j = 0; j < play_dssi_audio->output_lines; j++){
1817 connect_port(play_dssi_audio_run->ladspa_handle[j],
1818 (unsigned long) (play_dssi_audio->output_port[j]),
1819 &(play_dssi_audio_run->output[j]));
1820 }
1821
1822 g_object_unref(play_dssi_audio);
1823 }
1824
1825 /**
1826 * ags_play_dssi_audio_run_new:
1827 * @audio: the #AgsAudio
1828 * @delay_audio_run: the #AgsDelayAudioRun dependency
1829 * @count_beats_audio_run: the #AgsCountBeatsAudioRun dependency
1830 *
1831 * Create a new instance of #AgsPlayDssiAudioRun
1832 *
1833 * Returns: the new #AgsPlayDssiAudioRun
1834 *
1835 * Since: 3.0.0
1836 */
1837 AgsPlayDssiAudioRun*
ags_play_dssi_audio_run_new(AgsAudio * audio,AgsDelayAudioRun * delay_audio_run,AgsCountBeatsAudioRun * count_beats_audio_run)1838 ags_play_dssi_audio_run_new(AgsAudio *audio,
1839 AgsDelayAudioRun *delay_audio_run,
1840 AgsCountBeatsAudioRun *count_beats_audio_run)
1841 {
1842 AgsPlayDssiAudioRun *play_dssi_audio_run;
1843
1844 play_dssi_audio_run = (AgsPlayDssiAudioRun *) g_object_new(AGS_TYPE_PLAY_DSSI_AUDIO_RUN,
1845 "audio", audio,
1846 "delay-audio-run", delay_audio_run,
1847 "count-beats-audio-run", count_beats_audio_run,
1848 NULL);
1849
1850 return(play_dssi_audio_run);
1851 }
1852