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_audio_container_manager.h>
21 
22 #include <ags/libags.h>
23 #include <ags/libags-audio.h>
24 
25 #include <stdlib.h>
26 
27 #include <ags/i18n.h>
28 
29 void ags_audio_container_manager_class_init(AgsAudioContainerManagerClass *audio_container_manager);
30 void ags_audio_container_manager_init(AgsAudioContainerManager *audio_container_manager);
31 void ags_audio_container_manager_set_property(GObject *gobject,
32 					      guint prop_id,
33 					      const GValue *value,
34 					      GParamSpec *param_spec);
35 void ags_audio_container_manager_get_property(GObject *gobject,
36 					      guint prop_id,
37 					      GValue *value,
38 					      GParamSpec *param_spec);
39 void ags_audio_container_manager_finalize(GObject *gobject);
40 
41 /**
42  * SECTION:ags_audio_container_manager
43  * @short_description: The audio container manager
44  * @title: AgsAudioContainerManager
45  * @section_id:
46  * @include: ags/audio_container/ags_audio_container_manager.h
47  *
48  * #AgsAudioContainerManager stores audio containers.
49  */
50 
51 enum{
52   PROP_0,
53   PROP_AUDIO_CONTAINER,
54 };
55 
56 static gpointer ags_audio_container_manager_parent_class = NULL;
57 
58 AgsAudioContainerManager *ags_audio_container_manager = NULL;
59 
60 GType
ags_audio_container_manager_get_type()61 ags_audio_container_manager_get_type()
62 {
63   static volatile gsize g_define_type_id__volatile = 0;
64 
65   if(g_once_init_enter (&g_define_type_id__volatile)){
66     GType ags_type_audio_container_manager = 0;
67 
68     static const GTypeInfo ags_audio_container_manager_info = {
69       sizeof (AgsAudioContainerManagerClass),
70       NULL, /* base_init */
71       NULL, /* base_finalize */
72       (GClassInitFunc) ags_audio_container_manager_class_init,
73       NULL, /* class_finalize */
74       NULL, /* class_data */
75       sizeof (AgsAudioContainerManager),
76       0,    /* n_preallocs */
77       (GInstanceInitFunc) ags_audio_container_manager_init,
78     };
79 
80     ags_type_audio_container_manager = g_type_register_static(G_TYPE_OBJECT,
81 							      "AgsAudioContainerManager", &ags_audio_container_manager_info,
82 							      0);
83 
84     g_once_init_leave(&g_define_type_id__volatile, ags_type_audio_container_manager);
85   }
86 
87   return g_define_type_id__volatile;
88 }
89 
90 void
ags_audio_container_manager_class_init(AgsAudioContainerManagerClass * audio_container_manager)91 ags_audio_container_manager_class_init(AgsAudioContainerManagerClass *audio_container_manager)
92 {
93   GObjectClass *gobject;
94 
95   GParamSpec *param_spec;
96 
97   ags_audio_container_manager_parent_class = g_type_class_peek_parent(audio_container_manager);
98 
99   /* GObjectClass */
100   gobject = (GObjectClass *) audio_container_manager;
101 
102   gobject->set_property = ags_audio_container_manager_set_property;
103   gobject->get_property = ags_audio_container_manager_get_property;
104 
105   gobject->finalize = ags_audio_container_manager_finalize;
106 
107   /* properties */
108   /**
109    * AgsAudioContainerManager:audio-container:
110    *
111    * The #GList-struct containing #AgsAudioContainer.
112    *
113    * Since: 3.4.0
114    */
115   param_spec = g_param_spec_pointer("audio-container",
116 				    i18n_pspec("containing audio_container"),
117 				    i18n_pspec("The audio_container it contains"),
118 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
119   g_object_class_install_property(gobject,
120 				  PROP_AUDIO_CONTAINER,
121 				  param_spec);
122 
123   /* AgsModel */
124 }
125 
126 void
ags_audio_container_manager_init(AgsAudioContainerManager * audio_container_manager)127 ags_audio_container_manager_init(AgsAudioContainerManager *audio_container_manager)
128 {
129   /* add audio container manager mutex */
130   g_rec_mutex_init(&(audio_container_manager->obj_mutex));
131 
132   audio_container_manager->audio_container = NULL;
133 }
134 
135 void
ags_audio_container_manager_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)136 ags_audio_container_manager_set_property(GObject *gobject,
137 					 guint prop_id,
138 					 const GValue *value,
139 					 GParamSpec *param_spec)
140 {
141   AgsAudioContainerManager *audio_container_manager;
142 
143   GRecMutex *audio_container_manager_mutex;
144 
145   audio_container_manager = AGS_AUDIO_CONTAINER_MANAGER(gobject);
146 
147   /* get audio container manager mutex */
148   audio_container_manager_mutex = AGS_AUDIO_CONTAINER_MANAGER_GET_OBJ_MUTEX(audio_container_manager);
149 
150   switch(prop_id){
151   case PROP_AUDIO_CONTAINER:
152   {
153     AgsAudioContainer *audio_container;
154 
155     /*  */
156     audio_container = (AgsAudioContainer *) g_value_get_pointer(value);
157 
158     ags_audio_container_manager_add_audio_container(audio_container_manager,
159 						    (GObject *) audio_container);
160   }
161   break;
162   default:
163     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
164     break;
165   }
166 }
167 
168 void
ags_audio_container_manager_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)169 ags_audio_container_manager_get_property(GObject *gobject,
170 					 guint prop_id,
171 					 GValue *value,
172 					 GParamSpec *param_spec)
173 {
174   AgsAudioContainerManager *audio_container_manager;
175 
176   GRecMutex *audio_container_manager_mutex;
177 
178   audio_container_manager = AGS_AUDIO_CONTAINER_MANAGER(gobject);
179 
180   /* get audio container manager mutex */
181   audio_container_manager_mutex = AGS_AUDIO_CONTAINER_MANAGER_GET_OBJ_MUTEX(audio_container_manager);
182 
183   switch(prop_id){
184   case PROP_AUDIO_CONTAINER:
185   {
186     g_rec_mutex_lock(audio_container_manager_mutex);
187 
188     g_value_set_pointer(value,
189 			g_list_copy_deep(audio_container_manager->audio_container,
190 					 (GCopyFunc) g_object_ref,
191 					 NULL));
192 
193     g_rec_mutex_unlock(audio_container_manager_mutex);
194   }
195   break;
196   default:
197     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
198     break;
199   }
200 }
201 
202 void
ags_audio_container_manager_finalize(GObject * gobject)203 ags_audio_container_manager_finalize(GObject *gobject)
204 {
205   AgsAudioContainerManager *audio_container_manager;
206 
207   audio_container_manager = (AgsAudioContainerManager *) gobject;
208 
209   /* call parent */
210   G_OBJECT_CLASS(ags_audio_container_manager_parent_class)->finalize(gobject);
211 }
212 
213 /**
214  * ags_audio_container_manager_add_audio_container:
215  * @audio_container_manager: the #AgsAudioContainerManager
216  * @audio_container: the #AgsAudioContainer
217  *
218  * Add @audio_container to @audio_container_manager.
219  *
220  * Since: 3.4.0
221  */
222 void
ags_audio_container_manager_add_audio_container(AgsAudioContainerManager * audio_container_manager,GObject * audio_container)223 ags_audio_container_manager_add_audio_container(AgsAudioContainerManager *audio_container_manager,
224 						GObject *audio_container)
225 {
226   GRecMutex *audio_container_manager_mutex;
227 
228   if(!AGS_IS_AUDIO_CONTAINER_MANAGER(audio_container_manager) ||
229      !AGS_IS_AUDIO_CONTAINER(audio_container)){
230     return;
231   }
232 
233   /* get audio container manager mutex */
234   audio_container_manager_mutex = AGS_AUDIO_CONTAINER_MANAGER_GET_OBJ_MUTEX(audio_container_manager);
235 
236   g_rec_mutex_lock(audio_container_manager_mutex);
237 
238   if(g_list_find(audio_container_manager->audio_container,
239 		 audio_container) == NULL){
240     g_object_ref(audio_container);
241     audio_container_manager->audio_container = g_list_prepend(audio_container_manager->audio_container,
242 							      audio_container);
243   }
244 
245   g_rec_mutex_unlock(audio_container_manager_mutex);
246 }
247 
248 /**
249  * ags_audio_container_manager_remove_audio_container:
250  * @audio_container_manager: the #AgsAudioContainerManager
251  * @audio_container: the #AgsAudioContainer
252  *
253  * Remove @audio_container from @audio_container_manager.
254  *
255  * Since: 3.4.0
256  */
257 void
ags_audio_container_manager_remove_audio_container(AgsAudioContainerManager * audio_container_manager,GObject * audio_container)258 ags_audio_container_manager_remove_audio_container(AgsAudioContainerManager *audio_container_manager,
259 						   GObject *audio_container)
260 {
261   GRecMutex *audio_container_manager_mutex;
262 
263   if(!AGS_IS_AUDIO_CONTAINER_MANAGER(audio_container_manager) ||
264      !AGS_IS_AUDIO_CONTAINER(audio_container)){
265     return;
266   }
267 
268   /* get audio container manager mutex */
269   audio_container_manager_mutex = AGS_AUDIO_CONTAINER_MANAGER_GET_OBJ_MUTEX(audio_container_manager);
270 
271   g_rec_mutex_lock(audio_container_manager_mutex);
272 
273   if(g_list_find(audio_container_manager->audio_container,
274 		 audio_container) != NULL){
275     g_object_unref(audio_container);
276     audio_container_manager->audio_container = g_list_remove(audio_container_manager->audio_container,
277 							     audio_container);
278   }
279 
280   g_rec_mutex_unlock(audio_container_manager_mutex);
281 }
282 
283 /**
284  * ags_audio_container_manager_find_audio_container:
285  * @audio_container_manager: the #AgsAudioContainerManager
286  * @filename: the string identifier
287  *
288  * Find audio container by @filename.
289  *
290  * Returns: (transfer none): the matching #AgsAudioContainer if found, otherwise %NULL
291  *
292  * Since: 3.4.0
293  */
294 GObject*
ags_audio_container_manager_find_audio_container(AgsAudioContainerManager * audio_container_manager,gchar * filename)295 ags_audio_container_manager_find_audio_container(AgsAudioContainerManager *audio_container_manager,
296 						 gchar *filename)
297 {
298   AgsAudioContainer *audio_container;
299 
300   GList *start_list, *list;
301 
302   gchar *current_filename;
303 
304   gboolean success;
305 
306   if(!AGS_IS_AUDIO_CONTAINER_MANAGER(audio_container_manager) ||
307      filename == NULL){
308     return(NULL);
309   }
310 
311   g_object_get(audio_container_manager,
312 	       "audio-container", &start_list,
313 	       NULL);
314 
315   audio_container = NULL;
316 
317   list = start_list;
318 
319   success = FALSE;
320 
321   while(list != NULL){
322     current_filename = NULL;
323 
324     g_object_get(AGS_AUDIO_CONTAINER(list->data),
325 		 "filename", &current_filename,
326 		 NULL);
327 
328     success = (!g_strcmp0(current_filename,
329 			  filename)) ? TRUE: FALSE;
330 
331     g_free(current_filename);
332 
333     if(success){
334       audio_container = list->data;
335 
336       break;
337     }
338 
339     list = list->next;
340   }
341 
342   g_list_free_full(start_list,
343 		   (GDestroyNotify) g_object_unref);
344 
345   return(audio_container);
346 }
347 
348 /**
349  * ags_audio_container_manager_get_instance:
350  *
351  * Get ags audio container manager instance.
352  *
353  * Returns: (transfer none): the #AgsAudioContainerManager singleton
354  *
355  * Since: 3.4.0
356  */
357 AgsAudioContainerManager*
ags_audio_container_manager_get_instance()358 ags_audio_container_manager_get_instance()
359 {
360   static GMutex mutex = {0,};
361 
362   g_mutex_lock(&mutex);
363 
364   if(ags_audio_container_manager == NULL){
365     ags_audio_container_manager = ags_audio_container_manager_new();
366   }
367 
368   g_mutex_unlock(&mutex);
369 
370   return(ags_audio_container_manager);
371 }
372 
373 /**
374  * ags_audio_container_manager_new:
375  *
376  * Creates an #AgsAudioContainerManager
377  *
378  * Returns: a new #AgsAudioContainerManager
379  *
380  * Since: 3.4.0
381  */
382 AgsAudioContainerManager*
ags_audio_container_manager_new()383 ags_audio_container_manager_new()
384 {
385   AgsAudioContainerManager *audio_container_manager;
386 
387   audio_container_manager = (AgsAudioContainerManager *) g_object_new(AGS_TYPE_AUDIO_CONTAINER_MANAGER,
388 								      NULL);
389 
390   return(audio_container_manager);
391 }
392