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", &note_x0,
1553 		 "x1", &note_x1,
1554 		 "y", &note_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", &note_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