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(®ex_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(®ex_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(®ex_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(®ex_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(®ex_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(®ex_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(®ex_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(®ex_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(®ex_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(®ex_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(®ex_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(®ex_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(®ex_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(®ex_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