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", ©_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", ©_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", ©_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", ©_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", ©_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", ©_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", ©_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", ©_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", ©_pattern_audio,
670 "recall-audio-run", ©_pattern_audio_run,
671 "recall-channel", ©_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