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_renew_controller.h>
21 
22 #include <ags/audio/ags_sound_provider.h>
23 #include <ags/audio/ags_audio.h>
24 #include <ags/audio/ags_channel.h>
25 #include <ags/audio/ags_output.h>
26 #include <ags/audio/ags_input.h>
27 #include <ags/audio/ags_recall.h>
28 #include <ags/audio/ags_port.h>
29 
30 #include <ags/audio/task/ags_resize_audio.h>
31 #include <ags/audio/task/ags_set_device.h>
32 #include <ags/audio/task/ags_set_audio_channels.h>
33 #include <ags/audio/task/ags_set_samplerate.h>
34 #include <ags/audio/task/ags_set_buffer_size.h>
35 #include <ags/audio/task/ags_set_format.h>
36 
37 #include <ags/audio/osc/ags_osc_response.h>
38 #include <ags/audio/osc/ags_osc_buffer_util.h>
39 
40 #include <ags/i18n.h>
41 
42 #include <stdlib.h>
43 #include <string.h>
44 #include <strings.h>
45 
46 #include <sys/types.h>
47 #include <regex.h>
48 
49 void ags_osc_renew_controller_class_init(AgsOscRenewControllerClass *osc_renew_controller);
50 void ags_osc_renew_controller_init(AgsOscRenewController *osc_renew_controller);
51 void ags_osc_renew_controller_set_property(GObject *gobject,
52 					   guint prop_id,
53 					   const GValue *value,
54 					   GParamSpec *param_spec);
55 void ags_osc_renew_controller_get_property(GObject *gobject,
56 					   guint prop_id,
57 					   GValue *value,
58 					   GParamSpec *param_spec);
59 void ags_osc_renew_controller_dispose(GObject *gobject);
60 void ags_osc_renew_controller_finalize(GObject *gobject);
61 
62 gpointer ags_osc_renew_controller_set_data_soundcard(AgsOscRenewController *osc_renew_controller,
63 						     AgsOscConnection *osc_connection,
64 						     GObject *soundcard,
65 						     unsigned char *message, guint message_size,
66 						     gchar *type_tag,
67 						     gchar *path, guint path_offset);
68 gpointer ags_osc_renew_controller_set_data_sequencer(AgsOscRenewController *osc_renew_controller,
69 						     AgsOscConnection *osc_connection,
70 						     GObject *sequencer,
71 						     unsigned char *message, guint message_size,
72 						     gchar *type_tag,
73 						     gchar *path, guint path_offset);
74 
75 gpointer ags_osc_renew_controller_set_data_audio(AgsOscRenewController *osc_renew_controller,
76 						 AgsOscConnection *osc_connection,
77 						 AgsAudio *audio,
78 						 unsigned char *message, guint message_size,
79 						 gchar *type_tag,
80 						 gchar *path, guint path_offset);
81 gpointer ags_osc_renew_controller_set_data_channel(AgsOscRenewController *osc_renew_controller,
82 						   AgsOscConnection *osc_connection,
83 						   AgsChannel *channel,
84 						   unsigned char *message, guint message_size,
85 						   gchar *type_tag,
86 						   gchar *path, guint path_offset);
87 
88 gpointer ags_osc_renew_controller_set_data_recall(AgsOscRenewController *osc_renew_controller,
89 						  AgsOscConnection *osc_connection,
90 						  AgsRecall *recall,
91 						  unsigned char *message, guint message_size,
92 						  gchar *type_tag,
93 						  gchar *path, guint path_offset);
94 
95 gpointer ags_osc_renew_controller_set_data_port(AgsOscRenewController *osc_renew_controller,
96 						AgsOscConnection *osc_connection,
97 						AgsRecall *parent,
98 						AgsPort *port,
99 						unsigned char *message, guint message_size,
100 						gchar *type_tag,
101 						gchar *path, guint path_offset);
102 
103 gpointer ags_osc_renew_controller_real_set_data(AgsOscRenewController *osc_renew_controller,
104 						AgsOscConnection *osc_connection,
105 						unsigned char *message, guint message_size);
106 
107 /**
108  * SECTION:ags_osc_renew_controller
109  * @short_description: OSC renew controller
110  * @title: AgsOscRenewController
111  * @section_id:
112  * @include: ags/audio/osc/controller/ags_osc_renew_controller.h
113  *
114  * The #AgsOscRenewController implements the OSC renew controller.
115  */
116 
117 enum{
118   PROP_0,
119 };
120 
121 enum{
122   SET_DATA,
123   LAST_SIGNAL,
124 };
125 
126 static gpointer ags_osc_renew_controller_parent_class = NULL;
127 static guint osc_renew_controller_signals[LAST_SIGNAL];
128 
129 static GMutex regex_mutex;
130 
131 GType
ags_osc_renew_controller_get_type()132 ags_osc_renew_controller_get_type()
133 {
134   static volatile gsize g_define_type_id__volatile = 0;
135 
136   if(g_once_init_enter (&g_define_type_id__volatile)){
137     GType ags_type_osc_renew_controller = 0;
138 
139     static const GTypeInfo ags_osc_renew_controller_info = {
140       sizeof (AgsOscRenewControllerClass),
141       NULL, /* base_init */
142       NULL, /* base_finalize */
143       (GClassInitFunc) ags_osc_renew_controller_class_init,
144       NULL, /* class_finalize */
145       NULL, /* class_data */
146       sizeof (AgsOscRenewController),
147       0,    /* n_preallocs */
148       (GInstanceInitFunc) ags_osc_renew_controller_init,
149     };
150 
151     ags_type_osc_renew_controller = g_type_register_static(AGS_TYPE_OSC_CONTROLLER,
152 							   "AgsOscRenewController",
153 							   &ags_osc_renew_controller_info,
154 							   0);
155 
156     g_once_init_leave(&g_define_type_id__volatile, ags_type_osc_renew_controller);
157   }
158 
159   return g_define_type_id__volatile;
160 }
161 
162 void
ags_osc_renew_controller_class_init(AgsOscRenewControllerClass * osc_renew_controller)163 ags_osc_renew_controller_class_init(AgsOscRenewControllerClass *osc_renew_controller)
164 {
165   GObjectClass *gobject;
166   GParamSpec *param_spec;
167 
168   ags_osc_renew_controller_parent_class = g_type_class_peek_parent(osc_renew_controller);
169 
170   /* GObjectClass */
171   gobject = (GObjectClass *) osc_renew_controller;
172 
173   gobject->set_property = ags_osc_renew_controller_set_property;
174   gobject->get_property = ags_osc_renew_controller_get_property;
175 
176   gobject->dispose = ags_osc_renew_controller_dispose;
177   gobject->finalize = ags_osc_renew_controller_finalize;
178 
179   /* properties */
180 
181   /* AgsOscRenewControllerClass */
182   osc_renew_controller->set_data = ags_osc_renew_controller_real_set_data;
183 
184   /* signals */
185   /**
186    * AgsOscRenewController::set-data:
187    * @osc_renew_controller: the #AgsOscRenewController
188    * @osc_connection: the #AgsOscConnection
189    * @message: the message received
190    * @message_size: the message size
191    *
192    * The ::set-data signal is emited during get data of renew controller.
193    *
194    * Returns: the #AgsOscResponse
195    *
196    * Since: 3.0.0
197    */
198   osc_renew_controller_signals[SET_DATA] =
199     g_signal_new("set-data",
200 		 G_TYPE_FROM_CLASS(osc_renew_controller),
201 		 G_SIGNAL_RUN_LAST,
202 		 G_STRUCT_OFFSET(AgsOscRenewControllerClass, set_data),
203 		 NULL, NULL,
204 		 ags_cclosure_marshal_POINTER__OBJECT_POINTER_UINT,
205 		 G_TYPE_POINTER, 3,
206 		 G_TYPE_OBJECT,
207 		 G_TYPE_POINTER,
208 		 G_TYPE_UINT);
209 }
210 
211 void
ags_osc_renew_controller_init(AgsOscRenewController * osc_renew_controller)212 ags_osc_renew_controller_init(AgsOscRenewController *osc_renew_controller)
213 {
214   g_object_set(osc_renew_controller,
215 	       "context-path", "/renew",
216 	       NULL);
217 }
218 
219 void
ags_osc_renew_controller_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)220 ags_osc_renew_controller_set_property(GObject *gobject,
221 				      guint prop_id,
222 				      const GValue *value,
223 				      GParamSpec *param_spec)
224 {
225   AgsOscRenewController *osc_renew_controller;
226 
227   GRecMutex *osc_controller_mutex;
228 
229   osc_renew_controller = AGS_OSC_RENEW_CONTROLLER(gobject);
230 
231   /* get osc controller mutex */
232   osc_controller_mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(osc_renew_controller);
233 
234   switch(prop_id){
235   default:
236     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
237     break;
238   }
239 }
240 
241 void
ags_osc_renew_controller_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)242 ags_osc_renew_controller_get_property(GObject *gobject,
243 				      guint prop_id,
244 				      GValue *value,
245 				      GParamSpec *param_spec)
246 {
247   AgsOscRenewController *osc_renew_controller;
248 
249   GRecMutex *osc_controller_mutex;
250 
251   osc_renew_controller = AGS_OSC_RENEW_CONTROLLER(gobject);
252 
253   /* get osc controller mutex */
254   osc_controller_mutex = AGS_OSC_CONTROLLER_GET_OBJ_MUTEX(osc_renew_controller);
255 
256   switch(prop_id){
257   default:
258     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
259     break;
260   }
261 }
262 
263 void
ags_osc_renew_controller_dispose(GObject * gobject)264 ags_osc_renew_controller_dispose(GObject *gobject)
265 {
266   AgsOscRenewController *osc_renew_controller;
267 
268   osc_renew_controller = AGS_OSC_RENEW_CONTROLLER(gobject);
269 
270   /* call parent */
271   G_OBJECT_CLASS(ags_osc_renew_controller_parent_class)->dispose(gobject);
272 }
273 
274 void
ags_osc_renew_controller_finalize(GObject * gobject)275 ags_osc_renew_controller_finalize(GObject *gobject)
276 {
277   AgsOscRenewController *osc_renew_controller;
278 
279   osc_renew_controller = AGS_OSC_RENEW_CONTROLLER(gobject);
280 
281   /* call parent */
282   G_OBJECT_CLASS(ags_osc_renew_controller_parent_class)->finalize(gobject);
283 }
284 
285 gpointer
ags_osc_renew_controller_set_data_soundcard(AgsOscRenewController * osc_renew_controller,AgsOscConnection * osc_connection,GObject * soundcard,unsigned char * message,guint message_size,gchar * type_tag,gchar * path,guint path_offset)286 ags_osc_renew_controller_set_data_soundcard(AgsOscRenewController *osc_renew_controller,
287 					    AgsOscConnection *osc_connection,
288 					    GObject *soundcard,
289 					    unsigned char *message, guint message_size,
290 					    gchar *type_tag,
291 					    gchar *path, guint path_offset)
292 {
293   AgsOscResponse *osc_response;
294 
295   AgsTaskLauncher *task_launcher;
296 
297   AgsApplicationContext *application_context;
298 
299   GList *start_response;
300 
301   unsigned char *packet;
302 
303   guint type_tag_length;
304   guint path_length;
305   guint real_packet_size;
306   guint packet_size;
307 
308   if(!AGS_IS_SOUNDCARD(soundcard)){
309     return(NULL);
310   }
311 
312   start_response = NULL;
313 
314   application_context = ags_application_context_get_instance();
315 
316   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));
317 
318   real_packet_size = 0;
319   packet_size = 0;
320 
321   if(!strncmp(path + path_offset,
322 	      ":",
323 	      1)){
324     osc_response = ags_osc_response_new();
325     start_response = g_list_prepend(start_response,
326 				    osc_response);
327 
328     packet = (unsigned char *) malloc(AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
329     memset(packet, 0, AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
330 
331     g_object_set(osc_response,
332 		 "packet", packet,
333 		 "packet-size", packet_size,
334 		 NULL);
335 
336     real_packet_size = AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE;
337 
338     type_tag_length = 4 * (guint) ceil((double) (strlen(type_tag) + 1) / 4.0);
339 
340     path_length = 4 * (guint) ceil((double) (strlen(path) + 1) / 4.0);
341     path_offset += 1;
342 
343     if(!strncmp(path + path_offset,
344 		"device",
345 		7)){
346       AgsSetDevice *set_device;
347 
348       gchar *device;
349 
350       gboolean success;
351 
352       success = (!strncmp(type_tag + 2, "s", 2)) ? TRUE: FALSE;
353 
354       if(!success ||
355 	 message_size < 16 + path_length){
356 	ags_osc_response_set_flags(osc_response,
357 				   AGS_OSC_RESPONSE_ERROR);
358 
359 	g_object_set(osc_response,
360 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
361 		     NULL);
362 
363 	g_object_unref(task_launcher);
364 
365 	return(start_response);
366       }
367 
368       /* read device */
369       ags_osc_buffer_util_get_string(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
370 				     &device, NULL);
371 
372       set_device = ags_set_device_new(soundcard,
373 				      device);
374       ags_task_launcher_add_task(task_launcher,
375 				  (AgsTask *) set_device);
376 
377       if(device != NULL){
378 	free(device);
379       }
380     }else if(!strncmp(path + path_offset,
381 		      "pcm-channels",
382 		      13)){
383       AgsSetAudioChannels *set_audio_channels;
384 
385       guint pcm_channels;
386       gboolean success;
387 
388       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
389 
390       if(!success ||
391 	 message_size < 16 + path_length + 4){
392 	ags_osc_response_set_flags(osc_response,
393 				   AGS_OSC_RESPONSE_ERROR);
394 
395 	g_object_set(osc_response,
396 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
397 		     NULL);
398 
399 	g_object_unref(task_launcher);
400 
401 	return(start_response);
402       }
403 
404       /* read pcm channels */
405       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
406 				    &pcm_channels);
407 
408       set_audio_channels = ags_set_audio_channels_new(soundcard,
409 						      pcm_channels);
410       ags_task_launcher_add_task(task_launcher,
411 				  (AgsTask *) set_audio_channels);
412     }else if(!strncmp(path + path_offset,
413 		      "samplerate",
414 		      11)){
415       AgsSetSamplerate *set_samplerate;
416 
417       guint samplerate;
418       gboolean success;
419 
420       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
421 
422       if(!success ||
423 	 message_size < 16 + path_length + 4){
424 	ags_osc_response_set_flags(osc_response,
425 				   AGS_OSC_RESPONSE_ERROR);
426 
427 	g_object_set(osc_response,
428 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
429 		     NULL);
430 
431 	g_object_unref(task_launcher);
432 
433 	return(start_response);
434       }
435 
436       /* read samplerate */
437       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
438 				    &samplerate);
439 
440       set_samplerate = ags_set_samplerate_new(soundcard,
441 					      samplerate);
442       ags_task_launcher_add_task(task_launcher,
443 				  (AgsTask *) set_samplerate);
444     }else if(!strncmp(path + path_offset,
445 		      "buffer-size",
446 		      12)){
447       AgsSetBufferSize *set_buffer_size;
448 
449       guint buffer_size;
450       gboolean success;
451 
452       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
453 
454       if(!success ||
455 	 message_size < 16 + path_length + 4){
456 	ags_osc_response_set_flags(osc_response,
457 				   AGS_OSC_RESPONSE_ERROR);
458 
459 	g_object_set(osc_response,
460 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
461 		     NULL);
462 
463 	g_object_unref(task_launcher);
464 
465 	return(start_response);
466       }
467 
468       /* read buffer size */
469       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
470 				    &buffer_size);
471 
472       set_buffer_size = ags_set_buffer_size_new(soundcard,
473 						buffer_size);
474       ags_task_launcher_add_task(task_launcher,
475 				  (AgsTask *) set_buffer_size);
476     }else if(!strncmp(path + path_offset,
477 		      "format",
478 		      7)){
479       AgsSetFormat *set_format;
480 
481       guint format;
482       gboolean success;
483 
484       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
485 
486       if(!success ||
487 	 message_size < 16 + path_length + 4){
488 	ags_osc_response_set_flags(osc_response,
489 				   AGS_OSC_RESPONSE_ERROR);
490 
491 	g_object_set(osc_response,
492 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
493 		     NULL);
494 
495 	g_object_unref(task_launcher);
496 
497 	return(start_response);
498       }
499 
500       /* read format */
501       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
502 				    &format);
503 
504       set_format = ags_set_format_new(soundcard,
505 				      format);
506       ags_task_launcher_add_task(task_launcher,
507 				  (AgsTask *) set_format);
508     }else{
509       ags_osc_response_set_flags(osc_response,
510 				 AGS_OSC_RESPONSE_ERROR);
511 
512       g_object_set(osc_response,
513 		   "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_UNKNOWN_ARGUMENT,
514 		   NULL);
515 
516       g_object_unref(task_launcher);
517 
518       return(start_response);
519     }
520 
521     g_object_set(osc_response,
522 		 "packet-size", packet_size,
523 		 NULL);
524   }else{
525     osc_response = ags_osc_response_new();
526     start_response = g_list_prepend(start_response,
527 				    osc_response);
528 
529     ags_osc_response_set_flags(osc_response,
530 			       AGS_OSC_RESPONSE_ERROR);
531 
532     g_object_set(osc_response,
533 		 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_UNKNOWN_PATH,
534 		 NULL);
535 
536     g_object_unref(task_launcher);
537 
538     return(start_response);
539   }
540 
541   g_object_unref(task_launcher);
542 
543   return(start_response);
544 }
545 
546 gpointer
ags_osc_renew_controller_set_data_sequencer(AgsOscRenewController * osc_renew_controller,AgsOscConnection * osc_connection,GObject * sequencer,unsigned char * message,guint message_size,gchar * type_tag,gchar * path,guint path_offset)547 ags_osc_renew_controller_set_data_sequencer(AgsOscRenewController *osc_renew_controller,
548 					    AgsOscConnection *osc_connection,
549 					    GObject *sequencer,
550 					    unsigned char *message, guint message_size,
551 					    gchar *type_tag,
552 					    gchar *path, guint path_offset)
553 {
554   AgsOscResponse *osc_response;
555 
556   AgsTaskLauncher *task_launcher;
557 
558   AgsApplicationContext *application_context;
559 
560   GList *start_response;
561 
562   unsigned char *packet;
563 
564   guint type_tag_length;
565   guint path_length;
566   guint real_packet_size;
567   guint packet_size;
568 
569   if(!AGS_IS_SEQUENCER(sequencer)){
570     return(NULL);
571   }
572 
573   start_response = NULL;
574 
575   application_context = ags_application_context_get_instance();
576 
577   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));
578 
579   real_packet_size = 0;
580   packet_size = 0;
581 
582   if(!strncmp(path + path_offset,
583 	      ":",
584 	      1)){
585     osc_response = ags_osc_response_new();
586     start_response = g_list_prepend(start_response,
587 				    osc_response);
588 
589     packet = (unsigned char *) malloc(AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
590     memset(packet, 0, AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
591 
592     g_object_set(osc_response,
593 		 "packet", packet,
594 		 "packet-size", packet_size,
595 		 NULL);
596 
597     real_packet_size = AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE;
598 
599     type_tag_length = 4 * (guint) ceil((double) (strlen(type_tag) + 1) / 4.0);
600 
601     path_length = 4 * (guint) ceil((double) (strlen(path) + 1) / 4.0);
602     path_offset += 1;
603 
604     if(!strncmp(path + path_offset,
605 		"device",
606 		12)){
607       AgsSetDevice *set_device;
608 
609       gchar *device;
610 
611       gboolean success;
612 
613       success = (!strncmp(type_tag + 2, "s", 2)) ? TRUE: FALSE;
614 
615       if(!success ||
616 	 message_size < 16 + path_length){
617 	ags_osc_response_set_flags(osc_response,
618 				   AGS_OSC_RESPONSE_ERROR);
619 
620 	g_object_set(osc_response,
621 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
622 		     NULL);
623 
624 	g_object_unref(task_launcher);
625 
626 	return(start_response);
627       }
628 
629       /* read device */
630       ags_osc_buffer_util_get_string(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
631 				     &device, NULL);
632 
633       set_device = ags_set_device_new(sequencer,
634 				      device);
635       ags_task_launcher_add_task(task_launcher,
636 				  (AgsTask *) set_device);
637 
638       if(device != NULL){
639 	free(device);
640       }
641     }else{
642       ags_osc_response_set_flags(osc_response,
643 				 AGS_OSC_RESPONSE_ERROR);
644 
645       g_object_set(osc_response,
646 		   "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_UNKNOWN_ARGUMENT,
647 		   NULL);
648 
649       g_object_unref(task_launcher);
650 
651       return(start_response);
652     }
653 
654     g_object_set(osc_response,
655 		 "packet-size", packet_size,
656 		 NULL);
657   }else{
658     osc_response = ags_osc_response_new();
659     start_response = g_list_prepend(start_response,
660 				    osc_response);
661 
662     ags_osc_response_set_flags(osc_response,
663 			       AGS_OSC_RESPONSE_ERROR);
664 
665     g_object_set(osc_response,
666 		 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_UNKNOWN_PATH,
667 		 NULL);
668 
669     g_object_unref(task_launcher);
670 
671     return(start_response);
672   }
673 
674   g_object_unref(task_launcher);
675 
676   return(start_response);
677 }
678 
679 gpointer
ags_osc_renew_controller_set_data_audio(AgsOscRenewController * osc_renew_controller,AgsOscConnection * osc_connection,AgsAudio * audio,unsigned char * message,guint message_size,gchar * type_tag,gchar * path,guint path_offset)680 ags_osc_renew_controller_set_data_audio(AgsOscRenewController *osc_renew_controller,
681 					AgsOscConnection *osc_connection,
682 					AgsAudio *audio,
683 					unsigned char *message, guint message_size,
684 					gchar *type_tag,
685 					gchar *path, guint path_offset)
686 {
687   AgsOscResponse *osc_response;
688 
689   AgsTaskLauncher *task_launcher;
690 
691   AgsApplicationContext *application_context;
692 
693   GList *start_response;
694 
695   unsigned char *packet;
696 
697   guint type_tag_length;
698   guint path_length;
699   guint real_packet_size;
700   guint packet_size;
701 
702   if(!AGS_IS_AUDIO(audio)){
703     return(NULL);
704   }
705 
706   start_response = NULL;
707 
708   application_context = ags_application_context_get_instance();
709 
710   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));
711 
712   real_packet_size = 0;
713   packet_size = 0;
714 
715   if(!strncmp(path + path_offset,
716 	      ":",
717 	      1)){
718     guint length;
719 
720     osc_response = ags_osc_response_new();
721     start_response = g_list_prepend(start_response,
722 				    osc_response);
723 
724     packet = (unsigned char *) malloc(AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
725     memset(packet, 0, AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
726 
727     g_object_set(osc_response,
728 		 "packet", packet,
729 		 "packet-size", packet_size,
730 		 NULL);
731 
732     real_packet_size = AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE;
733 
734     type_tag_length = 4 * (guint) ceil((double) (strlen(type_tag) + 1) / 4.0);
735 
736     path_length = 4 * (guint) ceil((double) (strlen(path) + 1) / 4.0);
737     path_offset += 1;
738 
739     /* properties */
740     if(!strncmp(path + path_offset,
741 		"audio-channels",
742 		15)){
743       AgsResizeAudio *resize_audio;
744 
745       guint output_pads, input_pads;
746       guint audio_channels;
747       gboolean success;
748 
749       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
750 
751       if(!success ||
752 	 message_size < 16 + path_length + 4){
753 	ags_osc_response_set_flags(osc_response,
754 				   AGS_OSC_RESPONSE_ERROR);
755 
756 	g_object_set(osc_response,
757 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
758 		     NULL);
759 
760 	g_object_unref(task_launcher);
761 
762 	return(start_response);
763       }
764 
765       /* read audio channels */
766       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
767 				    &audio_channels);
768 
769       g_object_get(audio,
770 		   "output-pads", &output_pads,
771 		   "input-pads", &input_pads,
772 		   NULL);
773 
774       resize_audio = ags_resize_audio_new(audio,
775 					  output_pads, input_pads,
776 					  audio_channels);
777       ags_task_launcher_add_task(task_launcher,
778 				  (AgsTask *) resize_audio);
779     }else if(!strncmp(path + path_offset,
780 		      "output-pads",
781 		      12)){
782       AgsResizeAudio *resize_audio;
783 
784       guint output_pads, input_pads;
785       guint audio_channels;
786       gboolean success;
787 
788       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
789 
790       if(!success ||
791 	 message_size < 16 + path_length + 4){
792 	ags_osc_response_set_flags(osc_response,
793 				   AGS_OSC_RESPONSE_ERROR);
794 
795 	g_object_set(osc_response,
796 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
797 		     NULL);
798 
799 	g_object_unref(task_launcher);
800 
801 	return(start_response);
802       }
803 
804       /* read output pads */
805       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
806 				    &output_pads);
807 
808       g_object_get(audio,
809 		   "input-pads", &input_pads,
810 		   "audio-channels", &audio_channels,
811 		   NULL);
812 
813       resize_audio = ags_resize_audio_new(audio,
814 					  output_pads, input_pads,
815 					  audio_channels);
816       ags_task_launcher_add_task(task_launcher,
817 				  (AgsTask *) resize_audio);
818     }else if(!strncmp(path + path_offset,
819 		      "input-pads",
820 		      11)){
821       AgsResizeAudio *resize_audio;
822 
823       guint output_pads, input_pads;
824       guint audio_channels;
825       gboolean success;
826 
827       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
828 
829       if(!success ||
830 	 message_size < 16 + path_length + 4){
831 	ags_osc_response_set_flags(osc_response,
832 				   AGS_OSC_RESPONSE_ERROR);
833 
834 	g_object_set(osc_response,
835 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
836 		     NULL);
837 
838 	g_object_unref(task_launcher);
839 
840 	return(start_response);
841       }
842 
843       /* read input pads */
844       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
845 				    &input_pads);
846 
847       g_object_get(audio,
848 		   "output-pads", &output_pads,
849 		   "audio-channels", &audio_channels,
850 		   NULL);
851 
852       resize_audio = ags_resize_audio_new(audio,
853 					  output_pads, input_pads,
854 					  audio_channels);
855       ags_task_launcher_add_task(task_launcher,
856 				  (AgsTask *) resize_audio);
857     }else if(!strncmp(path + path_offset,
858 		      "samplerate",
859 		      11)){
860       AgsSetSamplerate *set_samplerate;
861 
862       guint samplerate;
863       gboolean success;
864 
865       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
866 
867       if(!success ||
868 	 message_size < 16 + path_length + 4){
869 	ags_osc_response_set_flags(osc_response,
870 				   AGS_OSC_RESPONSE_ERROR);
871 
872 	g_object_set(osc_response,
873 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
874 		     NULL);
875 
876 	g_object_unref(task_launcher);
877 
878 	return(start_response);
879       }
880 
881       /* read samplerate */
882       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
883 				    &samplerate);
884 
885       set_samplerate = ags_set_samplerate_new((GObject *) audio,
886 					      samplerate);
887       ags_task_launcher_add_task(task_launcher,
888 				  (AgsTask *) set_samplerate);
889     }else if(!strncmp(path + path_offset,
890 		      "buffer-size",
891 		      12)){
892       AgsSetBufferSize *set_buffer_size;
893 
894       guint buffer_size;
895       gboolean success;
896 
897       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
898 
899       if(!success ||
900 	 message_size < 16 + path_length + 4){
901 	ags_osc_response_set_flags(osc_response,
902 				   AGS_OSC_RESPONSE_ERROR);
903 
904 	g_object_set(osc_response,
905 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
906 		     NULL);
907 
908 	g_object_unref(task_launcher);
909 
910 	return(start_response);
911       }
912 
913       /* read buffer size */
914       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
915 				    &buffer_size);
916 
917       set_buffer_size = ags_set_buffer_size_new((GObject *) audio,
918 						buffer_size);
919       ags_task_launcher_add_task(task_launcher,
920 				  (AgsTask *) set_buffer_size);
921     }else if(!strncmp(path + path_offset,
922 		      "format",
923 		      7)){
924       AgsSetFormat *set_format;
925 
926       guint format;
927       gboolean success;
928 
929       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
930 
931       if(!success ||
932 	 message_size < 16 + path_length + 4){
933 	ags_osc_response_set_flags(osc_response,
934 				   AGS_OSC_RESPONSE_ERROR);
935 
936 	g_object_set(osc_response,
937 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
938 		     NULL);
939 
940 	g_object_unref(task_launcher);
941 
942 	return(start_response);
943       }
944 
945       /* read format */
946       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
947 				    &format);
948 
949       set_format = ags_set_format_new((GObject *) audio,
950 				      format);
951       ags_task_launcher_add_task(task_launcher,
952 				  (AgsTask *) set_format);
953     }else{
954       ags_osc_response_set_flags(osc_response,
955 				 AGS_OSC_RESPONSE_ERROR);
956 
957       g_object_set(osc_response,
958 		   "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_UNKNOWN_ARGUMENT,
959 		   NULL);
960 
961       g_object_unref(task_launcher);
962 
963       return(start_response);
964     }
965 
966     g_object_set(osc_response,
967 		 "packet-size", packet_size,
968 		 NULL);
969   }else if(!strncmp(path + path_offset,
970 		    "/AgsOutput",
971 		    10) ||
972 	   !strncmp(path + path_offset,
973 		    "/AgsInput",
974 		    9)){
975     AgsChannel *start_channel;
976     AgsChannel *channel, *next_channel;
977 
978     regmatch_t match_arr[2];
979 
980     static regex_t single_access_regex;
981     static regex_t range_access_regex;
982     static regex_t voluntary_access_regex;
983     static regex_t more_access_regex;
984     static regex_t wildcard_access_regex;
985 
986     static gboolean regex_compiled = FALSE;
987 
988     static const gchar *single_access_pattern = "^\\[([0-9]+)\\]";
989     static const gchar *range_access_pattern = "^\\[([0-9]+)\\-([0-9]+)\\]";
990     static const gchar *voluntary_access_pattern = "^\\[(\\?)\\]";
991     static const gchar *more_access_pattern = "^\\[(\\+)\\]";
992     static const gchar *wildcard_access_pattern = "^\\[(\\*)\\]";
993 
994     static const size_t max_matches = 2;
995     static const size_t index_max_matches = 1;
996 
997     start_channel = NULL;
998 
999     if(!strncmp(path + path_offset,
1000 		"/AgsOutput",
1001 		10)){
1002       path_offset += 10;
1003 
1004       g_object_get(audio,
1005 		   "output", &start_channel,
1006 		   NULL);
1007     }else{
1008       path_offset += 9;
1009 
1010       g_object_get(audio,
1011 		   "input", &start_channel,
1012 		   NULL);
1013     }
1014 
1015     /* compile regex */
1016     g_mutex_lock(&regex_mutex);
1017 
1018     if(!regex_compiled){
1019       regex_compiled = TRUE;
1020 
1021       ags_regcomp(&single_access_regex, single_access_pattern, REG_EXTENDED);
1022       ags_regcomp(&range_access_regex, range_access_pattern, REG_EXTENDED);
1023       ags_regcomp(&voluntary_access_regex, voluntary_access_pattern, REG_EXTENDED);
1024       ags_regcomp(&more_access_regex, more_access_pattern, REG_EXTENDED);
1025       ags_regcomp(&wildcard_access_regex, wildcard_access_pattern, REG_EXTENDED);
1026     }
1027 
1028     g_mutex_unlock(&regex_mutex);
1029 
1030     if(ags_regexec(&single_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
1031       gchar *endptr;
1032 
1033       guint i_stop;
1034 
1035       endptr = NULL;
1036       i_stop = g_ascii_strtoull(path + path_offset + 1,
1037 				&endptr,
1038 				10);
1039 
1040       channel = ags_channel_nth(start_channel,
1041 				i_stop);
1042 
1043       path_offset += ((endptr + 1) - (path + path_offset));
1044 
1045       start_response = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
1046 								 osc_connection,
1047 								 channel,
1048 								 message, message_size,
1049 								 type_tag,
1050 								 path, path_offset);
1051 
1052       if(start_channel != NULL){
1053 	g_object_unref(start_channel);
1054       }
1055 
1056       if(channel != NULL){
1057 	g_object_unref(channel);
1058       }
1059     }else if(ags_regexec(&range_access_regex, path + path_offset, max_matches, match_arr, 0) == 0){
1060       gchar *endptr;
1061 
1062       guint i;
1063       guint i_start, i_stop;
1064 
1065       endptr = NULL;
1066       i_start = g_ascii_strtoull(path + path_offset + 1,
1067 				 &endptr,
1068 				 10);
1069 
1070       i_stop = g_ascii_strtoull(endptr + 1,
1071 				&endptr,
1072 				10);
1073 
1074       path_offset += ((endptr + 1) - (path + path_offset));
1075 
1076       channel = ags_channel_nth(start_channel,
1077 				i_start);
1078 
1079       next_channel = NULL;
1080 
1081       for(i = i_start; i <= i_stop && channel != NULL; i++){
1082 	GList *retval;
1083 
1084 	retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
1085 							   osc_connection,
1086 							   channel,
1087 							   message, message_size,
1088 							   type_tag,
1089 							   path, path_offset);
1090 
1091 	if(start_response != NULL){
1092 	  start_response = g_list_concat(start_response,
1093 					 retval);
1094 	}else{
1095 	  start_response = retval;
1096 	}
1097 
1098 	/* iterate */
1099 	next_channel = ags_channel_next(channel);
1100 
1101 	g_object_unref(channel);
1102 
1103 	channel = next_channel;
1104       }
1105 
1106       if(start_channel != NULL){
1107 	g_object_unref(start_channel);
1108       }
1109 
1110       if(next_channel != NULL){
1111 	g_object_unref(next_channel);
1112       }
1113     }else if(ags_regexec(&voluntary_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
1114       path_offset += 3;
1115 
1116       if(start_channel != NULL){
1117 	GList *retval;
1118 
1119 	retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
1120 							   osc_connection,
1121 							   start_channel,
1122 							   message, message_size,
1123 							   type_tag,
1124 							   path, path_offset);
1125 
1126 	g_object_unref(start_channel);
1127       }else{
1128 	osc_response = ags_osc_response_new();
1129 	start_response = g_list_prepend(start_response,
1130 					osc_response);
1131 
1132 	ags_osc_response_set_flags(osc_response,
1133 				   AGS_OSC_RESPONSE_OK);
1134 
1135 	g_object_unref(task_launcher);
1136 
1137 	return(start_response);
1138       }
1139     }else if(ags_regexec(&more_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
1140       path_offset += 3;
1141 
1142       if(start_channel == NULL){
1143 	osc_response = ags_osc_response_new();
1144 	start_response = g_list_prepend(start_response,
1145 					osc_response);
1146 
1147 	ags_osc_response_set_flags(osc_response,
1148 				   AGS_OSC_RESPONSE_ERROR);
1149 
1150 	g_object_set(osc_response,
1151 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
1152 		     NULL);
1153 
1154 	g_object_unref(task_launcher);
1155 
1156 	return(start_response);
1157       }
1158 
1159       /* prepare */
1160       channel = start_channel;
1161       g_object_ref(channel);
1162 
1163       next_channel = NULL;
1164 
1165       while(channel != NULL){
1166 	GList *retval;
1167 
1168 	retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
1169 							   osc_connection,
1170 							   channel,
1171 							   message, message_size,
1172 							   type_tag,
1173 							   path, path_offset);
1174 
1175 	if(start_response != NULL){
1176 	  start_response = g_list_concat(start_response,
1177 					 retval);
1178 	}else{
1179 	  start_response = retval;
1180 	}
1181 
1182 	/* iterate */
1183 	next_channel = ags_channel_next(channel);
1184 
1185 	g_object_unref(channel);
1186 
1187 	channel = next_channel;
1188       }
1189 
1190       /* unref */
1191       if(start_channel != NULL){
1192 	g_object_unref(start_channel);
1193       }
1194 
1195       if(next_channel != NULL){
1196 	g_object_unref(next_channel);
1197       }
1198     }else if(ags_regexec(&wildcard_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
1199       path_offset += 3;
1200 
1201       if(start_channel == NULL){
1202 	osc_response = ags_osc_response_new();
1203 	start_response = g_list_prepend(start_response,
1204 					osc_response);
1205 
1206 	ags_osc_response_set_flags(osc_response,
1207 				   AGS_OSC_RESPONSE_OK);
1208 
1209 	g_object_unref(task_launcher);
1210 
1211 	return(start_response);
1212       }
1213 
1214       /* prepare */
1215       channel = start_channel;
1216       g_object_ref(channel);
1217 
1218       next_channel = NULL;
1219 
1220       while(channel != NULL){
1221 	GList *retval;
1222 
1223 	retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
1224 							   osc_connection,
1225 							   channel,
1226 							   message, message_size,
1227 							   type_tag,
1228 							   path, path_offset);
1229 
1230 	if(start_response != NULL){
1231 	  start_response = g_list_concat(start_response,
1232 					 retval);
1233 	}else{
1234 	  start_response = retval;
1235 	}
1236 
1237 	/* iterate */
1238 	next_channel = ags_channel_next(channel);
1239 
1240 	g_object_unref(channel);
1241 
1242 	channel = next_channel;
1243       }
1244 
1245       /* unref */
1246       if(start_channel != NULL){
1247 	g_object_unref(start_channel);
1248       }
1249 
1250       if(next_channel != NULL){
1251 	g_object_unref(next_channel);
1252       }
1253     }else{
1254       osc_response = ags_osc_response_new();
1255       start_response = g_list_prepend(start_response,
1256 				      osc_response);
1257 
1258       ags_osc_response_set_flags(osc_response,
1259 				 AGS_OSC_RESPONSE_ERROR);
1260 
1261       g_object_set(osc_response,
1262 		   "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
1263 		   NULL);
1264 
1265       /* unref */
1266       g_object_unref(task_launcher);
1267 
1268       if(start_channel != NULL){
1269 	g_object_unref(start_channel);
1270       }
1271 
1272       return(start_response);
1273     }
1274   }else{
1275     GType recall_type;
1276 
1277     GList *start_play, *play;
1278     GList *start_recall, *recall;
1279 
1280     regmatch_t match_arr[3];
1281 
1282     gchar *type_name;
1283     gchar *str;
1284 
1285     guint type_name_length;
1286     guint str_length;
1287 
1288     static regex_t recall_regex;
1289     static regex_t single_access_regex;
1290     static regex_t range_access_regex;
1291     static regex_t voluntary_access_regex;
1292     static regex_t more_access_regex;
1293     static regex_t wildcard_access_regex;
1294 
1295     static gboolean regex_compiled = FALSE;
1296 
1297     static const gchar *recall_pattern = "^\\/([a-zA-Z]+)(\\/|\\[[0-9]+\\]|\\[[0-9]+\\-[0-9]+\\]|\\[\\?\\]|\\[\\+\\]|\\[\\*\\]|:)";
1298     static const gchar *single_access_pattern = "^\\[([0-9]+)\\]";
1299     static const gchar *range_access_pattern = "^\\[([0-9]+)\\-([0-9]+)\\]";
1300     static const gchar *voluntary_access_pattern = "^\\[(\\?)\\]";
1301     static const gchar *more_access_pattern = "^\\[(\\+)\\]";
1302     static const gchar *wildcard_access_pattern = "^\\[(\\*)\\]";
1303 
1304     static const size_t max_matches = 3;
1305     static const size_t index_max_matches = 2;
1306 
1307     /* compile regex */
1308     g_mutex_lock(&regex_mutex);
1309 
1310     if(!regex_compiled){
1311       regex_compiled = TRUE;
1312 
1313       ags_regcomp(&recall_regex, recall_pattern, REG_EXTENDED);
1314 
1315       ags_regcomp(&single_access_regex, single_access_pattern, REG_EXTENDED);
1316       ags_regcomp(&range_access_regex, range_access_pattern, REG_EXTENDED);
1317       ags_regcomp(&voluntary_access_regex, voluntary_access_pattern, REG_EXTENDED);
1318       ags_regcomp(&more_access_regex, more_access_pattern, REG_EXTENDED);
1319       ags_regcomp(&wildcard_access_regex, wildcard_access_pattern, REG_EXTENDED);
1320     }
1321 
1322     g_mutex_unlock(&regex_mutex);
1323 
1324     if(ags_regexec(&recall_regex, path + path_offset, max_matches, match_arr, 0) == 0){
1325       type_name_length = match_arr[1].rm_eo - match_arr[1].rm_so;
1326       type_name = g_strndup(path + path_offset + 1,
1327 			    type_name_length);
1328 
1329       str_length = match_arr[2].rm_eo - match_arr[2].rm_so;
1330       str = g_strndup(path + path_offset + 1 + type_name_length,
1331 		      str_length);
1332     }else{
1333       osc_response = ags_osc_response_new();
1334       start_response = g_list_prepend(start_response,
1335 				      osc_response);
1336 
1337       ags_osc_response_set_flags(osc_response,
1338 				 AGS_OSC_RESPONSE_ERROR);
1339 
1340       g_object_set(osc_response,
1341 		   "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_UNKNOWN_PATH,
1342 		   NULL);
1343 
1344       g_object_unref(task_launcher);
1345 
1346       return(start_response);
1347     }
1348 
1349     recall_type = g_type_from_name(type_name);
1350 
1351     g_object_get(audio,
1352 		 "play", &start_play,
1353 		 "recall", &start_recall,
1354 		 NULL);
1355 
1356     if(ags_regexec(&single_access_regex, str, index_max_matches, match_arr, 0) == 0){
1357       guint i;
1358       guint i_stop;
1359 
1360       path_offset += (type_name_length + 1) + str_length;
1361 
1362       i_stop = g_ascii_strtoull(str + 1,
1363 				NULL,
1364 				10);
1365 
1366       play = start_play;
1367       recall = start_recall;
1368 
1369       for(i = 0; i <= i_stop; i++){
1370 	play = ags_recall_template_find_type(play, recall_type);
1371 	recall = ags_recall_template_find_type(recall, recall_type);
1372 
1373 	if(i + 1 < i_stop){
1374 	  if(play != NULL){
1375 	    play = play->next;
1376 	  }
1377 
1378 	  if(recall != NULL){
1379 	    recall = recall->next;
1380 	  }
1381 	}
1382       }
1383 
1384       if(play != NULL){
1385 	AgsRecall *current;
1386 
1387 	GList *retval;
1388 
1389 	current = play->data;
1390 	retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1391 							  osc_connection,
1392 							  current,
1393 							  message, message_size,
1394 							  type_tag,
1395 							  path, path_offset);
1396 
1397 	if(start_response != NULL){
1398 	  start_response = g_list_concat(start_response,
1399 					 retval);
1400 	}else{
1401 	  start_response = retval;
1402 	}
1403       }
1404 
1405       if(recall != NULL){
1406 	AgsRecall *current;
1407 
1408 	GList *retval;
1409 
1410 	current = recall->data;
1411 	retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1412 							  osc_connection,
1413 							  current,
1414 							  message, message_size,
1415 							  type_tag,
1416 							  path, path_offset);
1417 
1418 	if(start_response != NULL){
1419 	  start_response = g_list_concat(start_response,
1420 					 retval);
1421 	}else{
1422 	  start_response = retval;
1423 	}
1424       }
1425     }else if(ags_regexec(&range_access_regex, str, max_matches, match_arr, 0) == 0){
1426       gchar *endptr;
1427 
1428       guint i;
1429       guint i_start, i_stop;
1430 
1431       path_offset += (type_name_length + 1) + str_length;
1432 
1433       endptr = NULL;
1434       i_start = g_ascii_strtoull(str + 1,
1435 				 &endptr,
1436 				 10);
1437 
1438       i_stop = g_ascii_strtoull(endptr + 1,
1439 				NULL,
1440 				10);
1441 
1442       play = start_play;
1443       recall = start_recall;
1444 
1445       for(i = 0; i <= i_stop; i++){
1446 	play = ags_recall_template_find_type(play, recall_type);
1447 	recall = ags_recall_template_find_type(recall, recall_type);
1448 
1449 	if(i >= i_start){
1450 	  if(play != NULL){
1451 	    AgsRecall *current;
1452 
1453 	    GList *retval;
1454 
1455 	    current = play->data;
1456 	    retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1457 							      osc_connection,
1458 							      current,
1459 							      message, message_size,
1460 							      type_tag,
1461 							      path, path_offset);
1462 
1463 	    if(start_response != NULL){
1464 	      start_response = g_list_concat(start_response,
1465 					     retval);
1466 	    }else{
1467 	      start_response = retval;
1468 	    }
1469 	  }
1470 
1471 	  if(recall != NULL){
1472 	    AgsRecall *current;
1473 
1474 	    GList *retval;
1475 
1476 	    current = recall->data;
1477 	    retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1478 							      osc_connection,
1479 							      current,
1480 							      message, message_size,
1481 							      type_tag,
1482 							      path, path_offset);
1483 
1484 	    if(start_response != NULL){
1485 	      start_response = g_list_concat(start_response,
1486 					     retval);
1487 	    }else{
1488 	      start_response = retval;
1489 	    }
1490 	  }
1491 	}
1492 
1493 	if(i + 1 < i_stop){
1494 	  if(play != NULL){
1495 	    play = play->next;
1496 	  }
1497 
1498 	  if(recall != NULL){
1499 	    recall = recall->next;
1500 	  }
1501 	}
1502       }
1503     }else if(ags_regexec(&voluntary_access_regex, str, index_max_matches, match_arr, 0) == 0){
1504       path_offset += (type_name_length + 1) + str_length;
1505 
1506       play = start_play;
1507       recall = start_recall;
1508 
1509       play = ags_recall_template_find_type(play, recall_type);
1510       recall = ags_recall_template_find_type(recall, recall_type);
1511 
1512       if(play != NULL){
1513 	AgsRecall *current;
1514 
1515 	current = play->data;
1516 	start_response = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1517 								  osc_connection,
1518 								  current,
1519 								  message, message_size,
1520 								  type_tag,
1521 								  path, path_offset);
1522       }
1523 
1524       if(recall != NULL){
1525 	AgsRecall *current;
1526 
1527 	current = recall->data;
1528 	start_response = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1529 								  osc_connection,
1530 								  current,
1531 								  message, message_size,
1532 								  type_tag,
1533 								  path, path_offset);
1534       }
1535 
1536       if(play == NULL && recall == NULL){
1537 	osc_response = ags_osc_response_new();
1538 	start_response = g_list_prepend(start_response,
1539 					osc_response);
1540 
1541 	ags_osc_response_set_flags(osc_response,
1542 				   AGS_OSC_RESPONSE_OK);
1543 
1544 	g_list_free_full(start_play,
1545 			 g_object_unref);
1546 	g_list_free_full(start_recall,
1547 			 g_object_unref);
1548 
1549 	g_object_unref(task_launcher);
1550 
1551 	return(start_response);
1552       }
1553     }else if(ags_regexec(&more_access_regex, str, index_max_matches, match_arr, 0) == 0){
1554       path_offset += (type_name_length + 1) + str_length;
1555 
1556       play = start_play;
1557       recall = start_recall;
1558 
1559       play = ags_recall_template_find_type(play, recall_type);
1560       recall = ags_recall_template_find_type(recall, recall_type);
1561 
1562       if(play == NULL && recall == NULL){
1563 	osc_response = ags_osc_response_new();
1564 	start_response = g_list_prepend(start_response,
1565 					osc_response);
1566 
1567 	ags_osc_response_set_flags(osc_response,
1568 				   AGS_OSC_RESPONSE_ERROR);
1569 
1570 	g_object_set(osc_response,
1571 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
1572 		     NULL);
1573 
1574 	g_list_free_full(start_play,
1575 			 g_object_unref);
1576 	g_list_free_full(start_recall,
1577 			 g_object_unref);
1578 
1579 	g_object_unref(task_launcher);
1580 
1581 	return(start_response);
1582       }
1583 
1584       if(play != NULL){
1585 	AgsRecall *current;
1586 
1587 	current = play->data;
1588 	start_response = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1589 								  osc_connection,
1590 								  current,
1591 								  message, message_size,
1592 								  type_tag,
1593 								  path, path_offset);
1594       }
1595 
1596       if(recall != NULL){
1597 	AgsRecall *current;
1598 
1599 	GList *retval;
1600 
1601 	current = recall->data;
1602 	retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1603 							  osc_connection,
1604 							  current,
1605 							  message, message_size,
1606 							  type_tag,
1607 							  path, path_offset);
1608 
1609 	if(start_response != NULL){
1610 	  start_response = g_list_concat(start_response,
1611 					 retval);
1612 	}else{
1613 	  start_response = retval;
1614 	}
1615       }
1616 
1617       while(play != NULL || recall != NULL){
1618 	play = ags_recall_template_find_type(play, recall_type);
1619 	recall = ags_recall_template_find_type(recall, recall_type);
1620 
1621 	if(play != NULL){
1622 	  AgsRecall *current;
1623 
1624 	  GList *retval;
1625 
1626 	  current = play->data;
1627 	  retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1628 							    osc_connection,
1629 							    current,
1630 							    message, message_size,
1631 							    type_tag,
1632 							    path, path_offset);
1633 
1634 	  start_response = g_list_concat(start_response,
1635 					 retval);
1636 	}
1637 
1638 	if(recall != NULL){
1639 	  AgsRecall *current;
1640 
1641 	  GList *retval;
1642 
1643 	  current = recall->data;
1644 	  retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1645 							    osc_connection,
1646 							    current,
1647 							    message, message_size,
1648 							    type_tag,
1649 							    path, path_offset);
1650 
1651 	  start_response = g_list_concat(start_response,
1652 					 retval);
1653 	}
1654 
1655 	if(play != NULL){
1656 	  play = play->next;
1657 	}
1658 
1659 	if(recall != NULL){
1660 	  recall = recall->next;
1661 	}
1662       }
1663     }else if(ags_regexec(&wildcard_access_regex, str, index_max_matches, match_arr, 0) == 0){
1664       path_offset += (type_name_length + 1) + str_length;
1665 
1666       play = start_play;
1667       recall = start_recall;
1668 
1669       while(play != NULL || recall != NULL){
1670 	play = ags_recall_template_find_type(play, recall_type);
1671 	recall = ags_recall_template_find_type(recall, recall_type);
1672 
1673 	if(play != NULL){
1674 	  AgsRecall *current;
1675 
1676 	  GList *retval;
1677 
1678 	  current = play->data;
1679 	  retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1680 							    osc_connection,
1681 							    current,
1682 							    message, message_size,
1683 							    type_tag,
1684 							    path, path_offset);
1685 
1686 	  if(start_response != NULL){
1687 	    start_response = g_list_concat(start_response,
1688 					   retval);
1689 	  }else{
1690 	    start_response = retval;
1691 	  }
1692 	}
1693 
1694 	if(recall != NULL){
1695 	  AgsRecall *current;
1696 
1697 	  GList *retval;
1698 
1699 	  current = recall->data;
1700 	  retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
1701 							    osc_connection,
1702 							    current,
1703 							    message, message_size,
1704 							    type_tag,
1705 							    path, path_offset);
1706 
1707 	  if(start_response != NULL){
1708 	    start_response = g_list_concat(start_response,
1709 					   retval);
1710 	  }else{
1711 	    start_response = retval;
1712 	  }
1713 	}
1714 
1715 	if(play != NULL){
1716 	  play = play->next;
1717 	}
1718 
1719 	if(recall != NULL){
1720 	  recall = recall->next;
1721 	}
1722       }
1723     }else{
1724       osc_response = ags_osc_response_new();
1725       start_response = g_list_prepend(start_response,
1726 				      osc_response);
1727 
1728       ags_osc_response_set_flags(osc_response,
1729 				 AGS_OSC_RESPONSE_ERROR);
1730 
1731       g_object_set(osc_response,
1732 		   "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
1733 		   NULL);
1734 
1735       g_list_free_full(start_play,
1736 		       g_object_unref);
1737       g_list_free_full(start_recall,
1738 		       g_object_unref);
1739 
1740       g_object_unref(task_launcher);
1741 
1742       return(start_response);
1743     }
1744 
1745     g_list_free_full(start_play,
1746 		     g_object_unref);
1747     g_list_free_full(start_recall,
1748 		     g_object_unref);
1749   }
1750 
1751   g_object_unref(task_launcher);
1752 
1753   return(start_response);
1754 }
1755 
1756 gpointer
ags_osc_renew_controller_set_data_channel(AgsOscRenewController * osc_renew_controller,AgsOscConnection * osc_connection,AgsChannel * channel,unsigned char * message,guint message_size,gchar * type_tag,gchar * path,guint path_offset)1757 ags_osc_renew_controller_set_data_channel(AgsOscRenewController *osc_renew_controller,
1758 					  AgsOscConnection *osc_connection,
1759 					  AgsChannel *channel,
1760 					  unsigned char *message, guint message_size,
1761 					  gchar *type_tag,
1762 					  gchar *path, guint path_offset)
1763 {
1764   AgsOscResponse *osc_response;
1765 
1766   AgsTaskLauncher *task_launcher;
1767 
1768   AgsApplicationContext *application_context;
1769 
1770   GList *start_response;
1771 
1772   unsigned char *packet;
1773 
1774   guint type_tag_length;
1775   guint path_length;
1776   guint real_packet_size;
1777   guint packet_size;
1778 
1779   if(!AGS_IS_CHANNEL(channel)){
1780     return(NULL);
1781   }
1782 
1783   start_response = NULL;
1784 
1785   application_context = ags_application_context_get_instance();
1786 
1787   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));
1788 
1789   real_packet_size = 0;
1790   packet_size = 0;
1791 
1792   if(!strncmp(path + path_offset,
1793 	      ":",
1794 	      1)){
1795     guint length;
1796 
1797     osc_response = ags_osc_response_new();
1798     start_response = g_list_prepend(start_response,
1799 				    osc_response);
1800 
1801     packet = (unsigned char *) malloc(AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
1802     memset(packet, 0, AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
1803 
1804     g_object_set(osc_response,
1805 		 "packet", packet,
1806 		 "packet-size", packet_size,
1807 		 NULL);
1808 
1809     real_packet_size = AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE;
1810 
1811     type_tag_length = 4 * (guint) ceil((double) (strlen(type_tag) + 1) / 4.0);
1812 
1813     path_length = 4 * (guint) ceil((double) (strlen(path) + 1) / 4.0);
1814     path_offset += 1;
1815 
1816     if(!strncmp(path + path_offset,
1817 		"samplerate",
1818 		11)){
1819       AgsSetSamplerate *set_samplerate;
1820 
1821       guint samplerate;
1822       gboolean success;
1823 
1824       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
1825 
1826       if(!success ||
1827 	 message_size < 16 + path_length + 4){
1828 	ags_osc_response_set_flags(osc_response,
1829 				   AGS_OSC_RESPONSE_ERROR);
1830 
1831 	g_object_set(osc_response,
1832 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
1833 		     NULL);
1834 
1835 	g_object_unref(task_launcher);
1836 
1837 	return(start_response);
1838       }
1839 
1840       /* read samplerate */
1841       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
1842 				    &samplerate);
1843 
1844       set_samplerate = ags_set_samplerate_new((GObject *) channel,
1845 					      samplerate);
1846       ags_task_launcher_add_task(task_launcher,
1847 				  (AgsTask *) set_samplerate);
1848     }else if(!strncmp(path + path_offset,
1849 		      "buffer-size",
1850 		      12)){
1851       AgsSetBufferSize *set_buffer_size;
1852 
1853       guint buffer_size;
1854       gboolean success;
1855 
1856       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
1857 
1858       if(!success ||
1859 	 message_size < 16 + path_length + 4){
1860 	ags_osc_response_set_flags(osc_response,
1861 				   AGS_OSC_RESPONSE_ERROR);
1862 
1863 	g_object_set(osc_response,
1864 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
1865 		     NULL);
1866 
1867 	g_object_unref(task_launcher);
1868 
1869 	return(start_response);
1870       }
1871 
1872       /* read buffer size */
1873       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
1874 				    &buffer_size);
1875 
1876       set_buffer_size = ags_set_buffer_size_new((GObject *) channel,
1877 						buffer_size);
1878       ags_task_launcher_add_task(task_launcher,
1879 				  (AgsTask *) set_buffer_size);
1880     }else if(!strncmp(path + path_offset,
1881 		      "format",
1882 		      7)){
1883       AgsSetFormat *set_format;
1884 
1885       guint format;
1886       gboolean success;
1887 
1888       success = (!strncmp(type_tag + 2, "i", 2)) ? TRUE: FALSE;
1889 
1890       if(!success ||
1891 	 message_size < 16 + path_length + 4){
1892 	ags_osc_response_set_flags(osc_response,
1893 				   AGS_OSC_RESPONSE_ERROR);
1894 
1895 	g_object_set(osc_response,
1896 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
1897 		     NULL);
1898 
1899 	g_object_unref(task_launcher);
1900 
1901 	return(start_response);
1902       }
1903 
1904       /* read format */
1905       ags_osc_buffer_util_get_int32(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + type_tag_length + path_length,
1906 				    &format);
1907 
1908       set_format = ags_set_format_new((GObject *) channel,
1909 				      format);
1910       ags_task_launcher_add_task(task_launcher,
1911 				  (AgsTask *) set_format);
1912     }else{
1913       ags_osc_response_set_flags(osc_response,
1914 				 AGS_OSC_RESPONSE_ERROR);
1915 
1916       g_object_set(osc_response,
1917 		   "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_UNKNOWN_ARGUMENT,
1918 		   NULL);
1919 
1920       g_object_unref(task_launcher);
1921 
1922       return(start_response);
1923     }
1924 
1925     g_object_set(osc_response,
1926 		 "packet-size", packet_size,
1927 		 NULL);
1928   }else{
1929     GType recall_type;
1930 
1931     GList *start_play, *play;
1932     GList *start_recall, *recall;
1933 
1934     regmatch_t match_arr[3];
1935 
1936     gchar *type_name;
1937     gchar *str;
1938 
1939     guint type_name_length;
1940     guint str_length;
1941 
1942     static regex_t recall_regex;
1943     static regex_t single_access_regex;
1944     static regex_t range_access_regex;
1945     static regex_t voluntary_access_regex;
1946     static regex_t more_access_regex;
1947     static regex_t wildcard_access_regex;
1948 
1949     static gboolean regex_compiled = FALSE;
1950 
1951     static const gchar *recall_pattern = "^\\/([a-zA-Z]+)(\\/|\\[[0-9]+\\]|\\[[0-9]+\\-[0-9]+\\]|\\[\\?\\]|\\[\\+\\]|\\[\\*\\]|:)";
1952     static const gchar *single_access_pattern = "^\\[([0-9]+)\\]";
1953     static const gchar *range_access_pattern = "^\\[([0-9]+)\\-([0-9]+)\\]";
1954     static const gchar *voluntary_access_pattern = "^\\[(\\?)\\]";
1955     static const gchar *more_access_pattern = "^\\[(\\+)\\]";
1956     static const gchar *wildcard_access_pattern = "^\\[(\\*)\\]";
1957 
1958     static const size_t max_matches = 3;
1959     static const size_t index_max_matches = 2;
1960 
1961     /* compile regex */
1962     g_mutex_lock(&regex_mutex);
1963 
1964     if(!regex_compiled){
1965       regex_compiled = TRUE;
1966 
1967       ags_regcomp(&recall_regex, recall_pattern, REG_EXTENDED);
1968 
1969       ags_regcomp(&single_access_regex, single_access_pattern, REG_EXTENDED);
1970       ags_regcomp(&range_access_regex, range_access_pattern, REG_EXTENDED);
1971       ags_regcomp(&voluntary_access_regex, voluntary_access_pattern, REG_EXTENDED);
1972       ags_regcomp(&more_access_regex, more_access_pattern, REG_EXTENDED);
1973       ags_regcomp(&wildcard_access_regex, wildcard_access_pattern, REG_EXTENDED);
1974     }
1975 
1976     g_mutex_unlock(&regex_mutex);
1977 
1978     if(ags_regexec(&recall_regex, path + path_offset, max_matches, match_arr, 0) == 0){
1979       type_name_length = match_arr[1].rm_eo - match_arr[1].rm_so;
1980       type_name = g_strndup(path + path_offset + 1,
1981 			    type_name_length);
1982 
1983       str_length = match_arr[2].rm_eo - match_arr[2].rm_so;
1984       str = g_strndup(path + path_offset + 1 + type_name_length,
1985 		      str_length);
1986     }else{
1987       osc_response = ags_osc_response_new();
1988       start_response = g_list_prepend(start_response,
1989 				      osc_response);
1990 
1991       ags_osc_response_set_flags(osc_response,
1992 				 AGS_OSC_RESPONSE_ERROR);
1993 
1994       g_object_set(osc_response,
1995 		   "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_UNKNOWN_PATH,
1996 		   NULL);
1997 
1998       g_object_unref(task_launcher);
1999 
2000       return(start_response);
2001     }
2002 
2003     recall_type = g_type_from_name(type_name);
2004 
2005     g_object_get(channel,
2006 		 "play", &start_play,
2007 		 "recall", &start_recall,
2008 		 NULL);
2009 
2010     if(ags_regexec(&single_access_regex, str, index_max_matches, match_arr, 0) == 0){
2011       guint i;
2012       guint i_stop;
2013 
2014       path_offset += (type_name_length + 1) + str_length;
2015 
2016       i_stop = g_ascii_strtoull(str + 1,
2017 				NULL,
2018 				10);
2019 
2020       play = start_play;
2021       recall = start_recall;
2022 
2023       for(i = 0; i <= i_stop; i++){
2024 	play = ags_recall_template_find_type(play, recall_type);
2025 	recall = ags_recall_template_find_type(recall, recall_type);
2026 
2027 	if(i + 1 < i_stop){
2028 	  if(play != NULL){
2029 	    play = play->next;
2030 	  }
2031 
2032 	  if(recall != NULL){
2033 	    recall = recall->next;
2034 	  }
2035 	}
2036       }
2037 
2038       if(play != NULL){
2039 	AgsRecall *current;
2040 
2041 	GList *retval;
2042 
2043 	current = play->data;
2044 	retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2045 							  osc_connection,
2046 							  current,
2047 							  message, message_size,
2048 							  type_tag,
2049 							  path, path_offset);
2050 
2051 	if(start_response != NULL){
2052 	  start_response = g_list_concat(start_response,
2053 					 retval);
2054 	}else{
2055 	  start_response = retval;
2056 	}
2057       }
2058 
2059       if(recall != NULL){
2060 	AgsRecall *current;
2061 
2062 	GList *retval;
2063 
2064 	current = recall->data;
2065 	retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2066 							  osc_connection,
2067 							  current,
2068 							  message, message_size,
2069 							  type_tag,
2070 							  path, path_offset);
2071 
2072 	if(start_response != NULL){
2073 	  start_response = g_list_concat(start_response,
2074 					 retval);
2075 	}else{
2076 	  start_response = retval;
2077 	}
2078       }
2079     }else if(ags_regexec(&range_access_regex, str, max_matches, match_arr, 0) == 0){
2080       gchar *endptr;
2081 
2082       guint i;
2083       guint i_start, i_stop;
2084 
2085       path_offset += (type_name_length + 1) + str_length;
2086 
2087       endptr = NULL;
2088       i_start = g_ascii_strtoull(str + 1,
2089 				 &endptr,
2090 				 10);
2091 
2092       i_stop = g_ascii_strtoull(endptr + 1,
2093 				NULL,
2094 				10);
2095 
2096       play = start_play;
2097       recall = start_recall;
2098 
2099       for(i = 0; i <= i_stop; i++){
2100 	play = ags_recall_template_find_type(play, recall_type);
2101 	recall = ags_recall_template_find_type(recall, recall_type);
2102 
2103 	if(i >= i_start){
2104 	  if(play != NULL){
2105 	    AgsRecall *current;
2106 
2107 	    GList *retval;
2108 
2109 	    current = play->data;
2110 	    retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2111 							      osc_connection,
2112 							      current,
2113 							      message, message_size,
2114 							      type_tag,
2115 							      path, path_offset);
2116 
2117 	    if(start_response != NULL){
2118 	      start_response = g_list_concat(start_response,
2119 					     retval);
2120 	    }else{
2121 	      start_response = retval;
2122 	    }
2123 	  }
2124 
2125 	  if(recall != NULL){
2126 	    AgsRecall *current;
2127 
2128 	    GList *retval;
2129 
2130 	    current = recall->data;
2131 	    retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2132 							      osc_connection,
2133 							      current,
2134 							      message, message_size,
2135 							      type_tag,
2136 							      path, path_offset);
2137 
2138 	    if(start_response != NULL){
2139 	      start_response = g_list_concat(start_response,
2140 					     retval);
2141 	    }else{
2142 	      start_response = retval;
2143 	    }
2144 	  }
2145 	}
2146 
2147 	if(i + 1 < i_stop){
2148 	  if(play != NULL){
2149 	    play = play->next;
2150 	  }
2151 
2152 	  if(recall != NULL){
2153 	    recall = recall->next;
2154 	  }
2155 	}
2156       }
2157     }else if(ags_regexec(&voluntary_access_regex, str, index_max_matches, match_arr, 0) == 0){
2158       path_offset += (type_name_length + 1) + str_length;
2159 
2160       play = start_play;
2161       recall = start_recall;
2162 
2163       play = ags_recall_template_find_type(play, recall_type);
2164       recall = ags_recall_template_find_type(recall, recall_type);
2165 
2166       if(play != NULL){
2167 	AgsRecall *current;
2168 
2169 	current = play->data;
2170 	start_response = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2171 								  osc_connection,
2172 								  current,
2173 								  message, message_size,
2174 								  type_tag,
2175 								  path, path_offset);
2176       }
2177 
2178       if(recall != NULL){
2179 	AgsRecall *current;
2180 
2181 	current = recall->data;
2182 	start_response = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2183 								  osc_connection,
2184 								  current,
2185 								  message, message_size,
2186 								  type_tag,
2187 								  path, path_offset);
2188       }
2189 
2190       if(play == NULL && recall == NULL){
2191 	osc_response = ags_osc_response_new();
2192 	start_response = g_list_prepend(start_response,
2193 					osc_response);
2194 
2195 	ags_osc_response_set_flags(osc_response,
2196 				   AGS_OSC_RESPONSE_OK);
2197 
2198 	g_list_free_full(start_play,
2199 			 g_object_unref);
2200 	g_list_free_full(start_recall,
2201 			 g_object_unref);
2202 
2203 	g_object_unref(task_launcher);
2204 
2205 	return(start_response);
2206       }
2207     }else if(ags_regexec(&more_access_regex, str, index_max_matches, match_arr, 0) == 0){
2208       path_offset += (type_name_length + 1) + str_length;
2209 
2210       play = start_play;
2211       recall = start_recall;
2212 
2213       play = ags_recall_template_find_type(play, recall_type);
2214       recall = ags_recall_template_find_type(recall, recall_type);
2215 
2216       if(play == NULL && recall == NULL){
2217 	osc_response = ags_osc_response_new();
2218 	start_response = g_list_prepend(start_response,
2219 					osc_response);
2220 
2221 	ags_osc_response_set_flags(osc_response,
2222 				   AGS_OSC_RESPONSE_ERROR);
2223 
2224 	g_object_set(osc_response,
2225 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
2226 		     NULL);
2227 
2228 	g_list_free_full(start_play,
2229 			 g_object_unref);
2230 	g_list_free_full(start_recall,
2231 			 g_object_unref);
2232 
2233 	g_object_unref(task_launcher);
2234 
2235 	return(start_response);
2236       }
2237 
2238       if(play != NULL){
2239 	AgsRecall *current;
2240 
2241 	current = play->data;
2242 	start_response = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2243 								  osc_connection,
2244 								  current,
2245 								  message, message_size,
2246 								  type_tag,
2247 								  path, path_offset);
2248       }
2249 
2250       if(recall != NULL){
2251 	AgsRecall *current;
2252 
2253 	GList *retval;
2254 
2255 	current = recall->data;
2256 	retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2257 							  osc_connection,
2258 							  current,
2259 							  message, message_size,
2260 							  type_tag,
2261 							  path, path_offset);
2262 
2263 	if(start_response != NULL){
2264 	  start_response = g_list_concat(start_response,
2265 					 retval);
2266 	}else{
2267 	  start_response = retval;
2268 	}
2269       }
2270 
2271       while(play != NULL || recall != NULL){
2272 	play = ags_recall_template_find_type(play, recall_type);
2273 	recall = ags_recall_template_find_type(recall, recall_type);
2274 
2275 	if(play != NULL){
2276 	  AgsRecall *current;
2277 
2278 	  GList *retval;
2279 
2280 	  current = play->data;
2281 	  retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2282 							    osc_connection,
2283 							    current,
2284 							    message, message_size,
2285 							    type_tag,
2286 							    path, path_offset);
2287 
2288 	  start_response = g_list_concat(start_response,
2289 					 retval);
2290 	}
2291 
2292 	if(recall != NULL){
2293 	  AgsRecall *current;
2294 
2295 	  GList *retval;
2296 
2297 	  current = recall->data;
2298 	  retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2299 							    osc_connection,
2300 							    current,
2301 							    message, message_size,
2302 							    type_tag,
2303 							    path, path_offset);
2304 
2305 	  start_response = g_list_concat(start_response,
2306 					 retval);
2307 	}
2308 
2309 	if(play != NULL){
2310 	  play = play->next;
2311 	}
2312 
2313 	if(recall != NULL){
2314 	  recall = recall->next;
2315 	}
2316       }
2317     }else if(ags_regexec(&wildcard_access_regex, str, index_max_matches, match_arr, 0) == 0){
2318       path_offset += (type_name_length + 1) + str_length;
2319 
2320       play = start_play;
2321       recall = start_recall;
2322 
2323       while(play != NULL || recall != NULL){
2324 	play = ags_recall_template_find_type(play, recall_type);
2325 	recall = ags_recall_template_find_type(recall, recall_type);
2326 
2327 	if(play != NULL){
2328 	  AgsRecall *current;
2329 
2330 	  GList *retval;
2331 
2332 	  current = play->data;
2333 	  retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2334 							    osc_connection,
2335 							    current,
2336 							    message, message_size,
2337 							    type_tag,
2338 							    path, path_offset);
2339 
2340 	  if(start_response != NULL){
2341 	    start_response = g_list_concat(start_response,
2342 					   retval);
2343 	  }else{
2344 	    start_response = retval;
2345 	  }
2346 	}
2347 
2348 	if(recall != NULL){
2349 	  AgsRecall *current;
2350 
2351 	  GList *retval;
2352 
2353 	  current = recall->data;
2354 	  retval = ags_osc_renew_controller_set_data_recall(osc_renew_controller,
2355 							    osc_connection,
2356 							    current,
2357 							    message, message_size,
2358 							    type_tag,
2359 							    path, path_offset);
2360 
2361 	  if(start_response != NULL){
2362 	    start_response = g_list_concat(start_response,
2363 					   retval);
2364 	  }else{
2365 	    start_response = retval;
2366 	  }
2367 	}
2368 
2369 	if(play != NULL){
2370 	  play = play->next;
2371 	}
2372 
2373 	if(recall != NULL){
2374 	  recall = recall->next;
2375 	}
2376       }
2377     }else{
2378       osc_response = ags_osc_response_new();
2379       start_response = g_list_prepend(start_response,
2380 				      osc_response);
2381 
2382       ags_osc_response_set_flags(osc_response,
2383 				 AGS_OSC_RESPONSE_ERROR);
2384 
2385       g_object_set(osc_response,
2386 		   "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
2387 		   NULL);
2388 
2389       g_list_free_full(start_play,
2390 		       g_object_unref);
2391       g_list_free_full(start_recall,
2392 		       g_object_unref);
2393 
2394       g_object_unref(task_launcher);
2395 
2396       return(start_response);
2397     }
2398 
2399     g_list_free_full(start_play,
2400 		     g_object_unref);
2401     g_list_free_full(start_recall,
2402 		     g_object_unref);
2403   }
2404 
2405   g_object_unref(task_launcher);
2406 
2407   return(start_response);
2408 }
2409 
2410 gpointer
ags_osc_renew_controller_set_data_recall(AgsOscRenewController * osc_renew_controller,AgsOscConnection * osc_connection,AgsRecall * recall,unsigned char * message,guint message_size,gchar * type_tag,gchar * path,guint path_offset)2411 ags_osc_renew_controller_set_data_recall(AgsOscRenewController *osc_renew_controller,
2412 					 AgsOscConnection *osc_connection,
2413 					 AgsRecall *recall,
2414 					 unsigned char *message, guint message_size,
2415 					 gchar *type_tag,
2416 					 gchar *path, guint path_offset)
2417 {
2418   AgsOscResponse *osc_response;
2419 
2420   AgsTaskLauncher *task_launcher;
2421 
2422   AgsApplicationContext *application_context;
2423 
2424   GList *start_response;
2425 
2426   unsigned char *packet;
2427 
2428   guint path_length;
2429   guint real_packet_size;
2430   guint packet_size;
2431 
2432   if(!AGS_IS_RECALL(recall)){
2433     return(NULL);
2434   }
2435 
2436   start_response = NULL;
2437 
2438   application_context = ags_application_context_get_instance();
2439 
2440   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));
2441 
2442   real_packet_size = 0;
2443   packet_size = 0;
2444 
2445   if(!strncmp(path + path_offset,
2446 	      ":",
2447 	      1)){
2448     guint length;
2449 
2450     osc_response = ags_osc_response_new();
2451     start_response = g_list_prepend(start_response,
2452 				    osc_response);
2453 
2454     packet = (unsigned char *) malloc(AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
2455     memset(packet, 0, AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
2456 
2457     g_object_set(osc_response,
2458 		 "packet", packet,
2459 		 "packet-size", packet_size,
2460 		 NULL);
2461 
2462     real_packet_size = AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE;
2463 
2464     path_length = 4 * (guint) ceil((double) (strlen(path) + 1) / 4.0);
2465     path_offset += 1;
2466 
2467     ags_osc_response_set_flags(osc_response,
2468 			       AGS_OSC_RESPONSE_ERROR);
2469 
2470     g_object_set(osc_response,
2471 		 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_UNKNOWN_ARGUMENT,
2472 		 NULL);
2473 
2474     g_object_unref(task_launcher);
2475 
2476     return(start_response);
2477   }else if(!strncmp(path + path_offset,
2478 		    "/AgsPort",
2479 		    8)){
2480     GList *start_port, *port;
2481 
2482     regmatch_t match_arr[3];
2483 
2484     static regex_t single_access_regex;
2485     static regex_t range_access_regex;
2486     static regex_t voluntary_access_regex;
2487     static regex_t more_access_regex;
2488     static regex_t wildcard_access_regex;
2489 
2490     static gboolean regex_compiled = FALSE;
2491 
2492     static const gchar *single_access_pattern = "^\\[([0-9]+)\\]";
2493     static const gchar *range_access_pattern = "^\\[([0-9]+)\\-([0-9]+)\\]";
2494     static const gchar *voluntary_access_pattern = "^\\[(\\?)\\]";
2495     static const gchar *more_access_pattern = "^\\[(\\+)\\]";
2496     static const gchar *wildcard_access_pattern = "^\\[(\\*)\\]";
2497 
2498     static const size_t max_matches = 3;
2499     static const size_t index_max_matches = 2;
2500 
2501     path_offset += 8;
2502 
2503     /* compile regex */
2504     g_mutex_lock(&regex_mutex);
2505 
2506     if(!regex_compiled){
2507       regex_compiled = TRUE;
2508 
2509       ags_regcomp(&single_access_regex, single_access_pattern, REG_EXTENDED);
2510       ags_regcomp(&range_access_regex, range_access_pattern, REG_EXTENDED);
2511       ags_regcomp(&voluntary_access_regex, voluntary_access_pattern, REG_EXTENDED);
2512       ags_regcomp(&more_access_regex, more_access_pattern, REG_EXTENDED);
2513       ags_regcomp(&wildcard_access_regex, wildcard_access_pattern, REG_EXTENDED);
2514     }
2515 
2516     g_mutex_unlock(&regex_mutex);
2517 
2518     g_object_get(recall,
2519 		 "port", &start_port,
2520 		 NULL);
2521 
2522     port = start_port;
2523 
2524     if(ags_regexec(&single_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
2525       AgsPort *current;
2526 
2527       gchar *endptr;
2528 
2529       guint i_stop;
2530 
2531       endptr = NULL;
2532       i_stop = g_ascii_strtoull(path + path_offset + 1,
2533 				&endptr,
2534 				10);
2535 
2536       current = g_list_nth_data(start_port,
2537 				i_stop);
2538 
2539       path_offset += ((endptr + 1) - (path + path_offset));
2540 
2541       start_response = ags_osc_renew_controller_set_data_port(osc_renew_controller,
2542 							      osc_connection,
2543 							      recall,
2544 							      current,
2545 							      message, message_size,
2546 							      type_tag,
2547 							      path, path_offset);
2548     }else if(ags_regexec(&range_access_regex, path + path_offset, max_matches, match_arr, 0) == 0){
2549       gchar *endptr;
2550 
2551       guint i;
2552       guint i_start, i_stop;
2553 
2554       endptr = NULL;
2555       i_start = g_ascii_strtoull(path + path_offset + 1,
2556 				 &endptr,
2557 				 10);
2558 
2559       i_stop = g_ascii_strtoull(endptr + 1,
2560 				&endptr,
2561 				10);
2562 
2563       path_offset += ((endptr + 1) - (path + path_offset));
2564 
2565       port = g_list_nth(start_port,
2566 			i_start);
2567 
2568       for(i = i_start; i <= i_stop; i++){
2569 	GList *retval;
2570 
2571 	retval = ags_osc_renew_controller_set_data_port(osc_renew_controller,
2572 							osc_connection,
2573 							recall,
2574 							port->data,
2575 							message, message_size,
2576 							type_tag,
2577 							path, path_offset);
2578 
2579 	if(start_response != NULL){
2580 	  start_response = g_list_concat(start_response,
2581 					 retval);
2582 	}else{
2583 	  start_response = retval;
2584 	}
2585 
2586 	port = port->next;
2587       }
2588     }else if(ags_regexec(&voluntary_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
2589       path_offset += 3;
2590 
2591       if(start_port != NULL){
2592 	start_response = ags_osc_renew_controller_set_data_port(osc_renew_controller,
2593 								osc_connection,
2594 								recall,
2595 								start_port->data,
2596 								message, message_size,
2597 								type_tag,
2598 								path, path_offset);
2599       }else{
2600 	osc_response = ags_osc_response_new();
2601 	start_response = g_list_prepend(start_response,
2602 					osc_response);
2603 
2604 	ags_osc_response_set_flags(osc_response,
2605 				   AGS_OSC_RESPONSE_OK);
2606 
2607 	g_object_unref(task_launcher);
2608 
2609 	return(start_response);
2610       }
2611     }else if(ags_regexec(&more_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
2612       path_offset += 3;
2613 
2614       if(start_port == NULL){
2615 	osc_response = ags_osc_response_new();
2616 	start_response = g_list_prepend(start_response,
2617 					osc_response);
2618 
2619 	ags_osc_response_set_flags(osc_response,
2620 				   AGS_OSC_RESPONSE_ERROR);
2621 
2622 	g_object_set(osc_response,
2623 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
2624 		     NULL);
2625 
2626 	g_object_unref(task_launcher);
2627 
2628 	return(start_response);
2629       }
2630 
2631       port = start_port;
2632 
2633       while(port != NULL){
2634 	GList *retval;
2635 
2636 	retval = ags_osc_renew_controller_set_data_port(osc_renew_controller,
2637 							osc_connection,
2638 							recall,
2639 							port->data,
2640 							message, message_size,
2641 							type_tag,
2642 							path, path_offset);
2643 
2644 	if(start_response != NULL){
2645 	  start_response = g_list_concat(start_response,
2646 					 retval);
2647 	}else{
2648 	  start_response = retval;
2649 	}
2650 
2651 	port = port->next;
2652       }
2653     }else if(ags_regexec(&wildcard_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
2654       path_offset += 3;
2655 
2656       if(start_port == NULL){
2657 	osc_response = ags_osc_response_new();
2658 	start_response = g_list_prepend(start_response,
2659 					osc_response);
2660 
2661 	ags_osc_response_set_flags(osc_response,
2662 				   AGS_OSC_RESPONSE_OK);
2663 
2664 	g_object_unref(task_launcher);
2665 
2666 	return(start_response);
2667       }
2668 
2669       while(port != NULL){
2670 	GList *retval;
2671 
2672 	retval = ags_osc_renew_controller_set_data_port(osc_renew_controller,
2673 							osc_connection,
2674 							recall,
2675 							port->data,
2676 							message, message_size,
2677 							type_tag,
2678 							path, path_offset);
2679 
2680 	if(start_response != NULL){
2681 	  start_response = g_list_concat(start_response,
2682 					 retval);
2683 	}else{
2684 	  start_response = retval;
2685 	}
2686 
2687 	port = port->next;
2688       }
2689     }else if(path[path_offset] == '[' &&
2690 	     path[path_offset + 1] == '"'){
2691       AgsPort *current;
2692 
2693       gchar *port_specifier;
2694       gchar *offset;
2695 
2696       guint length;
2697 
2698       if((offset = strchr(path + path_offset + 2, '"')) == NULL){
2699 	osc_response = ags_osc_response_new();
2700 	start_response = g_list_prepend(start_response,
2701 					osc_response);
2702 
2703 	ags_osc_response_set_flags(osc_response,
2704 				   AGS_OSC_RESPONSE_ERROR);
2705 
2706 	g_object_set(osc_response,
2707 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_CHUNK_SIZE_EXCEEDED,
2708 		     NULL);
2709 
2710 	g_list_free_full(start_port,
2711 			 g_object_unref);
2712 
2713 	g_object_unref(task_launcher);
2714 
2715 	return(start_response);
2716       }
2717 
2718       length = offset - (path + path_offset + 2);
2719 
2720       port_specifier = (gchar *) malloc((length + 1) * sizeof(gchar));
2721       memcpy(port_specifier, path + path_offset + 2, (length) * sizeof(gchar));
2722       port_specifier[length] = '\0';
2723 
2724       current = NULL;
2725       port = ags_port_find_specifier(start_port,
2726 				     port_specifier);
2727 
2728       if(port != NULL){
2729 	current = port->data;
2730       }
2731 
2732       path_offset += (length + 4);
2733       start_response  = ags_osc_renew_controller_set_data_port(osc_renew_controller,
2734 							       osc_connection,
2735 							       recall,
2736 							       current,
2737 							       message, message_size,
2738 							       type_tag,
2739 							       path, path_offset);
2740 
2741       free(port_specifier);
2742     }else{
2743       osc_response = ags_osc_response_new();
2744       start_response = g_list_prepend(start_response,
2745 				      osc_response);
2746 
2747       ags_osc_response_set_flags(osc_response,
2748 				 AGS_OSC_RESPONSE_ERROR);
2749 
2750       g_object_set(osc_response,
2751 		   "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
2752 		   NULL);
2753 
2754       g_list_free_full(start_port,
2755 		       g_object_unref);
2756 
2757       g_object_unref(task_launcher);
2758 
2759       return(start_response);
2760     }
2761 
2762     g_list_free_full(start_port,
2763 		     g_object_unref);
2764   }else{
2765     osc_response = ags_osc_response_new();
2766     start_response = g_list_prepend(start_response,
2767 				    osc_response);
2768 
2769     ags_osc_response_set_flags(osc_response,
2770 			       AGS_OSC_RESPONSE_ERROR);
2771 
2772     g_object_set(osc_response,
2773 		 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
2774 		 NULL);
2775 
2776     g_object_unref(task_launcher);
2777 
2778     return(start_response);
2779   }
2780 
2781   g_object_unref(task_launcher);
2782 
2783   return(start_response);
2784 }
2785 
2786 gpointer
ags_osc_renew_controller_set_data_port(AgsOscRenewController * osc_renew_controller,AgsOscConnection * osc_connection,AgsRecall * parent,AgsPort * port,unsigned char * message,guint message_size,gchar * type_tag,gchar * path,guint path_offset)2787 ags_osc_renew_controller_set_data_port(AgsOscRenewController *osc_renew_controller,
2788 				       AgsOscConnection *osc_connection,
2789 				       AgsRecall *parent,
2790 				       AgsPort *port,
2791 				       unsigned char *message, guint message_size,
2792 				       gchar *type_tag,
2793 				       gchar *path, guint path_offset)
2794 {
2795   AgsOscResponse *osc_response;
2796 
2797   AgsApplicationContext *application_context;
2798 
2799   AgsTaskLauncher *task_launcher;
2800 
2801   GList *start_response;
2802 
2803   unsigned char *packet;
2804 
2805   guint path_length;
2806   guint type_tag_offset;
2807   guint real_packet_size;
2808   guint packet_size;
2809 
2810   if(!AGS_IS_PORT(port)){
2811     return(NULL);
2812   }
2813 
2814   start_response = NULL;
2815 
2816   application_context = ags_application_context_get_instance();
2817 
2818   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));
2819 
2820   real_packet_size = 0;
2821   packet_size = 0;
2822 
2823   if(path[path_offset] == ':'){
2824     guint length;
2825 
2826     osc_response = ags_osc_response_new();
2827     start_response = g_list_prepend(start_response,
2828 				    osc_response);
2829 
2830     packet = (unsigned char *) malloc(AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
2831     memset(packet, 0, AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE * sizeof(unsigned char));
2832 
2833     g_object_set(osc_response,
2834 		 "packet", packet,
2835 		 "packet-size", packet_size,
2836 		 NULL);
2837 
2838     real_packet_size = AGS_OSC_RESPONSE_DEFAULT_CHUNK_SIZE;
2839 
2840     path_length = 4 * (guint) ceil((double) (strlen(path) + 1) / 4.0);
2841     path_offset += 1;
2842 
2843     if(!strncmp(path + path_offset,
2844 		"value",
2845 		6)){
2846       GType port_value_type;
2847 
2848       guint port_value_length;
2849       gboolean port_value_is_pointer;
2850 
2851       GRecMutex *port_mutex;
2852 
2853       /* get port mutex */
2854       port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
2855 
2856       /* check array type */
2857       g_object_get(port,
2858 		   "port-value-is-pointer", &port_value_is_pointer,
2859 		   "port-value-type", &port_value_type,
2860 		   "port-value-length", &port_value_length,
2861 		   NULL);
2862 
2863       path_offset = 4 * (guint) ceil((double) (path_offset + 7) / 4.0);
2864 
2865       if(port_value_is_pointer){
2866 	guint i;
2867 
2868 	if(message_size < 16 + path_length + 2 ||
2869 	   type_tag[2] != '['){
2870 	  ags_osc_response_set_flags(osc_response,
2871 				     AGS_OSC_RESPONSE_ERROR);
2872 
2873 	  g_object_set(osc_response,
2874 		       "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
2875 		       NULL);
2876 
2877 	  g_object_unref(task_launcher);
2878 
2879 	  return(start_response);
2880 	}
2881 
2882 	if(port_value_type == G_TYPE_BOOLEAN){
2883 	  guint value_count;
2884 	  gboolean success;
2885 
2886 	  value_count = 0;
2887 	  success = TRUE;
2888 
2889 	  g_rec_mutex_lock(port_mutex);
2890 
2891 	  for(i = 0; 16 + path_length + 3 + i < message_size && type_tag[3 + i] != '\0' && type_tag[3 + i] != ']' && i < port_value_length; i++){
2892 	    if(type_tag[3 + i] == 'T'){
2893 	      port->port_value.ags_port_boolean_ptr[i] = TRUE;
2894 	    }else if(type_tag[3 + i] == 'F'){
2895 	      port->port_value.ags_port_boolean_ptr[i] = FALSE;
2896 	    }else{
2897 	      success = FALSE;
2898 
2899 	      break;
2900 	    }
2901 	  }
2902 
2903 	  g_rec_mutex_unlock(port_mutex);
2904 
2905 	  if(!success ||
2906 	     type_tag[3 + i] != ']'){
2907 	    ags_osc_response_set_flags(osc_response,
2908 				       AGS_OSC_RESPONSE_ERROR);
2909 
2910 	    g_object_set(osc_response,
2911 			 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
2912 			 NULL);
2913 
2914 	    g_object_unref(task_launcher);
2915 
2916 	    return(start_response);
2917 	  }
2918 
2919 	  value_count = i;
2920 	}else if(port_value_type == G_TYPE_INT64){
2921 	  gint64 value;
2922 	  guint value_count;
2923 	  gboolean success;
2924 
2925 	  value_count = 0;
2926 	  success = TRUE;
2927 
2928 	  for(i = 0; 16 + path_length + 3 + i < message_size && type_tag[3 + i] != '\0' && type_tag[3 + i] != ']' && i < port_value_length; i++){
2929 	    if(type_tag[3 + i] != 'h'){
2930 	      success = FALSE;
2931 
2932 	      break;
2933 	    }
2934 	  }
2935 
2936 	  if(!success ||
2937 	     type_tag[3 + i] != ']'){
2938 	    ags_osc_response_set_flags(osc_response,
2939 				       AGS_OSC_RESPONSE_ERROR);
2940 
2941 	    g_object_set(osc_response,
2942 			 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
2943 			 NULL);
2944 
2945 	    g_object_unref(task_launcher);
2946 
2947 	    return(start_response);
2948 	  }
2949 
2950 	  type_tag_offset = 4 * (guint) ceil((double) (5 + i) / 4.0);
2951 	  value_count = i;
2952 
2953 	  g_rec_mutex_lock(port_mutex);
2954 
2955 	  for(i = 0; path_offset + type_tag_offset + (i * 8) < message_size && i < value_count; i++){
2956 	    ags_osc_buffer_util_get_int64(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + path_offset + type_tag_offset + (i * 8),
2957 					  &value);
2958 
2959 	    port->port_value.ags_port_int_ptr[i] = value;
2960 	  }
2961 
2962 	  g_rec_mutex_unlock(port_mutex);
2963 	}else if(port_value_type == G_TYPE_UINT64){
2964 	  guint64 value;
2965 	  guint value_count;
2966 	  gboolean success;
2967 
2968 	  value_count = 0;
2969 	  success = TRUE;
2970 
2971 	  for(i = 0; 16 + path_length + 3 + i < message_size && type_tag[3 + i] != '\0' && type_tag[3 + i] != ']' && i < port_value_length; i++){
2972 	    if(type_tag[3 + i] != 'h'){
2973 	      success = FALSE;
2974 
2975 	      break;
2976 	    }
2977 	  }
2978 
2979 	  if(!success ||
2980 	     type_tag[3 + i] != ']'){
2981 	    ags_osc_response_set_flags(osc_response,
2982 				       AGS_OSC_RESPONSE_ERROR);
2983 
2984 	    g_object_set(osc_response,
2985 			 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
2986 			 NULL);
2987 
2988 	    g_object_unref(task_launcher);
2989 
2990 	    return(start_response);
2991 	  }
2992 
2993 	  type_tag_offset = 4 * (guint) ceil((double) (5 + i) / 4.0);
2994 	  value_count = i;
2995 
2996 	  g_rec_mutex_lock(port_mutex);
2997 
2998 	  for(i = 0; path_offset + type_tag_offset + (i * 8) < message_size && i < value_count; i++){
2999 	    ags_osc_buffer_util_get_int64(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + path_offset + type_tag_offset + (i * 8),
3000 					  &value);
3001 
3002 	    port->port_value.ags_port_uint_ptr[i] = value;
3003 	  }
3004 
3005 	  g_rec_mutex_unlock(port_mutex);
3006 	}else if(port_value_type == G_TYPE_FLOAT){
3007 	  gfloat value;
3008 	  guint value_count;
3009 	  gboolean success;
3010 
3011 	  value_count = 0;
3012 	  success = TRUE;
3013 
3014 	  for(i = 0; 16 + path_length + 3 + i < message_size && type_tag[3 + i] != '\0' && type_tag[3 + i] != ']' && i < port_value_length; i++){
3015 	    if(type_tag[3 + i] != 'f'){
3016 	      success = FALSE;
3017 
3018 	      break;
3019 	    }
3020 	  }
3021 
3022 	  if(!success ||
3023 	     type_tag[3 + i] != ']'){
3024 	    ags_osc_response_set_flags(osc_response,
3025 				       AGS_OSC_RESPONSE_ERROR);
3026 
3027 	    g_object_set(osc_response,
3028 			 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
3029 			 NULL);
3030 
3031 	    g_object_unref(task_launcher);
3032 
3033 	    return(start_response);
3034 	  }
3035 
3036 	  type_tag_offset = 4 * (guint) ceil((double) (5 + i) / 4.0);
3037 	  value_count = i;
3038 
3039 	  g_rec_mutex_lock(port_mutex);
3040 
3041 	  for(i = 0; path_offset + type_tag_offset + (i * 4) < message_size && i < value_count; i++){
3042 	    ags_osc_buffer_util_get_float(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + path_offset + type_tag_offset + (i * 4),
3043 					  &value);
3044 
3045 	    port->port_value.ags_port_float_ptr[i] = value;
3046 	  }
3047 
3048 	  g_rec_mutex_unlock(port_mutex);
3049 	}else if(port_value_type == G_TYPE_DOUBLE){
3050 	  gdouble value;
3051 	  guint value_count;
3052 	  gboolean success;
3053 
3054 	  value_count = 0;
3055 	  success = TRUE;
3056 
3057 	  for(i = 0; 16 + path_length + 3 + i < message_size && type_tag[3 + i] != '\0' && type_tag[3 + i] != ']' && i < port_value_length; i++){
3058 	    if(type_tag[3 + i] != 'd'){
3059 	      success = FALSE;
3060 
3061 	      break;
3062 	    }
3063 	  }
3064 
3065 	  if(!success ||
3066 	     type_tag[3 + i] != ']'){
3067 	    ags_osc_response_set_flags(osc_response,
3068 				       AGS_OSC_RESPONSE_ERROR);
3069 
3070 	    g_object_set(osc_response,
3071 			 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
3072 			 NULL);
3073 
3074 	    g_object_unref(task_launcher);
3075 
3076 	    return(start_response);
3077 	  }
3078 
3079 	  type_tag_offset = 4 * (guint) ceil((double) (5 + i) / 4.0);
3080 	  value_count = i;
3081 
3082 	  g_rec_mutex_lock(port_mutex);
3083 
3084 	  for(i = 0; path_offset + type_tag_offset + (i * 8) < message_size && i < value_count; i++){
3085 	    ags_osc_buffer_util_get_double(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + path_offset + type_tag_offset + (i * 8),
3086 					   &value);
3087 
3088 	    port->port_value.ags_port_double_ptr[i] = value;
3089 	  }
3090 
3091 	  g_rec_mutex_unlock(port_mutex);
3092 	}
3093       }else{
3094 	if(port_value_type == G_TYPE_BOOLEAN){
3095 	  gboolean success;
3096 
3097 	  success = TRUE;
3098 
3099 	  g_rec_mutex_lock(port_mutex);
3100 
3101 	  if(message_size < 16 + path_length + 2){
3102 	    if(type_tag[2] == 'T'){
3103 	      port->port_value.ags_port_boolean = TRUE;
3104 	    }else if(type_tag[2] == 'F'){
3105 	      port->port_value.ags_port_boolean = FALSE;
3106 	    }else{
3107 	      success = FALSE;
3108 	    }
3109 	  }else{
3110 	    success = FALSE;
3111 	  }
3112 
3113 	  g_rec_mutex_unlock(port_mutex);
3114 
3115 	  if(!success ||
3116 	     type_tag[3] != '\0'){
3117 	    ags_osc_response_set_flags(osc_response,
3118 				       AGS_OSC_RESPONSE_ERROR);
3119 
3120 	    g_object_set(osc_response,
3121 			 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
3122 			 NULL);
3123 
3124 	    g_object_unref(task_launcher);
3125 
3126 	    return(start_response);
3127 	  }
3128 	}else if(port_value_type == G_TYPE_INT64){
3129 	  gint64 value;
3130 	  gboolean success;
3131 
3132 	  type_tag_offset = 4;
3133 
3134 	  success = TRUE;
3135 
3136 	  if(message_size >= 8 + path_offset + type_tag_offset + 8){
3137 	    if(type_tag[2] == 'h'){
3138 	      ags_osc_buffer_util_get_int64(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + path_offset + type_tag_offset,
3139 					    &value);
3140 
3141 	      /* set value */
3142 	      g_rec_mutex_lock(port_mutex);
3143 
3144 	      port->port_value.ags_port_int = value;
3145 
3146 	      g_rec_mutex_unlock(port_mutex);
3147 	    }else{
3148 	      success = FALSE;
3149 	    }
3150 	  }else{
3151 	    success = FALSE;
3152 	  }
3153 
3154 	  if(!success ||
3155 	     type_tag[3] != '\0'){
3156 	    ags_osc_response_set_flags(osc_response,
3157 				       AGS_OSC_RESPONSE_ERROR);
3158 
3159 	    g_object_set(osc_response,
3160 			 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
3161 			 NULL);
3162 
3163 	    g_object_unref(task_launcher);
3164 
3165 	    return(start_response);
3166 	  }
3167 	}else if(port_value_type == G_TYPE_UINT64){
3168 	  guint64 value;
3169 	  gboolean success;
3170 
3171 	  type_tag_offset = 4;
3172 
3173 	  success = TRUE;
3174 
3175 	  if(message_size >= 8 + path_offset + type_tag_offset + 8){
3176 	    if(type_tag[2] == 'h'){
3177 	      ags_osc_buffer_util_get_int64(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + path_offset + type_tag_offset,
3178 					    &value);
3179 
3180 	      /* set value */
3181 	      g_rec_mutex_lock(port_mutex);
3182 
3183 	      port->port_value.ags_port_uint = value;
3184 
3185 	      g_rec_mutex_unlock(port_mutex);
3186 	    }else{
3187 	      success = FALSE;
3188 	    }
3189 	  }else{
3190 	    success = FALSE;
3191 	  }
3192 
3193 	  if(!success ||
3194 	     type_tag[3] != '\0'){
3195 	    ags_osc_response_set_flags(osc_response,
3196 				       AGS_OSC_RESPONSE_ERROR);
3197 
3198 	    g_object_set(osc_response,
3199 			 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
3200 			 NULL);
3201 
3202 	    g_object_unref(task_launcher);
3203 
3204 	    return(start_response);
3205 	  }
3206 	}else if(port_value_type == G_TYPE_FLOAT){
3207 	  gfloat value;
3208 	  gboolean success;
3209 
3210 	  type_tag_offset = 4;
3211 
3212 	  success = TRUE;
3213 
3214 	  if(message_size >= 8 + path_offset + type_tag_offset + 4){
3215 	    if(type_tag[2] == 'f'){
3216 	      ags_osc_buffer_util_get_float(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + path_offset + type_tag_offset,
3217 					    &value);
3218 
3219 	      /* set value */
3220 	      g_rec_mutex_lock(port_mutex);
3221 
3222 	      port->port_value.ags_port_float = value;
3223 
3224 	      g_rec_mutex_unlock(port_mutex);
3225 	    }else{
3226 	      success = FALSE;
3227 	    }
3228 	  }else{
3229 	    success = FALSE;
3230 	  }
3231 
3232 	  if(!success ||
3233 	     type_tag[3] != '\0'){
3234 	    ags_osc_response_set_flags(osc_response,
3235 				       AGS_OSC_RESPONSE_ERROR);
3236 
3237 	    g_object_set(osc_response,
3238 			 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
3239 			 NULL);
3240 
3241 	    g_object_unref(task_launcher);
3242 
3243 	    return(start_response);
3244 	  }
3245 	}else if(port_value_type == G_TYPE_DOUBLE){
3246 	  gdouble value;
3247 	  gboolean success;
3248 
3249 	  type_tag_offset = 4;
3250 
3251 	  success = TRUE;
3252 
3253 	  if(message_size >= 8 + path_offset + type_tag_offset + 8){
3254 	    if(type_tag[2] == 'd'){
3255 	      ags_osc_buffer_util_get_double(message + AGS_OSC_RENEW_CONTROLLER_CONTEXT_PATH_LENGTH + path_offset + type_tag_offset,
3256 					     &value);
3257 
3258 	      /* set value */
3259 	      g_rec_mutex_lock(port_mutex);
3260 
3261 	      port->port_value.ags_port_double = value;
3262 
3263 	      g_rec_mutex_unlock(port_mutex);
3264 	    }else{
3265 	      success = FALSE;
3266 	    }
3267 	  }else{
3268 	    success = FALSE;
3269 	  }
3270 
3271 	  if(!success ||
3272 	     type_tag[3] != '\0'){
3273 	    ags_osc_response_set_flags(osc_response,
3274 				       AGS_OSC_RESPONSE_ERROR);
3275 
3276 	    g_object_set(osc_response,
3277 			 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
3278 			 NULL);
3279 
3280 	    g_object_unref(task_launcher);
3281 
3282 	    return(start_response);
3283 	  }
3284 	}
3285       }
3286     }
3287   }
3288 
3289   g_object_unref(task_launcher);
3290 
3291   return(start_response);
3292 }
3293 
3294 gpointer
ags_osc_renew_controller_real_set_data(AgsOscRenewController * osc_renew_controller,AgsOscConnection * osc_connection,unsigned char * message,guint message_size)3295 ags_osc_renew_controller_real_set_data(AgsOscRenewController *osc_renew_controller,
3296 				       AgsOscConnection *osc_connection,
3297 				       unsigned char *message, guint message_size)
3298 {
3299   AgsOscResponse *osc_response;
3300 
3301   AgsApplicationContext *application_context;
3302 
3303   GList *start_response;
3304 
3305   gchar *type_tag;
3306   gchar *path;
3307 
3308   guint path_offset;
3309   gboolean success;
3310 
3311   start_response = NULL;
3312 
3313   /* read type tag */
3314   ags_osc_buffer_util_get_string(message + 8,
3315 				 &type_tag, NULL);
3316 
3317   success = (type_tag != NULL &&
3318 	     !strncmp(type_tag, ",s", 2)) ? TRUE: FALSE;
3319 
3320   if(!success){
3321     osc_response = ags_osc_response_new();
3322     start_response = g_list_prepend(start_response,
3323 				    osc_response);
3324 
3325     ags_osc_response_set_flags(osc_response,
3326 			       AGS_OSC_RESPONSE_ERROR);
3327 
3328     g_object_set(osc_response,
3329 		 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
3330 		 NULL);
3331 
3332     if(type_tag != NULL){
3333       free(type_tag);
3334     }
3335 
3336     return(start_response);
3337   }
3338 
3339   /* read argument */
3340   ags_osc_buffer_util_get_string(message + 8 + (4 * (guint) ceil((gdouble) (strlen(type_tag) + 1) / 4.0)),
3341 				 &path, NULL);
3342 
3343   if(path == NULL){
3344     osc_response = ags_osc_response_new();
3345     start_response = g_list_prepend(start_response,
3346 				    osc_response);
3347 
3348     ags_osc_response_set_flags(osc_response,
3349 			       AGS_OSC_RESPONSE_ERROR);
3350 
3351     g_object_set(osc_response,
3352 		 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_MALFORMED_REQUEST,
3353 		 NULL);
3354 
3355     free(type_tag);
3356 
3357     return(start_response);
3358   }
3359 
3360   /* create packet */
3361   application_context = ags_application_context_get_instance();
3362 
3363   path_offset = 0;
3364 
3365   if(!strncmp(path,
3366 	      "/AgsSoundProvider",
3367 	      17)){
3368     path_offset = 17;
3369 
3370     if(!strncmp(path + path_offset,
3371 		"/AgsSoundcard",
3372 		13)){
3373       GList *start_soundcard, *soundcard;
3374 
3375       regmatch_t match_arr[2];
3376 
3377       static regex_t single_access_regex;
3378       static regex_t range_access_regex;
3379       static regex_t voluntary_access_regex;
3380       static regex_t more_access_regex;
3381       static regex_t wildcard_access_regex;
3382 
3383       static gboolean regex_compiled = FALSE;
3384 
3385       static const gchar *single_access_pattern = "^\\[([0-9]+)\\]";
3386       static const gchar *range_access_pattern = "^\\[([0-9]+)\\-([0-9]+)\\]";
3387       static const gchar *voluntary_access_pattern = "^\\[(\\?)\\]";
3388       static const gchar *more_access_pattern = "^\\[(\\+)\\]";
3389       static const gchar *wildcard_access_pattern = "^\\[(\\*)\\]";
3390 
3391       static const size_t max_matches = 2;
3392       static const size_t index_max_matches = 1;
3393 
3394       path_offset += 13;
3395 
3396       /* compile regex */
3397       g_mutex_lock(&regex_mutex);
3398 
3399       if(!regex_compiled){
3400 	regex_compiled = TRUE;
3401 
3402 	ags_regcomp(&single_access_regex, single_access_pattern, REG_EXTENDED);
3403 	ags_regcomp(&range_access_regex, range_access_pattern, REG_EXTENDED);
3404 	ags_regcomp(&voluntary_access_regex, voluntary_access_pattern, REG_EXTENDED);
3405 	ags_regcomp(&more_access_regex, more_access_pattern, REG_EXTENDED);
3406 	ags_regcomp(&wildcard_access_regex, wildcard_access_pattern, REG_EXTENDED);
3407       }
3408 
3409       g_mutex_unlock(&regex_mutex);
3410 
3411       soundcard =
3412 	start_soundcard = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context));
3413 
3414       if(ags_regexec(&single_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
3415 	GObject *current;
3416 
3417 	gchar *endptr;
3418 
3419 	guint i_stop;
3420 
3421 	endptr = NULL;
3422 	i_stop = g_ascii_strtoull(path + path_offset + 1,
3423 				  &endptr,
3424 				  10);
3425 
3426 	current = g_list_nth_data(start_soundcard,
3427 				  i_stop);
3428 
3429 	path_offset += ((endptr + 1) - (path + path_offset));
3430 
3431 	start_response = ags_osc_renew_controller_set_data_soundcard(osc_renew_controller,
3432 								     osc_connection,
3433 								     current,
3434 								     message, message_size,
3435 								     type_tag,
3436 								     path, path_offset);
3437       }else if(ags_regexec(&range_access_regex, path + path_offset, max_matches, match_arr, 0) == 0){
3438 	gchar *endptr;
3439 
3440 	guint i;
3441 	guint i_start, i_stop;
3442 
3443 	endptr = NULL;
3444 	i_start = g_ascii_strtoull(path + path_offset + 1,
3445 				   &endptr,
3446 				   10);
3447 
3448 	i_stop = g_ascii_strtoull(endptr + 1,
3449 				  &endptr,
3450 				  10);
3451 
3452 	path_offset += ((endptr + 1) - (path + path_offset));
3453 
3454 	soundcard = g_list_nth(start_soundcard,
3455 			       i_start);
3456 
3457 	for(i = i_start; i <= i_stop; i++){
3458 	  GList *retval;
3459 
3460 	  retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
3461 							     osc_connection,
3462 							     soundcard->data,
3463 							     message, message_size,
3464 							     type_tag,
3465 							     path, path_offset);
3466 
3467 	  if(start_response != NULL){
3468 	    start_response = g_list_concat(start_response,
3469 					   retval);
3470 	  }else{
3471 	    start_response = retval;
3472 	  }
3473 
3474 	  soundcard = soundcard->next;
3475 	}
3476       }else if(ags_regexec(&voluntary_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
3477 	path_offset += 3;
3478 
3479 	if(start_soundcard != NULL){
3480 	  GList *retval;
3481 
3482 	  retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
3483 							     osc_connection,
3484 							     start_soundcard->data,
3485 							     message, message_size,
3486 							     type_tag,
3487 							     path, path_offset);
3488 	}else{
3489 	  osc_response = ags_osc_response_new();
3490 	  start_response = g_list_prepend(start_response,
3491 					  osc_response);
3492 
3493 	  ags_osc_response_set_flags(osc_response,
3494 				     AGS_OSC_RESPONSE_OK);
3495 
3496 	  free(type_tag);
3497 	  free(path);
3498 
3499 	  return(start_response);
3500 	}
3501       }else if(ags_regexec(&more_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
3502 	path_offset += 3;
3503 
3504 	if(start_soundcard == NULL){
3505 	  osc_response = ags_osc_response_new();
3506 	  start_response = g_list_prepend(start_response,
3507 					  osc_response);
3508 
3509 	  ags_osc_response_set_flags(osc_response,
3510 				     AGS_OSC_RESPONSE_ERROR);
3511 
3512 	  g_object_set(osc_response,
3513 		       "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
3514 		       NULL);
3515 
3516 	  free(type_tag);
3517 	  free(path);
3518 
3519 	  return(start_response);
3520 	}
3521 
3522 	soundcard = start_soundcard;
3523 
3524 	while(soundcard != NULL){
3525 	  GList *retval;
3526 
3527 	  retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
3528 							     osc_connection,
3529 							     soundcard->data,
3530 							     message, message_size,
3531 							     type_tag,
3532 							     path, path_offset);
3533 
3534 	  if(start_response != NULL){
3535 	    start_response = g_list_concat(start_response,
3536 					   retval);
3537 	  }else{
3538 	    start_response = retval;
3539 	  }
3540 
3541 	  soundcard = soundcard->next;
3542 	}
3543       }else if(ags_regexec(&wildcard_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
3544 	path_offset += 3;
3545 
3546 	if(start_soundcard == NULL){
3547 	  osc_response = ags_osc_response_new();
3548 	  start_response = g_list_prepend(start_response,
3549 					  osc_response);
3550 
3551 	  ags_osc_response_set_flags(osc_response,
3552 				     AGS_OSC_RESPONSE_OK);
3553 
3554 	  free(type_tag);
3555 	  free(path);
3556 
3557 	  return(start_response);
3558 	}
3559 
3560 	while(soundcard != NULL){
3561 	  GList *retval;
3562 
3563 	  retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
3564 							     osc_connection,
3565 							     soundcard->data,
3566 							     message, message_size,
3567 							     type_tag,
3568 							     path, path_offset);
3569 
3570 	  if(start_response != NULL){
3571 	    start_response = g_list_concat(start_response,
3572 					   retval);
3573 	  }else{
3574 	    start_response = retval;
3575 	  }
3576 
3577 	  soundcard = soundcard->next;
3578 	}
3579       }else{
3580 	osc_response = ags_osc_response_new();
3581 	start_response = g_list_prepend(start_response,
3582 					osc_response);
3583 
3584 	ags_osc_response_set_flags(osc_response,
3585 				   AGS_OSC_RESPONSE_ERROR);
3586 
3587 	g_object_set(osc_response,
3588 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
3589 		     NULL);
3590 
3591 	g_list_free_full(start_soundcard,
3592 			 g_object_unref);
3593 
3594 	free(type_tag);
3595 	free(path);
3596 
3597 	return(start_response);
3598       }
3599 
3600       g_list_free_full(start_soundcard,
3601 		       g_object_unref);
3602     }else if(!strncmp(path + path_offset,
3603 		      "/AgsSequencer",
3604 		      13)){
3605       GList *start_sequencer, *sequencer;
3606 
3607       regmatch_t match_arr[2];
3608 
3609       static regex_t single_access_regex;
3610       static regex_t range_access_regex;
3611       static regex_t voluntary_access_regex;
3612       static regex_t more_access_regex;
3613       static regex_t wildcard_access_regex;
3614 
3615       static gboolean regex_compiled = FALSE;
3616 
3617       static const gchar *single_access_pattern = "^\\[([0-9]+)\\]";
3618       static const gchar *range_access_pattern = "^\\[([0-9]+)\\-([0-9]+)\\]";
3619       static const gchar *voluntary_access_pattern = "^\\[(\\?)\\]";
3620       static const gchar *more_access_pattern = "^\\[(\\+)\\]";
3621       static const gchar *wildcard_access_pattern = "^\\[(\\*)\\]";
3622 
3623       static const size_t max_matches = 2;
3624       static const size_t index_max_matches = 1;
3625 
3626       path_offset += 13;
3627 
3628       /* compile regex */
3629       g_mutex_lock(&regex_mutex);
3630 
3631       if(!regex_compiled){
3632 	regex_compiled = TRUE;
3633 
3634 	ags_regcomp(&single_access_regex, single_access_pattern, REG_EXTENDED);
3635 	ags_regcomp(&range_access_regex, range_access_pattern, REG_EXTENDED);
3636 	ags_regcomp(&voluntary_access_regex, voluntary_access_pattern, REG_EXTENDED);
3637 	ags_regcomp(&more_access_regex, more_access_pattern, REG_EXTENDED);
3638 	ags_regcomp(&wildcard_access_regex, wildcard_access_pattern, REG_EXTENDED);
3639       }
3640 
3641       g_mutex_unlock(&regex_mutex);
3642 
3643       sequencer =
3644 	start_sequencer = ags_sound_provider_get_sequencer(AGS_SOUND_PROVIDER(application_context));
3645 
3646       if(ags_regexec(&single_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
3647 	GObject *current;
3648 
3649 	gchar *endptr;
3650 
3651 	guint i_stop;
3652 
3653 	endptr = NULL;
3654 	i_stop = g_ascii_strtoull(path + path_offset + 1,
3655 				  &endptr,
3656 				  10);
3657 
3658 	current = g_list_nth_data(start_sequencer,
3659 				  i_stop);
3660 
3661 	path_offset += ((endptr + 1) - (path + path_offset));
3662 
3663 	start_response = ags_osc_renew_controller_set_data_sequencer(osc_renew_controller,
3664 								     osc_connection,
3665 								     current,
3666 								     message, message_size,
3667 								     type_tag,
3668 								     path, path_offset);
3669       }else if(ags_regexec(&range_access_regex, path + path_offset, max_matches, match_arr, 0) == 0){
3670 	gchar *endptr;
3671 
3672 	guint i;
3673 	guint i_start, i_stop;
3674 
3675 	endptr = NULL;
3676 	i_start = g_ascii_strtoull(path + path_offset + 1,
3677 				   &endptr,
3678 				   10);
3679 
3680 	i_stop = g_ascii_strtoull(endptr + 1,
3681 				  &endptr,
3682 				  10);
3683 
3684 	path_offset += ((endptr + 1) - (path + path_offset));
3685 
3686 	sequencer = g_list_nth(start_sequencer,
3687 			       i_start);
3688 
3689 	for(i = i_start; i <= i_stop; i++){
3690 	  GList *retval;
3691 
3692 	  retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
3693 							     osc_connection,
3694 							     sequencer->data,
3695 							     message, message_size,
3696 							     type_tag,
3697 							     path, path_offset);
3698 
3699 	  if(start_response != NULL){
3700 	    start_response = g_list_concat(start_response,
3701 					   retval);
3702 	  }else{
3703 	    start_response = retval;
3704 	  }
3705 
3706 	  sequencer = sequencer->next;
3707 	}
3708       }else if(ags_regexec(&voluntary_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
3709 	path_offset += 3;
3710 
3711 	if(start_sequencer != NULL){
3712 	  GList *retval;
3713 
3714 	  retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
3715 							     osc_connection,
3716 							     start_sequencer->data,
3717 							     message, message_size,
3718 							     type_tag,
3719 							     path, path_offset);
3720 	}else{
3721 	  osc_response = ags_osc_response_new();
3722 	  start_response = g_list_prepend(start_response,
3723 					  osc_response);
3724 
3725 	  ags_osc_response_set_flags(osc_response,
3726 				     AGS_OSC_RESPONSE_OK);
3727 
3728 	  free(type_tag);
3729 	  free(path);
3730 
3731 	  return(start_response);
3732 	}
3733       }else if(ags_regexec(&more_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
3734 	path_offset += 3;
3735 
3736 	if(start_sequencer == NULL){
3737 	  osc_response = ags_osc_response_new();
3738 	  start_response = g_list_prepend(start_response,
3739 					  osc_response);
3740 
3741 	  ags_osc_response_set_flags(osc_response,
3742 				     AGS_OSC_RESPONSE_ERROR);
3743 
3744 	  g_object_set(osc_response,
3745 		       "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
3746 		       NULL);
3747 
3748 	  free(type_tag);
3749 	  free(path);
3750 
3751 	  return(start_response);
3752 	}
3753 
3754 	sequencer = start_sequencer;
3755 
3756 	while(sequencer != NULL){
3757 	  GList *retval;
3758 
3759 	  retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
3760 							     osc_connection,
3761 							     sequencer->data,
3762 							     message, message_size,
3763 							     type_tag,
3764 							     path, path_offset);
3765 
3766 	  if(start_response != NULL){
3767 	    start_response = g_list_concat(start_response,
3768 					   retval);
3769 	  }else{
3770 	    start_response = retval;
3771 	  }
3772 
3773 	  sequencer = sequencer->next;
3774 	}
3775       }else if(ags_regexec(&wildcard_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
3776 	path_offset += 3;
3777 
3778 	if(start_sequencer == NULL){
3779 	  osc_response = ags_osc_response_new();
3780 	  start_response = g_list_prepend(start_response,
3781 					  osc_response);
3782 
3783 	  ags_osc_response_set_flags(osc_response,
3784 				     AGS_OSC_RESPONSE_OK);
3785 
3786 	  free(type_tag);
3787 	  free(path);
3788 
3789 	  return(start_response);
3790 	}
3791 
3792 	while(sequencer != NULL){
3793 	  GList *retval;
3794 
3795 	  retval = ags_osc_renew_controller_set_data_channel(osc_renew_controller,
3796 							     osc_connection,
3797 							     sequencer->data,
3798 							     message, message_size,
3799 							     type_tag,
3800 							     path, path_offset);
3801 
3802 	  if(start_response != NULL){
3803 	    start_response = g_list_concat(start_response,
3804 					   retval);
3805 	  }else{
3806 	    start_response = retval;
3807 	  }
3808 
3809 	  sequencer = sequencer->next;
3810 	}
3811       }else{
3812 	osc_response = ags_osc_response_new();
3813 	start_response = g_list_prepend(start_response,
3814 					osc_response);
3815 
3816 	ags_osc_response_set_flags(osc_response,
3817 				   AGS_OSC_RESPONSE_ERROR);
3818 
3819 	g_object_set(osc_response,
3820 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
3821 		     NULL);
3822 
3823 	g_list_free_full(start_sequencer,
3824 			 g_object_unref);
3825 
3826 	free(type_tag);
3827 	free(path);
3828 
3829 	return(start_response);
3830       }
3831 
3832       g_list_free_full(start_sequencer,
3833 		       g_object_unref);
3834     }else if(!strncmp(path + path_offset,
3835 		      "/AgsAudio",
3836 		      9)){
3837       GList *start_audio, *audio;
3838 
3839       regmatch_t match_arr[2];
3840 
3841       static regex_t single_access_regex;
3842       static regex_t range_access_regex;
3843       static regex_t voluntary_access_regex;
3844       static regex_t more_access_regex;
3845       static regex_t wildcard_access_regex;
3846 
3847       static gboolean regex_compiled = FALSE;
3848 
3849       static const gchar *single_access_pattern = "^\\[([0-9]+)\\]";
3850       static const gchar *range_access_pattern = "^\\[([0-9]+)\\-([0-9]+)\\]";
3851       static const gchar *voluntary_access_pattern = "^\\[(\\?)\\]";
3852       static const gchar *more_access_pattern = "^\\[(\\+)\\]";
3853       static const gchar *wildcard_access_pattern = "^\\[(\\*)\\]";
3854 
3855       static const size_t max_matches = 2;
3856       static const size_t index_max_matches = 1;
3857 
3858       path_offset += 9;
3859 
3860       /* compile regex */
3861       g_mutex_lock(&regex_mutex);
3862 
3863       if(!regex_compiled){
3864 	regex_compiled = TRUE;
3865 
3866 	ags_regcomp(&single_access_regex, single_access_pattern, REG_EXTENDED);
3867 	ags_regcomp(&range_access_regex, range_access_pattern, REG_EXTENDED);
3868 	ags_regcomp(&voluntary_access_regex, voluntary_access_pattern, REG_EXTENDED);
3869 	ags_regcomp(&more_access_regex, more_access_pattern, REG_EXTENDED);
3870 	ags_regcomp(&wildcard_access_regex, wildcard_access_pattern, REG_EXTENDED);
3871       }
3872 
3873       g_mutex_unlock(&regex_mutex);
3874 
3875       audio =
3876 	start_audio = ags_sound_provider_get_audio(AGS_SOUND_PROVIDER(application_context));
3877 
3878       if(ags_regexec(&single_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
3879 	AgsAudio *current;
3880 
3881 	gchar *endptr;
3882 
3883 	guint i_stop;
3884 
3885 	endptr = NULL;
3886 	i_stop = g_ascii_strtoull(path + path_offset + 1,
3887 				  &endptr,
3888 				  10);
3889 
3890 	current = g_list_nth_data(start_audio,
3891 				  i_stop);
3892 
3893 	path_offset += ((endptr + 1) - (path + path_offset));
3894 
3895 	start_response = ags_osc_renew_controller_set_data_audio(osc_renew_controller,
3896 								 osc_connection,
3897 								 current,
3898 								 message, message_size,
3899 								 type_tag,
3900 								 path, path_offset);
3901       }else if(ags_regexec(&range_access_regex, path + path_offset, max_matches, match_arr, 0) == 0){
3902 	gchar *endptr;
3903 
3904 	guint i;
3905 	guint i_start, i_stop;
3906 
3907 	endptr = NULL;
3908 	i_start = g_ascii_strtoull(path + path_offset + 1,
3909 				   &endptr,
3910 				   10);
3911 
3912 	i_stop = g_ascii_strtoull(endptr + 1,
3913 				  &endptr,
3914 				  10);
3915 
3916 	path_offset += ((endptr + 1) - (path + path_offset));
3917 
3918 	audio = g_list_nth(start_audio,
3919 			   i_start);
3920 
3921 	for(i = i_start; i <= i_stop; i++){
3922 	  GList *retval;
3923 
3924 	  retval = ags_osc_renew_controller_set_data_audio(osc_renew_controller,
3925 							   osc_connection,
3926 							   audio->data,
3927 							   message, message_size,
3928 							   type_tag,
3929 							   path, path_offset);
3930 
3931 	  if(start_response != NULL){
3932 	    start_response = g_list_concat(start_response,
3933 					   retval);
3934 	  }else{
3935 	    start_response = retval;
3936 	  }
3937 
3938 	  audio = audio->next;
3939 	}
3940       }else if(ags_regexec(&voluntary_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
3941 	path_offset += 3;
3942 
3943 	if(start_audio != NULL){
3944 	  GList *retval;
3945 
3946 	  retval = ags_osc_renew_controller_set_data_audio(osc_renew_controller,
3947 							   osc_connection,
3948 							   start_audio->data,
3949 							   message, message_size,
3950 							   type_tag,
3951 							   path, path_offset);
3952 	}else{
3953 	  osc_response = ags_osc_response_new();
3954 	  start_response = g_list_prepend(start_response,
3955 					  osc_response);
3956 
3957 	  ags_osc_response_set_flags(osc_response,
3958 				     AGS_OSC_RESPONSE_OK);
3959 
3960 	  free(type_tag);
3961 	  free(path);
3962 
3963 	  return(start_response);
3964 	}
3965       }else if(ags_regexec(&more_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
3966 	path_offset += 3;
3967 
3968 	if(start_audio == NULL){
3969 	  osc_response = ags_osc_response_new();
3970 	  start_response = g_list_prepend(start_response,
3971 					  osc_response);
3972 
3973 	  ags_osc_response_set_flags(osc_response,
3974 				     AGS_OSC_RESPONSE_ERROR);
3975 
3976 	  g_object_set(osc_response,
3977 		       "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
3978 		       NULL);
3979 
3980 	  free(type_tag);
3981 	  free(path);
3982 
3983 	  return(start_response);
3984 	}
3985 
3986 	audio = start_audio;
3987 
3988 	while(audio != NULL){
3989 	  GList *retval;
3990 
3991 	  retval = ags_osc_renew_controller_set_data_audio(osc_renew_controller,
3992 							   osc_connection,
3993 							   audio->data,
3994 							   message, message_size,
3995 							   type_tag,
3996 							   path, path_offset);
3997 
3998 	  if(start_response != NULL){
3999 	    start_response = g_list_concat(start_response,
4000 					   retval);
4001 	  }else{
4002 	    start_response = retval;
4003 	  }
4004 
4005 	  audio = audio->next;
4006 	}
4007       }else if(ags_regexec(&wildcard_access_regex, path + path_offset, index_max_matches, match_arr, 0) == 0){
4008 	path_offset += 3;
4009 
4010 	if(start_audio == NULL){
4011 	  osc_response = ags_osc_response_new();
4012 	  start_response = g_list_prepend(start_response,
4013 					  osc_response);
4014 
4015 	  ags_osc_response_set_flags(osc_response,
4016 				     AGS_OSC_RESPONSE_OK);
4017 
4018 	  free(type_tag);
4019 	  free(path);
4020 
4021 	  return(start_response);
4022 	}
4023 
4024 	while(audio != NULL){
4025 	  GList *retval;
4026 
4027 	  retval = ags_osc_renew_controller_set_data_audio(osc_renew_controller,
4028 							   osc_connection,
4029 							   audio->data,
4030 							   message, message_size,
4031 							   type_tag,
4032 							   path, path_offset);
4033 
4034 	  if(start_response != NULL){
4035 	    start_response = g_list_concat(start_response,
4036 					   retval);
4037 	  }else{
4038 	    start_response = retval;
4039 	  }
4040 
4041 	  audio = audio->next;
4042 	}
4043       }else if(path[path_offset] == '[' &&
4044 	       path[path_offset + 1] == '"'){
4045 	AgsAudio *current;
4046 
4047 	gchar *audio_name;
4048 	gchar *offset;
4049 
4050 	guint length;
4051 
4052 	if((offset = strchr(path + path_offset + 2, '"')) == NULL){
4053 	  osc_response = ags_osc_response_new();
4054 	  start_response = g_list_prepend(start_response,
4055 					  osc_response);
4056 
4057 	  ags_osc_response_set_flags(osc_response,
4058 				     AGS_OSC_RESPONSE_ERROR);
4059 
4060 	  g_object_set(osc_response,
4061 		       "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_CHUNK_SIZE_EXCEEDED,
4062 		       NULL);
4063 
4064 	  g_list_free_full(start_audio,
4065 			   g_object_unref);
4066 
4067 	  free(type_tag);
4068 	  free(path);
4069 
4070 	  return(start_response);
4071 	}
4072 
4073 	length = offset - (path + path_offset + 2);
4074 
4075 	audio_name = (gchar *) malloc((length + 1) * sizeof(gchar));
4076 	memcpy(audio_name, path + path_offset + 2, (length) * sizeof(gchar));
4077 	audio_name[length] = '\0';
4078 
4079 	current = NULL;
4080 	audio = ags_audio_find_name(start_audio,
4081 				    audio_name);
4082 
4083 	if(audio != NULL){
4084 	  current = audio->data;
4085 	}
4086 
4087 	path_offset += (length + 4);
4088 	start_response = ags_osc_renew_controller_set_data_audio(osc_renew_controller,
4089 								 osc_connection,
4090 								 current,
4091 								 message, message_size,
4092 								 type_tag,
4093 								 path, path_offset);
4094       }else{
4095 	osc_response = ags_osc_response_new();
4096 	start_response = g_list_prepend(start_response,
4097 					osc_response);
4098 
4099 	ags_osc_response_set_flags(osc_response,
4100 				   AGS_OSC_RESPONSE_ERROR);
4101 
4102 	g_object_set(osc_response,
4103 		     "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
4104 		     NULL);
4105 
4106 	g_list_free_full(start_audio,
4107 			 g_object_unref);
4108 
4109 	free(type_tag);
4110 	free(path);
4111 
4112 	return(start_response);
4113       }
4114 
4115       g_list_free_full(start_audio,
4116 		       g_object_unref);
4117     }else{
4118       osc_response = ags_osc_response_new();
4119       start_response = g_list_prepend(start_response,
4120 				      osc_response);
4121 
4122       ags_osc_response_set_flags(osc_response,
4123 				 AGS_OSC_RESPONSE_ERROR);
4124 
4125       g_object_set(osc_response,
4126 		   "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_UNKNOWN_ARGUMENT,
4127 		   NULL);
4128 
4129       free(type_tag);
4130       free(path);
4131 
4132       return(start_response);
4133     }
4134   }
4135 
4136   if(start_response == NULL){
4137     osc_response = ags_osc_response_new();
4138     start_response = g_list_prepend(start_response,
4139 				    osc_response);
4140 
4141     ags_osc_response_set_flags(osc_response,
4142 			       AGS_OSC_RESPONSE_ERROR);
4143 
4144     g_object_set(osc_response,
4145 		 "error-message", AGS_OSC_RESPONSE_ERROR_MESSAGE_SERVER_FAILURE,
4146 		 NULL);
4147 
4148     free(type_tag);
4149     free(path);
4150 
4151     return(start_response);
4152   }
4153 
4154   free(type_tag);
4155   free(path);
4156 
4157   return(start_response);
4158 }
4159 
4160 /**
4161  * ags_osc_renew_controller_set_data:
4162  * @osc_renew_controller: the #AgsOscRenewController
4163  * @osc_connection: the #AgsOscConnection
4164  * @message: the message received
4165  * @message_size: the message size
4166  *
4167  * Renew data.
4168  *
4169  * Returns: the #GList-struct containing #AgsOscResponse
4170  *
4171  * Since: 3.0.0
4172  */
4173 gpointer
ags_osc_renew_controller_set_data(AgsOscRenewController * osc_renew_controller,AgsOscConnection * osc_connection,unsigned char * message,guint message_size)4174 ags_osc_renew_controller_set_data(AgsOscRenewController *osc_renew_controller,
4175 				  AgsOscConnection *osc_connection,
4176 				  unsigned char *message, guint message_size)
4177 {
4178   gpointer osc_response;
4179 
4180   g_return_val_if_fail(AGS_IS_OSC_RENEW_CONTROLLER(osc_renew_controller), NULL);
4181 
4182   g_object_ref((GObject *) osc_renew_controller);
4183   g_signal_emit(G_OBJECT(osc_renew_controller),
4184 		osc_renew_controller_signals[SET_DATA], 0,
4185 		osc_connection,
4186 		message, message_size,
4187 		&osc_response);
4188   g_object_unref((GObject *) osc_renew_controller);
4189 
4190   return(osc_response);
4191 }
4192 
4193 /**
4194  * ags_osc_renew_controller_new:
4195  *
4196  * Instantiate new #AgsOscRenewController
4197  *
4198  * Returns: the #AgsOscRenewController
4199  *
4200  * Since: 3.0.0
4201  */
4202 AgsOscRenewController*
ags_osc_renew_controller_new()4203 ags_osc_renew_controller_new()
4204 {
4205   AgsOscRenewController *osc_renew_controller;
4206 
4207   osc_renew_controller = (AgsOscRenewController *) g_object_new(AGS_TYPE_OSC_RENEW_CONTROLLER,
4208 								NULL);
4209 
4210   return(osc_renew_controller);
4211 }
4212