1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2019 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 Affero General Public License as
8  * published by the Free Software Foundation, either version 3 of the
9  * License, or (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 Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/audio/osc/controller/ags_osc_front_controller.h>
21 
22 #include <ags/audio/osc/ags_osc_server.h>
23 #include <ags/audio/osc/ags_osc_message.h>
24 #include <ags/audio/osc/ags_osc_response.h>
25 #include <ags/audio/osc/ags_osc_util.h>
26 #include <ags/audio/osc/ags_osc_buffer_util.h>
27 
28 #include <ags/audio/osc/controller/ags_osc_action_controller.h>
29 #include <ags/audio/osc/controller/ags_osc_config_controller.h>
30 #include <ags/audio/osc/controller/ags_osc_controller.h>
31 #include <ags/audio/osc/controller/ags_osc_info_controller.h>
32 #include <ags/audio/osc/controller/ags_osc_meter_controller.h>
33 #include <ags/audio/osc/controller/ags_osc_node_controller.h>
34 #include <ags/audio/osc/controller/ags_osc_plugin_controller.h>
35 #include <ags/audio/osc/controller/ags_osc_renew_controller.h>
36 #include <ags/audio/osc/controller/ags_osc_status_controller.h>
37 
38 #include <stdlib.h>
39 #include <math.h>
40 
41 #ifdef __APPLE__
42 #include <mach/clock.h>
43 #include <mach/mach.h>
44 #endif
45 
46 #include <ags/i18n.h>
47 
48 void ags_osc_front_controller_class_init(AgsOscFrontControllerClass *osc_front_controller);
49 void ags_osc_front_controller_init(AgsOscFrontController *osc_front_controller);
50 void ags_osc_front_controller_set_property(GObject *gobject,
51 					   guint prop_id,
52 					   const GValue *value,
53 					   GParamSpec *param_spec);
54 void ags_osc_front_controller_get_property(GObject *gobject,
55 					   guint prop_id,
56 					   GValue *value,
57 					   GParamSpec *param_spec);
58 void ags_osc_front_controller_dispose(GObject *gobject);
59 void ags_osc_front_controller_finalize(GObject *gobject);
60 
61 void* ags_osc_front_controller_delegate_thread(void *ptr);
62 
63 void ags_osc_front_controller_real_start_delegate(AgsOscFrontController *osc_front_controller);
64 void ags_osc_front_controller_real_stop_delegate(AgsOscFrontController *osc_front_controller);
65 
66 gsize ags_osc_front_controller_read_bundle(AgsOscFrontController *osc_front_controller,
67 					   AgsOscConnection *osc_connection,
68 					   guchar *packet, gsize packet_size,
69 					   gsize offset);
70 gsize ags_osc_front_controller_read_message(AgsOscFrontController *osc_front_controller,
71 					    AgsOscConnection *osc_connection,
72 					    guchar *packet, gsize packet_size,
73 					    gsize offset,
74 					    gint32 tv_sec, gint32 tv_fraction, gboolean immediately);
75 
76 gpointer ags_osc_front_controller_real_do_request(AgsOscFrontController *osc_front_controller,
77 						  AgsOscConnection *osc_connection,
78 						  guchar *packet, gsize packet_size);
79 
80 /**
81  * SECTION:ags_osc_front_controller
82  * @short_description: OSC front controller
83  * @title: AgsOscFrontController
84  * @section_id:
85  * @include: ags/audio/osc/controller/ags_osc_front_controller.h
86  *
87  * The #AgsOscFrontController implements the OSC front controller.
88  */
89 
90 enum{
91   PROP_0,
92 };
93 
94 enum{
95   START_DELEGATE,
96   STOP_DELEGATE,
97   DO_REQUEST,
98   LAST_SIGNAL,
99 };
100 
101 static gpointer ags_osc_front_controller_parent_class = NULL;
102 static guint osc_front_controller_signals[LAST_SIGNAL];
103 
104 GType
ags_osc_front_controller_get_type()105 ags_osc_front_controller_get_type()
106 {
107   static volatile gsize g_define_type_id__volatile = 0;
108 
109   if(g_once_init_enter (&g_define_type_id__volatile)){
110     GType ags_type_osc_front_controller = 0;
111 
112     static const GTypeInfo ags_osc_front_controller_info = {
113       sizeof (AgsOscFrontControllerClass),
114       NULL, /* base_init */
115       NULL, /* base_finalize */
116       (GClassInitFunc) ags_osc_front_controller_class_init,
117       NULL, /* class_finalize */
118       NULL, /* class_data */
119       sizeof (AgsOscFrontController),
120       0,    /* n_preallocs */
121       (GInstanceInitFunc) ags_osc_front_controller_init,
122     };
123 
124     ags_type_osc_front_controller = g_type_register_static(AGS_TYPE_OSC_CONTROLLER,
125 							   "AgsOscFrontController",
126 							   &ags_osc_front_controller_info,
127 							   0);
128 
129     g_once_init_leave(&g_define_type_id__volatile, ags_type_osc_front_controller);
130   }
131 
132   return g_define_type_id__volatile;
133 }
134 
135 void
ags_osc_front_controller_class_init(AgsOscFrontControllerClass * osc_front_controller)136 ags_osc_front_controller_class_init(AgsOscFrontControllerClass *osc_front_controller)
137 {
138   GObjectClass *gobject;
139   GParamSpec *param_spec;
140 
141   ags_osc_front_controller_parent_class = g_type_class_peek_parent(osc_front_controller);
142 
143   /* GObjectClass */
144   gobject = (GObjectClass *) osc_front_controller;
145 
146   //  gobject->set_property = ags_osc_front_controller_set_property;
147   //  gobject->get_property = ags_osc_front_controller_get_property;
148 
149   gobject->dispose = ags_osc_front_controller_dispose;
150   gobject->finalize = ags_osc_front_controller_finalize;
151 
152   /* properties */
153 
154   /* AgsOscFrontControllerClass */
155   osc_front_controller->start_delegate = ags_osc_front_controller_real_start_delegate;
156   osc_front_controller->stop_delegate = ags_osc_front_controller_real_stop_delegate;
157 
158   osc_front_controller->do_request = ags_osc_front_controller_real_do_request;
159 
160   /* signals */
161   /**
162    * AgsOscFrontController::start-delegate:
163    * @osc_front_controller: the #AgsOscFrontController
164    *
165    * The ::start-delegate signal is emited during start of delegating messages.
166    *
167    * Since: 3.0.0
168    */
169   osc_front_controller_signals[START_DELEGATE] =
170     g_signal_new("start-delegate",
171 		 G_TYPE_FROM_CLASS(osc_front_controller),
172 		 G_SIGNAL_RUN_LAST,
173 		 G_STRUCT_OFFSET(AgsOscFrontControllerClass, start_delegate),
174 		 NULL, NULL,
175 		 g_cclosure_marshal_VOID__VOID,
176 		 G_TYPE_NONE, 0);
177 
178   /**
179    * AgsOscFrontController::stop-delegate:
180    * @osc_front_controller: the #AgsOscFrontController
181    *
182    * The ::stop-delegate signal is emited during stop of delegating messages.
183    *
184    * Since: 3.0.0
185    */
186   osc_front_controller_signals[STOP_DELEGATE] =
187     g_signal_new("stop-delegate",
188 		 G_TYPE_FROM_CLASS(osc_front_controller),
189 		 G_SIGNAL_RUN_LAST,
190 		 G_STRUCT_OFFSET(AgsOscFrontControllerClass, stop_delegate),
191 		 NULL, NULL,
192 		 g_cclosure_marshal_VOID__VOID,
193 		 G_TYPE_NONE, 0);
194 
195   /**
196    * AgsOscFrontController::do-request:
197    * @osc_front_controller: the #AgsOscFrontController
198    * @osc_connection: the #AgsOscConnection
199    * @packet: the packet received
200    * @packet_size: the packet size
201    *
202    * The ::do-request signal is emited during do request of front controller.
203    *
204    * Since: 3.0.0
205    */
206   osc_front_controller_signals[DO_REQUEST] =
207     g_signal_new("do-request",
208 		 G_TYPE_FROM_CLASS(osc_front_controller),
209 		 G_SIGNAL_RUN_LAST,
210 		 G_STRUCT_OFFSET(AgsOscFrontControllerClass, do_request),
211 		 NULL, NULL,
212 		 ags_cclosure_marshal_POINTER__OBJECT_POINTER_INT64,
213 		 G_TYPE_POINTER, 3,
214 		 G_TYPE_OBJECT,
215 		 G_TYPE_POINTER,
216 		 G_TYPE_INT64);
217 }
218 
219 void
ags_osc_front_controller_init(AgsOscFrontController * osc_front_controller)220 ags_osc_front_controller_init(AgsOscFrontController *osc_front_controller)
221 {
222   g_object_set(osc_front_controller,
223 	       "context-path", "/",
224 	       NULL);
225 
226   osc_front_controller->flags = 0;
227 
228   osc_front_controller->delegate_timeout = (struct timespec *) malloc(sizeof(struct timespec));
229 
230   osc_front_controller->delegate_timeout = 0;
231 
232   g_atomic_int_set(&(osc_front_controller->do_reset),
233 		   FALSE);
234 
235   g_mutex_init(&(osc_front_controller->delegate_mutex));
236 
237   g_cond_init(&(osc_front_controller->delegate_cond));
238 
239   osc_front_controller->delegate_thread = NULL;
240 
241   osc_front_controller->message = NULL;
242 }
243 
244 void
ags_osc_front_controller_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)245 ags_osc_front_controller_set_property(GObject *gobject,
246 				      guint prop_id,
247 				      const GValue *value,
248 				      GParamSpec *param_spec)
249 {
250   AgsOscFrontController *osc_front_controller;
251 
252   GRecMutex *osc_controller_mutex;
253 
254   osc_front_controller = AGS_OSC_FRONT_CONTROLLER(gobject);
255 
256   /* get osc controller mutex */
257   osc_controller_mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(osc_front_controller);
258 
259   switch(prop_id){
260   default:
261     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
262     break;
263   }
264 }
265 
266 void
ags_osc_front_controller_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)267 ags_osc_front_controller_get_property(GObject *gobject,
268 				      guint prop_id,
269 				      GValue *value,
270 				      GParamSpec *param_spec)
271 {
272   AgsOscFrontController *osc_front_controller;
273 
274   GRecMutex *osc_controller_mutex;
275 
276   osc_front_controller = AGS_OSC_FRONT_CONTROLLER(gobject);
277 
278   /* get osc controller mutex */
279   osc_controller_mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(osc_front_controller);
280 
281   switch(prop_id){
282   default:
283     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
284     break;
285   }
286 }
287 
288 void
ags_osc_front_controller_dispose(GObject * gobject)289 ags_osc_front_controller_dispose(GObject *gobject)
290 {
291   AgsOscFrontController *osc_front_controller;
292 
293   osc_front_controller = AGS_OSC_FRONT_CONTROLLER(gobject);
294 
295   if(osc_front_controller->message != NULL){
296     g_list_free_full(osc_front_controller->message,
297 		     (GDestroyNotify) g_object_unref);
298 
299     osc_front_controller->message = NULL;
300   }
301 
302   /* call parent */
303   G_OBJECT_CLASS(ags_osc_front_controller_parent_class)->dispose(gobject);
304 }
305 
306 void
ags_osc_front_controller_finalize(GObject * gobject)307 ags_osc_front_controller_finalize(GObject *gobject)
308 {
309   AgsOscFrontController *osc_front_controller;
310 
311   osc_front_controller = AGS_OSC_FRONT_CONTROLLER(gobject);
312 
313   if(osc_front_controller->message != NULL){
314     g_list_free_full(osc_front_controller->message,
315 		     (GDestroyNotify) g_object_unref);
316   }
317 
318   /* call parent */
319   G_OBJECT_CLASS(ags_osc_front_controller_parent_class)->finalize(gobject);
320 }
321 
322 void*
ags_osc_front_controller_delegate_thread(void * ptr)323 ags_osc_front_controller_delegate_thread(void *ptr)
324 {
325   AgsOscServer *osc_server;
326   AgsOscFrontController *osc_front_controller;
327 
328   GList *start_controller, *controller;
329 
330   gint64 time_now, time_next;
331   gint64 current_time;
332 
333   GRecMutex *osc_controller_mutex;
334 
335   osc_front_controller = AGS_OSC_FRONT_CONTROLLER(ptr);
336 
337   g_object_get(osc_front_controller,
338 	       "osc-server", &osc_server,
339 	       NULL);
340 
341   g_object_get(osc_server,
342 	       "controller", &start_controller,
343 	       NULL);
344 
345   /* get OSC front controller mutex */
346   osc_controller_mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(osc_front_controller);
347 
348   time_next = 0;
349 
350   ags_osc_front_controller_set_flags(osc_front_controller,
351 				     AGS_OSC_FRONT_CONTROLLER_DELEGATE_RUNNING);
352 
353   while(ags_osc_front_controller_test_flags(osc_front_controller, AGS_OSC_FRONT_CONTROLLER_DELEGATE_RUNNING)){
354     GList *start_message, *message;
355     GList *start_list, *list;
356 
357     g_mutex_lock(&(osc_front_controller->delegate_mutex));
358 
359     time_now = g_get_monotonic_time();
360     osc_front_controller->delegate_timeout = time_now + (G_TIME_SPAN_SECOND / 30);
361 
362     while(!g_atomic_int_get(&(osc_front_controller->do_reset)) &&
363 	  ((time_now < time_next) &&
364 	   (time_now < osc_front_controller->delegate_timeout)) &&
365 	  ags_osc_front_controller_test_flags(osc_front_controller, AGS_OSC_FRONT_CONTROLLER_DELEGATE_RUNNING) &&
366 	  time_now > 0){
367       g_cond_wait_until(&(osc_front_controller->delegate_cond),
368 			&(osc_front_controller->delegate_mutex),
369 			osc_front_controller->delegate_timeout);
370 
371       time_now = g_get_monotonic_time();
372     }
373 
374     g_atomic_int_set(&(osc_front_controller->do_reset),
375 		     FALSE);
376 
377     g_mutex_unlock(&(osc_front_controller->delegate_mutex));
378 
379     /* check delegate */
380     g_rec_mutex_lock(osc_controller_mutex);
381 
382     start_message = NULL;
383     list =
384       start_list = g_list_copy(osc_front_controller->message);
385 
386     while(list != NULL){
387       if(AGS_OSC_MESSAGE(list->data)->immediately){
388 	start_message = g_list_prepend(start_message,
389 				       list->data);
390 	g_object_ref(list->data);
391 
392 	ags_osc_front_controller_remove_message(osc_front_controller,
393 						list->data);
394       }else{
395 	current_time = AGS_OSC_MESSAGE(list->data)->tv_sec + AGS_OSC_MESSAGE(list->data)->tv_fraction / 4.294967296 * 1000.0;
396 
397 	if(current_time < time_now){
398 	  start_message = g_list_prepend(start_message,
399 					 list->data);
400 	  g_object_ref(list->data);
401 
402 	  ags_osc_front_controller_remove_message(osc_front_controller,
403 						  list->data);
404 	}else{
405 	  break;
406 	}
407       }
408 
409       list = list->next;
410     }
411 
412     g_rec_mutex_unlock(osc_controller_mutex);
413 
414     g_list_free(start_list);
415 
416     message =
417       start_message = g_list_reverse(start_message);
418 
419     while(message != NULL){
420       GList *start_osc_response, *osc_response;
421 
422       AgsOscMessage *current;
423 
424       gchar *path;
425 
426       ags_osc_buffer_util_get_string(AGS_OSC_MESSAGE(message->data)->message,
427 				     &path, NULL);
428 
429       controller = start_controller;
430       start_osc_response = NULL;
431 
432       while(controller != NULL){
433 	gboolean success;
434 
435 	GRecMutex *mutex;
436 
437 	/* get OSC controller mutex */
438 	mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(controller->data);
439 
440 	/* match path */
441 	g_rec_mutex_lock(mutex);
442 
443 	success = !g_strcmp0(AGS_OSC_CONTROLLER(controller->data)->context_path,
444 			     path);
445 
446 	g_rec_mutex_unlock(mutex);
447 
448 	if(success){
449 	  current = AGS_OSC_MESSAGE(message->data);
450 
451 	  /* delegate */
452 	  if(AGS_IS_OSC_ACTION_CONTROLLER(controller->data)){
453 	    start_osc_response = ags_osc_action_controller_run_action(controller->data,
454 								      current->osc_connection,
455 								      current->message, current->message_size);
456 	  }else if(AGS_IS_OSC_CONFIG_CONTROLLER(controller->data)){
457 	    start_osc_response = ags_osc_config_controller_apply_config(controller->data,
458 									current->osc_connection,
459 									current->message, current->message_size);
460 	  }else if(AGS_IS_OSC_INFO_CONTROLLER(controller->data)){
461 	    start_osc_response = ags_osc_info_controller_get_info(controller->data,
462 								  current->osc_connection,
463 								  current->message, current->message_size);
464 	  }else if(AGS_IS_OSC_METER_CONTROLLER(controller->data)){
465 	    start_osc_response = ags_osc_meter_controller_monitor_meter(controller->data,
466 									current->osc_connection,
467 									current->message, current->message_size);
468 	  }else if(AGS_IS_OSC_NODE_CONTROLLER(controller->data)){
469 	    start_osc_response = ags_osc_node_controller_get_data(controller->data,
470 								  current->osc_connection,
471 								  current->message, current->message_size);
472 	  }else if(AGS_IS_OSC_RENEW_CONTROLLER(controller->data)){
473 	    start_osc_response = ags_osc_renew_controller_set_data(controller->data,
474 								   current->osc_connection,
475 								   current->message, current->message_size);
476 	  }else if(AGS_IS_OSC_STATUS_CONTROLLER(controller->data)){
477 	    start_osc_response = ags_osc_status_controller_get_status(controller->data,
478 								      current->osc_connection,
479 								      current->message, current->message_size);
480 	  }else if(AGS_IS_OSC_PLUGIN_CONTROLLER(controller->data)){
481 	    start_osc_response = ags_osc_plugin_controller_do_request(AGS_OSC_PLUGIN_CONTROLLER(controller->data),
482 								      current->osc_connection,
483 								      current->message, current->message_size);
484 	  }
485 
486 	  break;
487 	}
488 
489 	controller = controller->next;
490       }
491 
492       /* write response */
493       osc_response = start_osc_response;
494 
495       while(osc_response != NULL){
496 	ags_osc_connection_write_response(current->osc_connection,
497 					  osc_response->data);
498 
499 	osc_response = osc_response->next;
500       }
501 
502       g_list_free_full(start_osc_response,
503 		       g_object_unref);
504 
505       message = message->next;
506     }
507 
508     /* free messages */
509     g_list_free_full(start_message,
510 		     (GDestroyNotify) g_object_unref);
511 
512     /* next */
513     g_mutex_lock(&(osc_front_controller->delegate_mutex));
514 
515     if(osc_front_controller->message != NULL){
516       time_now = g_get_monotonic_time();
517 
518       time_next = AGS_OSC_MESSAGE(osc_front_controller->message)->tv_sec + AGS_OSC_MESSAGE(osc_front_controller->message)->tv_fraction / 4.294967296 * 1000.0;
519 
520       if(time_next == -1){
521 	time_next = time_now + 1;
522       }else if(time_next > time_now + G_TIME_SPAN_SECOND / 30){
523 	time_next = time_now + G_TIME_SPAN_SECOND / 30;
524       }
525     }else{
526       time_now = g_get_monotonic_time();
527 
528       time_next = time_now + G_TIME_SPAN_SECOND / 30;
529     }
530 
531     g_mutex_unlock(&(osc_front_controller->delegate_mutex));
532   }
533 
534   g_object_unref(osc_server);
535 
536   g_list_free_full(start_controller,
537 		   g_object_unref);
538 
539   g_thread_exit(NULL);
540 
541   return(NULL);
542 }
543 
544 /**
545  * ags_osc_front_controller_test_flags:
546  * @osc_front_controller: the #AgsOscFrontController
547  * @flags: the flags
548  *
549  * Test @flags to be set on @osc_front_controller.
550  *
551  * Returns: %TRUE if flags are set, else %FALSE
552  *
553  * Since: 3.0.0
554  */
555 gboolean
ags_osc_front_controller_test_flags(AgsOscFrontController * osc_front_controller,guint flags)556 ags_osc_front_controller_test_flags(AgsOscFrontController *osc_front_controller, guint flags)
557 {
558   gboolean retval;
559 
560   GRecMutex *osc_controller_mutex;
561 
562   if(!AGS_IS_OSC_FRONT_CONTROLLER(osc_front_controller)){
563     return(FALSE);
564   }
565 
566   /* get OSC front controller mutex */
567   osc_controller_mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(osc_front_controller);
568 
569   /* test */
570   g_rec_mutex_lock(osc_controller_mutex);
571 
572   retval = (flags & (osc_front_controller->flags)) ? TRUE: FALSE;
573 
574   g_rec_mutex_unlock(osc_controller_mutex);
575 
576   return(retval);
577 }
578 
579 /**
580  * ags_osc_front_controller_set_flags:
581  * @osc_front_controller: the #AgsOscFrontController
582  * @flags: the flags
583  *
584  * Set flags.
585  *
586  * Since: 3.0.0
587  */
588 void
ags_osc_front_controller_set_flags(AgsOscFrontController * osc_front_controller,guint flags)589 ags_osc_front_controller_set_flags(AgsOscFrontController *osc_front_controller, guint flags)
590 {
591   GRecMutex *osc_controller_mutex;
592 
593   if(!AGS_IS_OSC_FRONT_CONTROLLER(osc_front_controller)){
594     return;
595   }
596 
597   /* get OSC front controller mutex */
598   osc_controller_mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(osc_front_controller);
599 
600   /* set flags */
601   g_rec_mutex_lock(osc_controller_mutex);
602 
603   osc_front_controller->flags |= flags;
604 
605   g_rec_mutex_unlock(osc_controller_mutex);
606 }
607 
608 /**
609  * ags_osc_front_controller_unset_flags:
610  * @osc_front_controller: the #AgsOscFrontController
611  * @flags: the flags
612  *
613  * Unset flags.
614  *
615  * Since: 3.0.0
616  */
617 void
ags_osc_front_controller_unset_flags(AgsOscFrontController * osc_front_controller,guint flags)618 ags_osc_front_controller_unset_flags(AgsOscFrontController *osc_front_controller, guint flags)
619 {
620   GRecMutex *osc_controller_mutex;
621 
622   if(!AGS_IS_OSC_FRONT_CONTROLLER(osc_front_controller)){
623     return;
624   }
625 
626   /* get OSC front controller mutex */
627   osc_controller_mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(osc_front_controller);
628 
629   /* set flags */
630   g_rec_mutex_lock(osc_controller_mutex);
631 
632   osc_front_controller->flags &= (~flags);
633 
634   g_rec_mutex_unlock(osc_controller_mutex);
635 }
636 
637 /**
638  * ags_osc_front_controller_add_message:
639  * @osc_front_controller: the #AgsOscFrontController
640  * @message: the #AgsOscMessage
641  *
642  * Add @message to @osc_front_controller.
643  *
644  * Since: 3.0.0
645  */
646 void
ags_osc_front_controller_add_message(AgsOscFrontController * osc_front_controller,GObject * message)647 ags_osc_front_controller_add_message(AgsOscFrontController *osc_front_controller,
648 				     GObject *message)
649 {
650   GRecMutex *osc_controller_mutex;
651 
652   if(!AGS_IS_OSC_FRONT_CONTROLLER(osc_front_controller) ||
653      message == NULL){
654     return;
655   }
656 
657   /* get OSC front controller mutex */
658   osc_controller_mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(osc_front_controller);
659 
660   /* add */
661   g_rec_mutex_lock(osc_controller_mutex);
662 
663   if(g_list_find(osc_front_controller->message, message) == NULL){
664     osc_front_controller->message = g_list_insert_sorted(osc_front_controller->message,
665 							 message,
666 							 ags_osc_message_sort_func);
667     g_object_ref(message);
668   }
669 
670   g_rec_mutex_unlock(osc_controller_mutex);
671 }
672 
673 /**
674  * ags_osc_front_controller_remove_message:
675  * @osc_front_controller: the #AgsOscFrontController
676  * @message: the #AgsOscMessage
677  *
678  * Remove @message from @osc_front_controller.
679  *
680  * Since: 3.0.0
681  */
682 void
ags_osc_front_controller_remove_message(AgsOscFrontController * osc_front_controller,GObject * message)683 ags_osc_front_controller_remove_message(AgsOscFrontController *osc_front_controller,
684 					GObject *message)
685 {
686   GRecMutex *osc_controller_mutex;
687 
688   if(!AGS_IS_OSC_FRONT_CONTROLLER(osc_front_controller) ||
689      message == NULL){
690     return;
691   }
692 
693   /* get OSC front controller mutex */
694   osc_controller_mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(osc_front_controller);
695 
696   /* remove */
697   g_rec_mutex_lock(osc_controller_mutex);
698 
699   if(g_list_find(osc_front_controller->message, message) != NULL){
700     osc_front_controller->message = g_list_remove(osc_front_controller->message,
701 						  message);
702     g_object_unref(message);
703   }
704 
705   g_rec_mutex_unlock(osc_controller_mutex);
706 }
707 
708 void
ags_osc_front_controller_real_start_delegate(AgsOscFrontController * osc_front_controller)709 ags_osc_front_controller_real_start_delegate(AgsOscFrontController *osc_front_controller)
710 {
711   GRecMutex *osc_controller_mutex;
712 
713   /* get OSC front controller mutex */
714   osc_controller_mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(osc_front_controller);
715 
716   /* test if already started */
717   g_rec_mutex_lock(osc_controller_mutex);
718 
719   if(ags_osc_front_controller_test_flags(osc_front_controller, AGS_OSC_FRONT_CONTROLLER_DELEGATE_STARTED)){
720     g_rec_mutex_unlock(osc_controller_mutex);
721 
722     return;
723   }
724 
725   ags_osc_front_controller_set_flags(osc_front_controller, AGS_OSC_FRONT_CONTROLLER_DELEGATE_STARTED);
726 
727   g_rec_mutex_unlock(osc_controller_mutex);
728 
729   /* create delegate thread */
730   osc_front_controller->delegate_thread = g_thread_new("Advanced Gtk+ Sequencer OSC Server - delegate thread",
731 						       ags_osc_front_controller_delegate_thread,
732 						       osc_front_controller);
733 }
734 
735 /**
736  * ags_osc_front_controller_start_delegate:
737  * @osc_front_controller: the #AgsOscFrontController
738  *
739  * Start delegating.
740  *
741  * Since: 3.0.0
742  */
743 void
ags_osc_front_controller_start_delegate(AgsOscFrontController * osc_front_controller)744 ags_osc_front_controller_start_delegate(AgsOscFrontController *osc_front_controller)
745 {
746   g_return_if_fail(AGS_IS_OSC_FRONT_CONTROLLER(osc_front_controller));
747 
748   g_object_ref((GObject *) osc_front_controller);
749   g_signal_emit(G_OBJECT(osc_front_controller),
750 		osc_front_controller_signals[START_DELEGATE], 0);
751   g_object_unref((GObject *) osc_front_controller);
752 }
753 
754 void
ags_osc_front_controller_real_stop_delegate(AgsOscFrontController * osc_front_controller)755 ags_osc_front_controller_real_stop_delegate(AgsOscFrontController *osc_front_controller)
756 {
757   if(!ags_osc_front_controller_test_flags(osc_front_controller, AGS_OSC_FRONT_CONTROLLER_DELEGATE_RUNNING)){
758     return;
759   }
760 
761   ags_osc_front_controller_set_flags(osc_front_controller, AGS_OSC_FRONT_CONTROLLER_DELEGATE_TERMINATING);
762   ags_osc_front_controller_unset_flags(osc_front_controller, AGS_OSC_FRONT_CONTROLLER_DELEGATE_RUNNING);
763 
764   /* join thread */
765   //TODO:JK: this was disabled as a work-around
766 #if 1
767   g_thread_join(osc_front_controller->delegate_thread);
768 #endif
769 
770   ags_osc_front_controller_unset_flags(osc_front_controller, (AGS_OSC_FRONT_CONTROLLER_DELEGATE_TERMINATING |
771 							      AGS_OSC_FRONT_CONTROLLER_DELEGATE_STARTED));
772 }
773 
774 /**
775  * ags_osc_front_controller_stop_delegate:
776  * @osc_front_controller: the #AgsOscFrontController
777  *
778  * Stop delegating.
779  *
780  * Since: 3.0.0
781  */
782 void
ags_osc_front_controller_stop_delegate(AgsOscFrontController * osc_front_controller)783 ags_osc_front_controller_stop_delegate(AgsOscFrontController *osc_front_controller)
784 {
785   g_return_if_fail(AGS_IS_OSC_FRONT_CONTROLLER(osc_front_controller));
786 
787   g_object_ref((GObject *) osc_front_controller);
788   g_signal_emit(G_OBJECT(osc_front_controller),
789 		osc_front_controller_signals[STOP_DELEGATE], 0);
790   g_object_unref((GObject *) osc_front_controller);
791 }
792 
793 gsize
ags_osc_front_controller_read_bundle(AgsOscFrontController * osc_front_controller,AgsOscConnection * osc_connection,guchar * packet,gsize packet_size,gsize offset)794 ags_osc_front_controller_read_bundle(AgsOscFrontController *osc_front_controller,
795 				     AgsOscConnection *osc_connection,
796 				     guchar *packet, gsize packet_size,
797 				     gsize offset)
798 {
799   gint32 tv_sec;
800   gint32 tv_fraction;
801   gboolean immediately;
802   gsize read_count;
803   gint32 length;
804 
805   read_count = 8;
806 
807   ags_osc_buffer_util_get_timetag(packet + offset + read_count,
808 				  &(tv_sec), &(tv_fraction), &(immediately));
809   read_count += 8;
810 
811   for(; offset < packet_size;){
812     ags_osc_buffer_util_get_int32(packet + offset + read_count,
813 				  &length);
814     read_count += 4;
815 
816     if(!g_strcmp0(packet + offset + read_count, "#bundle")){
817       ags_osc_front_controller_read_bundle(osc_front_controller,
818 					   osc_connection,
819 					   packet, packet_size,
820 					   offset + read_count);
821 
822       read_count += ((gsize) 4 * ceil((double) length / 4.0));
823     }else if(packet[offset + read_count] == '/'){
824       ags_osc_front_controller_read_message(osc_front_controller,
825 					    osc_connection,
826 					    packet, packet_size,
827 					    offset + read_count,
828 					    tv_sec, tv_fraction, immediately);
829 
830       read_count += ((gsize) 4 * ceil((double) length / 4.0));
831     }else{
832       read_count += 1;
833 
834       g_warning("malformed data");
835     }
836   }
837 
838   return(read_count);
839 }
840 
841 gsize
ags_osc_front_controller_read_message(AgsOscFrontController * osc_front_controller,AgsOscConnection * osc_connection,guchar * packet,gsize packet_size,gsize offset,gint32 tv_sec,gint32 tv_fraction,gboolean immediately)842 ags_osc_front_controller_read_message(AgsOscFrontController *osc_front_controller,
843 				      AgsOscConnection *osc_connection,
844 				      guchar *packet, gsize packet_size,
845 				      gsize offset,
846 				      gint32 tv_sec, gint32 tv_fraction, gboolean immediately)
847 {
848   AgsOscMessage *osc_message;
849 
850   guchar *message;
851   gchar *address_pattern;
852   gchar *type_tag;
853 
854   gsize address_pattern_length;
855   gsize type_tag_length;
856   gsize data_length;
857   gsize read_count;
858   guint i;
859 
860   read_count = 0;
861 
862   ags_osc_buffer_util_get_string(packet + offset,
863 				 &address_pattern, &address_pattern_length);
864 
865   if(address_pattern == NULL){
866     return(0);
867   }
868 
869   read_count += (4 * (gsize) ceil((double) (address_pattern_length + 1) / 4.0));
870   free(address_pattern);
871 
872   type_tag = NULL;
873 
874   if(packet_size > offset + read_count){
875     if(packet[offset + read_count] == ','){
876       ags_osc_buffer_util_get_string(packet + offset + read_count,
877 				     &type_tag, &type_tag_length);
878 
879       read_count += (4 * (gsize) ceil((double) (type_tag_length + 1) / 4.0));
880     }
881   }
882 
883   data_length = 0;
884 
885   if(type_tag != NULL){
886     for(i = 1; i < type_tag_length; i++){
887       switch(type_tag[i]){
888       case AGS_OSC_UTIL_TYPE_TAG_STRING_TRUE:
889       case AGS_OSC_UTIL_TYPE_TAG_STRING_FALSE:
890       case AGS_OSC_UTIL_TYPE_TAG_STRING_NIL:
891       case AGS_OSC_UTIL_TYPE_TAG_STRING_INFINITE:
892       case AGS_OSC_UTIL_TYPE_TAG_STRING_ARRAY_START:
893       case AGS_OSC_UTIL_TYPE_TAG_STRING_ARRAY_END:
894       {
895 	//empty
896       }
897       break;
898       case AGS_OSC_UTIL_TYPE_TAG_STRING_CHAR:
899       case AGS_OSC_UTIL_TYPE_TAG_STRING_INT32:
900       case AGS_OSC_UTIL_TYPE_TAG_STRING_FLOAT:
901       case AGS_OSC_UTIL_TYPE_TAG_STRING_RGBA:
902       case AGS_OSC_UTIL_TYPE_TAG_STRING_MIDI:
903       {
904 	data_length += 4;
905       }
906       break;
907       case AGS_OSC_UTIL_TYPE_TAG_STRING_INT64:
908       case AGS_OSC_UTIL_TYPE_TAG_STRING_DOUBLE:
909       case AGS_OSC_UTIL_TYPE_TAG_STRING_TIMETAG:
910       {
911 	data_length += 8;
912       }
913       break;
914       case AGS_OSC_UTIL_TYPE_TAG_STRING_SYMBOL:
915       case AGS_OSC_UTIL_TYPE_TAG_STRING_STRING:
916       {
917 	gsize length;
918 
919 	length = strlen(packet + offset + read_count + data_length);
920 
921 	data_length += (4 * (gsize) ceil((double) (length + 1) / 4.0));
922       }
923       break;
924       case AGS_OSC_UTIL_TYPE_TAG_STRING_BLOB:
925       {
926 	gint32 data_size;
927 
928 	ags_osc_buffer_util_get_int32(packet + offset + read_count + data_length,
929 				      &data_size);
930 
931 	data_length += data_size;
932       }
933       break;
934       }
935     }
936 
937     free(type_tag);
938   }
939 
940   read_count += (4 * (gsize) ceil((double) data_length / 4.0));
941 
942   osc_message = ags_osc_message_new();
943 
944   message = (guchar *) malloc(read_count * sizeof(guchar));
945   memcpy(message,
946 	 packet + offset,
947 	 read_count * sizeof(guchar));
948 
949   g_object_set(osc_message,
950 	       "osc-connection", osc_connection,
951 	       "tv-sec", tv_sec,
952 	       "tv-fraction", tv_fraction,
953 	       "immediately", immediately,
954 	       "message-size", read_count,
955 	       "message", message,
956 	       NULL);
957 
958   ags_osc_front_controller_add_message(osc_front_controller,
959 				       osc_message);
960 
961   return(read_count);
962 }
963 
964 gpointer
ags_osc_front_controller_real_do_request(AgsOscFrontController * osc_front_controller,AgsOscConnection * osc_connection,guchar * packet,gsize packet_size)965 ags_osc_front_controller_real_do_request(AgsOscFrontController *osc_front_controller,
966 					 AgsOscConnection *osc_connection,
967 					 guchar *packet, gsize packet_size)
968 {
969   gint32 tv_sec;
970   gint32 tv_fraction;
971   gboolean immediately;
972   gsize offset;
973 
974   if(packet == NULL ||
975      packet_size < 0){
976     return(NULL);
977   }
978 
979   tv_sec = 0;
980   tv_fraction = 0;
981   immediately = TRUE;
982 
983   for(offset = 4; offset < packet_size;){
984     gsize read_count;
985 
986 #ifdef AGS_DEBUG
987     g_message("%d %d", offset, packet_size);
988     g_message("%x[%c]", packet[offset], packet[offset]);
989 #endif
990 
991     read_count = 0;
992 
993     if(!g_strcmp0(packet + offset, "#bundle")){
994       read_count = ags_osc_front_controller_read_bundle(osc_front_controller,
995 							osc_connection,
996 							packet, packet_size,
997 							offset);
998     }else if(packet[offset] == '/'){
999       read_count = ags_osc_front_controller_read_message(osc_front_controller,
1000 							 osc_connection,
1001 							 packet, packet_size,
1002 							 offset,
1003 							 0, 0, TRUE);
1004     }
1005 
1006     if(read_count > 0){
1007       offset += ((gsize) 4 * ceil((double) read_count / 4.0));
1008     }else{
1009       offset += 1;
1010 
1011       g_warning("malformed data");
1012     }
1013   }
1014 
1015   return(NULL);
1016 }
1017 
1018 /**
1019  * ags_osc_front_controller_write_response:
1020  * @osc_front_controller: the #AgsOscFrontController
1021  * @osc_connection: the #AgsOscConnection
1022  * @packet: the packet received
1023  * @packet_size: the packet size
1024  *
1025  * Do request.
1026  *
1027  * Returns: %NULL
1028  *
1029  * Since: 3.0.0
1030  */
1031 gpointer
ags_osc_front_controller_do_request(AgsOscFrontController * osc_front_controller,AgsOscConnection * osc_connection,guchar * packet,gsize packet_size)1032 ags_osc_front_controller_do_request(AgsOscFrontController *osc_front_controller,
1033 				    AgsOscConnection *osc_connection,
1034 				    guchar *packet, gsize packet_size)
1035 {
1036   gpointer osc_response;
1037 
1038   g_return_val_if_fail(AGS_IS_OSC_FRONT_CONTROLLER(osc_front_controller), NULL);
1039 
1040   g_object_ref((GObject *) osc_front_controller);
1041   g_object_ref((GObject *) osc_connection);
1042   g_signal_emit(G_OBJECT(osc_front_controller),
1043 		osc_front_controller_signals[DO_REQUEST], 0,
1044 		osc_connection,
1045 		packet, (gint64) packet_size,
1046 		&osc_response);
1047   g_object_unref((GObject *) osc_connection);
1048   g_object_unref((GObject *) osc_front_controller);
1049 
1050   return(osc_response);
1051 }
1052 
1053 /**
1054  * ags_osc_front_controller_new:
1055  *
1056  * Instantiate new #AgsOscFrontController
1057  *
1058  * Returns: the #AgsOscFrontController
1059  *
1060  * Since: 3.0.0
1061  */
1062 AgsOscFrontController*
ags_osc_front_controller_new()1063 ags_osc_front_controller_new()
1064 {
1065   AgsOscFrontController *osc_front_controller;
1066 
1067   osc_front_controller = (AgsOscFrontController *) g_object_new(AGS_TYPE_OSC_FRONT_CONTROLLER,
1068 								NULL);
1069 
1070   return(osc_front_controller);
1071 }
1072