1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2021 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/object/ags_application_context.h>
21 
22 #include <ags/lib/ags_log.h>
23 
24 #include <ags/file/ags_file.h>
25 
26 #include <ags/object/ags_connectable.h>
27 
28 #include <gio/gio.h>
29 
30 #include <sys/types.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 
35 #include <ags/i18n.h>
36 
37 void ags_application_context_class_init(AgsApplicationContextClass *application_context);
38 void ags_application_context_connectable_interface_init(AgsConnectableInterface *connectable);
39 void ags_application_context_init(AgsApplicationContext *application_context);
40 void ags_application_context_set_property(GObject *gobject,
41 					  guint prop_id,
42 					  const GValue *value,
43 					  GParamSpec *param_spec);
44 void ags_application_context_get_property(GObject *gobject,
45 					  guint prop_id,
46 					  GValue *value,
47 					  GParamSpec *param_spec);
48 void ags_application_context_dispose(GObject *gobject);
49 void ags_application_context_finalize(GObject *gobject);
50 
51 AgsUUID* ags_application_context_get_uuid(AgsConnectable *connectable);
52 gboolean ags_application_context_has_resource(AgsConnectable *connectable);
53 gboolean ags_application_context_is_ready(AgsConnectable *connectable);
54 void ags_application_context_add_to_registry(AgsConnectable *connectable);
55 void ags_application_context_remove_from_registry(AgsConnectable *connectable);
56 xmlNode* ags_application_context_list_resource(AgsConnectable *connectable);
57 xmlNode* ags_application_context_xml_compose(AgsConnectable *connectable);
58 void ags_application_context_xml_parse(AgsConnectable *connectable,
59 				       xmlNode *node);
60 gboolean ags_application_context_is_connected(AgsConnectable *connectable);
61 void ags_application_context_connect(AgsConnectable *connectable);
62 void ags_application_context_disconnect(AgsConnectable *connectable);
63 
64 void ags_application_context_real_load_config(AgsApplicationContext *application_context);
65 
66 void ags_application_context_real_prepare(AgsApplicationContext *application_context);
67 void ags_application_context_real_setup(AgsApplicationContext *application_context);
68 
69 void ags_application_context_real_register_types(AgsApplicationContext *application_context);
70 
71 void ags_application_context_real_quit(AgsApplicationContext *application_context);
72 
73 /**
74  * SECTION:ags_application_context
75  * @short_description: The application context
76  * @title: AgsApplicationContext
77  * @section_id:
78  * @include: ags/object/ags_application_context.h
79  *
80  * #AgsApplicationContext is a context provider is your and libraries entry
81  * point to the application. You might subtype it to implement your own contices.
82  * Thus you should consider to create a provider interface for reusability.
83  */
84 
85 enum{
86   LOAD_CONFIG,
87   PREPARE,
88   SETUP,
89   REGISTER_TYPES,
90   QUIT,
91   LAST_SIGNAL,
92 };
93 
94 enum{
95   PROP_0,
96   PROP_MAIN_LOOP,
97   PROP_TASK_LAUNCHER,
98   PROP_CONFIG,
99   PROP_FILE,
100 };
101 
102 static gpointer ags_application_context_parent_class = NULL;
103 static guint application_context_signals[LAST_SIGNAL];
104 
105 AgsApplicationContext *ags_application_context = NULL;
106 
107 GType
ags_application_context_get_type()108 ags_application_context_get_type()
109 {
110   static volatile gsize g_define_type_id__volatile = 0;
111 
112   if(g_once_init_enter (&g_define_type_id__volatile)){
113     GType ags_type_application_context = 0;
114 
115     static const GTypeInfo ags_application_context_info = {
116       sizeof (AgsApplicationContextClass),
117       NULL, /* base_init */
118       NULL, /* base_finalize */
119       (GClassInitFunc) ags_application_context_class_init,
120       NULL, /* class_finalize */
121       NULL, /* class_data */
122       sizeof (AgsApplicationContext),
123       0,    /* n_preallocs */
124       (GInstanceInitFunc) ags_application_context_init,
125     };
126 
127     static const GInterfaceInfo ags_connectable_interface_info = {
128       (GInterfaceInitFunc) ags_application_context_connectable_interface_init,
129       NULL, /* interface_finalize */
130       NULL, /* interface_data */
131     };
132 
133     ags_type_application_context = g_type_register_static(G_TYPE_OBJECT,
134 							  "AgsApplicationContext",
135 							  &ags_application_context_info,
136 							  0);
137 
138     g_type_add_interface_static(ags_type_application_context,
139 				AGS_TYPE_CONNECTABLE,
140 				&ags_connectable_interface_info);
141 
142     g_once_init_leave(&g_define_type_id__volatile, ags_type_application_context);
143   }
144 
145   return g_define_type_id__volatile;
146 }
147 
148 GType
ags_application_context_flags_get_type()149 ags_application_context_flags_get_type()
150 {
151   static volatile gsize g_flags_type_id__volatile;
152 
153   if(g_once_init_enter (&g_flags_type_id__volatile)){
154     static const GFlagsValue values[] = {
155       { AGS_APPLICATION_CONTEXT_ADDED_TO_REGISTRY, "AGS_APPLICATION_CONTEXT_ADDED_TO_REGISTRY", "application-context-added-to-registry" },
156       { AGS_APPLICATION_CONTEXT_CONNECTED, "AGS_APPLICATION_CONTEXT_CONNECTED", "application-context-connected" },
157       { AGS_APPLICATION_CONTEXT_TYPES_REGISTERED, "AGS_APPLICATION_CONTEXT_TYPES_REGISTERED", "application-context-types-registered" },
158       { 0, NULL, NULL }
159     };
160 
161     GType g_flags_type_id = g_flags_register_static(g_intern_static_string("AgsApplicationContextFlags"), values);
162 
163     g_once_init_leave (&g_flags_type_id__volatile, g_flags_type_id);
164   }
165 
166   return g_flags_type_id__volatile;
167 }
168 
169 void
ags_application_context_class_init(AgsApplicationContextClass * application_context)170 ags_application_context_class_init(AgsApplicationContextClass *application_context)
171 {
172   GObjectClass *gobject;
173 
174   GParamSpec *param_spec;
175 
176   ags_application_context_parent_class = g_type_class_peek_parent(application_context);
177 
178   /* GObjectClass */
179   gobject = (GObjectClass *) application_context;
180 
181   gobject->set_property = ags_application_context_set_property;
182   gobject->get_property = ags_application_context_get_property;
183 
184   gobject->dispose = ags_application_context_dispose;
185   gobject->finalize = ags_application_context_finalize;
186 
187   /* properties */
188   /**
189    * AgsApplicationContext:main-loop:
190    *
191    * The assigned main-loop.
192    *
193    * Since: 3.0.0
194    */
195   param_spec = g_param_spec_object("main-loop",
196 				   i18n_pspec("main loop of application context"),
197 				   i18n_pspec("The main loop of application context running"),
198 				   G_TYPE_OBJECT,
199 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
200   g_object_class_install_property(gobject,
201 				  PROP_MAIN_LOOP,
202 				  param_spec);
203 
204   /**
205    * AgsApplicationContext:task-launcher:
206    *
207    * The assigned task launcher.
208    *
209    * Since: 3.0.0
210    */
211   param_spec = g_param_spec_object("task-launcher",
212 				   i18n_pspec("task launcher"),
213 				   i18n_pspec("The task launcher"),
214 				   G_TYPE_OBJECT,
215 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
216   g_object_class_install_property(gobject,
217 				  PROP_TASK_LAUNCHER,
218 				  param_spec);
219 
220   /**
221    * AgsApplicationContext:config:
222    *
223    * The assigned config.
224    *
225    * Since: 3.0.0
226    */
227   param_spec = g_param_spec_object("config",
228 				   i18n_pspec("config of application context"),
229 				   i18n_pspec("The config what application context is running in"),
230 				   G_TYPE_OBJECT,
231 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
232   g_object_class_install_property(gobject,
233 				  PROP_CONFIG,
234 				  param_spec);
235 
236   /**
237    * AgsApplicationContext:file:
238    *
239    * The assigned file.
240    *
241    * Since: 3.0.0
242    */
243   param_spec = g_param_spec_object("file",
244 				   i18n_pspec("file of application context"),
245 				   i18n_pspec("The file what application context does persist"),
246 				   G_TYPE_OBJECT,
247 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
248   g_object_class_install_property(gobject,
249 				  PROP_FILE,
250 				  param_spec);
251 
252   /* AgsApplicationContextClass */
253   application_context->load_config = ags_application_context_real_load_config;
254 
255   application_context->prepare = ags_application_context_real_prepare;
256   application_context->setup = ags_application_context_real_setup;
257 
258   application_context->register_types = ags_application_context_real_register_types;
259 
260   application_context->read = NULL;
261   application_context->write = NULL;
262 
263   application_context->quit = ags_application_context_real_quit;
264 
265   /* signals */
266   /**
267    * AgsApplicationContext::load-config:
268    * @application_context: the #AgsApplicationContext
269    *
270    * The ::load-config notifies to load configuration.
271    *
272    * Since: 3.0.0
273    */
274   application_context_signals[LOAD_CONFIG] =
275     g_signal_new("load-config",
276 		 G_TYPE_FROM_CLASS (application_context),
277 		 G_SIGNAL_RUN_LAST,
278 		 G_STRUCT_OFFSET (AgsApplicationContextClass, load_config),
279 		 NULL, NULL,
280 		 g_cclosure_marshal_VOID__VOID,
281 		 G_TYPE_NONE, 0);
282 
283   /**
284    * AgsApplicationContext::prepare:
285    * @application_context: the  #AgsApplicationContext
286    *
287    * The ::prepare signal should be implemented to prepare
288    * your application context.
289    *
290    * Since: 3.0.0
291    */
292   application_context_signals[PREPARE] =
293     g_signal_new("prepare",
294 		 G_TYPE_FROM_CLASS (application_context),
295 		 G_SIGNAL_RUN_LAST,
296 		 G_STRUCT_OFFSET (AgsApplicationContextClass, prepare),
297 		 NULL, NULL,
298 		 g_cclosure_marshal_VOID__VOID,
299 		 G_TYPE_NONE, 0);
300 
301   /**
302    * AgsApplicationContext::setup:
303    * @application_context: the  #AgsApplicationContext
304    *
305    * The ::setup signal should be implemented to setup
306    * your application context.
307    *
308    * Since: 3.0.0
309    */
310   application_context_signals[SETUP] =
311     g_signal_new("setup",
312 		 G_TYPE_FROM_CLASS (application_context),
313 		 G_SIGNAL_RUN_LAST,
314 		 G_STRUCT_OFFSET (AgsApplicationContextClass, setup),
315 		 NULL, NULL,
316 		 g_cclosure_marshal_VOID__VOID,
317 		 G_TYPE_NONE, 0);
318 
319   /**
320    * AgsApplicationContext::register-types:
321    * @application_context: the  #AgsApplicationContext
322    *
323    * The ::register-types signal should be implemented to load
324    * your types.
325    *
326    * Since: 3.0.0
327    */
328   application_context_signals[REGISTER_TYPES] =
329     g_signal_new("register-types",
330 		 G_TYPE_FROM_CLASS (application_context),
331 		 G_SIGNAL_RUN_LAST,
332 		 G_STRUCT_OFFSET (AgsApplicationContextClass, register_types),
333 		 NULL, NULL,
334 		 g_cclosure_marshal_VOID__VOID,
335 		 G_TYPE_NONE, 0);
336 
337   /**
338    * AgsApplicationContext::quit:
339    * @application_context: the #AgsApplicationContext
340    *
341    * The ::quit notifies to load configuration.
342    *
343    * Since: 3.0.0
344    */
345   application_context_signals[QUIT] =
346     g_signal_new("quit",
347 		 G_TYPE_FROM_CLASS (application_context),
348 		 G_SIGNAL_RUN_LAST,
349 		 G_STRUCT_OFFSET (AgsApplicationContextClass, quit),
350 		 NULL, NULL,
351 		 g_cclosure_marshal_VOID__VOID,
352 		 G_TYPE_NONE, 0);
353 }
354 
355 void
ags_application_context_connectable_interface_init(AgsConnectableInterface * connectable)356 ags_application_context_connectable_interface_init(AgsConnectableInterface *connectable)
357 {
358   connectable->get_uuid = ags_application_context_get_uuid;
359   connectable->has_resource = ags_application_context_has_resource;
360 
361   connectable->is_ready = ags_application_context_is_ready;
362   connectable->add_to_registry = ags_application_context_add_to_registry;
363   connectable->remove_from_registry = ags_application_context_remove_from_registry;
364 
365   connectable->list_resource = ags_application_context_list_resource;
366   connectable->xml_compose = ags_application_context_xml_compose;
367   connectable->xml_parse = ags_application_context_xml_parse;
368 
369   connectable->is_connected = ags_application_context_is_connected;
370   connectable->connect = ags_application_context_connect;
371   connectable->disconnect = ags_application_context_disconnect;
372 
373   connectable->connect_connection = NULL;
374   connectable->disconnect_connection = NULL;
375 }
376 
377 void
ags_application_context_init(AgsApplicationContext * application_context)378 ags_application_context_init(AgsApplicationContext *application_context)
379 {
380   GFile *file;
381 
382   application_context->flags = 0;
383 
384   g_rec_mutex_init(&(application_context->obj_mutex));
385 
386   /* uuid */
387   application_context->uuid = ags_uuid_alloc();
388   ags_uuid_generate(application_context->uuid);
389 
390   application_context->argc = 0;
391   application_context->argv = NULL;
392 
393   application_context->version = g_strdup(AGS_VERSION);
394   application_context->build_id = g_strdup(AGS_BUILD_ID);
395 
396   application_context->log = NULL;
397 
398   application_context->domain = NULL;
399 
400   application_context->config = NULL;
401 
402   application_context->main_loop = NULL;
403   application_context->task_launcher = NULL;
404 
405   application_context->file = NULL;
406   application_context->history = NULL;
407 }
408 
409 void
ags_application_context_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)410 ags_application_context_set_property(GObject *gobject,
411 				     guint prop_id,
412 				     const GValue *value,
413 				     GParamSpec *param_spec)
414 {
415   AgsApplicationContext *application_context;
416 
417   GRecMutex *application_context_mutex;
418 
419   application_context = AGS_APPLICATION_CONTEXT(gobject);
420 
421   /* get application context mutex */
422   application_context_mutex = AGS_APPLICATION_CONTEXT_GET_OBJ_MUTEX(application_context);
423 
424   switch(prop_id){
425   case PROP_MAIN_LOOP:
426     {
427       GObject *main_loop;
428 
429       main_loop = (GObject *) g_value_get_object(value);
430 
431       g_rec_mutex_lock(application_context_mutex);
432 
433       if(main_loop == application_context->main_loop){
434 	g_rec_mutex_unlock(application_context_mutex);
435 
436 	return;
437       }
438 
439       if(application_context->main_loop != NULL){
440 	g_object_unref(application_context->main_loop);
441       }
442 
443       if(main_loop != NULL){
444 	g_object_ref(G_OBJECT(main_loop));
445       }
446 
447       application_context->main_loop = main_loop;
448 
449       g_rec_mutex_unlock(application_context_mutex);
450     }
451     break;
452   case PROP_TASK_LAUNCHER:
453     {
454       GObject *task_launcher;
455 
456       task_launcher = (GObject *) g_value_get_object(value);
457 
458       g_rec_mutex_lock(application_context_mutex);
459 
460       if(task_launcher == application_context->task_launcher){
461 	g_rec_mutex_unlock(application_context_mutex);
462 
463 	return;
464       }
465 
466       if(application_context->task_launcher != NULL){
467 	g_object_unref(application_context->task_launcher);
468       }
469 
470       if(task_launcher != NULL){
471 	g_object_ref(G_OBJECT(task_launcher));
472       }
473 
474       application_context->task_launcher = task_launcher;
475 
476       g_rec_mutex_unlock(application_context_mutex);
477     }
478     break;
479   case PROP_CONFIG:
480     {
481       AgsConfig *config;
482 
483       config = (AgsConfig *) g_value_get_object(value);
484 
485       g_rec_mutex_lock(application_context_mutex);
486 
487       if(config == application_context->config){
488 	g_rec_mutex_unlock(application_context_mutex);
489 
490 	return;
491       }
492 
493       if(application_context->config != NULL){
494 	g_object_unref(application_context->config);
495       }
496 
497       if(config != NULL){
498 	g_object_ref(G_OBJECT(config));
499       }
500 
501       application_context->config = config;
502 
503       g_rec_mutex_unlock(application_context_mutex);
504     }
505     break;
506   case PROP_FILE:
507     {
508       AgsFile *file;
509 
510       file = (AgsFile *) g_value_get_object(value);
511 
512       g_rec_mutex_lock(application_context_mutex);
513 
514       if(file == application_context->file){
515 	g_rec_mutex_unlock(application_context_mutex);
516 
517 	return;
518       }
519 
520       if(application_context->file != NULL){
521 	g_object_unref(application_context->file);
522       }
523 
524       if(file != NULL){
525 	g_object_ref(G_OBJECT(file));
526       }
527 
528       application_context->file = (AgsFile *) file;
529 
530       g_rec_mutex_unlock(application_context_mutex);
531     }
532     break;
533   default:
534     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
535     break;
536   }
537 
538 }
539 
540 void
ags_application_context_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)541 ags_application_context_get_property(GObject *gobject,
542 				     guint prop_id,
543 				     GValue *value,
544 				     GParamSpec *param_spec)
545 {
546   AgsApplicationContext *application_context;
547 
548   GRecMutex *application_context_mutex;
549 
550   application_context = AGS_APPLICATION_CONTEXT(gobject);
551 
552   /* get application context mutex */
553   application_context_mutex = AGS_APPLICATION_CONTEXT_GET_OBJ_MUTEX(application_context);
554 
555   switch(prop_id){
556   case PROP_MAIN_LOOP:
557     {
558       g_rec_mutex_lock(application_context_mutex);
559 
560       g_value_set_object(value, application_context->main_loop);
561 
562       g_rec_mutex_unlock(application_context_mutex);
563     }
564     break;
565   case PROP_TASK_LAUNCHER:
566     {
567       g_rec_mutex_lock(application_context_mutex);
568 
569       g_value_set_object(value, application_context->task_launcher);
570 
571       g_rec_mutex_unlock(application_context_mutex);
572     }
573     break;
574   case PROP_CONFIG:
575     {
576       g_rec_mutex_lock(application_context_mutex);
577 
578       g_value_set_object(value, application_context->config);
579 
580       g_rec_mutex_unlock(application_context_mutex);
581     }
582     break;
583   case PROP_FILE:
584     {
585       g_rec_mutex_lock(application_context_mutex);
586 
587       g_value_set_object(value, application_context->file);
588 
589       g_rec_mutex_unlock(application_context_mutex);
590     }
591     break;
592   default:
593     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
594     break;
595   }
596 }
597 
598 void
ags_application_context_dispose(GObject * gobject)599 ags_application_context_dispose(GObject *gobject)
600 {
601   AgsApplicationContext *application_context;
602 
603   application_context = AGS_APPLICATION_CONTEXT(gobject);
604 
605   /* log */
606   if(application_context->log != NULL){
607     g_object_unref(application_context->log);
608 
609     application_context->log = NULL;
610   }
611 
612   /* config */
613   if(application_context->config != NULL){
614     g_object_unref(application_context->config);
615 
616     application_context->config = NULL;
617   }
618 
619   /* main loop */
620   if(application_context->main_loop != NULL){
621     g_object_unref(application_context->main_loop);
622 
623     application_context->main_loop = NULL;
624   }
625 
626   /* task launcher */
627   if(application_context->task_launcher != NULL){
628     g_object_unref(application_context->task_launcher);
629 
630     application_context->task_launcher = NULL;
631   }
632 
633   /* file */
634   if(application_context->file != NULL){
635     g_object_unref(application_context->file);
636 
637     application_context->file = NULL;
638   }
639 
640   /* call parent */
641   G_OBJECT_CLASS(ags_application_context_parent_class)->dispose(gobject);
642 }
643 
644 void
ags_application_context_finalize(GObject * gobject)645 ags_application_context_finalize(GObject *gobject)
646 {
647   AgsApplicationContext *application_context;
648 
649   application_context = AGS_APPLICATION_CONTEXT(gobject);
650 
651   g_free(application_context->version);
652   g_free(application_context->build_id);
653 
654   /* log */
655   if(application_context->log != NULL){
656     g_object_unref(application_context->log);
657   }
658 
659   /* config */
660   if(application_context->config != NULL){
661     g_object_unref(application_context->config);
662   }
663 
664   /* main loop */
665   if(application_context->main_loop != NULL){
666     g_object_unref(application_context->main_loop);
667   }
668 
669   /* task launcher */
670   if(application_context->task_launcher != NULL){
671     g_object_unref(application_context->task_launcher);
672   }
673 
674   /* file */
675   if(application_context->file != NULL){
676     g_object_unref(application_context->file);
677   }
678 
679   if(application_context == ags_application_context){
680     ags_application_context = NULL;
681   }
682 
683   /* call parent */
684   G_OBJECT_CLASS(ags_application_context_parent_class)->finalize(gobject);
685 }
686 
687 AgsUUID*
ags_application_context_get_uuid(AgsConnectable * connectable)688 ags_application_context_get_uuid(AgsConnectable *connectable)
689 {
690   AgsApplicationContext *application_context;
691 
692   AgsUUID *ptr;
693 
694   GRecMutex *application_context_mutex;
695 
696   application_context = AGS_APPLICATION_CONTEXT(connectable);
697 
698   /* get application_context mutex */
699   application_context_mutex = AGS_APPLICATION_CONTEXT_GET_OBJ_MUTEX(application_context);
700 
701   /* get UUID */
702   g_rec_mutex_lock(application_context_mutex);
703 
704   ptr = application_context->uuid;
705 
706   g_rec_mutex_unlock(application_context_mutex);
707 
708   return(ptr);
709 }
710 
711 gboolean
ags_application_context_has_resource(AgsConnectable * connectable)712 ags_application_context_has_resource(AgsConnectable *connectable)
713 {
714   return(TRUE);
715 }
716 
717 gboolean
ags_application_context_is_ready(AgsConnectable * connectable)718 ags_application_context_is_ready(AgsConnectable *connectable)
719 {
720   AgsApplicationContext *application_context;
721 
722   gboolean is_ready;
723 
724   GRecMutex *application_context_mutex;
725 
726   application_context = AGS_APPLICATION_CONTEXT(connectable);
727 
728   /* get application_context mutex */
729   application_context_mutex = AGS_APPLICATION_CONTEXT_GET_OBJ_MUTEX(application_context);
730 
731   /* check is added */
732   g_rec_mutex_lock(application_context_mutex);
733 
734   is_ready = (((AGS_APPLICATION_CONTEXT_ADDED_TO_REGISTRY & (application_context->flags)) != 0) ? TRUE: FALSE);
735 
736   g_rec_mutex_unlock(application_context_mutex);
737 
738   return(is_ready);
739 }
740 
741 void
ags_application_context_add_to_registry(AgsConnectable * connectable)742 ags_application_context_add_to_registry(AgsConnectable *connectable)
743 {
744   AgsApplicationContext *application_context;
745 
746   if(ags_connectable_is_ready(connectable)){
747     return;
748   }
749 
750   application_context = AGS_APPLICATION_CONTEXT(connectable);
751 
752   ags_application_context_set_flags(application_context, AGS_APPLICATION_CONTEXT_ADDED_TO_REGISTRY);
753 }
754 
755 void
ags_application_context_remove_from_registry(AgsConnectable * connectable)756 ags_application_context_remove_from_registry(AgsConnectable *connectable)
757 {
758   AgsApplicationContext *application_context;
759 
760   if(!ags_connectable_is_ready(connectable)){
761     return;
762   }
763 
764   application_context = AGS_APPLICATION_CONTEXT(connectable);
765 
766   ags_application_context_unset_flags(application_context, AGS_APPLICATION_CONTEXT_ADDED_TO_REGISTRY);
767 }
768 
769 xmlNode*
ags_application_context_list_resource(AgsConnectable * connectable)770 ags_application_context_list_resource(AgsConnectable *connectable)
771 {
772   xmlNode *node;
773 
774   node = NULL;
775 
776   //TODO:JK: implement me
777 
778   return(node);
779 }
780 
781 xmlNode*
ags_application_context_xml_compose(AgsConnectable * connectable)782 ags_application_context_xml_compose(AgsConnectable *connectable)
783 {
784   xmlNode *node;
785 
786   node = NULL;
787 
788   //TODO:JK: implement me
789 
790   return(node);
791 }
792 
793 void
ags_application_context_xml_parse(AgsConnectable * connectable,xmlNode * node)794 ags_application_context_xml_parse(AgsConnectable *connectable,
795 				  xmlNode *node)
796 {
797   //TODO:JK: implement me
798 }
799 
800 gboolean
ags_application_context_is_connected(AgsConnectable * connectable)801 ags_application_context_is_connected(AgsConnectable *connectable)
802 {
803   AgsApplicationContext *application_context;
804 
805   gboolean is_connected;
806 
807   GRecMutex *application_context_mutex;
808 
809   application_context = AGS_APPLICATION_CONTEXT(connectable);
810 
811   /* get application_context mutex */
812   application_context_mutex = AGS_APPLICATION_CONTEXT_GET_OBJ_MUTEX(application_context);
813 
814   /* check is connected */
815   g_rec_mutex_lock(application_context_mutex);
816 
817   is_connected = (((AGS_APPLICATION_CONTEXT_CONNECTED & (application_context->flags)) != 0) ? TRUE: FALSE);
818 
819   g_rec_mutex_unlock(application_context_mutex);
820 
821   return(is_connected);
822 }
823 
824 void
ags_application_context_connect(AgsConnectable * connectable)825 ags_application_context_connect(AgsConnectable *connectable)
826 {
827   AgsApplicationContext *application_context;
828 
829   if(ags_connectable_is_connected(connectable)){
830     return;
831   }
832 
833   application_context = AGS_APPLICATION_CONTEXT(connectable);
834 
835   ags_application_context_set_flags(application_context, AGS_APPLICATION_CONTEXT_CONNECTED);
836 }
837 
838 void
ags_application_context_disconnect(AgsConnectable * connectable)839 ags_application_context_disconnect(AgsConnectable *connectable)
840 {
841   AgsApplicationContext *application_context;
842 
843   if(!ags_connectable_is_connected(connectable)){
844     return;
845   }
846 
847   application_context = AGS_APPLICATION_CONTEXT(connectable);
848 
849   ags_application_context_unset_flags(application_context, AGS_APPLICATION_CONTEXT_CONNECTED);
850 }
851 
852 /**
853  * ags_application_context_test_flags:
854  * @application_context: the #AgsApplicationContext
855  * @flags: the flags
856  *
857  * Test @flags to be set on @application_context.
858  *
859  * Returns: %TRUE if flags are set, else %FALSE
860  *
861  * Since: 3.0.0
862  */
863 gboolean
ags_application_context_test_flags(AgsApplicationContext * application_context,guint flags)864 ags_application_context_test_flags(AgsApplicationContext *application_context, guint flags)
865 {
866   gboolean retval;
867 
868   GRecMutex *application_context_mutex;
869 
870   if(!AGS_IS_APPLICATION_CONTEXT(application_context)){
871     return(FALSE);
872   }
873 
874   /* get application_context mutex */
875   application_context_mutex = AGS_APPLICATION_CONTEXT_GET_OBJ_MUTEX(application_context);
876 
877   /* test */
878   g_rec_mutex_lock(application_context_mutex);
879 
880   retval = (flags & (application_context->flags)) ? TRUE: FALSE;
881 
882   g_rec_mutex_unlock(application_context_mutex);
883 
884   return(retval);
885 }
886 
887 /**
888  * ags_application_context_set_flags:
889  * @application_context: the #AgsApplicationContext
890  * @flags: see enum AgsApplicationContextFlags
891  *
892  * Enable a feature of #AgsApplicationContext.
893  *
894  * Since: 3.0.0
895  */
896 void
ags_application_context_set_flags(AgsApplicationContext * application_context,guint flags)897 ags_application_context_set_flags(AgsApplicationContext *application_context, guint flags)
898 {
899   guint application_context_flags;
900 
901   GRecMutex *application_context_mutex;
902 
903   if(!AGS_IS_APPLICATION_CONTEXT(application_context)){
904     return;
905   }
906 
907   /* get application_context mutex */
908   application_context_mutex = AGS_APPLICATION_CONTEXT_GET_OBJ_MUTEX(application_context);
909 
910   /* set flags */
911   g_rec_mutex_lock(application_context_mutex);
912 
913   application_context->flags |= flags;
914 
915   g_rec_mutex_unlock(application_context_mutex);
916 }
917 
918 /**
919  * ags_application_context_unset_flags:
920  * @application_context: the #AgsApplicationContext
921  * @flags: see enum AgsApplicationContextFlags
922  *
923  * Disable a feature of AgsApplicationContext.
924  *
925  * Since: 3.0.0
926  */
927 void
ags_application_context_unset_flags(AgsApplicationContext * application_context,guint flags)928 ags_application_context_unset_flags(AgsApplicationContext *application_context, guint flags)
929 {
930   guint application_context_flags;
931 
932   GRecMutex *application_context_mutex;
933 
934   if(!AGS_IS_APPLICATION_CONTEXT(application_context)){
935     return;
936   }
937 
938   /* get application_context mutex */
939   application_context_mutex = AGS_APPLICATION_CONTEXT_GET_OBJ_MUTEX(application_context);
940 
941   /* unset flags */
942   g_rec_mutex_lock(application_context_mutex);
943 
944   application_context->flags &= (~flags);
945 
946   g_rec_mutex_unlock(application_context_mutex);
947 }
948 
949 void
ags_application_context_real_load_config(AgsApplicationContext * application_context)950 ags_application_context_real_load_config(AgsApplicationContext *application_context)
951 {
952   //TODO:JK: implement me
953 }
954 
955 /**
956  * ags_application_context_load_config:
957  * @application_context: the #AgsApplicationContext
958  *
959  * Signal to load and parse configuration.
960  *
961  * Since: 3.0.0
962  */
963 void
ags_application_context_load_config(AgsApplicationContext * application_context)964 ags_application_context_load_config(AgsApplicationContext *application_context)
965 {
966   g_return_if_fail(AGS_IS_APPLICATION_CONTEXT(application_context));
967 
968   g_object_ref(G_OBJECT(application_context));
969   g_signal_emit(G_OBJECT(application_context),
970 		application_context_signals[LOAD_CONFIG], 0);
971   g_object_unref(G_OBJECT(application_context));
972 }
973 
974 void
ags_application_context_real_prepare(AgsApplicationContext * application_context)975 ags_application_context_real_prepare(AgsApplicationContext *application_context)
976 {
977   ags_log_add_message(ags_log_get_instance(), "prepare Advanced Gtk+ Sequencer");
978 }
979 
980 /**
981  * ags_application_context_prepare:
982  * @application_context: the #AgsApplicationContext
983  *
984  * Prepare @application_context.
985  *
986  * Since: 3.0.0
987  */
988 void
ags_application_context_prepare(AgsApplicationContext * application_context)989 ags_application_context_prepare(AgsApplicationContext *application_context)
990 {
991   g_return_if_fail(AGS_IS_APPLICATION_CONTEXT(application_context));
992 
993   g_object_ref(G_OBJECT(application_context));
994   g_signal_emit(G_OBJECT(application_context),
995 		application_context_signals[PREPARE], 0);
996   g_object_unref(G_OBJECT(application_context));
997 }
998 
999 void
ags_application_context_real_setup(AgsApplicationContext * application_context)1000 ags_application_context_real_setup(AgsApplicationContext *application_context)
1001 {
1002   ags_log_add_message(ags_log_get_instance(), "setup Advanced Gtk+ Sequencer");
1003 }
1004 
1005 /**
1006  * ags_application_context_setup:
1007  * @application_context: the #AgsApplicationContext
1008  *
1009  * Setup @application_context.
1010  *
1011  * Since: 3.0.0
1012  */
1013 void
ags_application_context_setup(AgsApplicationContext * application_context)1014 ags_application_context_setup(AgsApplicationContext *application_context)
1015 {
1016   g_return_if_fail(AGS_IS_APPLICATION_CONTEXT(application_context));
1017 
1018   g_object_ref(G_OBJECT(application_context));
1019   g_signal_emit(G_OBJECT(application_context),
1020 		application_context_signals[SETUP], 0);
1021   g_object_unref(G_OBJECT(application_context));
1022 }
1023 
1024 void
ags_application_context_real_register_types(AgsApplicationContext * application_context)1025 ags_application_context_real_register_types(AgsApplicationContext *application_context)
1026 {
1027   //TODO:JK: implement me
1028 }
1029 
1030 /**
1031  * ags_application_context_register_types:
1032  * @application_context: the #AgsApplicationContext
1033  *
1034  * Notification to register your types.
1035  *
1036  * Since: 3.0.0
1037  */
1038 void
ags_application_context_register_types(AgsApplicationContext * application_context)1039 ags_application_context_register_types(AgsApplicationContext *application_context)
1040 {
1041   g_return_if_fail(AGS_IS_APPLICATION_CONTEXT(application_context));
1042 
1043   g_object_ref(G_OBJECT(application_context));
1044   g_signal_emit(G_OBJECT(application_context),
1045 		application_context_signals[REGISTER_TYPES], 0);
1046   g_object_unref(G_OBJECT(application_context));
1047 }
1048 
1049 void
ags_application_context_real_quit(AgsApplicationContext * application_context)1050 ags_application_context_real_quit(AgsApplicationContext *application_context)
1051 {
1052   //TODO:JK: enhance me
1053   exit(0);
1054 }
1055 
1056 /**
1057  * ags_application_context_quit:
1058  * @application_context: the #AgsApplicationContext
1059  *
1060  * Calls exit()
1061  *
1062  * Since: 3.0.0
1063  */
1064 void
ags_application_context_quit(AgsApplicationContext * application_context)1065 ags_application_context_quit(AgsApplicationContext *application_context)
1066 {
1067   g_return_if_fail(AGS_IS_APPLICATION_CONTEXT(application_context));
1068 
1069   g_object_ref(G_OBJECT(application_context));
1070   g_signal_emit(G_OBJECT(application_context),
1071 		application_context_signals[QUIT], 0);
1072   g_object_unref(G_OBJECT(application_context));
1073 }
1074 
1075 /**
1076  * ags_application_context_get_instance:
1077  *
1078  * Get your application context instance.
1079  *
1080  * Returns: (transfer none): the #AgsApplicationContext instance
1081  *
1082  * Since: 3.0.0
1083  */
1084 AgsApplicationContext*
ags_application_context_get_instance()1085 ags_application_context_get_instance()
1086 {
1087   static GMutex mutex;
1088 
1089   g_mutex_lock(&mutex);
1090 
1091   if(ags_application_context == NULL){
1092     ags_application_context = ags_application_context_new(NULL,
1093 							  NULL);
1094   }
1095 
1096   g_mutex_unlock(&mutex);
1097 
1098   return(ags_application_context);
1099 }
1100 
1101 /**
1102  * ags_application_context_new:
1103  * @main_loop: (nullable): the #AgsMainLoop
1104  * @config: (nullable): the #AgsConfig
1105  *
1106  * Create a new instance of #AgsApplicationContext
1107  *
1108  * Returns: the #AgsApplicationContext instance
1109  *
1110  * Since: 3.0.0
1111  */
1112 AgsApplicationContext*
ags_application_context_new(GObject * main_loop,AgsConfig * config)1113 ags_application_context_new(GObject *main_loop,
1114 			    AgsConfig *config)
1115 {
1116   AgsApplicationContext *application_context;
1117 
1118   application_context = (AgsApplicationContext *) g_object_new(AGS_TYPE_APPLICATION_CONTEXT,
1119 							       "main-loop", main_loop,
1120 							       "config", config,
1121 							       NULL);
1122 
1123   return(application_context);
1124 }
1125