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_ipatch_sf2_reader.h>
21 
22 #include <stdlib.h>
23 
24 #include <ags/i18n.h>
25 
26 void ags_ipatch_sf2_reader_class_init(AgsIpatchSF2ReaderClass *ipatch_sf2_reader);
27 void ags_ipatch_sf2_reader_connectable_interface_init(AgsConnectableInterface *connectable);
28 void ags_ipatch_sf2_reader_init(AgsIpatchSF2Reader *ipatch_sf2_reader);
29 void ags_ipatch_sf2_reader_set_property(GObject *gobject,
30 					guint prop_id,
31 					const GValue *value,
32 					GParamSpec *param_spec);
33 void ags_ipatch_sf2_reader_get_property(GObject *gobject,
34 					guint prop_id,
35 					GValue *value,
36 					GParamSpec *param_spec);
37 void ags_ipatch_sf2_reader_dispose(GObject *gobject);
38 void ags_ipatch_sf2_reader_finalize(GObject *gobject);
39 
40 AgsUUID* ags_ipatch_sf2_reader_get_uuid(AgsConnectable *connectable);
41 gboolean ags_ipatch_sf2_reader_has_resource(AgsConnectable *connectable);
42 gboolean ags_ipatch_sf2_reader_is_ready(AgsConnectable *connectable);
43 void ags_ipatch_sf2_reader_add_to_registry(AgsConnectable *connectable);
44 void ags_ipatch_sf2_reader_remove_from_registry(AgsConnectable *connectable);
45 xmlNode* ags_ipatch_sf2_reader_list_resource(AgsConnectable *connectable);
46 xmlNode* ags_ipatch_sf2_reader_xml_compose(AgsConnectable *connectable);
47 void ags_ipatch_sf2_reader_xml_parse(AgsConnectable *connectable,
48 				   xmlNode *node);
49 gboolean ags_ipatch_sf2_reader_is_connected(AgsConnectable *connectable);
50 void ags_ipatch_sf2_reader_connect(AgsConnectable *connectable);
51 void ags_ipatch_sf2_reader_disconnect(AgsConnectable *connectable);
52 
53 /**
54  * SECTION:ags_ipatch_sf2_reader
55  * @short_description: interfacing Soundfont2 related API of libinstpatch
56  * @title: AgsIpatchSF2Reader
57  * @section_id:
58  * @include: ags/audio/file/ags_ipatch_sf2_reader.h
59  *
60  * #AgsIpatchSF2Reader is the base object to ineract with Soundfont2 related API.
61  */
62 
63 static gpointer ags_ipatch_sf2_reader_parent_class = NULL;
64 
65 enum{
66   PROP_0,
67   PROP_IPATCH,
68 };
69 
70 GType
ags_ipatch_sf2_reader_get_type()71 ags_ipatch_sf2_reader_get_type()
72 {
73   static volatile gsize g_define_type_id__volatile = 0;
74 
75   if(g_once_init_enter (&g_define_type_id__volatile)){
76     GType ags_type_ipatch_sf2_reader = 0;
77 
78     static const GTypeInfo ags_ipatch_sf2_reader_info = {
79       sizeof(AgsIpatchSF2ReaderClass),
80       NULL, /* base_init */
81       NULL, /* base_finalize */
82       (GClassInitFunc) ags_ipatch_sf2_reader_class_init,
83       NULL, /* class_finalize */
84       NULL, /* class_data */
85       sizeof(AgsIpatchSF2Reader),
86       0,    /* n_preallocs */
87       (GInstanceInitFunc) ags_ipatch_sf2_reader_init,
88     };
89 
90     static const GInterfaceInfo ags_connectable_interface_info = {
91       (GInterfaceInitFunc) ags_ipatch_sf2_reader_connectable_interface_init,
92       NULL, /* interface_finalize */
93       NULL, /* interface_data */
94     };
95 
96     ags_type_ipatch_sf2_reader = g_type_register_static(G_TYPE_OBJECT,
97 							"AgsIpatchSF2Reader",
98 							&ags_ipatch_sf2_reader_info,
99 							0);
100 
101     g_type_add_interface_static(ags_type_ipatch_sf2_reader,
102 				AGS_TYPE_CONNECTABLE,
103 				&ags_connectable_interface_info);
104 
105     g_once_init_leave(&g_define_type_id__volatile, ags_type_ipatch_sf2_reader);
106   }
107 
108   return g_define_type_id__volatile;
109 }
110 
111 void
ags_ipatch_sf2_reader_class_init(AgsIpatchSF2ReaderClass * ipatch_sf2_reader)112 ags_ipatch_sf2_reader_class_init(AgsIpatchSF2ReaderClass *ipatch_sf2_reader)
113 {
114   GObjectClass *gobject;
115   GParamSpec *param_spec;
116 
117   ags_ipatch_sf2_reader_parent_class = g_type_class_peek_parent(ipatch_sf2_reader);
118 
119   gobject = (GObjectClass *) ipatch_sf2_reader;
120 
121   gobject->set_property = ags_ipatch_sf2_reader_set_property;
122   gobject->get_property = ags_ipatch_sf2_reader_get_property;
123 
124   gobject->dispose = ags_ipatch_sf2_reader_dispose;
125   gobject->finalize = ags_ipatch_sf2_reader_finalize;
126 
127   /* properties */
128   /**
129    * AgsIpatchSF2Reader:ipatch:
130    *
131    * The assigned #AgsIpatch
132    *
133    * Since: 3.0.0
134    */
135   param_spec = g_param_spec_object("ipatch",
136 				   i18n_pspec("the ipatch"),
137 				   i18n_pspec("The assigned ipatch"),
138 				   AGS_TYPE_IPATCH,
139 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
140   g_object_class_install_property(gobject,
141 				  PROP_IPATCH,
142 				  param_spec);
143 }
144 
145 void
ags_ipatch_sf2_reader_connectable_interface_init(AgsConnectableInterface * connectable)146 ags_ipatch_sf2_reader_connectable_interface_init(AgsConnectableInterface *connectable)
147 {
148   connectable->get_uuid = ags_ipatch_sf2_reader_get_uuid;
149   connectable->has_resource = ags_ipatch_sf2_reader_has_resource;
150   connectable->is_ready = ags_ipatch_sf2_reader_is_ready;
151 
152   connectable->add_to_registry = ags_ipatch_sf2_reader_add_to_registry;
153   connectable->remove_from_registry = ags_ipatch_sf2_reader_remove_from_registry;
154 
155   connectable->list_resource = ags_ipatch_sf2_reader_list_resource;
156   connectable->xml_compose = ags_ipatch_sf2_reader_xml_compose;
157   connectable->xml_parse = ags_ipatch_sf2_reader_xml_parse;
158 
159   connectable->is_connected = ags_ipatch_sf2_reader_is_connected;
160 
161   connectable->connect = ags_ipatch_sf2_reader_connect;
162   connectable->disconnect = ags_ipatch_sf2_reader_disconnect;
163 
164   connectable->connect_connection = NULL;
165   connectable->disconnect_connection = NULL;
166 }
167 
168 void
ags_ipatch_sf2_reader_init(AgsIpatchSF2Reader * ipatch_sf2_reader)169 ags_ipatch_sf2_reader_init(AgsIpatchSF2Reader *ipatch_sf2_reader)
170 {
171   guint i;
172 
173   ipatch_sf2_reader->flags = 0;
174 
175   /* add audio file mutex */
176   g_rec_mutex_init(&(ipatch_sf2_reader->obj_mutex));
177 
178   /* uuid */
179   ipatch_sf2_reader->uuid = ags_uuid_alloc();
180   ags_uuid_generate(ipatch_sf2_reader->uuid);
181 
182   ipatch_sf2_reader->level = 0;
183 
184   ipatch_sf2_reader->ipatch = NULL;
185 
186   /* selected */
187   ipatch_sf2_reader->index_selected = (guint *) malloc(4 * sizeof(guint));
188   memset(ipatch_sf2_reader->index_selected, 0, 4 * sizeof(guint));
189 
190   ipatch_sf2_reader->name_selected = (gchar **) malloc(5 * sizeof(gchar *));
191 
192   for(i = 0; i < 5; i++){
193     ipatch_sf2_reader->name_selected[i] = NULL;
194   }
195 
196   /* reader */
197   ipatch_sf2_reader->reader = NULL;
198   ipatch_sf2_reader->sf2 = NULL;
199 
200   ipatch_sf2_reader->preset = NULL;
201   ipatch_sf2_reader->instrument = NULL;
202   ipatch_sf2_reader->sample = NULL;
203 
204   ipatch_sf2_reader->error = NULL;
205 }
206 
207 void
ags_ipatch_sf2_reader_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)208 ags_ipatch_sf2_reader_set_property(GObject *gobject,
209 				   guint prop_id,
210 				   const GValue *value,
211 				   GParamSpec *param_spec)
212 {
213   AgsIpatchSF2Reader *ipatch_sf2_reader;
214 
215   GRecMutex *ipatch_sf2_reader_mutex;
216 
217   ipatch_sf2_reader = AGS_IPATCH_SF2_READER(gobject);
218 
219   /* get ipatch sample mutex */
220   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
221 
222   switch(prop_id){
223   case PROP_IPATCH:
224     {
225       AgsIpatch *ipatch;
226 
227       ipatch = (AgsIpatch *) g_value_get_object(value);
228 
229       g_rec_mutex_lock(ipatch_sf2_reader_mutex);
230 
231       if(ipatch_sf2_reader->ipatch == ipatch){
232 	g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
233 
234 	return;
235       }
236 
237       if(ipatch_sf2_reader->ipatch != NULL){
238 	g_object_unref(ipatch_sf2_reader->ipatch);
239       }
240 
241       if(ipatch != NULL){
242 	g_object_ref(ipatch);
243       }
244 
245       ipatch_sf2_reader->ipatch = ipatch;
246 
247       g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
248     }
249     break;
250   default:
251     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
252     break;
253   }
254 }
255 
256 void
ags_ipatch_sf2_reader_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)257 ags_ipatch_sf2_reader_get_property(GObject *gobject,
258 				   guint prop_id,
259 				   GValue *value,
260 				   GParamSpec *param_spec)
261 {
262   AgsIpatchSF2Reader *ipatch_sf2_reader;
263 
264   GRecMutex *ipatch_sf2_reader_mutex;
265 
266   ipatch_sf2_reader = AGS_IPATCH_SF2_READER(gobject);
267 
268   /* get ipatch sample mutex */
269   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
270 
271   switch(prop_id){
272   case PROP_IPATCH:
273     {
274       g_rec_mutex_lock(ipatch_sf2_reader_mutex);
275 
276       g_value_set_object(value, ipatch_sf2_reader->ipatch);
277 
278       g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
279     }
280     break;
281   default:
282     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
283     break;
284   }
285 }
286 
287 void
ags_ipatch_sf2_reader_dispose(GObject * gobject)288 ags_ipatch_sf2_reader_dispose(GObject *gobject)
289 {
290   AgsIpatchSF2Reader *ipatch_sf2_reader;
291 
292   ipatch_sf2_reader = AGS_IPATCH_SF2_READER(gobject);
293 
294   if(ipatch_sf2_reader->ipatch != NULL){
295     g_object_unref(ipatch_sf2_reader->ipatch);
296 
297     ipatch_sf2_reader->ipatch = NULL;
298   }
299 
300   /* call parent */
301   G_OBJECT_CLASS(ags_ipatch_sf2_reader_parent_class)->dispose(gobject);
302 }
303 
304 void
ags_ipatch_sf2_reader_finalize(GObject * gobject)305 ags_ipatch_sf2_reader_finalize(GObject *gobject)
306 {
307   AgsIpatchSF2Reader *ipatch_sf2_reader;
308 
309   ipatch_sf2_reader = AGS_IPATCH_SF2_READER(gobject);
310 
311   if(ipatch_sf2_reader->ipatch != NULL){
312     g_object_unref(ipatch_sf2_reader->ipatch);
313   }
314 
315   /* call parent */
316   G_OBJECT_CLASS(ags_ipatch_sf2_reader_parent_class)->finalize(gobject);
317 }
318 
319 AgsUUID*
ags_ipatch_sf2_reader_get_uuid(AgsConnectable * connectable)320 ags_ipatch_sf2_reader_get_uuid(AgsConnectable *connectable)
321 {
322   AgsIpatchSF2Reader *ipatch_sf2_reader;
323 
324   AgsUUID *ptr;
325 
326   GRecMutex *ipatch_sf2_reader_mutex;
327 
328   ipatch_sf2_reader = AGS_IPATCH_SF2_READER(connectable);
329 
330   /* get audio file mutex */
331   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
332 
333   /* get UUID */
334   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
335 
336   ptr = ipatch_sf2_reader->uuid;
337 
338   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
339 
340   return(ptr);
341 }
342 
343 gboolean
ags_ipatch_sf2_reader_has_resource(AgsConnectable * connectable)344 ags_ipatch_sf2_reader_has_resource(AgsConnectable *connectable)
345 {
346   return(TRUE);
347 }
348 
349 gboolean
ags_ipatch_sf2_reader_is_ready(AgsConnectable * connectable)350 ags_ipatch_sf2_reader_is_ready(AgsConnectable *connectable)
351 {
352   AgsIpatchSF2Reader *ipatch_sf2_reader;
353 
354   gboolean is_ready;
355 
356   ipatch_sf2_reader = AGS_IPATCH_SF2_READER(connectable);
357 
358   /* check is ready */
359   is_ready = ags_ipatch_sf2_reader_test_flags(ipatch_sf2_reader, AGS_IPATCH_SF2_READER_ADDED_TO_REGISTRY);
360 
361   return(is_ready);
362 }
363 
364 void
ags_ipatch_sf2_reader_add_to_registry(AgsConnectable * connectable)365 ags_ipatch_sf2_reader_add_to_registry(AgsConnectable *connectable)
366 {
367   AgsIpatchSF2Reader *ipatch_sf2_reader;
368 
369   AgsRegistry *registry;
370   AgsRegistryEntry *entry;
371 
372   AgsApplicationContext *application_context;
373 
374   if(ags_connectable_is_ready(connectable)){
375     return;
376   }
377 
378   ipatch_sf2_reader = AGS_IPATCH_SF2_READER(connectable);
379 
380   ags_ipatch_sf2_reader_set_flags(ipatch_sf2_reader, AGS_IPATCH_SF2_READER_ADDED_TO_REGISTRY);
381 
382   application_context = ags_application_context_get_instance();
383 
384   registry = (AgsRegistry *) ags_service_provider_get_registry(AGS_SERVICE_PROVIDER(application_context));
385 
386   if(registry != NULL){
387     entry = ags_registry_entry_alloc(registry);
388     g_value_set_object(entry->entry,
389 		       (gpointer) ipatch_sf2_reader);
390     ags_registry_add_entry(registry,
391 			   entry);
392   }
393 }
394 
395 void
ags_ipatch_sf2_reader_remove_from_registry(AgsConnectable * connectable)396 ags_ipatch_sf2_reader_remove_from_registry(AgsConnectable *connectable)
397 {
398   if(!ags_connectable_is_ready(connectable)){
399     return;
400   }
401 
402   //TODO:JK: implement me
403 }
404 
405 xmlNode*
ags_ipatch_sf2_reader_list_resource(AgsConnectable * connectable)406 ags_ipatch_sf2_reader_list_resource(AgsConnectable *connectable)
407 {
408   xmlNode *node;
409 
410   node = NULL;
411 
412   //TODO:JK: implement me
413 
414   return(node);
415 }
416 
417 xmlNode*
ags_ipatch_sf2_reader_xml_compose(AgsConnectable * connectable)418 ags_ipatch_sf2_reader_xml_compose(AgsConnectable *connectable)
419 {
420   xmlNode *node;
421 
422   node = NULL;
423 
424   //TODO:JK: implement me
425 
426   return(node);
427 }
428 
429 void
ags_ipatch_sf2_reader_xml_parse(AgsConnectable * connectable,xmlNode * node)430 ags_ipatch_sf2_reader_xml_parse(AgsConnectable *connectable,
431 			      xmlNode *node)
432 {
433   //TODO:JK: implement me
434 }
435 
436 gboolean
ags_ipatch_sf2_reader_is_connected(AgsConnectable * connectable)437 ags_ipatch_sf2_reader_is_connected(AgsConnectable *connectable)
438 {
439   AgsIpatchSF2Reader *ipatch_sf2_reader;
440 
441   gboolean is_connected;
442 
443   ipatch_sf2_reader = AGS_IPATCH_SF2_READER(connectable);
444 
445   /* check is connected */
446   is_connected = ags_ipatch_sf2_reader_test_flags(ipatch_sf2_reader, AGS_IPATCH_SF2_READER_CONNECTED);
447 
448   return(is_connected);
449 }
450 
451 void
ags_ipatch_sf2_reader_connect(AgsConnectable * connectable)452 ags_ipatch_sf2_reader_connect(AgsConnectable *connectable)
453 {
454   AgsIpatchSF2Reader *ipatch_sf2_reader;
455 
456   if(ags_connectable_is_connected(connectable)){
457     return;
458   }
459 
460   ipatch_sf2_reader = AGS_IPATCH_SF2_READER(connectable);
461 
462   ags_ipatch_sf2_reader_set_flags(ipatch_sf2_reader, AGS_IPATCH_SF2_READER_CONNECTED);
463 }
464 
465 void
ags_ipatch_sf2_reader_disconnect(AgsConnectable * connectable)466 ags_ipatch_sf2_reader_disconnect(AgsConnectable *connectable)
467 {
468   AgsIpatchSF2Reader *ipatch_sf2_reader;
469 
470   if(!ags_connectable_is_connected(connectable)){
471     return;
472   }
473 
474   ipatch_sf2_reader = AGS_IPATCH_SF2_READER(connectable);
475 
476   ags_ipatch_sf2_reader_unset_flags(ipatch_sf2_reader, AGS_IPATCH_SF2_READER_CONNECTED);
477 }
478 
479 /**
480  * ags_ipatch_sf2_reader_test_flags:
481  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
482  * @flags: the flags
483  *
484  * Test @flags to be set on @ipatch_sf2_reader.
485  *
486  * Returns: %TRUE if flags are set, else %FALSE
487  *
488  * Since: 3.0.0
489  */
490 gboolean
ags_ipatch_sf2_reader_test_flags(AgsIpatchSF2Reader * ipatch_sf2_reader,guint flags)491 ags_ipatch_sf2_reader_test_flags(AgsIpatchSF2Reader *ipatch_sf2_reader, guint flags)
492 {
493   gboolean retval;
494 
495   GRecMutex *ipatch_sf2_reader_mutex;
496 
497   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
498     return(FALSE);
499   }
500 
501   /* get ipatch sf2 reader mutex */
502   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
503 
504   /* test */
505   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
506 
507   retval = (flags & (ipatch_sf2_reader->flags)) ? TRUE: FALSE;
508 
509   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
510 
511   return(retval);
512 }
513 
514 /**
515  * ags_ipatch_sf2_reader_set_flags:
516  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
517  * @flags: see #AgsIpatchSF2ReaderFlags-enum
518  *
519  * Enable a feature of @ipatch_sf2_reader.
520  *
521  * Since: 3.0.0
522  */
523 void
ags_ipatch_sf2_reader_set_flags(AgsIpatchSF2Reader * ipatch_sf2_reader,guint flags)524 ags_ipatch_sf2_reader_set_flags(AgsIpatchSF2Reader *ipatch_sf2_reader, guint flags)
525 {
526   GRecMutex *ipatch_sf2_reader_mutex;
527 
528   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
529     return;
530   }
531 
532   /* get ipatch sf2 reader mutex */
533   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
534 
535   //TODO:JK: add more?
536 
537   /* set flags */
538   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
539 
540   ipatch_sf2_reader->flags |= flags;
541 
542   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
543 }
544 
545 /**
546  * ags_ipatch_sf2_reader_unset_flags:
547  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
548  * @flags: see #AgsIpatchSF2ReaderFlags-enum
549  *
550  * Disable a feature of @ipatch_sf2_reader.
551  *
552  * Since: 3.0.0
553  */
554 void
ags_ipatch_sf2_reader_unset_flags(AgsIpatchSF2Reader * ipatch_sf2_reader,guint flags)555 ags_ipatch_sf2_reader_unset_flags(AgsIpatchSF2Reader *ipatch_sf2_reader, guint flags)
556 {
557   GRecMutex *ipatch_sf2_reader_mutex;
558 
559   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
560     return;
561   }
562 
563   /* get ipatch sf2 reader mutex */
564   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
565 
566   //TODO:JK: add more?
567 
568   /* unset flags */
569   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
570 
571   ipatch_sf2_reader->flags &= (~flags);
572 
573   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
574 }
575 
576 /**
577  * ags_ipatch_sf2_reader_load:
578  * @ipatch_sf2_reader: the #AgsSF2Reader
579  * @handle: the #IpatchFileHandle
580  *
581  * Load Soundfont2 file.
582  *
583  * Returns: %TRUE on success, else %FALSE on failure
584  *
585  * Since: 3.0.0
586  */
587 gboolean
ags_ipatch_sf2_reader_load(AgsIpatchSF2Reader * ipatch_sf2_reader,IpatchFileHandle * handle)588 ags_ipatch_sf2_reader_load(AgsIpatchSF2Reader *ipatch_sf2_reader,
589 			   IpatchFileHandle *handle)
590 {
591   IpatchSF2Reader *reader;
592 
593   GError *error;
594 
595   GRecMutex *ipatch_sf2_reader_mutex;
596 
597   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
598     return(FALSE);
599   }
600 
601   /* get ipatch sf2 reader mutex */
602   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
603 
604   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
605 
606   reader =
607     ipatch_sf2_reader->reader = ipatch_sf2_reader_new(handle);
608 
609   error = NULL;
610   ipatch_sf2_reader->base = (IpatchBase *) ipatch_sf2_reader_load(reader,
611 								  &error);
612 
613   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
614 
615   if(error != NULL){
616     g_warning("%s", error->message);
617 
618     g_rec_mutex_lock(ipatch_sf2_reader_mutex);
619 
620     ipatch_sf2_reader->error = error;
621 
622     g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
623 
624     return(FALSE);
625   }
626 
627   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
628 
629   error = NULL;
630   ipatch_sf2_reader->sf2 = (IpatchSF2 *) ipatch_convert_object_to_type((GObject *) handle->file,
631 								       IPATCH_TYPE_SF2,
632 								       &error);
633 
634   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
635 
636   if(error != NULL){
637     g_warning("%s", error->message);
638 
639     g_rec_mutex_lock(ipatch_sf2_reader_mutex);
640 
641     ipatch_sf2_reader->error = error;
642 
643     g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
644 
645     return(FALSE);
646   }
647 
648   return(TRUE);
649 }
650 
651 /**
652  * ags_ipatch_sf2_reader_select_preset:
653  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
654  * @preset_index: the preset index
655  *
656  * Select preset.
657  *
658  * Returns: %TRUE on success, else %FALSE on failure
659  *
660  * Since: 3.0.0
661  */
662 gboolean
ags_ipatch_sf2_reader_select_preset(AgsIpatchSF2Reader * ipatch_sf2_reader,guint preset_index)663 ags_ipatch_sf2_reader_select_preset(AgsIpatchSF2Reader *ipatch_sf2_reader,
664 				    guint preset_index)
665 {
666   IpatchSF2 *sf2;
667   IpatchItem *ipatch_item;
668   IpatchList *ipatch_list;
669 
670   IpatchIter preset_iter;
671 
672   gboolean success;
673 
674   GRecMutex *ipatch_sf2_reader_mutex;
675 
676   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
677     return(FALSE);
678   }
679 
680   /* get ipatch sf2 reader mutex */
681   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
682 
683   success = FALSE;
684 
685   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
686 
687   sf2 = ipatch_sf2_reader->sf2;
688 
689   ipatch_list = ipatch_container_get_children((IpatchContainer *) sf2, IPATCH_TYPE_SF2_PRESET);
690 
691   if(ipatch_list != NULL){
692     ipatch_list_init_iter(ipatch_list, &preset_iter);
693 
694     if(preset_index < ipatch_iter_count(&preset_iter)){
695       success = TRUE;
696 
697       ipatch_iter_index(&preset_iter, preset_index);
698       ipatch_item = ipatch_iter_get(&preset_iter);
699 
700       /* selected index and name */
701       ipatch_sf2_reader->index_selected[AGS_SF2_PHDR] = preset_index;
702 
703       ipatch_sf2_reader->index_selected[AGS_SF2_IHDR] = 0;
704 
705       ipatch_sf2_reader->index_selected[AGS_SF2_SHDR] = 0;
706 
707       ipatch_sf2_reader->name_selected[AGS_SF2_PHDR] = g_strdup(ipatch_sf2_preset_get_name(IPATCH_SF2_PRESET(ipatch_item)));
708 
709       g_free(ipatch_sf2_reader->name_selected[AGS_SF2_IHDR]);
710       ipatch_sf2_reader->name_selected[AGS_SF2_IHDR] = NULL;
711 
712       g_free(ipatch_sf2_reader->name_selected[AGS_SF2_SHDR]);
713       ipatch_sf2_reader->name_selected[AGS_SF2_SHDR] = NULL;
714 
715       /* container */
716       ipatch_sf2_reader->preset = (IpatchContainer *) ipatch_item;
717 
718       ipatch_sf2_reader->instrument = NULL;
719       ipatch_sf2_reader->sample = NULL;
720     }
721   }
722 
723   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
724 
725   return(success);
726 }
727 
728 /**
729  * ags_ipatch_sf2_reader_select_instrument:
730  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
731  * @instrument_index: the instrument index
732  *
733  * Select instrument.
734  *
735  * Returns: %TRUE on success, else %FALSE on failure
736  *
737  * Since: 3.0.0
738  */
739 gboolean
ags_ipatch_sf2_reader_select_instrument(AgsIpatchSF2Reader * ipatch_sf2_reader,guint instrument_index)740 ags_ipatch_sf2_reader_select_instrument(AgsIpatchSF2Reader *ipatch_sf2_reader,
741 					guint instrument_index)
742 {
743   IpatchSF2 *sf2;
744   IpatchItem *ipatch_item;
745   IpatchList *ipatch_list;
746 
747   IpatchIter instrument_iter;
748 
749   gboolean success;
750 
751   GRecMutex *ipatch_sf2_reader_mutex;
752 
753   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
754     return(FALSE);
755   }
756 
757   /* get ipatch sf2 reader mutex */
758   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
759 
760   success = FALSE;
761 
762   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
763 
764   sf2 = ipatch_sf2_reader->sf2;
765 
766   ipatch_list = ipatch_sf2_preset_get_zones(ipatch_sf2_reader->preset);
767 
768   if(ipatch_list != NULL){
769     ipatch_list_init_iter(ipatch_list, &instrument_iter);
770 
771     if(instrument_index < ipatch_iter_count(&instrument_iter)){
772       success = TRUE;
773 
774       ipatch_iter_index(&instrument_iter, instrument_index);
775       ipatch_item = (IpatchItem *) ipatch_sf2_pzone_get_inst(ipatch_iter_get(&instrument_iter));
776 
777       /* selected index and name */
778       ipatch_sf2_reader->index_selected[AGS_SF2_IHDR] = instrument_index;
779 
780       ipatch_sf2_reader->index_selected[AGS_SF2_SHDR] = 0;
781 
782       g_free(ipatch_sf2_reader->name_selected[AGS_SF2_IHDR]);
783       ipatch_sf2_reader->name_selected[AGS_SF2_IHDR] = g_strdup(ipatch_sf2_inst_get_name(IPATCH_SF2_INST(ipatch_item)));
784 
785       g_free(ipatch_sf2_reader->name_selected[AGS_SF2_SHDR]);
786       ipatch_sf2_reader->name_selected[AGS_SF2_SHDR] = NULL;
787 
788       /* container */
789       ipatch_sf2_reader->instrument = (IpatchContainer *) ipatch_item;
790 
791       ipatch_sf2_reader->sample = NULL;
792     }
793   }
794 
795   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
796 
797   return(success);
798 }
799 
800 /**
801  * ags_ipatch_sf2_reader_select_sample:
802  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
803  * @sample_index: the sample index
804  *
805  * Select sample.
806  *
807  * Returns: %TRUE on success, else %FALSE on failure
808  *
809  * Since: 3.0.0
810  */
811 gboolean
ags_ipatch_sf2_reader_select_sample(AgsIpatchSF2Reader * ipatch_sf2_reader,guint sample_index)812 ags_ipatch_sf2_reader_select_sample(AgsIpatchSF2Reader *ipatch_sf2_reader,
813 				    guint sample_index)
814 {
815   IpatchSF2 *sf2;
816   IpatchItem *ipatch_item;
817   IpatchList *ipatch_list;
818 
819   IpatchIter sample_iter;
820 
821   gboolean success;
822 
823   GRecMutex *ipatch_sf2_reader_mutex;
824 
825   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
826     return(FALSE);
827   }
828 
829   /* get ipatch sf2 reader mutex */
830   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
831 
832   success = FALSE;
833 
834   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
835 
836   sf2 = ipatch_sf2_reader->sf2;
837 
838   ipatch_list = ipatch_sf2_inst_get_zones(ipatch_sf2_reader->instrument);
839 
840   if(ipatch_list != NULL){
841     ipatch_list_init_iter(ipatch_list, &sample_iter);
842 
843     if(sample_index < ipatch_iter_count(&sample_iter)){
844       success = TRUE;
845 
846       ipatch_iter_index(&sample_iter, sample_index);
847       ipatch_item = (IpatchItem *) ipatch_sf2_izone_get_sample(ipatch_iter_get(&sample_iter));
848 
849       /* selected index and name */
850       ipatch_sf2_reader->index_selected[AGS_SF2_SHDR] = sample_index;
851 
852       g_free(ipatch_sf2_reader->name_selected[AGS_SF2_SHDR]);
853       ipatch_sf2_reader->name_selected[AGS_SF2_SHDR] = g_strdup(ipatch_sf2_sample_get_name((IpatchSF2Sample *) ipatch_item));
854 
855       /* container */
856       ipatch_sf2_reader->sample = (IpatchContainer *) ipatch_item;
857     }
858   }
859 
860   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
861 
862   return(success);
863 }
864 
865 /**
866  * ags_ipatch_sf2_reader_get_preset_all:
867  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
868  *
869  * Get all preset names.
870  *
871  * Returns: (element-type utf8) (array zero-terminated=1) (transfer full): the string vector cotaining preset names or %NULL on failure
872  *
873  * Since: 3.0.0
874  */
875 gchar**
ags_ipatch_sf2_reader_get_preset_all(AgsIpatchSF2Reader * ipatch_sf2_reader)876 ags_ipatch_sf2_reader_get_preset_all(AgsIpatchSF2Reader *ipatch_sf2_reader)
877 {
878   IpatchSF2 *sf2;
879   IpatchItem *ipatch_item;
880   IpatchList *ipatch_list;
881 
882   IpatchIter preset_iter;
883 
884   gchar **preset;
885 
886   guint i, i_stop;
887 
888   GRecMutex *ipatch_sf2_reader_mutex;
889 
890   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
891     return(NULL);
892   }
893 
894   /* get ipatch sf2 reader mutex */
895   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
896 
897   preset = NULL;
898 
899   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
900 
901   sf2 = ipatch_sf2_reader->sf2;
902 
903   ipatch_list = ipatch_container_get_children((IpatchContainer *) sf2, IPATCH_TYPE_SF2_PRESET);
904 
905   if(ipatch_list != NULL){
906     ipatch_list_init_iter(ipatch_list, &preset_iter);
907 
908     i_stop = ipatch_iter_count(&preset_iter);
909 
910     if(i_stop > 0){
911       preset = (gchar **) malloc((i_stop + 1) * sizeof(gchar *));
912 
913       ipatch_iter_first(&preset_iter);
914 
915       for(i = 0; i < i_stop; i++){
916 	ipatch_item = ipatch_iter_get(&preset_iter);
917 	preset[i] = g_strdup(ipatch_sf2_preset_get_name(IPATCH_SF2_PRESET(ipatch_item)));
918 
919 	/* iterate */
920 	ipatch_iter_next(&preset_iter);
921       }
922 
923       preset[i] = NULL;
924     }
925   }
926 
927   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
928 
929   return(preset);
930 }
931 
932 /**
933  * ags_ipatch_sf2_reader_get_instrument_all:
934  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
935  *
936  * Get all instrument names.
937  *
938  * Returns: (element-type utf8) (array zero-terminated=1) (transfer full): the string vector cotaining instrument names or %NULL on failure
939  *
940  * Since: 3.0.0
941  */
942 gchar**
ags_ipatch_sf2_reader_get_instrument_all(AgsIpatchSF2Reader * ipatch_sf2_reader)943 ags_ipatch_sf2_reader_get_instrument_all(AgsIpatchSF2Reader *ipatch_sf2_reader)
944 {
945   IpatchSF2 *sf2;
946   IpatchItem *ipatch_item;
947   IpatchList *ipatch_list;
948 
949   IpatchIter instrument_iter;
950 
951   gchar **instrument;
952 
953   guint i, i_stop;
954 
955   GRecMutex *ipatch_sf2_reader_mutex;
956 
957   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
958     return(NULL);
959   }
960 
961   /* get ipatch sf2 reader mutex */
962   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
963 
964   instrument = NULL;
965 
966   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
967 
968   sf2 = ipatch_sf2_reader->sf2;
969 
970   ipatch_list = ipatch_container_get_children((IpatchContainer *) sf2, IPATCH_TYPE_SF2_INST);
971 
972   if(ipatch_list != NULL){
973     ipatch_list_init_iter(ipatch_list, &instrument_iter);
974 
975     i_stop = ipatch_iter_count(&instrument_iter);
976 
977     if(i_stop > 0){
978       instrument = (gchar **) malloc((i_stop + 1) * sizeof(gchar *));
979 
980       ipatch_iter_first(&instrument_iter);
981 
982       for(i = 0; i < i_stop; i++){
983 	ipatch_item = ipatch_iter_get(&instrument_iter);
984 	instrument[i] = g_strdup(ipatch_sf2_inst_get_name(IPATCH_SF2_INST(ipatch_item)));
985 
986 	/* iterate */
987 	ipatch_iter_next(&instrument_iter);
988       }
989 
990       instrument[i] = NULL;
991     }
992   }
993 
994   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
995 
996   return(instrument);
997 }
998 
999 /**
1000  * ags_ipatch_sf2_reader_get_sample_all:
1001  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
1002  *
1003  * Get all sample names.
1004  *
1005  * Returns: (element-type utf8) (array zero-terminated=1) (transfer full): the string vector cotaining sample names or %NULL on failure
1006  *
1007  * Since: 3.0.0
1008  */
1009 gchar**
ags_ipatch_sf2_reader_get_sample_all(AgsIpatchSF2Reader * ipatch_sf2_reader)1010 ags_ipatch_sf2_reader_get_sample_all(AgsIpatchSF2Reader *ipatch_sf2_reader)
1011 {
1012   IpatchSF2 *sf2;
1013   IpatchItem *ipatch_item;
1014   IpatchList *ipatch_list;
1015 
1016   IpatchIter sample_iter;
1017 
1018   gchar **sample;
1019 
1020   guint i, i_stop;
1021 
1022   GRecMutex *ipatch_sf2_reader_mutex;
1023 
1024   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
1025     return(NULL);
1026   }
1027 
1028   /* get ipatch sf2 reader mutex */
1029   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
1030 
1031   sample = NULL;
1032 
1033   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
1034 
1035   sf2 = ipatch_sf2_reader->sf2;
1036 
1037   ipatch_list = ipatch_container_get_children((IpatchContainer *) sf2, IPATCH_TYPE_SF2_SAMPLE);
1038 
1039   if(ipatch_list != NULL){
1040     ipatch_list_init_iter(ipatch_list, &sample_iter);
1041 
1042     i_stop = ipatch_iter_count(&sample_iter);
1043 
1044     if(i_stop > 0){
1045       sample = (gchar **) malloc((i_stop + 1) * sizeof(gchar *));
1046 
1047       ipatch_iter_first(&sample_iter);
1048 
1049       for(i = 0; i < i_stop; i++){
1050 	ipatch_item = ipatch_iter_get(&sample_iter);
1051 	sample[i] = g_strdup(ipatch_sf2_sample_get_name(IPATCH_SF2_SAMPLE(ipatch_item)));
1052 
1053 	/* iterate */
1054 	ipatch_iter_next(&sample_iter);
1055       }
1056 
1057       sample[i] = NULL;
1058     }
1059   }
1060 
1061   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
1062 
1063   return(sample);
1064 }
1065 
1066 /**
1067  * ags_ipatch_sf2_reader_get_instrument_by_preset_index:
1068  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
1069  * @preset_index: the preset index
1070  *
1071  * Get instrument by preset index.
1072  *
1073  * Returns: (element-type utf8) (array zero-terminated=1) (transfer full): the string vector cotaining instrument names or %NULL on failure
1074  *
1075  * Since: 3.0.0
1076  */
1077 gchar**
ags_ipatch_sf2_reader_get_instrument_by_preset_index(AgsIpatchSF2Reader * ipatch_sf2_reader,guint preset_index)1078 ags_ipatch_sf2_reader_get_instrument_by_preset_index(AgsIpatchSF2Reader *ipatch_sf2_reader,
1079 						     guint preset_index)
1080 {
1081   IpatchSF2 *sf2;
1082   IpatchContainer *preset;
1083   IpatchContainer *instrument;
1084 
1085   IpatchItem *ipatch_item;
1086   IpatchList *ipatch_list;
1087 
1088   IpatchIter preset_iter, instrument_iter, sample_iter;
1089 
1090   gchar **instrument_strv;
1091 
1092   guint i, i_stop;
1093   guint j, j_stop;
1094   guint k, k_stop;
1095   guint count;
1096 
1097   GRecMutex *ipatch_sf2_reader_mutex;
1098 
1099   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
1100     return(NULL);
1101   }
1102 
1103   /* get ipatch sf2 reader mutex */
1104   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
1105 
1106   instrument_strv = NULL;
1107 
1108   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
1109 
1110   sf2 = ipatch_sf2_reader->sf2;
1111 
1112   /* presets */
1113   ipatch_list = ipatch_container_get_children((IpatchContainer *) sf2, IPATCH_TYPE_SF2_PRESET);
1114 
1115   if(ipatch_list != NULL){
1116     ipatch_list_init_iter(ipatch_list, &preset_iter);
1117 
1118     i_stop = ipatch_iter_count(&preset_iter);
1119 
1120     if(i_stop > 0 && preset_index < i_stop){
1121       ipatch_iter_first(&preset_iter);
1122       ipatch_iter_index(&preset_iter, preset_index);
1123 
1124       preset = (IpatchContainer *) ipatch_iter_get(&preset_iter);
1125 
1126       /* instruments */
1127       ipatch_list = ipatch_sf2_preset_get_zones(preset);
1128 
1129       if(ipatch_list != NULL){
1130 	ipatch_list_init_iter(ipatch_list, &instrument_iter);
1131 
1132 	j_stop = ipatch_iter_count(&instrument_iter);
1133 	ipatch_iter_first(&instrument_iter);
1134 
1135 	if(j_stop > 0){
1136 	  instrument_strv = (gchar **) malloc((j_stop + 1) * sizeof(gchar *));
1137 
1138 	  for(j = 0, count = 0; j < j_stop; j++){
1139 	    instrument = (IpatchContainer *) ipatch_sf2_pzone_get_inst(ipatch_iter_get(&instrument_iter));
1140 	    instrument_strv[count] = g_strdup(ipatch_sf2_inst_get_name((IpatchSF2Inst *) instrument));
1141 
1142 	    /* iterate */
1143 	    ipatch_iter_next(&instrument_iter);
1144 	    count++;
1145 	  }
1146 
1147 	  instrument_strv[count] = NULL;
1148 	}
1149       }
1150     }
1151   }
1152 
1153   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
1154 
1155   return(instrument_strv);
1156 }
1157 
1158 /**
1159  * ags_ipatch_sf2_reader_get_sample_by_preset_index:
1160  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
1161  * @preset_index: the preset index
1162  *
1163  * Get sample by preset index.
1164  *
1165  * Returns: (element-type utf8) (array zero-terminated=1) (transfer full): the string vector cotaining sample names or %NULL on failure
1166  *
1167  * Since: 3.0.0
1168  */
1169 gchar**
ags_ipatch_sf2_reader_get_sample_by_preset_index(AgsIpatchSF2Reader * ipatch_sf2_reader,guint preset_index)1170 ags_ipatch_sf2_reader_get_sample_by_preset_index(AgsIpatchSF2Reader *ipatch_sf2_reader,
1171 						 guint preset_index)
1172 {
1173   IpatchSF2 *sf2;
1174   IpatchContainer *preset;
1175   IpatchContainer *instrument;
1176 
1177   IpatchItem *ipatch_item;
1178   IpatchList *ipatch_list;
1179 
1180   IpatchIter preset_iter, instrument_iter, sample_iter;
1181 
1182   gchar **sample_strv;
1183 
1184   guint i, i_stop;
1185   guint j, j_stop;
1186   guint k, k_stop;
1187   guint count;
1188 
1189   GRecMutex *ipatch_sf2_reader_mutex;
1190 
1191   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
1192     return(NULL);
1193   }
1194 
1195   /* get ipatch sf2 reader mutex */
1196   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
1197 
1198   sample_strv = NULL;
1199 
1200   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
1201 
1202   sf2 = ipatch_sf2_reader->sf2;
1203 
1204   /* presets */
1205   ipatch_list = ipatch_container_get_children((IpatchContainer *) sf2, IPATCH_TYPE_SF2_PRESET);
1206 
1207   if(ipatch_list != NULL){
1208     ipatch_list_init_iter(ipatch_list, &preset_iter);
1209 
1210     i_stop = ipatch_iter_count(&preset_iter);
1211 
1212     if(i_stop > 0){
1213       ipatch_iter_index(&preset_iter, preset_index);
1214 
1215       preset = (IpatchContainer *) ipatch_iter_get(&preset_iter);
1216 
1217       /* instruments */
1218       ipatch_list = ipatch_sf2_preset_get_zones(preset);
1219 
1220       if(ipatch_list != NULL){
1221 	ipatch_list_init_iter(ipatch_list, &instrument_iter);
1222 
1223 	j_stop = ipatch_iter_count(&instrument_iter);
1224 
1225 	if(j_stop > 0){
1226 	  for(j = 0, count = 0; j < j_stop; j++){
1227 	    instrument = (IpatchContainer *) ipatch_sf2_pzone_get_inst(ipatch_iter_get(&instrument_iter));
1228 
1229 	    /* samples */
1230 	    ipatch_list = ipatch_sf2_inst_get_zones(preset);
1231 
1232 	    if(ipatch_list != NULL){
1233 	      ipatch_list_init_iter(ipatch_list, &sample_iter);
1234 
1235 	      k_stop = ipatch_iter_count(&sample_iter);
1236 
1237 	      if(k_stop > 0){
1238 		if(sample_strv == NULL){
1239 		  sample_strv = (gchar **) malloc((k_stop + 1) * sizeof(gchar *));
1240 		}else{
1241 		  sample_strv = (gchar **) realloc(sample_strv,
1242 						   (count + k_stop + 1) * sizeof(gchar *));
1243 		}
1244 
1245 		for(k = 0; k < k_stop; k++){
1246 		  ipatch_item = (IpatchItem *) ipatch_sf2_izone_get_sample(ipatch_iter_get(&sample_iter));
1247 		  sample_strv[count] = g_strdup(ipatch_sf2_sample_get_name((IpatchSF2Sample *) ipatch_item));
1248 
1249 		  /* iterate */
1250 		  ipatch_iter_next(&sample_iter);
1251 		  count++;
1252 		}
1253 	      }
1254 	    }
1255 
1256 	    /* iterate */
1257 	    ipatch_iter_next(&instrument_iter);
1258 	  }
1259 	}
1260       }
1261 
1262       if(sample_strv != NULL){
1263 	sample_strv[count] = NULL;
1264       }
1265     }
1266   }
1267 
1268   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
1269 
1270   return(sample_strv);
1271 }
1272 
1273 /**
1274  * ags_ipatch_sf2_reader_get_sample_by_preset_and_instrument_index:
1275  * @ipatch_sf2_reader: the #AgsIpatchSF2Reader
1276  * @preset_index: the preset index
1277  * @instrument_index: the instrument index
1278  *
1279  * Get sample by preset and instrument index.
1280  *
1281  * Returns: (element-type utf8) (array zero-terminated=1) (transfer full): the string vector cotaining sample names or %NULL on failure
1282  *
1283  * Since: 3.0.0
1284  */
1285 gchar**
ags_ipatch_sf2_reader_get_sample_by_preset_and_instrument_index(AgsIpatchSF2Reader * ipatch_sf2_reader,guint preset_index,guint instrument_index)1286 ags_ipatch_sf2_reader_get_sample_by_preset_and_instrument_index(AgsIpatchSF2Reader *ipatch_sf2_reader,
1287 								guint preset_index, guint instrument_index)
1288 {
1289   IpatchSF2 *sf2;
1290   IpatchContainer *preset;
1291   IpatchContainer *instrument;
1292 
1293   IpatchItem *ipatch_item;
1294   IpatchList *ipatch_list;
1295 
1296   IpatchIter preset_iter, instrument_iter, sample_iter;
1297 
1298   gchar **sample;
1299 
1300   guint i, i_stop;
1301   guint j, j_stop;
1302   guint k, k_stop;
1303   guint count;
1304 
1305   GRecMutex *ipatch_sf2_reader_mutex;
1306 
1307   if(!AGS_IS_IPATCH_SF2_READER(ipatch_sf2_reader)){
1308     return(NULL);
1309   }
1310 
1311   /* get ipatch sf2 reader mutex */
1312   ipatch_sf2_reader_mutex = AGS_IPATCH_SF2_READER_GET_OBJ_MUTEX(ipatch_sf2_reader);
1313 
1314   sample = NULL;
1315 
1316   g_rec_mutex_lock(ipatch_sf2_reader_mutex);
1317 
1318   sf2 = ipatch_sf2_reader->sf2;
1319 
1320   /* presets */
1321   ipatch_list = ipatch_container_get_children((IpatchContainer *) sf2, IPATCH_TYPE_SF2_PRESET);
1322 
1323   if(ipatch_list != NULL){
1324     ipatch_list_init_iter(ipatch_list, &preset_iter);
1325 
1326     i_stop = ipatch_iter_count(&preset_iter);
1327 
1328     if(i_stop > 0 && preset_index < i_stop){
1329       ipatch_iter_index(&preset_iter, preset_index);
1330 
1331       preset = (IpatchContainer *) ipatch_iter_get(&preset_iter);
1332 
1333       /* instruments */
1334       ipatch_list = ipatch_sf2_preset_get_zones(preset);
1335 
1336       if(ipatch_list != NULL){
1337 	ipatch_list_init_iter(ipatch_list, &instrument_iter);
1338 
1339 	j_stop = ipatch_iter_count(&instrument_iter);
1340 
1341 	if(j_stop > 0 && instrument_index < j_stop){
1342 	  ipatch_iter_index(&instrument_iter, instrument_index);
1343 
1344 	  instrument = (IpatchContainer *) ipatch_sf2_pzone_get_inst(ipatch_iter_get(&instrument_iter));
1345 
1346 	  /* samples */
1347 	  ipatch_list = ipatch_sf2_inst_get_zones(instrument);
1348 
1349 	  if(ipatch_list != NULL){
1350 	    ipatch_list_init_iter(ipatch_list, &sample_iter);
1351 
1352 	    k_stop = ipatch_iter_count(&sample_iter);
1353 
1354 	    if(k_stop > 0){
1355 	      sample = (gchar **) malloc((k_stop + 1) * sizeof(gchar *));
1356 
1357 	      for(k = 0, count = 0; k < k_stop; k++){
1358 		ipatch_item = (IpatchItem *) ipatch_sf2_izone_get_sample(ipatch_iter_get(&sample_iter));
1359 		sample[count] = g_strdup(ipatch_sf2_sample_get_name((IpatchSF2Sample *) ipatch_item));
1360 
1361 		/* iterate */
1362 		ipatch_iter_next(&sample_iter);
1363 		count++;
1364 	      }
1365 
1366 	      sample[count] = NULL;
1367 	    }
1368 	  }
1369 	}
1370       }
1371     }
1372   }
1373 
1374   g_rec_mutex_unlock(ipatch_sf2_reader_mutex);
1375 
1376   return(sample);
1377 }
1378 
1379 /**
1380  * ags_ipatch_sf2_reader_new:
1381  * @ipatch: the #AgsIpatch
1382  *
1383  * Creates a new instance of #AgsIpatchSF2Reader.
1384  *
1385  * Returns: the new #AgsIpatchSF2Reader.
1386  *
1387  * Since: 3.0.0
1388  */
1389 AgsIpatchSF2Reader*
ags_ipatch_sf2_reader_new(AgsIpatch * ipatch)1390 ags_ipatch_sf2_reader_new(AgsIpatch *ipatch)
1391 {
1392   AgsIpatchSF2Reader *ipatch_sf2_reader;
1393 
1394   ipatch_sf2_reader = (AgsIpatchSF2Reader *) g_object_new(AGS_TYPE_IPATCH_SF2_READER,
1395 							  "ipatch", ipatch,
1396 							  NULL);
1397 
1398   return(ipatch_sf2_reader);
1399 }
1400