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/ags_recall_id.h>
21
22 #include <stdlib.h>
23 #include <stdio.h>
24
25 #include <ags/i18n.h>
26
27 void ags_recall_id_class_init(AgsRecallIDClass *recall_id);
28 void ags_recall_id_init(AgsRecallID *recall_id);
29 void ags_recall_id_set_property(GObject *gobject,
30 guint prop_id,
31 const GValue *value,
32 GParamSpec *param_spec);
33 void ags_recall_id_get_property(GObject *gobject,
34 guint prop_id,
35 GValue *value,
36 GParamSpec *param_spec);
37 void ags_recall_id_dispose(GObject *gobject);
38 void ags_recall_id_finalize(GObject *gobject);
39
40 /**
41 * SECTION:ags_recall_id
42 * @short_description: The object specifies run context.
43 * @title: AgsRecallID
44 * @section_id:
45 * @include: ags/audio/ags_recall_id.h
46 *
47 * #AgsRecallID acts as dynamic context identifier.
48 */
49
50 enum{
51 PROP_0,
52 PROP_RECYCLING_CONTEXT,
53 };
54
55 static gpointer ags_recall_id_parent_class = NULL;
56
57 GType
ags_recall_id_get_type(void)58 ags_recall_id_get_type(void)
59 {
60 static volatile gsize g_define_type_id__volatile = 0;
61
62 if(g_once_init_enter (&g_define_type_id__volatile)){
63 GType ags_type_recall_id = 0;
64
65 static const GTypeInfo ags_recall_id_info = {
66 sizeof(AgsRecallIDClass),
67 NULL, /* base_init */
68 NULL, /* base_finalize */
69 (GClassInitFunc) ags_recall_id_class_init,
70 NULL, /* class_finalize */
71 NULL, /* class_data */
72 sizeof(AgsRecallID),
73 0, /* n_preallocs */
74 (GInstanceInitFunc) ags_recall_id_init,
75 };
76
77 ags_type_recall_id = g_type_register_static(G_TYPE_OBJECT,
78 "AgsRecallID",
79 &ags_recall_id_info,
80 0);
81
82 g_once_init_leave(&g_define_type_id__volatile, ags_type_recall_id);
83 }
84
85 return g_define_type_id__volatile;
86 }
87
88 void
ags_recall_id_class_init(AgsRecallIDClass * recall_id)89 ags_recall_id_class_init(AgsRecallIDClass *recall_id)
90 {
91 GObjectClass *gobject;
92
93 GParamSpec *param_spec;
94
95 ags_recall_id_parent_class = g_type_class_peek_parent(recall_id);
96
97 /* GObjectClass */
98 gobject = (GObjectClass *) recall_id;
99
100 gobject->set_property = ags_recall_id_set_property;
101 gobject->get_property = ags_recall_id_get_property;
102
103 gobject->dispose = ags_recall_id_dispose;
104 gobject->finalize = ags_recall_id_finalize;
105
106 /* properties */
107 /**
108 * AgsRecallID:recycling-context:
109 *
110 * The dynamic run context belonging to.
111 *
112 * Since: 3.0.0
113 */
114 param_spec = g_param_spec_object("recycling-context",
115 i18n_pspec("assigned recycling context"),
116 i18n_pspec("The recycling context it is assigned with"),
117 G_TYPE_OBJECT,
118 G_PARAM_READABLE | G_PARAM_WRITABLE);
119 g_object_class_install_property(gobject,
120 PROP_RECYCLING_CONTEXT,
121 param_spec);
122 }
123
124 void
ags_recall_id_init(AgsRecallID * recall_id)125 ags_recall_id_init(AgsRecallID *recall_id)
126 {
127 recall_id->flags = 0;
128 recall_id->sound_scope = -1;
129 recall_id->staging_flags = 0;
130 recall_id->state_flags = 0;
131
132 /* recall id mutex */
133 g_rec_mutex_init(&(recall_id->obj_mutex));
134
135 /* recycling context */
136 recall_id->recycling_context = NULL;
137 }
138
139 void
ags_recall_id_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)140 ags_recall_id_set_property(GObject *gobject,
141 guint prop_id,
142 const GValue *value,
143 GParamSpec *param_spec)
144 {
145 AgsRecallID *recall_id;
146
147 GRecMutex *recall_id_mutex;
148
149 recall_id = AGS_RECALL_ID(gobject);
150
151 /* get recall id mutex */
152 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
153
154 switch(prop_id){
155 case PROP_RECYCLING_CONTEXT:
156 {
157 AgsRecyclingContext *recycling_context;
158
159 recycling_context = g_value_get_object(value);
160
161 g_rec_mutex_lock(recall_id_mutex);
162
163 if(recall_id->recycling_context == recycling_context){
164 g_rec_mutex_unlock(recall_id_mutex);
165
166 return;
167 }
168
169 if(recall_id->recycling_context != NULL){
170 g_object_unref(recall_id->recycling_context);
171 }
172
173 if(recycling_context != NULL){
174 g_object_ref(recycling_context);
175 }
176
177 recall_id->recycling_context = recycling_context;
178
179 g_rec_mutex_unlock(recall_id_mutex);
180 }
181 break;
182 default:
183 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
184 break;
185 }
186 }
187
188 void
ags_recall_id_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)189 ags_recall_id_get_property(GObject *gobject,
190 guint prop_id,
191 GValue *value,
192 GParamSpec *param_spec)
193 {
194 AgsRecallID *recall_id;
195
196 GRecMutex *recall_id_mutex;
197
198 recall_id = AGS_RECALL_ID(gobject);
199
200 /* get recall id mutex */
201 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
202
203 switch(prop_id){
204 case PROP_RECYCLING_CONTEXT:
205 {
206 g_rec_mutex_lock(recall_id_mutex);
207
208 g_value_set_object(value, recall_id->recycling_context);
209
210 g_rec_mutex_unlock(recall_id_mutex);
211 }
212 break;
213 default:
214 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
215 break;
216 }
217 }
218
219 void
ags_recall_id_dispose(GObject * gobject)220 ags_recall_id_dispose(GObject *gobject)
221 {
222 AgsRecallID *recall_id;
223
224 recall_id = AGS_RECALL_ID(gobject);
225
226 if(recall_id->recycling_context != NULL){
227 g_object_unref(recall_id->recycling_context);
228
229 recall_id->recycling_context = NULL;
230 }
231
232 /* call parent */
233 G_OBJECT_CLASS(ags_recall_id_parent_class)->dispose(gobject);
234 }
235
236 void
ags_recall_id_finalize(GObject * gobject)237 ags_recall_id_finalize(GObject *gobject)
238 {
239 AgsRecallID *recall_id;
240
241 recall_id = AGS_RECALL_ID(gobject);
242
243 if(recall_id->recycling_context != NULL){
244 g_object_unref(recall_id->recycling_context);
245 }
246
247 /* call parent */
248 G_OBJECT_CLASS(ags_recall_id_parent_class)->finalize(gobject);
249 }
250
251 /**
252 * ags_recall_id_set_scope:
253 * @recall_id: the #AgsRecallID
254 * @sound_scope: the sound scope
255 *
256 * Set @sound_scope for @recall_id.
257 *
258 * Since: 3.0.0
259 */
260 void
ags_recall_id_set_sound_scope(AgsRecallID * recall_id,gint sound_scope)261 ags_recall_id_set_sound_scope(AgsRecallID *recall_id, gint sound_scope)
262 {
263 GRecMutex *recall_id_mutex;
264
265 if(!AGS_IS_RECALL_ID(recall_id) ||
266 ags_recall_id_check_sound_scope(recall_id,
267 -1)){
268 return;
269 }
270
271 /* get recall id mutex */
272 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
273
274 /* set sound scope */
275 g_rec_mutex_lock(recall_id_mutex);
276
277 recall_id->sound_scope = sound_scope;
278
279 g_rec_mutex_unlock(recall_id_mutex);
280 }
281
282 /**
283 * ags_recall_id_check_sound_scope:
284 * @recall_id: the #AgsRecallID
285 * @sound_scope: the sound scope to check or -1 to check all
286 *
287 * Check if @sound_scope is set for @recall_id.
288 *
289 * Returns: %TRUE if sound scope matches, otherwise %FALSE
290 *
291 * Since: 3.0.0
292 */
293 gboolean
ags_recall_id_check_sound_scope(AgsRecallID * recall_id,gint sound_scope)294 ags_recall_id_check_sound_scope(AgsRecallID *recall_id, gint sound_scope)
295 {
296 gint recall_id_sound_scope;
297
298 GRecMutex *recall_id_mutex;
299
300 if(!AGS_IS_RECALL_ID(recall_id)){
301 return(FALSE);
302 }
303
304 /* get recall id mutex */
305 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
306
307 /* get sound scope */
308 g_rec_mutex_lock(recall_id_mutex);
309
310 recall_id_sound_scope = recall_id->sound_scope;
311
312 g_rec_mutex_unlock(recall_id_mutex);
313
314 if(sound_scope < 0){
315 switch(recall_id_sound_scope){
316 case AGS_SOUND_SCOPE_PLAYBACK:
317 case AGS_SOUND_SCOPE_NOTATION:
318 case AGS_SOUND_SCOPE_SEQUENCER:
319 case AGS_SOUND_SCOPE_WAVE:
320 case AGS_SOUND_SCOPE_MIDI:
321 return(TRUE);
322 default:
323 return(FALSE);
324 }
325 }else{
326 if(sound_scope < AGS_SOUND_SCOPE_LAST &&
327 sound_scope == recall_id_sound_scope){
328 return(TRUE);
329 }else{
330 return(FALSE);
331 }
332 }
333 }
334
335 /**
336 * ags_recall_id_test_staging_flags:
337 * @recall_id: the #AgsRecallID
338 * @staging_flags: the staging flags
339 *
340 * Test @staging_flags to be set on @recall_id.
341 *
342 * Returns: %TRUE if flags are set, else %FALSE
343 *
344 * Since: 3.0.0
345 */
346 gboolean
ags_recall_id_test_staging_flags(AgsRecallID * recall_id,guint staging_flags)347 ags_recall_id_test_staging_flags(AgsRecallID *recall_id,
348 guint staging_flags)
349 {
350 gboolean retval;
351
352 GRecMutex *recall_id_mutex;
353
354 if(!AGS_IS_RECALL_ID(recall_id)){
355 return(FALSE);
356 }
357
358 /* get recall id mutex */
359 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
360
361 /* test */
362 g_rec_mutex_lock(recall_id_mutex);
363
364 retval = (staging_flags & (recall_id->staging_flags)) ? TRUE: FALSE;
365
366 g_rec_mutex_unlock(recall_id_mutex);
367
368 return(retval);
369 }
370
371 /**
372 * ags_recall_id_set_staging_flags:
373 * @recall_id: the #AgsRecallID
374 * @staging_flags: staging flags to set
375 *
376 * Set staging flags.
377 *
378 * Since: 3.0.0
379 */
380 void
ags_recall_id_set_staging_flags(AgsRecallID * recall_id,guint staging_flags)381 ags_recall_id_set_staging_flags(AgsRecallID *recall_id, guint staging_flags)
382 {
383 GRecMutex *recall_id_mutex;
384
385 if(!AGS_IS_RECALL_ID(recall_id)){
386 return;
387 }
388
389 /* get recall id mutex */
390 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
391
392 /* set staging flags */
393 g_rec_mutex_lock(recall_id_mutex);
394
395 recall_id->staging_flags |= staging_flags;
396
397 g_rec_mutex_unlock(recall_id_mutex);
398 }
399
400 /**
401 * ags_recall_id_unset_staging_flags:
402 * @recall_id: the #AgsRecallID
403 * @staging_flags: staging flags to unset
404 *
405 * Unset staging flags.
406 *
407 * Since: 3.0.0
408 */
409 void
ags_recall_id_unset_staging_flags(AgsRecallID * recall_id,guint staging_flags)410 ags_recall_id_unset_staging_flags(AgsRecallID *recall_id, guint staging_flags)
411 {
412 GRecMutex *recall_id_mutex;
413
414 if(!AGS_IS_RECALL_ID(recall_id)){
415 return;
416 }
417
418 /* get recall id mutex */
419 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
420
421 /* unset staging flags */
422 g_rec_mutex_lock(recall_id_mutex);
423
424 recall_id->staging_flags &= (~staging_flags);
425
426 g_rec_mutex_unlock(recall_id_mutex);
427 }
428
429 /**
430 * ags_recall_id_check_staging_flags:
431 * @recall_id: the #AgsRecallID
432 * @staging_flags: staging flags to check
433 *
434 * Check the occurence of @staging_flags in @recall_id.
435 *
436 * Returns: %TRUE if all flags matched, otherwise %FALSE
437 *
438 * Since: 3.0.0
439 */
440 gboolean
ags_recall_id_check_staging_flags(AgsRecallID * recall_id,guint staging_flags)441 ags_recall_id_check_staging_flags(AgsRecallID *recall_id, guint staging_flags)
442 {
443 guint recall_id_staging_flags;
444
445 GRecMutex *recall_id_mutex;
446
447 if(!AGS_IS_RECALL_ID(recall_id)){
448 return(FALSE);
449 }
450
451 /* get recall id mutex */
452 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
453
454 /* get staging flags */
455 g_rec_mutex_lock(recall_id_mutex);
456
457 recall_id_staging_flags = recall_id->staging_flags;
458
459 g_rec_mutex_unlock(recall_id_mutex);
460
461 /* check staging flags */
462 if((AGS_SOUND_STAGING_CHECK_RT_DATA & (staging_flags)) != 0 &&
463 (AGS_SOUND_STAGING_CHECK_RT_DATA & (recall_id_staging_flags)) == 0){
464 return(FALSE);
465 }
466
467 if((AGS_SOUND_STAGING_RUN_INIT_PRE & (staging_flags)) != 0 &&
468 (AGS_SOUND_STAGING_RUN_INIT_PRE & (recall_id_staging_flags)) == 0){
469 return(FALSE);
470 }
471
472 if((AGS_SOUND_STAGING_RUN_INIT_INTER & (staging_flags)) != 0 &&
473 (AGS_SOUND_STAGING_RUN_INIT_INTER & (recall_id_staging_flags)) == 0){
474 return(FALSE);
475 }
476
477 if((AGS_SOUND_STAGING_RUN_INIT_POST & (staging_flags)) != 0 &&
478 (AGS_SOUND_STAGING_RUN_INIT_POST & (recall_id_staging_flags)) == 0){
479 return(FALSE);
480 }
481
482 if((AGS_SOUND_STAGING_FEED_INPUT_QUEUE & (staging_flags)) != 0 &&
483 (AGS_SOUND_STAGING_FEED_INPUT_QUEUE & (recall_id_staging_flags)) == 0){
484 return(FALSE);
485 }
486
487 if((AGS_SOUND_STAGING_AUTOMATE & (staging_flags)) != 0 &&
488 (AGS_SOUND_STAGING_AUTOMATE & (recall_id_staging_flags)) == 0){
489 return(FALSE);
490 }
491
492 if((AGS_SOUND_STAGING_RUN_PRE & (staging_flags)) != 0 &&
493 (AGS_SOUND_STAGING_RUN_PRE & (recall_id_staging_flags)) == 0){
494 return(FALSE);
495 }
496
497 if((AGS_SOUND_STAGING_RUN_INTER & (staging_flags)) != 0 &&
498 (AGS_SOUND_STAGING_RUN_INTER & (recall_id_staging_flags)) == 0){
499 return(FALSE);
500 }
501
502 if((AGS_SOUND_STAGING_RUN_POST & (staging_flags)) != 0 &&
503 (AGS_SOUND_STAGING_RUN_POST & (recall_id_staging_flags)) == 0){
504 return(FALSE);
505 }
506
507 if((AGS_SOUND_STAGING_DO_FEEDBACK & (staging_flags)) != 0 &&
508 (AGS_SOUND_STAGING_DO_FEEDBACK & (recall_id_staging_flags)) == 0){
509 return(FALSE);
510 }
511
512 if((AGS_SOUND_STAGING_FEED_OUTPUT_QUEUE & (staging_flags)) != 0 &&
513 (AGS_SOUND_STAGING_FEED_OUTPUT_QUEUE & (recall_id_staging_flags)) == 0){
514 return(FALSE);
515 }
516
517 if((AGS_SOUND_STAGING_FINI & (staging_flags)) != 0 &&
518 (AGS_SOUND_STAGING_FINI & (recall_id_staging_flags)) == 0){
519 return(FALSE);
520 }
521
522 if((AGS_SOUND_STAGING_CANCEL & (staging_flags)) != 0 &&
523 (AGS_SOUND_STAGING_CANCEL & (recall_id_staging_flags)) == 0){
524 return(FALSE);
525 }
526
527 if((AGS_SOUND_STAGING_DONE & (staging_flags)) != 0 &&
528 (AGS_SOUND_STAGING_DONE & (recall_id_staging_flags)) == 0){
529 return(FALSE);
530 }
531
532 if((AGS_SOUND_STAGING_REMOVE & (staging_flags)) != 0 &&
533 (AGS_SOUND_STAGING_REMOVE & (recall_id_staging_flags)) == 0){
534 return(FALSE);
535 }
536
537 return(TRUE);
538 }
539
540 /**
541 * ags_recall_id_test_state_flags:
542 * @recall_id: the #AgsRecallID
543 * @state_flags: the state flags
544 *
545 * Test @state_flags to be set on @recall_id.
546 *
547 * Returns: %TRUE if flags are set, else %FALSE
548 *
549 * Since: 3.0.0
550 */
551 gboolean
ags_recall_id_test_state_flags(AgsRecallID * recall_id,guint state_flags)552 ags_recall_id_test_state_flags(AgsRecallID *recall_id,
553 guint state_flags)
554 {
555 gboolean retval;
556
557 GRecMutex *recall_id_mutex;
558
559 if(!AGS_IS_RECALL_ID(recall_id)){
560 return(FALSE);
561 }
562
563 /* get recall_id mutex */
564 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
565
566 /* test */
567 g_rec_mutex_lock(recall_id_mutex);
568
569 retval = (state_flags & (recall_id->state_flags)) ? TRUE: FALSE;
570
571 g_rec_mutex_unlock(recall_id_mutex);
572
573 return(retval);
574 }
575
576 /**
577 * ags_recall_id_set_state_flags:
578 * @recall_id: the #AgsRecallID
579 * @state_flags: state flags to set
580 *
581 * Set state flags.
582 *
583 * Since: 3.0.0
584 */
585 void
ags_recall_id_set_state_flags(AgsRecallID * recall_id,guint state_flags)586 ags_recall_id_set_state_flags(AgsRecallID *recall_id, guint state_flags)
587 {
588 GRecMutex *recall_id_mutex;
589
590 if(!AGS_IS_RECALL_ID(recall_id)){
591 return;
592 }
593
594 /* get recall id mutex */
595 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
596
597 /* set state flags */
598 g_rec_mutex_lock(recall_id_mutex);
599
600 recall_id->state_flags |= state_flags;
601
602 g_rec_mutex_unlock(recall_id_mutex);
603 }
604
605 /**
606 * ags_recall_id_unset_state_flags:
607 * @recall_id: the #AgsRecallID
608 * @state_flags: state flags to unset
609 *
610 * Unset state flags.
611 *
612 * Since: 3.0.0
613 */
614 void
ags_recall_id_unset_state_flags(AgsRecallID * recall_id,guint state_flags)615 ags_recall_id_unset_state_flags(AgsRecallID *recall_id, guint state_flags)
616 {
617 GRecMutex *recall_id_mutex;
618
619 if(!AGS_IS_RECALL_ID(recall_id)){
620 return;
621 }
622
623 /* get recall id mutex */
624 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
625
626 /* unset state flags */
627 g_rec_mutex_lock(recall_id_mutex);
628
629 recall_id->state_flags &= (~state_flags);
630
631 g_rec_mutex_unlock(recall_id_mutex);
632 }
633
634 /**
635 * ags_recall_id_check_state_flags:
636 * @recall_id: the #AgsRecallID
637 * @state_flags: state flags to check
638 *
639 * Check the occurence of @state_flags in @recall_id.
640 *
641 * Returns: %TRUE if all flags matched, otherwise %FALSE
642 *
643 * Since: 3.0.0
644 */
645 gboolean
ags_recall_id_check_state_flags(AgsRecallID * recall_id,guint state_flags)646 ags_recall_id_check_state_flags(AgsRecallID *recall_id, guint state_flags)
647 {
648 guint recall_id_state_flags;
649
650 GRecMutex *recall_id_mutex;
651
652 if(!AGS_IS_RECALL_ID(recall_id)){
653 return(FALSE);
654 }
655
656 /* get recall id mutex */
657 recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
658
659 /* get state flags */
660 g_rec_mutex_lock(recall_id_mutex);
661
662 recall_id_state_flags = recall_id->state_flags;
663
664 g_rec_mutex_unlock(recall_id_mutex);
665
666 /* check state flags */
667 if((AGS_SOUND_STATE_IS_WAITING & (state_flags)) != 0 &&
668 (AGS_SOUND_STATE_IS_WAITING & (recall_id_state_flags)) == 0){
669 return(FALSE);
670 }
671
672 if((AGS_SOUND_STATE_IS_ACTIVE & (state_flags)) != 0 &&
673 (AGS_SOUND_STATE_IS_ACTIVE & (recall_id_state_flags)) == 0){
674 return(FALSE);
675 }
676
677 if((AGS_SOUND_STATE_IS_PROCESSING & (state_flags)) != 0 &&
678 (AGS_SOUND_STATE_IS_PROCESSING & (recall_id_state_flags)) == 0){
679 return(FALSE);
680 }
681
682 if((AGS_SOUND_STATE_IS_TERMINATING & (state_flags)) != 0 &&
683 (AGS_SOUND_STATE_IS_TERMINATING & (recall_id_state_flags)) == 0){
684 return(FALSE);
685 }
686
687 return(TRUE);
688 }
689
690 /**
691 * ags_recall_id_get_recycling_context:
692 * @recall_id: the #AgsRecallId
693 *
694 * Get recycling context.
695 *
696 * Returns: (transfer full): the #AgsRecyclingContext
697 *
698 * Since: 3.3.0
699 */
700 AgsRecyclingContext*
ags_recall_id_get_recycling_context(AgsRecallID * recall_id)701 ags_recall_id_get_recycling_context(AgsRecallID *recall_id)
702 {
703 AgsRecyclingContext *recycling_context;
704
705 if(!AGS_IS_RECALL_ID(recall_id)){
706 return(NULL);
707 }
708
709 g_object_get(recall_id,
710 "recycling-context", &recycling_context,
711 NULL);
712
713 return(recycling_context);
714 }
715
716 /**
717 * ags_recall_id_set_recycling_context:
718 * @recall_id: the #AgsRecallId
719 * @recycling_context: the #AgsRecyclingContext
720 *
721 * Set recycling context.
722 *
723 * Since: 3.3.0
724 */
725 void
ags_recall_id_set_recycling_context(AgsRecallID * recall_id,AgsRecyclingContext * recycling_context)726 ags_recall_id_set_recycling_context(AgsRecallID *recall_id, AgsRecyclingContext *recycling_context)
727 {
728 if(!AGS_IS_RECALL_ID(recall_id)){
729 return;
730 }
731
732 g_object_set(recall_id,
733 "recycling-context", recycling_context,
734 NULL);
735 }
736
737 /**
738 * ags_recall_id_find_recycling_context:
739 * @recall_id: (element-type AgsAudio.RecallID) (transfer none): the #GList-struct containing #AgsRecallID
740 * @recycling_context: the #AgsRecyclingContext to match
741 *
742 * Retrieve recall id by recycling context.
743 *
744 * Returns: (transfer none): Matching #AgsRecallID
745 *
746 * Since: 3.0.0
747 */
748 AgsRecallID*
ags_recall_id_find_recycling_context(GList * recall_id,AgsRecyclingContext * recycling_context)749 ags_recall_id_find_recycling_context(GList *recall_id,
750 AgsRecyclingContext *recycling_context)
751 {
752 while(recall_id != NULL){
753 AgsRecyclingContext *current_recycling_context;
754
755 gboolean success;
756
757 current_recycling_context = NULL;
758
759 g_object_get(recall_id->data,
760 "recycling-context", ¤t_recycling_context,
761 NULL);
762
763 success = (current_recycling_context == recycling_context) ? TRUE: FALSE;
764
765 if(current_recycling_context != NULL){
766 g_object_unref(current_recycling_context);
767 }
768
769 if(success){
770 return(recall_id->data);
771 }
772
773 recall_id = recall_id->next;
774 }
775
776 return(NULL);
777 }
778
779 /**
780 * ags_recall_id_find_parent_recycling_context:
781 * @recall_id: (element-type AgsAudio.RecallID) (transfer none): the #GList-struct containing #AgsRecallID
782 * @parent_recycling_context: the #AgsRecyclingContext to match
783 *
784 * Retrieve recall id by recycling context.
785 *
786 * Returns: (transfer none): Matching #AgsRecallID
787 *
788 * Since: 3.0.0
789 */
790 AgsRecallID*
ags_recall_id_find_parent_recycling_context(GList * recall_id,AgsRecyclingContext * parent_recycling_context)791 ags_recall_id_find_parent_recycling_context(GList *recall_id,
792 AgsRecyclingContext *parent_recycling_context)
793 {
794 while(recall_id != NULL){
795 AgsRecyclingContext *current_recycling_context;
796
797 gboolean success;
798
799 current_recycling_context = NULL;
800
801 success = FALSE;
802
803 g_object_get(recall_id->data,
804 "recycling-context", ¤t_recycling_context,
805 NULL);
806
807 if(current_recycling_context != NULL){
808 AgsRecyclingContext *current_parent_recycling_context;
809
810 current_parent_recycling_context = NULL;
811
812 g_object_get(current_recycling_context,
813 "parent", ¤t_parent_recycling_context,
814 NULL);
815
816 if(current_parent_recycling_context == parent_recycling_context){
817 success = TRUE;
818 }
819
820 /* unref */
821 if(current_parent_recycling_context != NULL){
822 g_object_unref(current_parent_recycling_context);
823 }
824
825 g_object_unref(current_recycling_context);
826 }
827
828 if(success){
829 return(recall_id->data);
830 }
831
832 recall_id = recall_id->next;
833 }
834
835 return(NULL);
836 }
837
838 /**
839 * ags_recall_id_new:
840 *
841 * Creates a #AgsRecallID
842 *
843 * Returns: a new #AgsRecallID
844 *
845 * Since: 3.0.0
846 */
847 AgsRecallID*
ags_recall_id_new()848 ags_recall_id_new()
849 {
850 AgsRecallID *recall_id;
851
852 recall_id = (AgsRecallID *) g_object_new(AGS_TYPE_RECALL_ID,
853 NULL);
854
855 return(recall_id);
856 }
857