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_audio_run.h>
21
22 #include <ags/audio/ags_recall_container.h>
23
24 #include <ags/audio/recall/ags_copy_pattern_audio.h>
25
26 #include <ags/i18n.h>
27
28 void ags_copy_pattern_audio_run_class_init(AgsCopyPatternAudioRunClass *copy_pattern_audio_run);
29 void ags_copy_pattern_audio_run_init(AgsCopyPatternAudioRun *copy_pattern_audio_run);
30 void ags_copy_pattern_audio_run_set_property(GObject *gobject,
31 guint prop_id,
32 const GValue *value,
33 GParamSpec *param_spec);
34 void ags_copy_pattern_audio_run_get_property(GObject *gobject,
35 guint prop_id,
36 GValue *value,
37 GParamSpec *param_spec);
38 void ags_copy_pattern_audio_run_dispose(GObject *gobject);
39 void ags_copy_pattern_audio_run_finalize(GObject *gobject);
40
41 void ags_copy_pattern_audio_run_resolve_dependency(AgsRecall *recall);
42 void ags_copy_pattern_audio_run_notify_dependency(AgsRecall *recall,
43 guint dependency, gboolean increase);
44
45 /**
46 * SECTION:ags_copy_pattern_audio_run
47 * @short_description: copy pattern
48 * @title: AgsCopyPatternAudioRun
49 * @section_id:
50 * @include: ags/audio/recall/ags_copy_pattern_audio_run.h
51 *
52 * The #AgsCopyPatternAudioRun class copy pattern.
53 */
54
55 enum{
56 PROP_0,
57 PROP_DELAY_AUDIO_RUN,
58 PROP_COUNT_BEATS_AUDIO_RUN,
59 };
60
61 static gpointer ags_copy_pattern_audio_run_parent_class = NULL;
62
63 GType
ags_copy_pattern_audio_run_get_type()64 ags_copy_pattern_audio_run_get_type()
65 {
66 static volatile gsize g_define_type_id__volatile = 0;
67
68 if(g_once_init_enter (&g_define_type_id__volatile)){
69 GType ags_type_copy_pattern_audio_run = 0;
70
71 static const GTypeInfo ags_copy_pattern_audio_run_info = {
72 sizeof(AgsCopyPatternAudioRunClass),
73 NULL, /* base_init */
74 NULL, /* base_finalize */
75 (GClassInitFunc) ags_copy_pattern_audio_run_class_init,
76 NULL, /* class_finalize */
77 NULL, /* class_data */
78 sizeof(AgsCopyPatternAudioRun),
79 0, /* n_preallocs */
80 (GInstanceInitFunc) ags_copy_pattern_audio_run_init,
81 };
82
83 ags_type_copy_pattern_audio_run = g_type_register_static(AGS_TYPE_RECALL_AUDIO_RUN,
84 "AgsCopyPatternAudioRun",
85 &ags_copy_pattern_audio_run_info,
86 0);
87
88 g_once_init_leave(&g_define_type_id__volatile, ags_type_copy_pattern_audio_run);
89 }
90
91 return g_define_type_id__volatile;
92 }
93
94 void
ags_copy_pattern_audio_run_class_init(AgsCopyPatternAudioRunClass * copy_pattern_audio_run)95 ags_copy_pattern_audio_run_class_init(AgsCopyPatternAudioRunClass *copy_pattern_audio_run)
96 {
97 GObjectClass *gobject;
98 AgsRecallClass *recall;
99
100 GParamSpec *param_spec;
101
102 ags_copy_pattern_audio_run_parent_class = g_type_class_peek_parent(copy_pattern_audio_run);
103
104 /* GObjectClass */
105 gobject = (GObjectClass *) copy_pattern_audio_run;
106
107 gobject->set_property = ags_copy_pattern_audio_run_set_property;
108 gobject->get_property = ags_copy_pattern_audio_run_get_property;
109
110 gobject->dispose = ags_copy_pattern_audio_run_dispose;
111 gobject->finalize = ags_copy_pattern_audio_run_finalize;
112
113 /* properties */
114 /**
115 * AgsCopyPatternAudioRun:delay-audio-run:
116 *
117 * The delay audio run dependency.
118 *
119 * Since: 3.0.0
120 */
121 param_spec = g_param_spec_object("delay-audio-run",
122 i18n_pspec("assigned AgsDelayAudioRun"),
123 i18n_pspec("the AgsDelayAudioRun which emits alloc signal"),
124 AGS_TYPE_DELAY_AUDIO_RUN,
125 G_PARAM_READABLE | G_PARAM_WRITABLE);
126 g_object_class_install_property(gobject,
127 PROP_DELAY_AUDIO_RUN,
128 param_spec);
129
130 /**
131 * AgsCopyPatternAudioRun:count-beats-audio-run:
132 *
133 * The count beats audio run dependency.
134 *
135 * Since: 3.0.0
136 */
137 param_spec = g_param_spec_object("count-beats-audio-run",
138 i18n_pspec("assigned AgsCountBeatsAudioRun"),
139 i18n_pspec("the AgsCountBeatsAudioRun which emits beat signal"),
140 AGS_TYPE_COUNT_BEATS_AUDIO_RUN,
141 G_PARAM_READABLE | G_PARAM_WRITABLE);
142 g_object_class_install_property(gobject,
143 PROP_COUNT_BEATS_AUDIO_RUN,
144 param_spec);
145
146 /* AgsRecallClass */
147 recall = (AgsRecallClass *) copy_pattern_audio_run;
148
149 recall->resolve_dependency = ags_copy_pattern_audio_run_resolve_dependency;
150 recall->notify_dependency = ags_copy_pattern_audio_run_notify_dependency;
151 }
152
153 void
ags_copy_pattern_audio_run_init(AgsCopyPatternAudioRun * copy_pattern_audio_run)154 ags_copy_pattern_audio_run_init(AgsCopyPatternAudioRun *copy_pattern_audio_run)
155 {
156 ags_recall_set_ability_flags((AgsRecall *) copy_pattern_audio_run, (AGS_SOUND_ABILITY_SEQUENCER));
157
158 AGS_RECALL(copy_pattern_audio_run)->name = "ags-copy-pattern";
159 AGS_RECALL(copy_pattern_audio_run)->version = AGS_RECALL_DEFAULT_VERSION;
160 AGS_RECALL(copy_pattern_audio_run)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
161 AGS_RECALL(copy_pattern_audio_run)->xml_type = "ags-copy-pattern-audio-run";
162 AGS_RECALL(copy_pattern_audio_run)->port = NULL;
163
164 copy_pattern_audio_run->hide_ref = 0;
165 copy_pattern_audio_run->hide_ref_counter = 0;
166
167 copy_pattern_audio_run->delay_audio_run = NULL;
168 copy_pattern_audio_run->count_beats_audio_run = NULL;
169 }
170
171 void
ags_copy_pattern_audio_run_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)172 ags_copy_pattern_audio_run_set_property(GObject *gobject,
173 guint prop_id,
174 const GValue *value,
175 GParamSpec *param_spec)
176 {
177 AgsCopyPatternAudioRun *copy_pattern_audio_run;
178
179 GRecMutex *recall_mutex;
180
181 copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(gobject);
182
183 /* get recall mutex */
184 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(copy_pattern_audio_run);
185
186 switch(prop_id){
187 case PROP_DELAY_AUDIO_RUN:
188 {
189 AgsDelayAudioRun *delay_audio_run, *old_delay_audio_run;
190
191 gboolean is_template;
192
193 delay_audio_run = (AgsDelayAudioRun *) g_value_get_object(value);
194 old_delay_audio_run = NULL;
195
196 g_rec_mutex_lock(recall_mutex);
197
198 if(copy_pattern_audio_run->delay_audio_run == delay_audio_run){
199 g_rec_mutex_unlock(recall_mutex);
200
201 return;
202 }
203
204 if(copy_pattern_audio_run->delay_audio_run != NULL){
205 old_delay_audio_run = copy_pattern_audio_run->delay_audio_run;
206
207 g_object_unref(G_OBJECT(copy_pattern_audio_run->delay_audio_run));
208 }
209
210 if(delay_audio_run != NULL){
211 g_object_ref(G_OBJECT(delay_audio_run));
212 }
213
214 copy_pattern_audio_run->delay_audio_run = delay_audio_run;
215
216 g_rec_mutex_unlock(recall_mutex);
217
218 /* dependency */
219 if(ags_recall_test_flags((AgsRecall *) delay_audio_run, AGS_RECALL_TEMPLATE)){
220 is_template = TRUE;
221 }else{
222 is_template = FALSE;
223 }
224
225 if(is_template){
226 if(old_delay_audio_run != NULL){
227 AgsRecallDependency *recall_dependency;
228
229 GList *list;
230
231 recall_dependency = NULL;
232 list = ags_recall_dependency_find_dependency(AGS_RECALL(copy_pattern_audio_run)->recall_dependency,
233 (GObject *) old_delay_audio_run);
234
235 if(list != NULL){
236 recall_dependency = list->data;
237 }
238
239 ags_recall_remove_recall_dependency(AGS_RECALL(copy_pattern_audio_run),
240 recall_dependency);
241 }
242 }
243
244 if(is_template &&
245 delay_audio_run != NULL){
246 ags_recall_add_recall_dependency(AGS_RECALL(copy_pattern_audio_run),
247 ags_recall_dependency_new((GObject *) delay_audio_run));
248 }
249 }
250 break;
251 case PROP_COUNT_BEATS_AUDIO_RUN:
252 {
253 AgsCountBeatsAudioRun *count_beats_audio_run, *old_count_beats_audio_run;
254
255 gboolean is_template;
256
257 count_beats_audio_run = (AgsCountBeatsAudioRun *) g_value_get_object(value);
258 old_count_beats_audio_run = NULL;
259
260 g_rec_mutex_lock(recall_mutex);
261
262 if(copy_pattern_audio_run->count_beats_audio_run == count_beats_audio_run){
263 g_rec_mutex_unlock(recall_mutex);
264
265 return;
266 }
267
268 if(copy_pattern_audio_run->count_beats_audio_run != NULL){
269 old_count_beats_audio_run = copy_pattern_audio_run->count_beats_audio_run;
270
271 g_object_unref(G_OBJECT(copy_pattern_audio_run->count_beats_audio_run));
272 }
273
274 if(count_beats_audio_run != NULL){
275 g_object_ref(G_OBJECT(count_beats_audio_run));
276 }
277
278 copy_pattern_audio_run->count_beats_audio_run = count_beats_audio_run;
279
280 g_rec_mutex_unlock(recall_mutex);
281
282 /* check template */
283 if(count_beats_audio_run != NULL &&
284 ags_recall_test_flags((AgsRecall *) count_beats_audio_run, AGS_RECALL_TEMPLATE)){
285 is_template = TRUE;
286 }else{
287 is_template = FALSE;
288 }
289
290 /* dependency - remove */
291 if(is_template){
292 if(old_count_beats_audio_run != NULL){
293 AgsRecallDependency *recall_dependency;
294
295 GList *list;
296
297 recall_dependency = NULL;
298 list = ags_recall_dependency_find_dependency(AGS_RECALL(copy_pattern_audio_run)->recall_dependency,
299 (GObject *) old_count_beats_audio_run);
300
301 if(list != NULL){
302 recall_dependency = list->data;
303 }
304
305 ags_recall_remove_recall_dependency(AGS_RECALL(copy_pattern_audio_run),
306 recall_dependency);
307 }
308 }
309
310 /* dependency - add */
311 if(is_template &&
312 count_beats_audio_run != NULL){
313 ags_recall_add_recall_dependency(AGS_RECALL(copy_pattern_audio_run),
314 ags_recall_dependency_new((GObject *) count_beats_audio_run));
315 }
316 }
317 break;
318 default:
319 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
320 break;
321 };
322 }
323
324 void
ags_copy_pattern_audio_run_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)325 ags_copy_pattern_audio_run_get_property(GObject *gobject,
326 guint prop_id,
327 GValue *value,
328 GParamSpec *param_spec)
329 {
330 AgsCopyPatternAudioRun *copy_pattern_audio_run;
331
332 GRecMutex *recall_mutex;
333
334 copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(gobject);
335
336 /* get recall mutex */
337 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(copy_pattern_audio_run);
338
339 switch(prop_id){
340 case PROP_DELAY_AUDIO_RUN:
341 {
342 g_rec_mutex_lock(recall_mutex);
343
344 g_value_set_object(value, copy_pattern_audio_run->delay_audio_run);
345
346 g_rec_mutex_unlock(recall_mutex);
347 }
348 break;
349 case PROP_COUNT_BEATS_AUDIO_RUN:
350 {
351 g_rec_mutex_lock(recall_mutex);
352
353 g_value_set_object(value, copy_pattern_audio_run->count_beats_audio_run);
354
355 g_rec_mutex_unlock(recall_mutex);
356 }
357 break;
358 default:
359 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
360 break;
361 };
362 }
363
364 void
ags_copy_pattern_audio_run_dispose(GObject * gobject)365 ags_copy_pattern_audio_run_dispose(GObject *gobject)
366 {
367 AgsCopyPatternAudioRun *copy_pattern_audio_run;
368
369 copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(gobject);
370
371 /* delay audio run */
372 if(copy_pattern_audio_run->delay_audio_run != NULL){
373 g_object_unref(copy_pattern_audio_run->delay_audio_run);
374
375 copy_pattern_audio_run->delay_audio_run = NULL;
376 }
377
378 /* count beats audio run */
379 if(copy_pattern_audio_run->count_beats_audio_run != NULL){
380 g_object_unref(copy_pattern_audio_run->count_beats_audio_run);
381
382 copy_pattern_audio_run->count_beats_audio_run = NULL;
383 }
384
385 /* call parent */
386 G_OBJECT_CLASS(ags_copy_pattern_audio_run_parent_class)->dispose(gobject);
387 }
388
389 void
ags_copy_pattern_audio_run_finalize(GObject * gobject)390 ags_copy_pattern_audio_run_finalize(GObject *gobject)
391 {
392 AgsCopyPatternAudioRun *copy_pattern_audio_run;
393
394 copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(gobject);
395
396 /* delay audio run */
397 if(copy_pattern_audio_run->delay_audio_run != NULL){
398 g_object_unref(copy_pattern_audio_run->delay_audio_run);
399 }
400
401 /* count beats audio run */
402 if(copy_pattern_audio_run->count_beats_audio_run != NULL){
403 g_object_unref(copy_pattern_audio_run->count_beats_audio_run);
404 }
405
406 /* call parent */
407 G_OBJECT_CLASS(ags_copy_pattern_audio_run_parent_class)->finalize(gobject);
408 }
409
410 void
ags_copy_pattern_audio_run_resolve_dependency(AgsRecall * recall)411 ags_copy_pattern_audio_run_resolve_dependency(AgsRecall *recall)
412 {
413 AgsRecall *template;
414 AgsRecallContainer *recall_container;
415 AgsRecallID *parent_recall_id;
416 AgsRecallID *recall_id;
417 AgsRecyclingContext *parent_recycling_context;
418 AgsRecyclingContext *recycling_context;
419 AgsRecallDependency *recall_dependency;
420
421 AgsDelayAudioRun *delay_audio_run;
422 AgsCountBeatsAudioRun *count_beats_audio_run;
423
424 GList *list_start, *list;
425
426 guint i, i_stop;
427
428 g_object_get(recall,
429 "recall-container", &recall_container,
430 NULL);
431
432 g_object_get(recall_container,
433 "recall-audio-run", &list_start,
434 NULL);
435
436 list = ags_recall_find_template(list_start);
437
438 if(list == NULL){
439 g_warning("AgsRecallClass::resolve - missing dependency");
440
441 g_object_unref(recall_container);
442
443 g_list_free_full(list_start,
444 g_object_unref);
445
446 return;
447 }
448
449 template = AGS_RECALL(list->data);
450
451 g_list_free_full(list_start,
452 g_object_unref);
453
454 g_object_get(template,
455 "recall-dependency", &list_start,
456 NULL);
457
458 g_object_get(recall,
459 "recall-id", &recall_id,
460 NULL);
461
462 g_object_get(recall_id,
463 "recycling-context", &recycling_context,
464 NULL);
465
466 g_object_get(recycling_context,
467 "parent", &parent_recycling_context,
468 NULL);
469
470 g_object_get(parent_recycling_context,
471 "recall-id", &parent_recall_id,
472 NULL);
473
474 /* prepare to resolve */
475 delay_audio_run = NULL;
476 count_beats_audio_run = NULL;
477
478 list = list_start;
479
480 i_stop = 2;
481
482 for(i = 0; i < i_stop && list != NULL;){
483 GObject *dependency;
484
485 recall_dependency = AGS_RECALL_DEPENDENCY(list->data);
486
487 g_object_get(recall_dependency,
488 "dependency", &dependency,
489 NULL);
490
491 if(AGS_IS_DELAY_AUDIO_RUN(dependency)){
492 delay_audio_run = (AgsDelayAudioRun *) ags_recall_dependency_resolve(recall_dependency,
493 parent_recall_id);
494
495 i++;
496 }else if(AGS_IS_COUNT_BEATS_AUDIO_RUN(dependency)){
497 count_beats_audio_run = (AgsCountBeatsAudioRun *) ags_recall_dependency_resolve(recall_dependency,
498 parent_recall_id);
499
500 i++;
501 }
502
503 g_object_unref(dependency);
504
505 list = list->next;
506 }
507
508 g_object_set(G_OBJECT(recall),
509 "delay-audio-run", delay_audio_run,
510 "count-beats-audio-run", count_beats_audio_run,
511 NULL);
512
513 g_object_unref(recall_container);
514
515 g_list_free_full(list_start,
516 g_object_unref);
517
518 g_object_unref(recall_id);
519
520 g_object_unref(recycling_context);
521 g_object_unref(parent_recycling_context);
522
523 g_object_unref(parent_recall_id);
524 }
525
526 void
ags_copy_pattern_audio_run_notify_dependency(AgsRecall * recall,guint dependency,gboolean increase)527 ags_copy_pattern_audio_run_notify_dependency(AgsRecall *recall,
528 guint dependency, gboolean increase)
529 {
530 AgsCopyPatternAudioRun *copy_pattern_audio_run;
531
532 GRecMutex *recall_mutex;
533
534 copy_pattern_audio_run = AGS_COPY_PATTERN_AUDIO_RUN(recall);
535
536 /* get mutex */
537 recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(copy_pattern_audio_run);
538
539 /* notify */
540 g_rec_mutex_lock(recall_mutex);
541
542 switch(dependency){
543 case AGS_RECALL_NOTIFY_RUN:
544 break;
545 case AGS_RECALL_NOTIFY_AUDIO:
546 break;
547 case AGS_RECALL_NOTIFY_AUDIO_RUN:
548 break;
549 case AGS_RECALL_NOTIFY_CHANNEL:
550 break;
551 case AGS_RECALL_NOTIFY_CHANNEL_RUN:
552 if(increase){
553 copy_pattern_audio_run->hide_ref += 1;
554 }else{
555 copy_pattern_audio_run->hide_ref -= 1;
556 }
557 break;
558 default:
559 g_message("ags_copy_pattern_audio_run.c - ags_copy_pattern_audio_run_notify: unknown notify");
560 }
561
562 g_rec_mutex_unlock(recall_mutex);
563 }
564
565 /**
566 * ags_copy_pattern_audio_run_new:
567 * @audio: the #AgsAudio
568 * @delay_audio_run: the #AgsDelayAudioRun dependency
569 * @count_beats_audio_run: the #AgsCountBeatsAudioRun dependency
570 *
571 * Create a new instance of #AgsCopyPatternAudioRun
572 *
573 * Returns: the new #AgsCopyPatternAudioRun
574 *
575 * Since: 3.0.0
576 */
577 AgsCopyPatternAudioRun*
ags_copy_pattern_audio_run_new(AgsAudio * audio,AgsDelayAudioRun * delay_audio_run,AgsCountBeatsAudioRun * count_beats_audio_run)578 ags_copy_pattern_audio_run_new(AgsAudio *audio,
579 AgsDelayAudioRun *delay_audio_run,
580 AgsCountBeatsAudioRun *count_beats_audio_run)
581 {
582 AgsCopyPatternAudioRun *copy_pattern_audio_run;
583
584 copy_pattern_audio_run = (AgsCopyPatternAudioRun *) g_object_new(AGS_TYPE_COPY_PATTERN_AUDIO_RUN,
585 "audio", audio,
586 "delay-audio-run", delay_audio_run,
587 "count-beats-audio-run", count_beats_audio_run,
588 NULL);
589
590 return(copy_pattern_audio_run);
591 }
592