1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2019 Joël Krähemann
3  *
4  * This file is part of GSequencer.
5  *
6  * GSequencer is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSequencer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/audio/recall/ags_copy_pattern_channel_run.h>
21 
22 #include <ags/audio/ags_audio.h>
23 #include <ags/audio/ags_recycling.h>
24 #include <ags/audio/ags_audio_signal.h>
25 #include <ags/audio/ags_preset.h>
26 #include <ags/audio/ags_pattern.h>
27 #include <ags/audio/ags_recall_id.h>
28 #include <ags/audio/ags_recall_container.h>
29 
30 #include <ags/audio/recall/ags_copy_pattern_audio.h>
31 #include <ags/audio/recall/ags_copy_pattern_audio_run.h>
32 #include <ags/audio/recall/ags_copy_pattern_channel.h>
33 #include <ags/audio/recall/ags_delay_audio_run.h>
34 #include <ags/audio/recall/ags_count_beats_audio_run.h>
35 
36 #include <stdlib.h>
37 
38 void ags_copy_pattern_channel_run_class_init(AgsCopyPatternChannelRunClass *copy_pattern_channel_run);
39 void ags_copy_pattern_channel_run_connectable_interface_init(AgsConnectableInterface *connectable);
40 void ags_copy_pattern_channel_run_init(AgsCopyPatternChannelRun *copy_pattern_channel_run);
41 void ags_copy_pattern_channel_run_dispose(GObject *gobject);
42 void ags_copy_pattern_channel_run_finalize(GObject *gobject);
43 
44 void ags_copy_pattern_channel_run_notify_recall_audio_run(GObject *gobject,
45 							  GParamSpec *pspec,
46 							  gpointer user_data);
47 void ags_copy_pattern_channel_run_notify_recall_audio_run_after(GObject *gobject,
48 								GParamSpec *pspec,
49 								gpointer user_data);
50 void ags_copy_pattern_channel_run_notify_delay_audio_run(GObject *gobject,
51 							 GParamSpec *pspec,
52 							 AgsCopyPatternChannelRun *copy_pattern_channel_run);
53 void ags_copy_pattern_channel_run_notify_delay_audio_run_after(GObject *gobject,
54 							       GParamSpec *pspec,
55 							       AgsCopyPatternChannelRun *copy_pattern_channel_run);
56 
57 void ags_copy_pattern_channel_run_connect(AgsConnectable *connectable);
58 void ags_copy_pattern_channel_run_disconnect(AgsConnectable *connectable);
59 void ags_copy_pattern_channel_run_connect_connection(AgsConnectable *connectable, GObject *connection);
60 void ags_copy_pattern_channel_run_disconnect_connection(AgsConnectable *connectable, GObject *connection);
61 
62 void ags_copy_pattern_channel_run_run_init_pre(AgsRecall *recall);
63 void ags_copy_pattern_channel_run_done(AgsRecall *recall);
64 
65 void ags_copy_pattern_channel_run_sequencer_alloc_callback(AgsDelayAudioRun *delay_audio_run,
66 							   guint run_order,
67 							   gdouble delay, guint attack,
68 							   AgsCopyPatternChannelRun *copy_pattern_channel_run);
69 
70 /**
71  * SECTION:ags_copy_pattern_channel_run
72  * @short_description: copys pattern
73  * @title: AgsCopyPatternChannelRun
74  * @section_id:
75  * @include: ags/audio/recall/ags_copy_pattern_channel_run.h
76  *
77  * The #AgsCopyPatternChannelRun class copys pattern.
78  */
79 
80 static gpointer ags_copy_pattern_channel_run_parent_class = NULL;
81 static AgsConnectableInterface* ags_copy_pattern_channel_run_parent_connectable_interface;
82 
83 GType
ags_copy_pattern_channel_run_get_type()84 ags_copy_pattern_channel_run_get_type()
85 {
86   static volatile gsize g_define_type_id__volatile = 0;
87 
88   if(g_once_init_enter (&g_define_type_id__volatile)){
89     GType ags_type_copy_pattern_channel_run = 0;
90 
91     static const GTypeInfo ags_copy_pattern_channel_run_info = {
92       sizeof (AgsCopyPatternChannelRunClass),
93       NULL, /* base_init */
94       NULL, /* base_finalize */
95       (GClassInitFunc) ags_copy_pattern_channel_run_class_init,
96       NULL, /* class_finalize */
97       NULL, /* class_data */
98       sizeof (AgsCopyPatternChannelRun),
99       0,    /* n_preallocs */
100       (GInstanceInitFunc) ags_copy_pattern_channel_run_init,
101     };
102 
103     static const GInterfaceInfo ags_connectable_interface_info = {
104       (GInterfaceInitFunc) ags_copy_pattern_channel_run_connectable_interface_init,
105       NULL, /* interface_finalize */
106       NULL, /* interface_data */
107     };
108 
109     ags_type_copy_pattern_channel_run = g_type_register_static(AGS_TYPE_RECALL_CHANNEL_RUN,
110 							       "AgsCopyPatternChannelRun",
111 							       &ags_copy_pattern_channel_run_info,
112 							       0);
113 
114     g_type_add_interface_static(ags_type_copy_pattern_channel_run,
115 				AGS_TYPE_CONNECTABLE,
116 				&ags_connectable_interface_info);
117 
118     g_once_init_leave(&g_define_type_id__volatile, ags_type_copy_pattern_channel_run);
119   }
120 
121   return g_define_type_id__volatile;
122 }
123 
124 void
ags_copy_pattern_channel_run_class_init(AgsCopyPatternChannelRunClass * copy_pattern_channel_run)125 ags_copy_pattern_channel_run_class_init(AgsCopyPatternChannelRunClass *copy_pattern_channel_run)
126 {
127   GObjectClass *gobject;
128   AgsRecallClass *recall;
129 
130   ags_copy_pattern_channel_run_parent_class = g_type_class_peek_parent(copy_pattern_channel_run);
131 
132   /* GObjectClass */
133   gobject = (GObjectClass *) copy_pattern_channel_run;
134 
135   gobject->dispose = ags_copy_pattern_channel_run_dispose;
136   gobject->finalize = ags_copy_pattern_channel_run_finalize;
137 
138   /* AgsRecallClass */
139   recall = (AgsRecallClass *) copy_pattern_channel_run;
140 
141   recall->run_init_pre = ags_copy_pattern_channel_run_run_init_pre;
142   recall->done = ags_copy_pattern_channel_run_done;
143 }
144 
145 void
ags_copy_pattern_channel_run_connectable_interface_init(AgsConnectableInterface * connectable)146 ags_copy_pattern_channel_run_connectable_interface_init(AgsConnectableInterface *connectable)
147 {
148   AgsConnectableInterface *ags_copy_pattern_channel_run_connectable_parent_interface;
149 
150   ags_copy_pattern_channel_run_parent_connectable_interface = g_type_interface_peek_parent(connectable);
151 
152   connectable->connect = ags_copy_pattern_channel_run_connect;
153   connectable->disconnect = ags_copy_pattern_channel_run_disconnect;
154 
155   connectable->connect_connection = ags_copy_pattern_channel_run_connect_connection;
156   connectable->disconnect_connection = ags_copy_pattern_channel_run_disconnect_connection;
157 }
158 
159 void
ags_copy_pattern_channel_run_init(AgsCopyPatternChannelRun * copy_pattern_channel_run)160 ags_copy_pattern_channel_run_init(AgsCopyPatternChannelRun *copy_pattern_channel_run)
161 {
162   ags_recall_set_ability_flags((AgsRecall *) copy_pattern_channel_run, (AGS_SOUND_ABILITY_SEQUENCER));
163 
164   //  g_signal_connect(copy_pattern_channel_run, "notify::recall-audio-run",
165   //		   G_CALLBACK(ags_copy_pattern_channel_run_notify_recall_audio_run), NULL);
166 
167   g_signal_connect_after(copy_pattern_channel_run, "notify::recall-audio-run",
168 			 G_CALLBACK(ags_copy_pattern_channel_run_notify_recall_audio_run_after), NULL);
169 
170   /*  */
171   AGS_RECALL(copy_pattern_channel_run)->name = "ags-copy-pattern";
172   AGS_RECALL(copy_pattern_channel_run)->version = AGS_RECALL_DEFAULT_VERSION;
173   AGS_RECALL(copy_pattern_channel_run)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
174   AGS_RECALL(copy_pattern_channel_run)->xml_type = "ags-copy-pattern-channel-run";
175   AGS_RECALL(copy_pattern_channel_run)->port = NULL;
176 
177   AGS_RECALL(copy_pattern_channel_run)->child_type = G_TYPE_NONE;
178 
179   copy_pattern_channel_run->note = NULL;
180 }
181 
182 void
ags_copy_pattern_channel_run_dispose(GObject * gobject)183 ags_copy_pattern_channel_run_dispose(GObject *gobject)
184 {
185   AgsCopyPatternChannelRun *copy_pattern_channel_run;
186 
187   copy_pattern_channel_run = (AgsCopyPatternChannelRun *) gobject;
188 
189   /* note */
190   g_list_free_full(copy_pattern_channel_run->note,
191 		   g_object_unref);
192 
193   copy_pattern_channel_run->note = NULL;
194 
195   /* call parent */
196   G_OBJECT_CLASS(ags_copy_pattern_channel_run_parent_class)->dispose(gobject);
197 }
198 
199 void
ags_copy_pattern_channel_run_finalize(GObject * gobject)200 ags_copy_pattern_channel_run_finalize(GObject *gobject)
201 {
202   AgsCopyPatternChannelRun *copy_pattern_channel_run;
203 
204   copy_pattern_channel_run = (AgsCopyPatternChannelRun *) gobject;
205 
206   /* note */
207   g_list_free_full(copy_pattern_channel_run->note,
208 		   g_object_unref);
209 
210   /* call parent */
211   G_OBJECT_CLASS(ags_copy_pattern_channel_run_parent_class)->finalize(gobject);
212 }
213 
214 void
ags_copy_pattern_channel_run_notify_recall_audio_run(GObject * gobject,GParamSpec * pspec,gpointer user_data)215 ags_copy_pattern_channel_run_notify_recall_audio_run(GObject *gobject,
216 						     GParamSpec *pspec,
217 						     gpointer user_data)
218 {
219   AgsCopyPatternAudioRun *copy_pattern_audio_run;
220   AgsCopyPatternChannelRun *copy_pattern_channel_run;
221 
222   copy_pattern_channel_run = AGS_COPY_PATTERN_CHANNEL_RUN(gobject);
223 
224   g_object_get(copy_pattern_channel_run,
225 	       "recall-audio-run", &copy_pattern_audio_run,
226 	       NULL);
227 
228   if(copy_pattern_audio_run != NULL){
229     AgsDelayAudioRun *delay_audio_run;
230 
231     //    g_object_disconnect(copy_pattern_audio_run,
232     //			"any_signal::notify::delay-audio-run",
233     //			G_CALLBACK(ags_copy_pattern_channel_run_notify_delay_audio_run),
234     //			copy_pattern_channel_run,
235     //			NULL);
236 
237     g_object_disconnect(copy_pattern_audio_run,
238 			"any_signal::notify::delay-audio-run",
239 			G_CALLBACK(ags_copy_pattern_channel_run_notify_delay_audio_run_after),
240 			copy_pattern_channel_run,
241 			NULL);
242 
243     /* connection */
244     g_object_get(copy_pattern_audio_run,
245 		 "delay-audio-run", &delay_audio_run,
246 		 NULL);
247 
248     if(delay_audio_run != NULL &&
249        ags_connectable_is_connected(AGS_CONNECTABLE(copy_pattern_channel_run))){
250       ags_copy_pattern_channel_run_disconnect_connection(AGS_CONNECTABLE(copy_pattern_channel_run), (GObject *) delay_audio_run);
251     }
252 
253     if(delay_audio_run != NULL){
254       g_object_unref(delay_audio_run);
255     }
256 
257     g_object_unref(copy_pattern_audio_run);
258   }
259 }
260 
261 void
ags_copy_pattern_channel_run_notify_recall_audio_run_after(GObject * gobject,GParamSpec * pspec,gpointer user_data)262 ags_copy_pattern_channel_run_notify_recall_audio_run_after(GObject *gobject,
263 							   GParamSpec *pspec,
264 							   gpointer user_data)
265 {
266   AgsCopyPatternAudioRun *copy_pattern_audio_run;
267   AgsCopyPatternChannelRun *copy_pattern_channel_run;
268 
269   copy_pattern_channel_run = AGS_COPY_PATTERN_CHANNEL_RUN(gobject);
270 
271   g_object_get(copy_pattern_channel_run,
272 	       "recall-audio-run", &copy_pattern_audio_run,
273 	       NULL);
274 
275   if(copy_pattern_audio_run != NULL){
276     AgsDelayAudioRun *delay_audio_run;
277 
278     //    g_signal_connect(copy_pattern_audio_run, "notify::delay-audio-run",
279     //		     G_CALLBACK(ags_copy_pattern_channel_run_notify_delay_audio_run), copy_pattern_channel_run);
280 
281     g_signal_connect_after(copy_pattern_audio_run, "notify::delay-audio-run",
282 			   G_CALLBACK(ags_copy_pattern_channel_run_notify_delay_audio_run_after), copy_pattern_channel_run);
283 
284     /* connection */
285     g_object_get(copy_pattern_audio_run,
286 		 "delay-audio-run", &delay_audio_run,
287 		 NULL);
288 
289     if(delay_audio_run != NULL &&
290        ags_connectable_is_connected(AGS_CONNECTABLE(copy_pattern_channel_run))){
291       ags_copy_pattern_channel_run_connect_connection(AGS_CONNECTABLE(copy_pattern_channel_run), (GObject *) delay_audio_run);
292     }
293 
294     if(delay_audio_run != NULL){
295       g_object_unref(delay_audio_run);
296     }
297 
298     g_object_unref(copy_pattern_audio_run);
299   }
300 }
301 
302 void
ags_copy_pattern_channel_run_notify_delay_audio_run(GObject * gobject,GParamSpec * pspec,AgsCopyPatternChannelRun * copy_pattern_channel_run)303 ags_copy_pattern_channel_run_notify_delay_audio_run(GObject *gobject,
304 						    GParamSpec *pspec,
305 						    AgsCopyPatternChannelRun *copy_pattern_channel_run)
306 {
307   AgsCopyPatternAudioRun *copy_pattern_audio_run;
308   AgsDelayAudioRun *delay_audio_run;
309 
310   copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(gobject);
311 
312   g_object_get(copy_pattern_audio_run,
313 	       "delay-audio-run", &delay_audio_run,
314 	       NULL);
315 
316   if(delay_audio_run != NULL &&
317      ags_connectable_is_connected(AGS_CONNECTABLE(copy_pattern_channel_run))){
318     ags_connectable_disconnect_connection(AGS_CONNECTABLE(copy_pattern_channel_run), (GObject *) delay_audio_run);
319   }
320 
321   if(delay_audio_run != NULL){
322     g_object_unref(delay_audio_run);
323   }
324 }
325 
326 void
ags_copy_pattern_channel_run_notify_delay_audio_run_after(GObject * gobject,GParamSpec * pspec,AgsCopyPatternChannelRun * copy_pattern_channel_run)327 ags_copy_pattern_channel_run_notify_delay_audio_run_after(GObject *gobject,
328 							  GParamSpec *pspec,
329 							  AgsCopyPatternChannelRun *copy_pattern_channel_run)
330 {
331   AgsCopyPatternAudioRun *copy_pattern_audio_run;
332   AgsDelayAudioRun *delay_audio_run;
333 
334   copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(gobject);
335 
336   g_object_get(copy_pattern_audio_run,
337 	       "delay-audio-run", &delay_audio_run,
338 	       NULL);
339 
340   if(delay_audio_run != NULL &&
341      ags_connectable_is_connected(AGS_CONNECTABLE(copy_pattern_channel_run))){
342     ags_connectable_connect_connection(AGS_CONNECTABLE(copy_pattern_channel_run), (GObject *) delay_audio_run);
343   }
344 
345   if(delay_audio_run != NULL){
346     g_object_unref(delay_audio_run);
347   }
348 }
349 
350 void
ags_copy_pattern_channel_run_connect(AgsConnectable * connectable)351 ags_copy_pattern_channel_run_connect(AgsConnectable *connectable)
352 {
353   AgsCopyPatternAudioRun *copy_pattern_audio_run;
354   AgsCopyPatternChannelRun *copy_pattern_channel_run;
355 
356   GRecMutex *recall_mutex;
357 
358   if(ags_connectable_is_connected(connectable)){
359     return;
360   }
361 
362   copy_pattern_channel_run = AGS_COPY_PATTERN_CHANNEL_RUN(connectable);
363 
364   ags_copy_pattern_channel_run_parent_connectable_interface->connect(connectable);
365 
366   /* get recall mutex */
367   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(copy_pattern_channel_run);
368 
369   /* connection */
370   g_object_get(copy_pattern_channel_run,
371 	       "recall-audio-run", &copy_pattern_audio_run,
372 	       NULL);
373 
374   if(copy_pattern_audio_run != NULL){
375     AgsDelayAudioRun *delay_audio_run;
376 
377     g_object_get(copy_pattern_audio_run,
378 		 "delay-audio-run", &delay_audio_run,
379 		 NULL);
380 
381     if(delay_audio_run != NULL){
382       ags_connectable_connect_connection(connectable, (GObject *) delay_audio_run);
383 
384       g_object_unref(delay_audio_run);
385     }
386 
387     g_object_unref(copy_pattern_audio_run);
388   }
389 }
390 
391 void
ags_copy_pattern_channel_run_disconnect(AgsConnectable * connectable)392 ags_copy_pattern_channel_run_disconnect(AgsConnectable *connectable)
393 {
394   AgsCopyPatternAudioRun *copy_pattern_audio_run;
395   AgsCopyPatternChannelRun *copy_pattern_channel_run;
396 
397   GRecMutex *recall_mutex;
398 
399   if(!ags_connectable_is_connected(connectable)){
400     return;
401   }
402 
403   copy_pattern_channel_run = AGS_COPY_PATTERN_CHANNEL_RUN(connectable);
404 
405   ags_copy_pattern_channel_run_parent_connectable_interface->disconnect(connectable);
406 
407   /* get recall mutex */
408   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(copy_pattern_channel_run);
409 
410   /* connection */
411   g_object_get(copy_pattern_channel_run,
412 	       "recall-audio-run", &copy_pattern_audio_run,
413 	       NULL);
414 
415   if(copy_pattern_audio_run != NULL){
416     AgsDelayAudioRun *delay_audio_run;
417 
418     g_object_get(copy_pattern_audio_run,
419 		 "delay-audio-run", &delay_audio_run,
420 		 NULL);
421 
422     if(delay_audio_run != NULL){
423       ags_connectable_disconnect_connection(connectable, (GObject *) delay_audio_run);
424 
425       g_object_unref(delay_audio_run);
426     }
427 
428     g_object_unref(copy_pattern_audio_run);
429   }
430 }
431 
432 void
ags_copy_pattern_channel_run_connect_connection(AgsConnectable * connectable,GObject * connection)433 ags_copy_pattern_channel_run_connect_connection(AgsConnectable *connectable, GObject *connection)
434 {
435   AgsCopyPatternAudioRun *copy_pattern_audio_run;
436   AgsCopyPatternChannelRun *copy_pattern_channel_run;
437 
438   copy_pattern_channel_run = AGS_COPY_PATTERN_CHANNEL_RUN(connectable);
439 
440   g_object_get(copy_pattern_channel_run,
441 	       "recall-audio-run", &copy_pattern_audio_run,
442 	       NULL);
443 
444   if(copy_pattern_audio_run != NULL){
445     AgsDelayAudioRun *delay_audio_run;
446 
447     g_object_get(copy_pattern_audio_run,
448 		 "delay-audio-run", &delay_audio_run,
449 		 NULL);
450 
451     if((GObject *) delay_audio_run == connection){
452       g_signal_connect(G_OBJECT(delay_audio_run), "sequencer-alloc-input",
453 		       G_CALLBACK(ags_copy_pattern_channel_run_sequencer_alloc_callback), copy_pattern_channel_run);
454     }
455 
456     if(delay_audio_run != NULL){
457       g_object_unref(delay_audio_run);
458     }
459 
460     g_object_unref(copy_pattern_audio_run);
461   }
462 }
463 
464 void
ags_copy_pattern_channel_run_disconnect_connection(AgsConnectable * connectable,GObject * connection)465 ags_copy_pattern_channel_run_disconnect_connection(AgsConnectable *connectable, GObject *connection)
466 {
467   AgsCopyPatternAudioRun *copy_pattern_audio_run;
468   AgsCopyPatternChannelRun *copy_pattern_channel_run;
469 
470   copy_pattern_channel_run = AGS_COPY_PATTERN_CHANNEL_RUN(connectable);
471 
472   g_object_get(copy_pattern_channel_run,
473 	       "recall-audio-run", &copy_pattern_audio_run,
474 	       NULL);
475 
476   if(copy_pattern_audio_run != NULL){
477     AgsDelayAudioRun *delay_audio_run;
478 
479     g_object_get(copy_pattern_audio_run,
480 		 "delay-audio-run", &delay_audio_run,
481 		 NULL);
482 
483     if((GObject *) delay_audio_run == connection){
484       g_object_disconnect(G_OBJECT(delay_audio_run),
485 			  "any_signal::sequencer-alloc-input",
486 			  G_CALLBACK(ags_copy_pattern_channel_run_sequencer_alloc_callback),
487 			  copy_pattern_channel_run,
488 			  NULL);
489     }
490 
491     if(delay_audio_run != NULL){
492       g_object_unref(delay_audio_run);
493     }
494 
495     g_object_unref(copy_pattern_audio_run);
496   }
497 }
498 
499 void
ags_copy_pattern_channel_run_run_init_pre(AgsRecall * recall)500 ags_copy_pattern_channel_run_run_init_pre(AgsRecall *recall)
501 {
502   AgsChannel *source;
503   AgsPattern *pattern;
504   AgsNote *note;
505   AgsPort *port;
506 
507   AgsCopyPatternChannel *copy_pattern_channel;
508   AgsCopyPatternChannelRun *copy_pattern_channel_run;
509 
510   guint pad;
511   guint i, i_stop;
512 
513   GValue pattern_value = { 0, };
514 
515   void (*parent_class_run_init_pre)(AgsRecall *recall);
516 
517   GRecMutex *recall_mutex;
518   GRecMutex *pattern_mutex;
519 
520   copy_pattern_channel_run = AGS_COPY_PATTERN_CHANNEL_RUN(recall);
521 
522   /* get mutex */
523   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(recall);
524 
525   /* get parent class */
526   parent_class_run_init_pre = AGS_RECALL_CLASS(ags_copy_pattern_channel_run_parent_class)->run_init_pre;
527 
528   /* call parent */
529   parent_class_run_init_pre(recall);
530 
531   /* get some fields */
532   g_object_get(copy_pattern_channel_run,
533 	       "source", &source,
534 	       "recall-channel", &copy_pattern_channel,
535 	       NULL);
536 
537   /* get AgsPattern */
538   g_object_get(copy_pattern_channel,
539 	       "pattern", &port,
540 	       NULL);
541 
542   g_value_init(&pattern_value, G_TYPE_POINTER);
543   ags_port_safe_read(port,
544 		     &pattern_value);
545 
546   pattern = g_value_get_pointer(&pattern_value);
547 
548   g_value_unset(&pattern_value);
549 
550   g_object_unref(port);
551 
552   /* add note */
553   g_object_get(source,
554 	       "pad", &pad,
555 	       NULL);
556 
557   /* get pattern mutex */
558   pattern_mutex = AGS_PATTERN_GET_OBJ_MUTEX(pattern);
559 
560   /* i stop */
561   g_rec_mutex_lock(pattern_mutex);
562 
563   i_stop = pattern->dim[2];
564 
565   g_rec_mutex_unlock(pattern_mutex);
566 
567   for(i = 0; i < i_stop; i++){
568     note = ags_note_new();
569 
570     note->x[0] = i;
571     note->x[1] = i + 1;
572 
573     note->y = pad;
574 
575     copy_pattern_channel_run->note = g_list_prepend(copy_pattern_channel_run->note,
576 						    note);
577     //    g_object_ref(note);
578   }
579 
580   copy_pattern_channel_run->note = g_list_reverse(copy_pattern_channel_run->note);
581 
582   /* unref */
583   g_object_unref(source);
584 
585   g_object_unref(copy_pattern_channel);
586 }
587 
588 void
ags_copy_pattern_channel_run_done(AgsRecall * recall)589 ags_copy_pattern_channel_run_done(AgsRecall *recall)
590 {
591   AgsCopyPatternAudioRun *copy_pattern_audio_run;
592   AgsCopyPatternChannelRun *copy_pattern_channel_run;
593   AgsCountBeatsAudioRun *count_beats_audio_run;
594 
595   void (*parent_class_done)(AgsRecall *recall);
596 
597   GRecMutex *recall_mutex;
598 
599   copy_pattern_channel_run = AGS_COPY_PATTERN_CHANNEL_RUN(recall);
600 
601   /* get mutex */
602   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(recall);
603 
604   /* get parent class */
605   parent_class_done = AGS_RECALL_CLASS(ags_copy_pattern_channel_run_parent_class)->done;
606 
607   /* get AgsCopyPatternAudioRun */
608   g_object_get(recall,
609 	       "recall-audio-run", &copy_pattern_audio_run,
610 	       NULL);
611 
612   /* denotify dependency */
613   g_object_get(copy_pattern_audio_run,
614 	       "count-beats-audio-run", &count_beats_audio_run,
615 	       NULL);
616 
617   ags_recall_notify_dependency((AgsRecall *) count_beats_audio_run,
618  			       AGS_RECALL_NOTIFY_CHANNEL_RUN, FALSE);
619 
620   /* free notes */
621   g_rec_mutex_lock(recall_mutex);
622 
623   g_list_free_full(copy_pattern_channel_run->note,
624 		   g_object_unref);
625 
626   copy_pattern_channel_run->note = NULL;
627 
628   g_rec_mutex_unlock(recall_mutex);
629 
630   /* call parent */
631   parent_class_done(recall);
632 
633   /* unref */
634   g_object_unref(copy_pattern_audio_run);
635 
636   g_object_unref(count_beats_audio_run);
637 }
638 
639 void
ags_copy_pattern_channel_run_sequencer_alloc_callback(AgsDelayAudioRun * delay_audio_run,guint run_order,gdouble delay,guint attack,AgsCopyPatternChannelRun * copy_pattern_channel_run)640 ags_copy_pattern_channel_run_sequencer_alloc_callback(AgsDelayAudioRun *delay_audio_run,
641 						      guint run_order,
642 						      gdouble delay, guint attack,
643 						      AgsCopyPatternChannelRun *copy_pattern_channel_run)
644 {
645   AgsAudio *audio;
646   AgsChannel *source;
647   AgsPattern *pattern;
648   AgsPort *port;
649 
650   AgsCopyPatternAudio *copy_pattern_audio;
651   AgsCopyPatternAudioRun *copy_pattern_audio_run;
652   AgsCopyPatternChannel *copy_pattern_channel;
653   AgsCountBeatsAudioRun *count_beats_audio_run;
654 
655   guint64 sequencer_counter;
656   gboolean current_bit;
657 
658   GValue pattern_value = { 0, };
659   GValue i_value = { 0, };
660   GValue j_value = { 0, };
661 
662   GRecMutex *pattern_mutex;
663 
664   if(delay != 0.0){
665     return;
666   }
667 
668   g_object_get(copy_pattern_channel_run,
669 	       "recall-audio", &copy_pattern_audio,
670 	       "recall-audio-run", &copy_pattern_audio_run,
671 	       "recall-channel", &copy_pattern_channel,
672 	       NULL);
673 
674   g_object_get(copy_pattern_audio_run,
675 	       "count-beats-audio-run", &count_beats_audio_run,
676 	       NULL);
677 
678   /* get bank index 0 */
679   g_object_get(copy_pattern_audio,
680 	       "bank-index-0", &port,
681 	       NULL);
682 
683   g_value_init(&i_value, G_TYPE_FLOAT);
684   ags_port_safe_read(port, &i_value);
685 
686   g_object_unref(port);
687 
688   /* get bank index 1 */
689   g_object_get(copy_pattern_audio,
690 	       "bank-index-1", &port,
691 	       NULL);
692 
693   g_value_init(&j_value, G_TYPE_FLOAT);
694   ags_port_safe_read(port, &j_value);
695 
696   g_object_unref(port);
697 
698   /* get AgsPattern */
699   g_object_get(copy_pattern_channel,
700 	       "pattern", &port,
701 	       NULL);
702 
703   g_value_init(&pattern_value, G_TYPE_POINTER);
704   ags_port_safe_read(port,
705 		     &pattern_value);
706 
707   pattern = g_value_get_pointer(&pattern_value);
708 
709   g_object_unref(port);
710 
711   /* get pattern mutex */
712   pattern_mutex = AGS_PATTERN_GET_OBJ_MUTEX(pattern);
713 
714   /* write pattern port - current offset */
715 #if 0
716   g_object_set(pattern,
717 	       "first-index", (guint) g_value_get_float(&i_value),
718 	       "second-index", (guint) g_value_get_float(&j_value),
719 	       NULL);
720 #endif
721 
722   /* get sequencer counter */
723   g_object_get(count_beats_audio_run,
724 	       "sequencer-counter", &sequencer_counter,
725 	       NULL);
726 
727   /* read pattern port - current bit */
728   current_bit = ags_pattern_get_bit(pattern,
729 				    (guint) g_value_get_float(&i_value),
730 				    (guint) g_value_get_float(&j_value),
731 				    (guint) sequencer_counter);
732 
733   g_value_unset(&pattern_value);
734 
735   g_value_unset(&i_value);
736   g_value_unset(&j_value);
737 
738   /*  */
739   if(current_bit){
740     AgsChannel *link;
741     AgsRecycling *first_recycling, *last_recycling;
742     AgsRecycling *recycling, *next_recycling;
743     AgsRecycling *end_recycling;
744     AgsAudioSignal *audio_signal;
745     AgsNote *note;
746     AgsPreset *current_preset;
747 
748     GObject *output_soundcard;
749 
750     GList *preset_start, *preset;
751 
752     guint pad;
753     guint audio_channel;
754     guint note_offset;
755 
756 //    g_message("ags_copy_pattern_channel_run_sequencer_alloc_callback - playing channel: %u; playing pattern: %u",
757 //	      AGS_RECALL_CHANNEL(copy_pattern_channel)->source->line,
758 //	      copy_pattern_audio_run->count_beats_audio_run->sequencer_counter);
759 
760     /* get audio */
761     g_object_get(copy_pattern_audio,
762 		 "audio", &audio,
763 		 NULL);
764 
765     /* get source */
766     g_object_get(copy_pattern_channel,
767 		 "source", &source,
768 		 NULL);
769 
770     /* get output soundcard */
771     g_object_get(copy_pattern_channel_run,
772 		 "output-soundcard", &output_soundcard,
773 		 NULL);
774 
775     note_offset = ags_soundcard_get_note_offset(AGS_SOUNDCARD(output_soundcard));
776 
777     /* source fields */
778     g_object_get(source,
779 		 "link", &link,
780 		 "first-recycling", &first_recycling,
781 		 "last-recycling", &last_recycling,
782 		 "pad", &pad,
783 		 "audio-channel", &audio_channel,
784 		 NULL);
785 
786     recycling = first_recycling;
787     g_object_ref(recycling);
788 
789     end_recycling = NULL;
790 
791     if(last_recycling != NULL){
792       end_recycling = ags_recycling_next(last_recycling);
793     }
794 
795     /* find preset scope envelope */
796     current_preset = NULL;
797 
798     g_object_get(audio,
799 		 "preset", &preset_start,
800 		 NULL);
801 
802     preset = preset_start;
803 
804     while((preset = ags_preset_find_scope(preset,
805 					  "ags-envelope")) != NULL){
806       guint audio_channel_start, audio_channel_end;
807       guint pad_start, pad_end;
808       guint x_start, x_end;
809 
810       g_object_get(preset->data,
811 		   "audio-channel-start", &audio_channel_start,
812 		   "audio-channel-end", &audio_channel_end,
813 		   "pad-start", &pad_start,
814 		   "pad-end", &pad_end,
815 		   "x-start", &x_start,
816 		   "x-end", &x_end,
817 		   NULL);
818 
819       if(audio_channel >= audio_channel_start &&
820 	 audio_channel < audio_channel_end &&
821 	 pad >= pad_start &&
822 	 pad < pad_end &&
823 	 sequencer_counter >= x_start &&
824 	 sequencer_counter < x_end){
825 	current_preset = preset->data;
826 
827 	break;
828       }
829 
830       preset = preset->next;
831     }
832 
833     g_list_free_full(preset_start,
834 		     g_object_unref);
835 
836     note = g_list_nth_data(copy_pattern_channel_run->note,
837 			   sequencer_counter);
838 
839     g_object_set(note,
840 		 "rt-attack", attack,
841 		 NULL);
842 
843     /* create audio signals */
844     next_recycling = NULL;
845 
846     if(recycling != NULL){
847       AgsRecallID *child_recall_id;
848 
849       while(recycling != end_recycling){
850 	AgsNote *copy_note;
851 
852 	child_recall_id = AGS_RECALL(copy_pattern_channel_run)->recall_id;
853 
854 	/* apply preset */
855 	copy_note = ags_note_duplicate(note);
856 	g_object_set(copy_note,
857 		     "x0", note_offset,
858 		     "x1", note_offset + 1,
859 		     NULL);
860 
861 	if(current_preset != NULL){
862 	  AgsComplex *val;
863 
864 	  GValue value = {0,};
865 
866 	  GError *error;
867 
868 	  ags_note_set_flags(copy_note,
869 			     AGS_NOTE_ENVELOPE);
870 
871 	  /* get attack */
872 	  g_value_init(&value,
873 		       AGS_TYPE_COMPLEX);
874 
875 	  error = NULL;
876 	  ags_preset_get_parameter((AgsPreset *) current_preset,
877 				   "attack", &value,
878 				   &error);
879 
880 	  if(error == NULL){
881 	    g_object_set_property((GObject *) copy_note,
882 				  "attack",
883 				  &value);
884 	  }else{
885 	    g_error_free(error);
886 	  }
887 
888 	  /* get decay */
889 	  g_value_reset(&value);
890 
891 	  error = NULL;
892 	  ags_preset_get_parameter((AgsPreset *) current_preset,
893 				   "decay", &value,
894 				   &error);
895 
896 	  if(error == NULL){
897 	    g_object_set_property((GObject *) copy_note,
898 				  "decay",
899 				  &value);
900 	  }else{
901 	    g_error_free(error);
902 	  }
903 
904 	  /* get sustain */
905 	  g_value_reset(&value);
906 
907 	  error = NULL;
908 	  ags_preset_get_parameter((AgsPreset *) current_preset,
909 				   "sustain", &value,
910 				   &error);
911 
912 	  if(error == NULL){
913 	    g_object_set_property((GObject *) copy_note,
914 				  "sustain",
915 				  &value);
916 	  }else{
917 	    g_error_free(error);
918 	  }
919 
920 	  /* get release */
921 	  g_value_reset(&value);
922 
923 	  error = NULL;
924 	  ags_preset_get_parameter((AgsPreset *) current_preset,
925 				   "release", &value,
926 				   &error);
927 
928 	  if(error == NULL){
929 	    g_object_set_property((GObject *) copy_note,
930 				  "release",
931 				  &value);
932 	  }else{
933 	    g_error_free(error);
934 	  }
935 
936 	  /* get ratio */
937 	  g_value_reset(&value);
938 
939 	  error = NULL;
940 	  ags_preset_get_parameter((AgsPreset *) current_preset,
941 				   "ratio", &value,
942 				   &error);
943 
944 	  if(error == NULL){
945 	    g_object_set_property((GObject *) copy_note,
946 				  "ratio",
947 				  &value);
948 	  }else{
949 	    g_error_free(error);
950 	  }
951 
952 	  g_value_unset(&value);
953 	}
954 
955 	if(!ags_recall_global_get_rt_safe()){
956 	  /* create audio signal */
957 	  audio_signal = ags_audio_signal_new(output_soundcard,
958 					      (GObject *) recycling,
959 					      (GObject *) child_recall_id);
960 	  ags_recycling_create_audio_signal_with_defaults(recycling,
961 							  audio_signal,
962 							  0.0, attack);
963 
964 	  ags_audio_signal_unset_flags(audio_signal, AGS_AUDIO_SIGNAL_TEMPLATE);
965 
966 	  audio_signal->stream_current = audio_signal->stream;
967 
968 	  ags_connectable_connect(AGS_CONNECTABLE(audio_signal));
969 
970 	  ags_recycling_add_audio_signal(recycling,
971 					 audio_signal);
972 
973 	  g_object_set(audio_signal,
974 		       "note", copy_note,
975 		       NULL);
976 
977 	  g_object_unref(copy_note);
978 	  //g_object_unref(audio_signal);
979 	}else{
980 	  GList *list_start, *list;
981 
982 	  audio_signal = NULL;
983 
984 	  g_object_get(recycling,
985 		       "audio-signal", &list_start,
986 		       NULL);
987 
988 	  list = ags_audio_signal_find_by_recall_id(list_start,
989 						    (GObject *) child_recall_id);
990 
991 	  if(list != NULL){
992 	    audio_signal = list->data;
993 
994 	    g_object_set(audio_signal,
995 			 "note", copy_note,
996 			 NULL);
997 
998 	    g_object_unref(copy_note);
999 	  }
1000 
1001 	  g_list_free_full(list_start,
1002 			   g_object_unref);
1003 
1004 	  g_object_set(note,
1005 		       "rt-offset", 0,
1006 		       NULL);
1007 	}
1008 
1009 	/*
1010 	 * emit add_audio_signal on AgsRecycling
1011 	 */
1012 #ifdef AGS_DEBUG
1013 	g_message("play %d %x", AGS_RECALL_CHANNEL_RUN(copy_pattern_channel_run)->source->line, AGS_RECALL(copy_pattern_channel_run)->recall_id);
1014 #endif
1015 
1016 	/*
1017 	 * unref AgsAudioSignal because AgsCopyPatternChannelRun has no need for it
1018 	 * if you need a valid reference to audio_signal you have to g_object_ref(audio_signal)
1019 	 */
1020 	//	g_object_unref(audio_signal);
1021 
1022 	/* iterate */
1023 	next_recycling = ags_recycling_next(recycling);
1024 
1025 	g_object_unref(recycling);
1026 
1027 	recycling = next_recycling;
1028       }
1029     }
1030 
1031     /* unref */
1032     g_object_unref(audio);
1033     g_object_unref(source);
1034 
1035     g_object_unref(output_soundcard);
1036 
1037     if(link != NULL){
1038       g_object_unref(link);
1039     }
1040 
1041     if(first_recycling != NULL){
1042       g_object_unref(first_recycling);
1043       g_object_unref(last_recycling);
1044     }
1045 
1046     if(end_recycling != NULL){
1047       g_object_unref(end_recycling);
1048     }
1049 
1050     if(next_recycling != NULL){
1051       g_object_unref(next_recycling);
1052     }
1053   }
1054 
1055   /* unref */
1056   g_object_unref(copy_pattern_audio);
1057   g_object_unref(copy_pattern_audio_run);
1058   g_object_unref(copy_pattern_channel);
1059 
1060   g_object_unref(count_beats_audio_run);
1061 }
1062 
1063 /**
1064  * ags_copy_pattern_channel_run_new:
1065  * @destination: the destination #AgsChannel
1066  * @source: the source #AgsChannel
1067  *
1068  * Create a new instance of #AgsCopyPatternChannelRun
1069  *
1070  * Returns: the new #AgsCopyPatternChannelRun
1071  *
1072  * Since: 3.0.0
1073  */
1074 AgsCopyPatternChannelRun*
ags_copy_pattern_channel_run_new(AgsChannel * destination,AgsChannel * source)1075 ags_copy_pattern_channel_run_new(AgsChannel *destination,
1076 				 AgsChannel *source)
1077 {
1078   AgsCopyPatternChannelRun *copy_pattern_channel_run;
1079 
1080   copy_pattern_channel_run = (AgsCopyPatternChannelRun *) g_object_new(AGS_TYPE_COPY_PATTERN_CHANNEL_RUN,
1081 								       "destination", destination,
1082 								       "channel", source,
1083 								       NULL);
1084 
1085   return(copy_pattern_channel_run);
1086 }
1087