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/plugin/ags_lv2_option_manager.h>
21 
22 #include <stdlib.h>
23 #include <string.h>
24 
25 void ags_lv2_option_manager_class_init(AgsLv2OptionManagerClass *lv2_option_manager);
26 void ags_lv2_option_manager_init(AgsLv2OptionManager *lv2_option_manager);
27 void ags_lv2_option_manager_finalize(GObject *gobject);
28 
29 void ags_lv2_option_manager_real_get_option(AgsLv2OptionManager *lv2_option_manager,
30 					    gpointer instance,
31 					    gpointer options,
32 					    gpointer retval);
33 void ags_lv2_option_manager_real_set_option(AgsLv2OptionManager *lv2_option_manager,
34 					    gpointer instance,
35 					    gpointer options,
36 					    gpointer retval);
37 
38 void ags_lv2_option_manager_destroy_data(gpointer data);
39 gboolean ags_lv2_option_ressource_equal(gpointer a, gpointer b);
40 gboolean ags_lv2_option_ressource_finder(gpointer key, gpointer value, gpointer user_data);
41 
42 /**
43  * SECTION:ags_lv2_option_manager
44  * @short_description: option manager
45  * @title: AgsLv2OptionManager
46  * @section_id:
47  * @include: ags/plugin/ags_lv2_option_manager.h
48  *
49  * The #AgsLv2OptionManager gives you access to plugin instances global
50  * configuration. And stores instance related ressources.
51  */
52 
53 enum{
54   GET_OPTION,
55   SET_OPTION,
56   LAST_SIGNAL,
57 };
58 
59 static gpointer ags_lv2_option_manager_parent_class = NULL;
60 static guint lv2_option_manager_signals[LAST_SIGNAL];
61 
62 AgsLv2OptionManager *ags_lv2_option_manager = NULL;
63 
64 GType
ags_lv2_option_manager_get_type()65 ags_lv2_option_manager_get_type()
66 {
67   static volatile gsize g_define_type_id__volatile = 0;
68 
69   if(g_once_init_enter (&g_define_type_id__volatile)){
70     GType ags_type_lv2_option_manager = 0;
71 
72     const GTypeInfo ags_lv2_option_manager_info = {
73       sizeof (AgsLv2OptionManagerClass),
74       NULL, /* base_init */
75       NULL, /* base_finalize */
76       (GClassInitFunc) ags_lv2_option_manager_class_init,
77       NULL, /* class_finalize */
78       NULL, /* class_data */
79       sizeof (AgsLv2OptionManager),
80       0,    /* n_preallocs */
81       (GInstanceInitFunc) ags_lv2_option_manager_init,
82     };
83 
84     ags_type_lv2_option_manager = g_type_register_static(G_TYPE_OBJECT,
85 							 "AgsLv2OptionManager",
86 							 &ags_lv2_option_manager_info,
87 							 0);
88 
89     g_once_init_leave(&g_define_type_id__volatile, ags_type_lv2_option_manager);
90   }
91 
92   return g_define_type_id__volatile;
93 }
94 
95 void
ags_lv2_option_manager_class_init(AgsLv2OptionManagerClass * lv2_option_manager)96 ags_lv2_option_manager_class_init(AgsLv2OptionManagerClass *lv2_option_manager)
97 {
98   GObjectClass *gobject;
99   GParamSpec *param_spec;
100 
101   ags_lv2_option_manager_parent_class = g_type_class_peek_parent(lv2_option_manager);
102 
103   /* GObject */
104   gobject = (GObjectClass *) lv2_option_manager;
105 
106   gobject->finalize = ags_lv2_option_manager_finalize;
107 
108   /* AgsLv2OptionManager  */
109   lv2_option_manager->get_option = ags_lv2_option_manager_real_get_option;
110   lv2_option_manager->set_option = ags_lv2_option_manager_real_set_option;
111 
112   /* signals */
113   /**
114    * AgsLv2OptionManager::get-option:
115    * @lv2_option_manager: the plugin to instantiate
116    * @intstance: the LV2 plugin instance
117    * @option: the LV2 option pointer
118    * @retval: the location of the return value
119    *
120    * The ::get-option signal gets options of the manager.
121    *
122    * Since: 3.0.0
123    */
124   lv2_option_manager_signals[GET_OPTION] =
125     g_signal_new("get-option",
126 		 G_TYPE_FROM_CLASS(lv2_option_manager),
127 		 G_SIGNAL_RUN_LAST,
128 		 G_STRUCT_OFFSET(AgsLv2OptionManagerClass, get_option),
129 		 NULL, NULL,
130 		 ags_cclosure_marshal_VOID__POINTER_POINTER_POINTER,
131 		 G_TYPE_NONE, 3,
132 		 G_TYPE_POINTER,
133 		 G_TYPE_POINTER,
134 		 G_TYPE_POINTER);
135 
136   /**
137    * AgsLv2OptionManager::set-option:
138    * @lv2_option_manager: the plugin to instantiate
139    * @intstance: the LV2 plugin instance
140    * @option: the LV2 option pointer
141    * @retval: the location of the return value
142    *
143    * The ::set-option signal sets options for the manager.
144    *
145    * Since: 3.0.0
146    */
147   lv2_option_manager_signals[SET_OPTION] =
148     g_signal_new("set-option",
149 		 G_TYPE_FROM_CLASS(lv2_option_manager),
150 		 G_SIGNAL_RUN_LAST,
151 		 G_STRUCT_OFFSET(AgsLv2OptionManagerClass, set_option),
152 		 NULL, NULL,
153 		 ags_cclosure_marshal_VOID__POINTER_POINTER_POINTER,
154 		 G_TYPE_NONE, 3,
155 		 G_TYPE_POINTER,
156 		 G_TYPE_POINTER,
157 		 G_TYPE_POINTER);
158 }
159 
160 void
ags_lv2_option_manager_init(AgsLv2OptionManager * lv2_option_manager)161 ags_lv2_option_manager_init(AgsLv2OptionManager *lv2_option_manager)
162 {
163   /* lv2 option manager mutex */
164   g_rec_mutex_init(&(lv2_option_manager->obj_mutex));
165 
166   lv2_option_manager->ressource = g_hash_table_new_full(g_direct_hash, (GEqualFunc) ags_lv2_option_ressource_equal,
167 							NULL,
168 							(GDestroyNotify) ags_lv2_option_manager_destroy_data);
169   g_hash_table_ref(lv2_option_manager->ressource);
170 }
171 
172 void
ags_lv2_option_manager_finalize(GObject * gobject)173 ags_lv2_option_manager_finalize(GObject *gobject)
174 {
175   AgsLv2OptionManager *lv2_option_manager;
176 
177   lv2_option_manager = AGS_LV2_OPTION_MANAGER(gobject);
178 
179   g_hash_table_destroy(lv2_option_manager->ressource);
180 
181   if(lv2_option_manager == ags_lv2_option_manager){
182     ags_lv2_option_manager = NULL;
183   }
184 
185   /* call parent */
186   G_OBJECT_CLASS(ags_lv2_option_manager_parent_class)->finalize(gobject);
187 }
188 
189 void
ags_lv2_option_manager_destroy_data(gpointer data)190 ags_lv2_option_manager_destroy_data(gpointer data)
191 {
192   /* empty */
193 }
194 
195 gboolean
ags_lv2_option_ressource_equal(gpointer a,gpointer b)196 ags_lv2_option_ressource_equal(gpointer a, gpointer b)
197 {
198   AgsLv2OptionRessource *lv2_option_ressource, *requested_lv2_option_ressource;
199 
200   GRecMutex *lv2_option_manager_mutex;
201 
202   if(a == NULL ||
203      b == NULL){
204     return(FALSE);
205   }
206 
207   lv2_option_ressource = AGS_LV2_OPTION_RESSOURCE(a);
208   requested_lv2_option_ressource = AGS_LV2_OPTION_RESSOURCE(b);
209 
210   if(lv2_option_ressource->instance == requested_lv2_option_ressource->instance &&
211      lv2_option_ressource->option != NULL &&
212      requested_lv2_option_ressource->option != NULL &&
213      lv2_option_ressource->option->subject == requested_lv2_option_ressource->option->subject &&
214      lv2_option_ressource->option->key == requested_lv2_option_ressource->option->key){
215     return(TRUE);
216   }
217 
218   return(FALSE);
219 }
220 
221 gboolean
ags_lv2_option_ressource_finder(gpointer key,gpointer value,gpointer user_data)222 ags_lv2_option_ressource_finder(gpointer key, gpointer value, gpointer user_data)
223 {
224   AgsLv2OptionRessource *lv2_option_ressource, *requested_lv2_option_ressource;
225 
226   LV2_Options_Option *option;
227 
228   lv2_option_ressource = AGS_LV2_OPTION_RESSOURCE(key);
229   requested_lv2_option_ressource = AGS_LV2_OPTION_RESSOURCE(user_data);
230 
231   if(lv2_option_ressource->instance == requested_lv2_option_ressource->instance &&
232      lv2_option_ressource->option->subject == requested_lv2_option_ressource->option->subject &&
233      lv2_option_ressource->option->key == requested_lv2_option_ressource->option->key){
234     return(TRUE);
235   }
236 
237   return(FALSE);
238 }
239 
240 /**
241  * ags_lv2_option_ressource_alloc:
242  *
243  * Allocate an #AgsLv2OptionRessource.
244  *
245  * Returns: (type gpointer) (transfer none): the newly created #AgsLv2OptionRessource-struct
246  *
247  * Since: 3.0.0
248  */
249 AgsLv2OptionRessource*
ags_lv2_option_ressource_alloc()250 ags_lv2_option_ressource_alloc()
251 {
252   AgsLv2OptionRessource *lv2_option_ressource;
253 
254   lv2_option_ressource = (AgsLv2OptionRessource *) malloc(sizeof(AgsLv2OptionRessource));
255 
256   lv2_option_ressource->instance = NULL;
257 
258   lv2_option_ressource->option = (LV2_Options_Option *) malloc(sizeof(LV2_Options_Option));
259 
260   lv2_option_ressource->option->context = 0;
261   lv2_option_ressource->option->subject = 0;
262   lv2_option_ressource->option->key = 0;
263 
264   lv2_option_ressource->option->size = 0;
265   lv2_option_ressource->option->type = 0;
266   lv2_option_ressource->option->value = NULL;
267 
268   return(lv2_option_ressource);
269 }
270 
271 /**
272  * ags_lv2_option_manager_ressource_insert:
273  * @lv2_option_manager: the #AgsLv2OptionManager
274  * @lv2_option_ressource: (type gpointer) (transfer none): the #AgsLv2OptionRessource-struct as key
275  * @data: the data
276  *
277  * Inserts a data into hash associated with @lv2_option_ressource.
278  *
279  * Returns: %TRUE on success, otherwise %FALSE
280  *
281  * Since: 3.0.0
282  */
283 gboolean
ags_lv2_option_manager_ressource_insert(AgsLv2OptionManager * lv2_option_manager,AgsLv2OptionRessource * lv2_option_ressource,gpointer data)284 ags_lv2_option_manager_ressource_insert(AgsLv2OptionManager *lv2_option_manager,
285 					AgsLv2OptionRessource *lv2_option_ressource, gpointer data)
286 {
287   GRecMutex *lv2_option_manager_mutex;
288 
289   if(!AGS_IS_LV2_OPTION_MANAGER(lv2_option_manager) ||
290      lv2_option_ressource == NULL ||
291      data == NULL){
292     return(FALSE);
293   }
294 
295   /* get lv2 option manager mutex */
296   lv2_option_manager_mutex = AGS_LV2_OPTION_MANAGER_GET_OBJ_MUTEX(lv2_option_manager);
297 
298   /*  */
299   g_rec_mutex_lock(lv2_option_manager_mutex);
300 
301   g_hash_table_insert(lv2_option_manager->ressource,
302 		      (gpointer) lv2_option_ressource, data);
303 
304   g_rec_mutex_unlock(lv2_option_manager_mutex);
305 
306   return(TRUE);
307 }
308 
309 /**
310  * ags_lv2_option_manager_ressource_remove:
311  * @lv2_option_manager: the #AgsLv2OptionManager
312  * @lv2_option_ressource: (type gpointer) (transfer none): the struct to remove
313  *
314  * Removes an entry associated with @lv2_option_ressource.
315  *
316  * Returns: %TRUE as successfully removed, otherwise %FALSE
317  *
318  * Since: 3.0.0
319  */
320 gboolean
ags_lv2_option_manager_ressource_remove(AgsLv2OptionManager * lv2_option_manager,AgsLv2OptionRessource * lv2_option_ressource)321 ags_lv2_option_manager_ressource_remove(AgsLv2OptionManager *lv2_option_manager,
322 					AgsLv2OptionRessource *lv2_option_ressource)
323 {
324   gpointer data;
325 
326   GRecMutex *lv2_option_manager_mutex;
327 
328   if(!AGS_IS_LV2_OPTION_MANAGER(lv2_option_manager) ||
329      lv2_option_ressource == NULL){
330     return(FALSE);
331   }
332 
333   /* get lv2 option manager mutex */
334   lv2_option_manager_mutex = AGS_LV2_OPTION_MANAGER_GET_OBJ_MUTEX(lv2_option_manager);
335 
336   /*  */
337   g_rec_mutex_lock(lv2_option_manager_mutex);
338 
339   g_hash_table_remove(lv2_option_manager->ressource,
340 		      lv2_option_ressource);
341 
342   g_rec_mutex_unlock(lv2_option_manager_mutex);
343 
344   return(TRUE);
345 }
346 
347 /**
348  * ags_lv2_option_manager_ressource_lookup:
349  * @lv2_option_manager: the #AgsLv2OptionManager
350  * @lv2_option_ressource: (type gpointer) (transfer none): the #AgsLv2OptionRessource to lookup
351  *
352  * Lookup a ressource associated with @lv2_option_ressource in
353  * @lv2_option_manager.
354  *
355  * Returns: the pointer on success, else NULL
356  *
357  * Since: 3.0.0
358  */
359 gpointer
ags_lv2_option_manager_ressource_lookup(AgsLv2OptionManager * lv2_option_manager,AgsLv2OptionRessource * lv2_option_ressource)360 ags_lv2_option_manager_ressource_lookup(AgsLv2OptionManager *lv2_option_manager,
361 					AgsLv2OptionRessource *lv2_option_ressource)
362 {
363   GList *key, *key_start;
364 
365   gpointer data, tmp;
366 
367   GRecMutex *lv2_option_manager_mutex;
368 
369   if(!AGS_IS_LV2_OPTION_MANAGER(lv2_option_manager) ||
370      lv2_option_ressource == NULL){
371     return(NULL);
372   }
373 
374   /* get lv2 option manager mutex */
375   lv2_option_manager_mutex = AGS_LV2_OPTION_MANAGER_GET_OBJ_MUTEX(lv2_option_manager);
376 
377   /*  */
378   g_rec_mutex_lock(lv2_option_manager_mutex);
379 
380   key_start =
381     key = g_hash_table_get_keys(lv2_option_manager->ressource);
382 
383   data = NULL;
384 
385   while(key != NULL){
386     tmp = (gpointer) g_hash_table_lookup(lv2_option_manager->ressource,
387 					 key->data);
388 
389     if(ags_lv2_option_ressource_equal(lv2_option_ressource,
390 				      key->data)){
391       data = tmp;
392 
393       break;
394     }
395 
396     key = key->next;
397   }
398 
399   g_list_free(key_start);
400 
401   g_rec_mutex_unlock(lv2_option_manager_mutex);
402 
403   return(data);
404 }
405 
406 /**
407  * ags_lv2_option_manager_ressource_lookup_extended:
408  * @lv2_option_manager: the #AgsLv2OptionManager
409  * @lv2_option_ressource: the #AgsLv2OptionRessource to lookup
410  * @orig_key: the original key found
411  * @value: the matched value
412  *
413  * Lookup a ressource associated with @lv2_option_ressource in
414  * @lv2_option_manager.
415  *
416  * Returns: %TRUE if ressource found, else %FALSE
417  *
418  * Since: 3.0.0
419  */
420 gboolean
ags_lv2_option_manager_ressource_lookup_extended(AgsLv2OptionManager * lv2_option_manager,AgsLv2OptionRessource * lv2_option_ressource,gpointer * orig_key,gpointer * value)421 ags_lv2_option_manager_ressource_lookup_extended(AgsLv2OptionManager *lv2_option_manager,
422 						 AgsLv2OptionRessource *lv2_option_ressource,
423 						 gpointer *orig_key, gpointer *value)
424 {
425   GList *key, *key_start;
426 
427   gpointer data, tmp;
428 
429   GRecMutex *lv2_option_manager_mutex;
430 
431   if(orig_key != NULL){
432     *orig_key = NULL;
433   }
434 
435   if(value != NULL){
436     *value = NULL;
437   }
438 
439   if(!AGS_IS_LV2_OPTION_MANAGER(lv2_option_manager) ||
440      lv2_option_ressource == NULL){
441     return(FALSE);
442   }
443 
444   /* get lv2 option manager mutex */
445   lv2_option_manager_mutex = AGS_LV2_OPTION_MANAGER_GET_OBJ_MUTEX(lv2_option_manager);
446 
447   /*  */
448   g_rec_mutex_lock(lv2_option_manager_mutex);
449 
450   key_start =
451     key = g_hash_table_get_keys(lv2_option_manager->ressource);
452 
453   data = NULL;
454 
455   while(key != NULL){
456     tmp = (gpointer) g_hash_table_lookup(lv2_option_manager->ressource,
457 					 key->data);
458 
459     if(ags_lv2_option_ressource_equal(lv2_option_ressource,
460 				      key->data)){
461       data = tmp;
462 
463       break;
464     }
465 
466     key = key->next;
467   }
468 
469   if(orig_key != NULL &&
470      key != NULL){
471     *orig_key = key->data;
472   }
473 
474   if(value != NULL &&
475      data != NULL){
476     *value = data;
477   }
478 
479   g_list_free(key_start);
480 
481   g_rec_mutex_unlock(lv2_option_manager_mutex);
482 
483   return(((data != NULL) ? TRUE: FALSE));
484 }
485 
486 void
ags_lv2_option_manager_real_get_option(AgsLv2OptionManager * lv2_option_manager,gpointer instance,gpointer option,gpointer retval)487 ags_lv2_option_manager_real_get_option(AgsLv2OptionManager *lv2_option_manager,
488 				       gpointer instance,
489 				       gpointer option,
490 				       gpointer retval)
491 {
492   AgsLv2OptionRessource *lookup_ressource;
493 
494   gpointer data;
495   gpointer key_ptr, value_ptr;
496 
497   uint32_t *ret;
498 
499   /* initial set to success */
500   ret = (uint32_t *) retval;
501 
502   if(ret != NULL){
503     *ret = 0;
504   }
505 
506   /* check option to be non NULL */
507   if(option == NULL){
508     if(ret != NULL){
509       *ret |= (LV2_OPTIONS_ERR_BAD_SUBJECT |
510 	       LV2_OPTIONS_ERR_BAD_KEY);
511     }
512 
513     return;
514   }
515 
516   /* get option */
517   if(AGS_LV2_OPTIONS_OPTION(option)->context == LV2_OPTIONS_RESOURCE){
518     key_ptr = NULL;
519     value_ptr = NULL;
520 
521     lookup_ressource = (AgsLv2OptionRessource *) malloc(sizeof(AgsLv2OptionRessource));
522 
523     lookup_ressource->instance = (LV2_Handle) instance;
524     lookup_ressource->option = (LV2_Options_Option *) option;
525 
526     if(ags_lv2_option_manager_ressource_lookup_extended(lv2_option_manager,
527 							lookup_ressource,
528 							&key_ptr, &value_ptr)){
529       /* set requested fields */
530       AGS_LV2_OPTIONS_OPTION(option)->type = AGS_LV2_OPTION_RESSOURCE(key_ptr)->option->type;
531       AGS_LV2_OPTIONS_OPTION(option)->size = AGS_LV2_OPTION_RESSOURCE(key_ptr)->option->size;
532       AGS_LV2_OPTIONS_OPTION(option)->value = value_ptr;
533     }else{
534       /* do error reporting */
535       if(ret != NULL){
536 	*ret |= (LV2_OPTIONS_ERR_BAD_SUBJECT |
537 		 LV2_OPTIONS_ERR_BAD_KEY);
538       }
539     }
540 
541     free(lookup_ressource);
542   }
543 }
544 
545 /**
546  * ags_lv2_option_manager_get_option:
547  * @lv2_option_manager: the #AgsLv2OptionManager
548  * @instance: the instance
549  * @option: the option
550  * @retval: return value for #LV2_Options_Status-enum
551  *
552  * Get option.
553  *
554  * Since: 3.0.0
555  */
556 void
ags_lv2_option_manager_get_option(AgsLv2OptionManager * lv2_option_manager,gpointer instance,gpointer option,gpointer retval)557 ags_lv2_option_manager_get_option(AgsLv2OptionManager *lv2_option_manager,
558 				  gpointer instance,
559 				  gpointer option,
560 				  gpointer retval)
561 {
562   g_return_if_fail(AGS_IS_LV2_OPTION_MANAGER(lv2_option_manager));
563   g_object_ref(G_OBJECT(lv2_option_manager));
564   g_signal_emit(G_OBJECT(lv2_option_manager),
565 		lv2_option_manager_signals[GET_OPTION], 0,
566 		instance,
567 		option,
568 		retval);
569   g_object_unref(G_OBJECT(lv2_option_manager));
570 }
571 
572 void
ags_lv2_option_manager_real_set_option(AgsLv2OptionManager * lv2_option_manager,gpointer instance,gpointer option,gpointer retval)573 ags_lv2_option_manager_real_set_option(AgsLv2OptionManager *lv2_option_manager,
574 				       gpointer instance,
575 				       gpointer option,
576 				       gpointer retval)
577 {
578   AgsLv2OptionRessource *lookup_ressource;
579 
580   gpointer data;
581   gpointer key_ptr, value_ptr;
582 
583   uint32_t *ret;
584 
585   /* initial set to success */
586   ret = (uint32_t *) retval;
587 
588   if(ret != NULL){
589     *ret = 0;
590   }
591 
592   /* check option to be non NULL */
593   if(option == NULL){
594     *ret |= (LV2_OPTIONS_ERR_BAD_SUBJECT |
595 	     LV2_OPTIONS_ERR_BAD_KEY);
596 
597     return;
598   }
599 
600   /* set option */
601   if(AGS_LV2_OPTIONS_OPTION(option)->context == LV2_OPTIONS_RESOURCE){
602     key_ptr = NULL;
603     value_ptr = NULL;
604 
605     lookup_ressource = (AgsLv2OptionRessource *) malloc(sizeof(AgsLv2OptionRessource));
606 
607     lookup_ressource->instance = (LV2_Handle) instance;
608     lookup_ressource->option = (LV2_Options_Option *) option;
609 
610     if(ags_lv2_option_manager_ressource_lookup_extended(lv2_option_manager,
611 							lookup_ressource,
612 							&key_ptr, &value_ptr)){
613       /* set fields */
614       AGS_LV2_OPTION_RESSOURCE(key_ptr)->option->type = AGS_LV2_OPTIONS_OPTION(option)->type;
615       AGS_LV2_OPTION_RESSOURCE(key_ptr)->option->size = AGS_LV2_OPTIONS_OPTION(option)->size;
616       AGS_LV2_OPTION_RESSOURCE(key_ptr)->option->value = AGS_LV2_OPTIONS_OPTION(option)->value;
617     }else{
618       AgsLv2OptionRessource *lv2_option_ressource;
619 
620       /* allocate new */
621       lv2_option_ressource = ags_lv2_option_ressource_alloc();
622 
623       /* set fields */
624       lv2_option_ressource->instance = instance;
625 
626       lv2_option_ressource->option->context = AGS_LV2_OPTIONS_OPTION(option)->context;
627       lv2_option_ressource->option->subject = AGS_LV2_OPTIONS_OPTION(option)->subject;
628       lv2_option_ressource->option->key = AGS_LV2_OPTIONS_OPTION(option)->key;
629 
630       lv2_option_ressource->option->type = AGS_LV2_OPTIONS_OPTION(option)->type;
631       lv2_option_ressource->option->size = AGS_LV2_OPTIONS_OPTION(option)->size;
632       lv2_option_ressource->option->value = AGS_LV2_OPTIONS_OPTION(option)->value;
633 
634       ags_lv2_option_manager_ressource_insert(lv2_option_manager,
635 					      lv2_option_ressource, (gpointer) AGS_LV2_OPTIONS_OPTION(option)->value);
636     }
637 
638     free(lookup_ressource);
639   }
640 }
641 
642 /**
643  * ags_lv2_option_manager_set_option:
644  * @lv2_option_manager: the #AgsLv2OptionManager
645  * @instance: the instance
646  * @option: the option
647  * @retval: return value for #LV2_Options_Status-enum
648  *
649  * Set option.
650  *
651  * Since: 3.0.0
652  */
653 void
ags_lv2_option_manager_set_option(AgsLv2OptionManager * lv2_option_manager,gpointer instance,gpointer option,gpointer retval)654 ags_lv2_option_manager_set_option(AgsLv2OptionManager *lv2_option_manager,
655 				  gpointer instance,
656 				  gpointer option,
657 				  gpointer retval)
658 {
659   g_return_if_fail(AGS_IS_LV2_OPTION_MANAGER(lv2_option_manager));
660   g_object_ref(G_OBJECT(lv2_option_manager));
661   g_signal_emit(G_OBJECT(lv2_option_manager),
662 		lv2_option_manager_signals[SET_OPTION], 0,
663 		instance,
664 		option,
665 		retval);
666   g_object_unref(G_OBJECT(lv2_option_manager));
667 }
668 
669 /**
670  * ags_lv2_option_manager_lv2_options_get:
671  * @instance: the lv2 instance
672  * @options: the LV2_Options
673  *
674  * The LV2 options interface's get method.
675  *
676  * Since: 3.0.0
677  */
678 uint32_t
ags_lv2_option_manager_lv2_options_get(LV2_Handle instance,LV2_Options_Option * options)679 ags_lv2_option_manager_lv2_options_get(LV2_Handle instance,
680 				       LV2_Options_Option *options)
681 {
682   uint32_t retval, tmpval;
683   guint i;
684 
685   if(options == NULL){
686     return(LV2_OPTIONS_ERR_BAD_SUBJECT |
687 	   LV2_OPTIONS_ERR_BAD_KEY);
688   }
689 
690   retval = 0;
691 
692   for(i = 0; ; i++){
693     if(options[i].subject == 0 &&
694        options[i].key == 0 &&
695        options[i].type == 0 &&
696        options[i].size == 0 &&
697        options[i].value == NULL){
698       break;
699     }
700 
701     ags_lv2_option_manager_get_option(ags_lv2_option_manager_get_instance(),
702 				      instance,
703 				      &(options[i]),
704 				      &tmpval);
705 
706     retval |= tmpval;
707   }
708 
709   return(retval);
710 }
711 
712 /**
713  * ags_lv2_option_manager_lv2_options_set:
714  * @instance: the lv2 instance
715  * @options: the LV2_Options
716  *
717  * The LV2 options interface's set method.
718  *
719  * Since: 3.0.0
720  */
721 uint32_t
ags_lv2_option_manager_lv2_options_set(LV2_Handle instance,LV2_Options_Option * options)722 ags_lv2_option_manager_lv2_options_set(LV2_Handle instance,
723 				       LV2_Options_Option* options)
724 {
725   uint32_t retval, tmpval;
726   guint i;
727 
728   if(options == NULL){
729     return(LV2_OPTIONS_ERR_BAD_SUBJECT |
730 	   LV2_OPTIONS_ERR_BAD_KEY);
731   }
732 
733   retval = 0;
734 
735   for(i = 0; ; i++){
736     if(options[i].subject == 0 &&
737        options[i].key == 0 &&
738        options[i].type == 0 &&
739        options[i].size == 0 &&
740        options[i].value == NULL){
741       break;
742     }
743 
744     ags_lv2_option_manager_set_option(ags_lv2_option_manager_get_instance(),
745 				      instance,
746 				      &(options[i]),
747 				      &tmpval);
748 
749     retval |= tmpval;
750   }
751 
752   return(retval);
753 }
754 
755 /**
756  * ags_lv2_option_manager_get_instance:
757  *
758  * Singleton function to optain the id manager instance.
759  *
760  * Returns: (transfer none): an instance of #AgsLv2OptionManager
761  *
762  * Since: 3.0.0
763  */
764 AgsLv2OptionManager*
ags_lv2_option_manager_get_instance()765 ags_lv2_option_manager_get_instance()
766 {
767   static GMutex mutex;
768 
769   g_mutex_lock(&mutex);
770 
771   if(ags_lv2_option_manager == NULL){
772     ags_lv2_option_manager = ags_lv2_option_manager_new();
773 
774     //    ags_lv2_option_manager_load_default(ags_lv2_option_manager);
775   }
776 
777   g_mutex_unlock(&mutex);
778 
779   return(ags_lv2_option_manager);
780 }
781 
782 /**
783  * ags_lv2_option_manager_new:
784  *
785  * Instantiate a id manager.
786  *
787  * Returns: a new #AgsLv2OptionManager
788  *
789  * Since: 3.0.0
790  */
791 AgsLv2OptionManager*
ags_lv2_option_manager_new()792 ags_lv2_option_manager_new()
793 {
794   AgsLv2OptionManager *lv2_option_manager;
795 
796   lv2_option_manager = (AgsLv2OptionManager *) g_object_new(AGS_TYPE_LV2_OPTION_MANAGER,
797 							    NULL);
798 
799   return(lv2_option_manager);
800 }
801