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/file/ags_sfz_region.h>
21 
22 #include <ags/audio/file/ags_sfz_group.h>
23 #include <ags/audio/file/ags_sfz_sample.h>
24 
25 #include <stdlib.h>
26 
27 #include <ags/i18n.h>
28 
29 void ags_sfz_region_class_init(AgsSFZRegionClass *sfz_region);
30 void ags_sfz_region_connectable_interface_init(AgsConnectableInterface *connectable);
31 void ags_sfz_region_init(AgsSFZRegion *sfz_region);
32 void ags_sfz_region_set_property(GObject *gobject,
33 				 guint prop_id,
34 				 const GValue *value,
35 				 GParamSpec *param_spec);
36 void ags_sfz_region_get_property(GObject *gobject,
37 				 guint prop_id,
38 				 GValue *value,
39 				 GParamSpec *param_spec);
40 void ags_sfz_region_dispose(GObject *gobject);
41 void ags_sfz_region_finalize(GObject *gobject);
42 
43 AgsUUID* ags_sfz_region_get_uuid(AgsConnectable *connectable);
44 gboolean ags_sfz_region_has_resource(AgsConnectable *connectable);
45 gboolean ags_sfz_region_is_ready(AgsConnectable *connectable);
46 void ags_sfz_region_add_to_registry(AgsConnectable *connectable);
47 void ags_sfz_region_remove_from_registry(AgsConnectable *connectable);
48 xmlNode* ags_sfz_region_list_resource(AgsConnectable *connectable);
49 xmlNode* ags_sfz_region_xml_compose(AgsConnectable *connectable);
50 void ags_sfz_region_xml_parse(AgsConnectable *connectable,
51 			      xmlNode *node);
52 gboolean ags_sfz_region_is_connected(AgsConnectable *connectable);
53 void ags_sfz_region_connect(AgsConnectable *connectable);
54 void ags_sfz_region_disconnect(AgsConnectable *connectable);
55 
56 /**
57  * SECTION:ags_sfz_region
58  * @short_description: interfacing SFZ regions
59  * @title: AgsSFZRegion
60  * @section_id:
61  * @include: ags/audio/file/ags_sfz_region.h
62  *
63  * #AgsSFZRegion is the base object to ineract with SFZ regions.
64  */
65 
66 enum{
67   PROP_0,
68   PROP_NTH_REGION,
69   PROP_GROUP,
70   PROP_SAMPLE,
71 };
72 
73 static gpointer ags_sfz_region_parent_class = NULL;
74 
75 GType
ags_sfz_region_get_type()76 ags_sfz_region_get_type()
77 {
78   static volatile gsize g_define_type_id__volatile = 0;
79 
80   if(g_once_init_enter (&g_define_type_id__volatile)){
81     GType ags_type_sfz_region = 0;
82 
83     static const GTypeInfo ags_sfz_region_info = {
84       sizeof(AgsSFZRegionClass),
85       NULL, /* base_init */
86       NULL, /* base_finalize */
87       (GClassInitFunc) ags_sfz_region_class_init,
88       NULL, /* class_finalize */
89       NULL, /* class_data */
90       sizeof(AgsSFZRegion),
91       0,    /* n_preallocs */
92       (GInstanceInitFunc) ags_sfz_region_init,
93     };
94 
95     static const GInterfaceInfo ags_connectable_interface_info = {
96       (GInterfaceInitFunc) ags_sfz_region_connectable_interface_init,
97       NULL, /* interface_finalize */
98       NULL, /* interface_data */
99     };
100 
101     ags_type_sfz_region = g_type_register_static(G_TYPE_OBJECT,
102 						 "AgsSFZRegion",
103 						 &ags_sfz_region_info,
104 						 0);
105 
106     g_type_add_interface_static(ags_type_sfz_region,
107 				AGS_TYPE_CONNECTABLE,
108 				&ags_connectable_interface_info);
109 
110     g_once_init_leave(&g_define_type_id__volatile, ags_type_sfz_region);
111   }
112 
113   return g_define_type_id__volatile;
114 }
115 
116 void
ags_sfz_region_class_init(AgsSFZRegionClass * sfz_region)117 ags_sfz_region_class_init(AgsSFZRegionClass *sfz_region)
118 {
119   GObjectClass *gobject;
120 
121   GParamSpec *param_spec;
122 
123   ags_sfz_region_parent_class = g_type_class_peek_parent(sfz_region);
124 
125   gobject = (GObjectClass *) sfz_region;
126 
127   gobject->set_property = ags_sfz_region_set_property;
128   gobject->get_property = ags_sfz_region_get_property;
129 
130   gobject->dispose = ags_sfz_region_dispose;
131   gobject->finalize = ags_sfz_region_finalize;
132 
133   /* properties */
134   /**
135    * AgsSFZRegion:nth-region:
136    *
137    * The nth region.
138    *
139    * Since: 3.0.0
140    */
141   param_spec = g_param_spec_int("nth-region",
142 				i18n_pspec("nth region"),
143 				i18n_pspec("The nth region it belongs to"),
144 				-1,
145 				G_MAXINT32,
146 				-1,
147 				G_PARAM_READABLE | G_PARAM_WRITABLE);
148   g_object_class_install_property(gobject,
149 				  PROP_NTH_REGION,
150 				  param_spec);
151 
152   /**
153    * AgsSFZRegion:group:
154    *
155    * The group assigned with.
156    *
157    * Since: 3.0.0
158    */
159   param_spec = g_param_spec_object("group",
160 				   i18n_pspec("assigned group"),
161 				   i18n_pspec("The group it is assigned with"),
162 				   AGS_TYPE_SFZ_GROUP,
163 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
164   g_object_class_install_property(gobject,
165 				  PROP_GROUP,
166 				  param_spec);
167 
168   /**
169    * AgsSFZRegion:sample:
170    *
171    * The sample assigned with.
172    *
173    * Since: 3.0.0
174    */
175   param_spec = g_param_spec_object("sample",
176 				   i18n_pspec("assigned sample"),
177 				   i18n_pspec("The sample it is assigned with"),
178 				   AGS_TYPE_SFZ_SAMPLE,
179 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
180   g_object_class_install_property(gobject,
181 				  PROP_SAMPLE,
182 				  param_spec);
183 }
184 
185 void
ags_sfz_region_connectable_interface_init(AgsConnectableInterface * connectable)186 ags_sfz_region_connectable_interface_init(AgsConnectableInterface *connectable)
187 {
188   connectable->get_uuid = ags_sfz_region_get_uuid;
189   connectable->has_resource = ags_sfz_region_has_resource;
190   connectable->is_ready = ags_sfz_region_is_ready;
191 
192   connectable->add_to_registry = ags_sfz_region_add_to_registry;
193   connectable->remove_from_registry = ags_sfz_region_remove_from_registry;
194 
195   connectable->list_resource = ags_sfz_region_list_resource;
196   connectable->xml_compose = ags_sfz_region_xml_compose;
197   connectable->xml_parse = ags_sfz_region_xml_parse;
198 
199   connectable->is_connected = ags_sfz_region_is_connected;
200 
201   connectable->connect = ags_sfz_region_connect;
202   connectable->disconnect = ags_sfz_region_disconnect;
203 
204   connectable->connect_connection = NULL;
205   connectable->disconnect_connection = NULL;
206 }
207 
208 void
ags_sfz_region_init(AgsSFZRegion * sfz_region)209 ags_sfz_region_init(AgsSFZRegion *sfz_region)
210 {
211   AgsConfig *config;
212 
213   sfz_region->flags = 0;
214 
215   /* add audio file mutex */
216   g_rec_mutex_init(&(sfz_region->obj_mutex));
217 
218   /* uuid */
219   sfz_region->uuid = ags_uuid_alloc();
220   ags_uuid_generate(sfz_region->uuid);
221 
222   sfz_region->nth_region = -1;
223 
224   sfz_region->group = NULL;
225   sfz_region->sample = NULL;
226 
227   sfz_region->control = g_hash_table_new_full(g_str_hash, g_str_equal,
228 					      NULL,
229 					      NULL);
230 }
231 
232 void
ags_sfz_region_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)233 ags_sfz_region_set_property(GObject *gobject,
234 			    guint prop_id,
235 			    const GValue *value,
236 			    GParamSpec *param_spec)
237 {
238   AgsSFZRegion *sfz_region;
239 
240   GRecMutex *sfz_region_mutex;
241 
242   sfz_region = AGS_SFZ_REGION(gobject);
243 
244   /* get sfz region mutex */
245   sfz_region_mutex = AGS_SFZ_REGION_GET_OBJ_MUTEX(sfz_region);
246 
247   switch(prop_id){
248   case PROP_NTH_REGION:
249   {
250     gint nth_region;
251 
252     nth_region = g_value_get_int(value);
253 
254     g_rec_mutex_lock(sfz_region_mutex);
255 
256     if(nth_region == sfz_region->nth_region){
257       g_rec_mutex_unlock(sfz_region_mutex);
258 
259       return;
260     }
261 
262     sfz_region->nth_region = nth_region;
263 
264     g_rec_mutex_unlock(sfz_region_mutex);
265   }
266   break;
267   case PROP_GROUP:
268   {
269     GObject *group;
270 
271     group = g_value_get_object(value);
272 
273     g_rec_mutex_lock(sfz_region_mutex);
274 
275     if(sfz_region->group == group){
276       g_rec_mutex_unlock(sfz_region_mutex);
277 
278       return;
279     }
280 
281     if(sfz_region->group != NULL){
282       g_object_unref(sfz_region->group);
283     }
284 
285     if(group != NULL){
286       g_object_ref(group);
287     }
288 
289     sfz_region->group = group;
290 
291     g_rec_mutex_unlock(sfz_region_mutex);
292   }
293   break;
294   case PROP_SAMPLE:
295   {
296     GObject *sample;
297 
298     sample = g_value_get_object(value);
299 
300     g_rec_mutex_lock(sfz_region_mutex);
301 
302     if(sfz_region->sample == sample){
303       g_rec_mutex_unlock(sfz_region_mutex);
304 
305       return;
306     }
307 
308     if(sfz_region->sample != NULL){
309       g_object_unref(sfz_region->sample);
310     }
311 
312     if(sample != NULL){
313       g_object_ref(sample);
314     }
315 
316     sfz_region->sample = sample;
317 
318     g_rec_mutex_unlock(sfz_region_mutex);
319   }
320   break;
321   default:
322     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
323   }
324 }
325 
326 void
ags_sfz_region_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)327 ags_sfz_region_get_property(GObject *gobject,
328 			    guint prop_id,
329 			    GValue *value,
330 			    GParamSpec *param_spec)
331 {
332   AgsSFZRegion *sfz_region;
333 
334   GRecMutex *sfz_region_mutex;
335 
336   sfz_region = (AgsSFZRegion *) gobject;
337 
338   /* get sfz region mutex */
339   sfz_region_mutex = AGS_SFZ_REGION_GET_OBJ_MUTEX(sfz_region);
340 
341   switch(prop_id){
342   case PROP_NTH_REGION:
343   {
344     g_rec_mutex_lock(sfz_region_mutex);
345 
346     g_value_set_int(value, sfz_region->nth_region);
347 
348     g_rec_mutex_unlock(sfz_region_mutex);
349   }
350   break;
351   case PROP_GROUP:
352   {
353     g_rec_mutex_lock(sfz_region_mutex);
354 
355     g_value_set_object(value, sfz_region->group);
356 
357     g_rec_mutex_unlock(sfz_region_mutex);
358   }
359   break;
360   case PROP_SAMPLE:
361   {
362     g_rec_mutex_lock(sfz_region_mutex);
363 
364     g_value_set_object(value, sfz_region->sample);
365 
366     g_rec_mutex_unlock(sfz_region_mutex);
367   }
368   break;
369   default:
370     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
371   }
372 }
373 
374 void
ags_sfz_region_dispose(GObject * gobject)375 ags_sfz_region_dispose(GObject *gobject)
376 {
377   AgsSFZRegion *sfz_region;
378 
379   sfz_region = AGS_SFZ_REGION(gobject);
380 
381   if(sfz_region->sample != NULL){
382     g_object_unref(sfz_region->sample);
383 
384     sfz_region->sample = NULL;
385   }
386 
387   if(sfz_region->group != NULL){
388     g_object_unref(sfz_region->group);
389 
390     sfz_region->group = NULL;
391   }
392 
393   /* call parent */
394   G_OBJECT_CLASS(ags_sfz_region_parent_class)->dispose(gobject);
395 }
396 
397 void
ags_sfz_region_finalize(GObject * gobject)398 ags_sfz_region_finalize(GObject *gobject)
399 {
400   AgsSFZRegion *sfz_region;
401 
402   sfz_region = AGS_SFZ_REGION(gobject);
403 
404   if(sfz_region->sample != NULL){
405     g_object_unref(sfz_region->sample);
406   }
407 
408   if(sfz_region->group != NULL){
409     g_object_unref(sfz_region->group);
410   }
411 
412   /* call parent */
413   G_OBJECT_CLASS(ags_sfz_region_parent_class)->finalize(gobject);
414 }
415 
416 AgsUUID*
ags_sfz_region_get_uuid(AgsConnectable * connectable)417 ags_sfz_region_get_uuid(AgsConnectable *connectable)
418 {
419   AgsSFZRegion *sfz_region;
420 
421   AgsUUID *ptr;
422 
423   GRecMutex *sfz_region_mutex;
424 
425   sfz_region = AGS_SFZ_REGION(connectable);
426 
427   /* get audio file mutex */
428   sfz_region_mutex = AGS_SFZ_REGION_GET_OBJ_MUTEX(sfz_region);
429 
430   /* get UUID */
431   g_rec_mutex_lock(sfz_region_mutex);
432 
433   ptr = sfz_region->uuid;
434 
435   g_rec_mutex_unlock(sfz_region_mutex);
436 
437   return(ptr);
438 }
439 
440 gboolean
ags_sfz_region_has_resource(AgsConnectable * connectable)441 ags_sfz_region_has_resource(AgsConnectable *connectable)
442 {
443   return(TRUE);
444 }
445 
446 gboolean
ags_sfz_region_is_ready(AgsConnectable * connectable)447 ags_sfz_region_is_ready(AgsConnectable *connectable)
448 {
449   AgsSFZRegion *sfz_region;
450 
451   gboolean is_ready;
452 
453   sfz_region = AGS_SFZ_REGION(connectable);
454 
455   /* check is ready */
456   is_ready = ags_sfz_region_test_flags(sfz_region, AGS_SFZ_REGION_ADDED_TO_REGISTRY);
457 
458   return(is_ready);
459 }
460 
461 void
ags_sfz_region_add_to_registry(AgsConnectable * connectable)462 ags_sfz_region_add_to_registry(AgsConnectable *connectable)
463 {
464   AgsSFZRegion *sfz_region;
465 
466   AgsRegistry *registry;
467   AgsRegistryEntry *entry;
468 
469   AgsApplicationContext *application_context;
470 
471   if(ags_connectable_is_ready(connectable)){
472     return;
473   }
474 
475   sfz_region = AGS_SFZ_REGION(connectable);
476 
477   ags_sfz_region_set_flags(sfz_region, AGS_SFZ_REGION_ADDED_TO_REGISTRY);
478 
479   application_context = ags_application_context_get_instance();
480 
481   registry = (AgsRegistry *) ags_service_provider_get_registry(AGS_SERVICE_PROVIDER(application_context));
482 
483   if(registry != NULL){
484     entry = ags_registry_entry_alloc(registry);
485     g_value_set_object(entry->entry,
486 		       (gpointer) sfz_region);
487     ags_registry_add_entry(registry,
488 			   entry);
489   }
490 }
491 
492 void
ags_sfz_region_remove_from_registry(AgsConnectable * connectable)493 ags_sfz_region_remove_from_registry(AgsConnectable *connectable)
494 {
495   if(!ags_connectable_is_ready(connectable)){
496     return;
497   }
498 
499   //TODO:JK: implement me
500 }
501 
502 xmlNode*
ags_sfz_region_list_resource(AgsConnectable * connectable)503 ags_sfz_region_list_resource(AgsConnectable *connectable)
504 {
505   xmlNode *node;
506 
507   node = NULL;
508 
509   //TODO:JK: implement me
510 
511   return(node);
512 }
513 
514 xmlNode*
ags_sfz_region_xml_compose(AgsConnectable * connectable)515 ags_sfz_region_xml_compose(AgsConnectable *connectable)
516 {
517   xmlNode *node;
518 
519   node = NULL;
520 
521   //TODO:JK: implement me
522 
523   return(node);
524 }
525 
526 void
ags_sfz_region_xml_parse(AgsConnectable * connectable,xmlNode * node)527 ags_sfz_region_xml_parse(AgsConnectable *connectable,
528 			 xmlNode *node)
529 {
530   //TODO:JK: implement me
531 }
532 
533 gboolean
ags_sfz_region_is_connected(AgsConnectable * connectable)534 ags_sfz_region_is_connected(AgsConnectable *connectable)
535 {
536   AgsSFZRegion *sfz_region;
537 
538   gboolean is_connected;
539 
540   sfz_region = AGS_SFZ_REGION(connectable);
541 
542   /* check is connected */
543   is_connected = ags_sfz_region_test_flags(sfz_region, AGS_SFZ_REGION_CONNECTED);
544 
545   return(is_connected);
546 }
547 
548 void
ags_sfz_region_connect(AgsConnectable * connectable)549 ags_sfz_region_connect(AgsConnectable *connectable)
550 {
551   AgsSFZRegion *sfz_region;
552 
553   if(ags_connectable_is_connected(connectable)){
554     return;
555   }
556 
557   sfz_region = AGS_SFZ_REGION(connectable);
558 
559   ags_sfz_region_set_flags(sfz_region, AGS_SFZ_REGION_CONNECTED);
560 }
561 
562 void
ags_sfz_region_disconnect(AgsConnectable * connectable)563 ags_sfz_region_disconnect(AgsConnectable *connectable)
564 {
565   AgsSFZRegion *sfz_region;
566 
567   if(!ags_connectable_is_connected(connectable)){
568     return;
569   }
570 
571   sfz_region = AGS_SFZ_REGION(connectable);
572 
573   ags_sfz_region_unset_flags(sfz_region, AGS_SFZ_REGION_CONNECTED);
574 }
575 
576 /**
577  * ags_sfz_region_test_flags:
578  * @sfz_region: the #AgsSFZRegion
579  * @flags: the flags
580  *
581  * Test @flags to be set on @sfz_region.
582  *
583  * Returns: %TRUE if flags are set, else %FALSE
584  *
585  * Since: 3.0.0
586  */
587 gboolean
ags_sfz_region_test_flags(AgsSFZRegion * sfz_region,guint flags)588 ags_sfz_region_test_flags(AgsSFZRegion *sfz_region, guint flags)
589 {
590   gboolean retval;
591 
592   GRecMutex *sfz_region_mutex;
593 
594   if(!AGS_IS_SFZ_REGION(sfz_region)){
595     return(FALSE);
596   }
597 
598   /* get sfz_region mutex */
599   sfz_region_mutex = AGS_SFZ_REGION_GET_OBJ_MUTEX(sfz_region);
600 
601   /* test */
602   g_rec_mutex_lock(sfz_region_mutex);
603 
604   retval = (flags & (sfz_region->flags)) ? TRUE: FALSE;
605 
606   g_rec_mutex_unlock(sfz_region_mutex);
607 
608   return(retval);
609 }
610 
611 /**
612  * ags_sfz_region_set_flags:
613  * @sfz_region: the #AgsSFZRegion
614  * @flags: see #AgsSFZRegionFlags-enum
615  *
616  * Enable a feature of @sfz_region.
617  *
618  * Since: 3.0.0
619  */
620 void
ags_sfz_region_set_flags(AgsSFZRegion * sfz_region,guint flags)621 ags_sfz_region_set_flags(AgsSFZRegion *sfz_region, guint flags)
622 {
623   GRecMutex *sfz_region_mutex;
624 
625   if(!AGS_IS_SFZ_REGION(sfz_region)){
626     return;
627   }
628 
629   /* get sfz_region mutex */
630   sfz_region_mutex = AGS_SFZ_REGION_GET_OBJ_MUTEX(sfz_region);
631 
632   //TODO:JK: add more?
633 
634   /* set flags */
635   g_rec_mutex_lock(sfz_region_mutex);
636 
637   sfz_region->flags |= flags;
638 
639   g_rec_mutex_unlock(sfz_region_mutex);
640 }
641 
642 /**
643  * ags_sfz_region_unset_flags:
644  * @sfz_region: the #AgsSFZRegion
645  * @flags: see #AgsSFZRegionFlags-enum
646  *
647  * Disable a feature of @sfz_region.
648  *
649  * Since: 3.0.0
650  */
651 void
ags_sfz_region_unset_flags(AgsSFZRegion * sfz_region,guint flags)652 ags_sfz_region_unset_flags(AgsSFZRegion *sfz_region, guint flags)
653 {
654   GRecMutex *sfz_region_mutex;
655 
656   if(!AGS_IS_SFZ_REGION(sfz_region)){
657     return;
658   }
659 
660   /* get sfz_region mutex */
661   sfz_region_mutex = AGS_SFZ_REGION_GET_OBJ_MUTEX(sfz_region);
662 
663   //TODO:JK: add more?
664 
665   /* unset flags */
666   g_rec_mutex_lock(sfz_region_mutex);
667 
668   sfz_region->flags &= (~flags);
669 
670   g_rec_mutex_unlock(sfz_region_mutex);
671 }
672 
673 /**
674  * ags_sfz_region_insert_control:
675  * @sfz_region: the #AgsSFZRegion
676  * @key: the key
677  * @value: the value
678  *
679  * Insert control specified by @key and @value to @sfz_region.
680  *
681  * Since: 3.0.0
682  */
683 void
ags_sfz_region_insert_control(AgsSFZRegion * sfz_region,gchar * key,gchar * value)684 ags_sfz_region_insert_control(AgsSFZRegion *sfz_region,
685 			      gchar *key,
686 			      gchar *value)
687 {
688   GRecMutex *sfz_region_mutex;
689 
690   if(!AGS_IS_SFZ_REGION(sfz_region)){
691     return;
692   }
693 
694   /* get sfz_region mutex */
695   sfz_region_mutex = AGS_SFZ_REGION_GET_OBJ_MUTEX(sfz_region);
696 
697   /* insert */
698   g_rec_mutex_lock(sfz_region_mutex);
699 
700   g_hash_table_insert(sfz_region->control,
701 		      key,
702 		      value);
703 
704   g_rec_mutex_unlock(sfz_region_mutex);
705 }
706 
707 /**
708  * ags_sfz_region_lookup_control:
709  * @sfz_region: the #AgsSFZRegion
710  * @key: the key
711  *
712  * Lookup control specified by @key of @sfz_region.
713  *
714  * Since: 3.0.0
715  */
716 gchar*
ags_sfz_region_lookup_control(AgsSFZRegion * sfz_region,gchar * key)717 ags_sfz_region_lookup_control(AgsSFZRegion *sfz_region,
718 			      gchar *key)
719 {
720   gchar *value;
721 
722   GRecMutex *sfz_region_mutex;
723 
724   if(!AGS_IS_SFZ_REGION(sfz_region)){
725     return(NULL);
726   }
727 
728   /* get sfz_region mutex */
729   sfz_region_mutex = AGS_SFZ_REGION_GET_OBJ_MUTEX(sfz_region);
730 
731   /* lookup */
732   g_rec_mutex_lock(sfz_region_mutex);
733 
734   value = g_hash_table_lookup(sfz_region->control,
735 			      key);
736 
737   value = g_strdup(value);
738 
739   g_rec_mutex_unlock(sfz_region_mutex);
740 
741   return(value);
742 }
743 
744 /**
745  * ags_sfz_region_new:
746  *
747  * Creates a new instance of #AgsSFZRegion.
748  *
749  * Returns: the new #AgsSFZRegion.
750  *
751  * Since: 3.0.0
752  */
753 AgsSFZRegion*
ags_sfz_region_new()754 ags_sfz_region_new()
755 {
756   AgsSFZRegion *sfz_region;
757 
758   sfz_region = (AgsSFZRegion *) g_object_new(AGS_TYPE_SFZ_REGION,
759 					     NULL);
760 
761   return(sfz_region);
762 }
763