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 General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSequencer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/audio/osc/ags_osc_parser.h>
21 
22 #include <ags/audio/osc/ags_osc_util.h>
23 
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include <ags/i18n.h>
28 
29 void ags_osc_parser_class_init(AgsOscParserClass *osc_parser);
30 void ags_osc_parser_init(AgsOscParser *osc_parser);
31 void ags_osc_parser_set_property(GObject *gobject,
32 				 guint prop_id,
33 				 const GValue *value,
34 				 GParamSpec *param_spec);
35 void ags_osc_parser_get_property(GObject *gobject,
36 				 guint prop_id,
37 				 GValue *value,
38 				 GParamSpec *param_spec);
39 void ags_osc_parser_finalize(GObject *gobject);
40 
41 int ags_osc_parser_real_osc_getc(AgsOscParser *osc_parser);
42 void ags_osc_parser_real_on_error(AgsOscParser *osc_parser,
43 				  GError **error);
44 
45 xmlDoc* ags_osc_parser_real_parse_full(AgsOscParser *osc_parser);
46 xmlNode* ags_osc_parser_real_parse_bytes(AgsOscParser *osc_parser,
47 					 unsigned char *osc_buffer,
48 					 guint buffer_length);
49 
50 xmlNode* ags_osc_parser_real_packet(AgsOscParser *osc_parser);
51 
52 xmlNode* ags_osc_parser_real_bundle(AgsOscParser *osc_parser);
53 
54 xmlNode* ags_osc_parser_real_message(AgsOscParser *osc_parser);
55 
56 xmlNode* ags_osc_parser_real_value(AgsOscParser *osc_parser,
57 				   guint v_type);
58 
59 /**
60  * SECTION:ags_osc_parser
61  * @short_description: the OSC parser
62  * @title: AgsOscParser
63  * @section_id:
64  * @include: ags/audio/osc/ags_osc_parser.h
65  *
66  * #AgsOscParser reads your osc parsers.
67  */
68 
69 enum{
70   PROP_0,
71 };
72 
73 enum{
74   OSC_GETC,
75   ON_ERROR,
76   PARSE_FULL,
77   PARSE_BYTES,
78   PACKET,
79   BUNDLE,
80   MESSAGE,
81   VALUE,
82   LAST_SIGNAL,
83 };
84 
85 static gpointer ags_osc_parser_parent_class = NULL;
86 static guint osc_parser_signals[LAST_SIGNAL];
87 
88 GType
ags_osc_parser_get_type(void)89 ags_osc_parser_get_type(void)
90 {
91   static volatile gsize g_define_type_id__volatile = 0;
92 
93   if(g_once_init_enter (&g_define_type_id__volatile)){
94     GType ags_type_osc_parser = 0;
95 
96     static const GTypeInfo ags_osc_parser_info = {
97       sizeof (AgsOscParserClass),
98       NULL, /* base_init */
99       NULL, /* base_finalize */
100       (GClassInitFunc) ags_osc_parser_class_init,
101       NULL, /* class_finalize */
102       NULL, /* class_data */
103       sizeof (AgsOscParser),
104       0,    /* n_preallocs */
105       (GInstanceInitFunc) ags_osc_parser_init,
106     };
107 
108     ags_type_osc_parser = g_type_register_static(G_TYPE_OBJECT,
109 						 "AgsOscParser", &ags_osc_parser_info,
110 						 0);
111 
112     g_once_init_leave(&g_define_type_id__volatile, ags_type_osc_parser);
113   }
114 
115   return g_define_type_id__volatile;
116 }
117 
118 void
ags_osc_parser_class_init(AgsOscParserClass * osc_parser)119 ags_osc_parser_class_init(AgsOscParserClass *osc_parser)
120 {
121   GObjectClass *gobject;
122   GParamSpec *param_spec;
123 
124   ags_osc_parser_parent_class = g_type_class_peek_parent(osc_parser);
125 
126   /* GObjectClass */
127   gobject = (GObjectClass *) osc_parser;
128 
129   gobject->set_property = ags_osc_parser_set_property;
130   gobject->get_property = ags_osc_parser_get_property;
131 
132   gobject->finalize = ags_osc_parser_finalize;
133 
134   /* AgsOscParser */
135   osc_parser->osc_getc = ags_osc_parser_real_osc_getc;
136   osc_parser->on_error = ags_osc_parser_real_on_error;
137 
138   osc_parser->parse_full = ags_osc_parser_real_parse_full;
139   osc_parser->parse_bytes = ags_osc_parser_real_parse_bytes;
140 
141   osc_parser->packet = ags_osc_parser_real_packet;
142 
143   osc_parser->bundle = ags_osc_parser_real_bundle;
144 
145   osc_parser->packet = ags_osc_parser_real_packet;
146 
147   osc_parser->value = ags_osc_parser_real_value;
148 
149   /* signals */
150   /**
151    * AgsOscParser::osc-getc:
152    * @osc_parser: the #AgsOscParser
153    *
154    * The ::osc-getc signal is emited during parsing of event.
155    *
156    * Returns: The character read
157    *
158    * Since: 3.0.0
159    */
160   osc_parser_signals[OSC_GETC] =
161     g_signal_new("osc-getc",
162 		 G_TYPE_FROM_CLASS(osc_parser),
163 		 G_SIGNAL_RUN_LAST,
164 		 G_STRUCT_OFFSET(AgsOscParserClass, osc_getc),
165 		 NULL, NULL,
166 		 ags_cclosure_marshal_INT__VOID,
167 		 G_TYPE_INT, 0);
168 
169   /**
170    * AgsOscParser::on-error:
171    * @osc_parser: the #AgsOscParser
172    * @error: the return location of #GError
173    *
174    * The ::on-error signal is emited as error occurs.
175    *
176    * Since: 3.0.0
177    */
178   osc_parser_signals[ON_ERROR] =
179     g_signal_new("on-error",
180 		 G_TYPE_FROM_CLASS(osc_parser),
181 		 G_SIGNAL_RUN_LAST,
182 		 G_STRUCT_OFFSET(AgsOscParserClass, on_error),
183 		 NULL, NULL,
184 		 g_cclosure_marshal_VOID__POINTER,
185 		 G_TYPE_NONE, 1,
186 		 G_TYPE_POINTER);
187 
188   /**
189    * AgsOscParser::parse-full:
190    * @osc_parser: the #AgsOscParser
191    *
192    * The ::parse-full signal is emited during parsing of osc file.
193    *
194    * Returns: The XML doc
195    *
196    * Since: 3.0.0
197    */
198   osc_parser_signals[PARSE_FULL] =
199     g_signal_new("parse-full",
200 		 G_TYPE_FROM_CLASS(osc_parser),
201 		 G_SIGNAL_RUN_LAST,
202 		 G_STRUCT_OFFSET(AgsOscParserClass, parse_full),
203 		 NULL, NULL,
204 		 ags_cclosure_marshal_POINTER__VOID,
205 		 G_TYPE_POINTER, 0);
206 
207   /**
208    * AgsOscParser::parse-bytes:
209    * @osc_parser: the #AgsOscParser
210    * @buffer: the OSC data
211    * @buffer_length: the buffer's length
212    *
213    * The ::parse-bytes signal is emited during parsing of bytes.
214    *
215    * Returns: The XML node representing the event
216    *
217    * Since: 3.0.0
218    */
219   osc_parser_signals[PARSE_BYTES] =
220     g_signal_new("parse-bytes",
221 		 G_TYPE_FROM_CLASS(osc_parser),
222 		 G_SIGNAL_RUN_LAST,
223 		 G_STRUCT_OFFSET(AgsOscParserClass, parse_bytes),
224 		 NULL, NULL,
225 		 ags_cclosure_marshal_POINTER__POINTER_UINT,
226 		 G_TYPE_POINTER, 2,
227 		 G_TYPE_POINTER,
228 		 G_TYPE_UINT);
229 
230   /**
231    * AgsOscParser::packet:
232    * @osc_parser: the #AgsOscParser
233    *
234    * The ::packet signal is emited during parsing.
235    *
236    * Returns: The XML node representing packet
237    *
238    * Since: 3.0.0
239    */
240   osc_parser_signals[PACKET] =
241     g_signal_new("packet",
242 		 G_TYPE_FROM_CLASS(osc_parser),
243 		 G_SIGNAL_RUN_LAST,
244 		 G_STRUCT_OFFSET(AgsOscParserClass, packet),
245 		 NULL, NULL,
246 		 ags_cclosure_marshal_POINTER__VOID,
247 		 G_TYPE_POINTER, 0);
248 
249   /**
250    * AgsOscParser::bundle:
251    * @osc_parser: the #AgsOscParser
252    *
253    * The ::bundle signal is emited during parsing.
254    *
255    * Returns: The XML node representing bundle
256    *
257    * Since: 3.0.0
258    */
259   osc_parser_signals[BUNDLE] =
260     g_signal_new("bundle",
261 		 G_TYPE_FROM_CLASS(osc_parser),
262 		 G_SIGNAL_RUN_LAST,
263 		 G_STRUCT_OFFSET(AgsOscParserClass, bundle),
264 		 NULL, NULL,
265 		 ags_cclosure_marshal_POINTER__VOID,
266 		 G_TYPE_POINTER, 0);
267 
268   /**
269    * AgsOscParser::message:
270    * @osc_parser: the #AgsOscParser
271    *
272    * The ::message signal is emited during parsing.
273    *
274    * Returns: The XML node representing message
275    *
276    * Since: 3.0.0
277    */
278   osc_parser_signals[MESSAGE] =
279     g_signal_new("message",
280 		 G_TYPE_FROM_CLASS(osc_parser),
281 		 G_SIGNAL_RUN_LAST,
282 		 G_STRUCT_OFFSET(AgsOscParserClass, message),
283 		 NULL, NULL,
284 		 ags_cclosure_marshal_POINTER__VOID,
285 		 G_TYPE_POINTER, 0);
286 
287   /**
288    * AgsOscParser::value:
289    * @osc_parser: the #AgsOscParser
290    * @v_type: value type
291    *
292    * The ::value signal is emited during parsing.
293    *
294    * Returns: The XML node representing value
295    *
296    * Since: 3.0.0
297    */
298   osc_parser_signals[VALUE] =
299     g_signal_new("value",
300 		 G_TYPE_FROM_CLASS(osc_parser),
301 		 G_SIGNAL_RUN_LAST,
302 		 G_STRUCT_OFFSET(AgsOscParserClass, value),
303 		 NULL, NULL,
304 		 ags_cclosure_marshal_POINTER__UINT,
305 		 G_TYPE_POINTER, 1,
306 		 G_TYPE_UINT);
307 }
308 
309 void
ags_osc_parser_init(AgsOscParser * osc_parser)310 ags_osc_parser_init(AgsOscParser *osc_parser)
311 {
312   osc_parser->flags = 0;
313 
314   /* osc parser mutex */
315   g_rec_mutex_init(&(osc_parser->obj_mutex));
316 
317   osc_parser->buffer = NULL;
318 
319   osc_parser->file_length = 0;
320   osc_parser->offset = 0;
321 
322   osc_parser->start_offset = 0;
323   osc_parser->packet_size = 0;
324 
325   osc_parser->doc = NULL;
326 }
327 
328 void
ags_osc_parser_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)329 ags_osc_parser_set_property(GObject *gobject,
330 			    guint prop_id,
331 			    const GValue *value,
332 			    GParamSpec *param_spec)
333 {
334   AgsOscParser *osc_parser;
335 
336   GRecMutex *osc_parser_mutex;
337 
338   osc_parser = AGS_OSC_PARSER(gobject);
339 
340   /* get osc parser mutex */
341   osc_parser_mutex = AGS_OSC_PARSER_GET_OBJ_MUTEX(osc_parser);
342 
343   switch(prop_id){
344   default:
345     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
346     break;
347   }
348 }
349 
350 void
ags_osc_parser_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)351 ags_osc_parser_get_property(GObject *gobject,
352 			    guint prop_id,
353 			    GValue *value,
354 			    GParamSpec *param_spec)
355 {
356   AgsOscParser *osc_parser;
357 
358   GRecMutex *osc_parser_mutex;
359 
360   osc_parser = AGS_OSC_PARSER(gobject);
361 
362   /* get osc parser mutex */
363   osc_parser_mutex = AGS_OSC_PARSER_GET_OBJ_MUTEX(osc_parser);
364 
365   switch(prop_id){
366   default:
367     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
368     break;
369   }
370 }
371 
372 void
ags_osc_parser_finalize(GObject * gobject)373 ags_osc_parser_finalize(GObject *gobject)
374 {
375   AgsOscParser *osc_parser;
376 
377   osc_parser = (AgsOscParser *) gobject;
378 
379   /* call parent */
380   G_OBJECT_CLASS(ags_osc_parser_parent_class)->finalize(gobject);
381 }
382 
383 /**
384  * ags_osc_parser_read_gint32:
385  * @osc_parser: the #AgsOscParser
386  *
387  * Read 32 bit integer.
388  *
389  * Returns: the gint32 read
390  *
391  * Since: 3.0.0
392  */
393 gint32
ags_osc_parser_read_gint32(AgsOscParser * osc_parser)394 ags_osc_parser_read_gint32(AgsOscParser *osc_parser)
395 {
396   char str[4];
397   gint32 value;
398 
399   str[0] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
400   str[1] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
401   str[2] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
402   str[3] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
403 
404   value = (str[0] & 0xff);
405   value = (value<<8) + (str[1] & 0xff);
406   value = (value<<8) + (str[2] & 0xff);
407   value = (value<<8) + (str[3] & 0xff);
408 
409   return(value);
410 }
411 
412 /**
413  * ags_osc_parser_read_gint64:
414  * @osc_parser: the #AgsOscParser
415  *
416  * Read 64 bit integer.
417  *
418  * Returns: the gint64 read
419  *
420  * Since: 3.0.0
421  */
422 gint64
ags_osc_parser_read_gint64(AgsOscParser * osc_parser)423 ags_osc_parser_read_gint64(AgsOscParser *osc_parser)
424 {
425   char str[8];
426   gint64 value;
427 
428   str[0] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
429   str[1] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
430   str[2] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
431   str[3] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
432   str[4] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
433   str[5] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
434   str[6] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
435   str[7] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
436 
437   value = (str[0] & 0xff);
438   value = (value << 8) + (str[1] & 0xff);
439   value = (value << 8) + (str[2] & 0xff);
440   value = (value << 8) + (str[3] & 0xff);
441   value = (value << 8) + (str[4] & 0xff);
442   value = (value << 8) + (str[5] & 0xff);
443   value = (value << 8) + (str[6] & 0xff);
444   value = (value << 8) + (str[7] & 0xff);
445 
446   return(value);
447 }
448 
449 /**
450  * ags_osc_parser_read_gfloat:
451  * @osc_parser: the #AgsOscParser
452  *
453  * Read floating point value.
454  *
455  * Returns: the gfloat read
456  *
457  * Since: 3.0.0
458  */
459 gfloat
ags_osc_parser_read_gfloat(AgsOscParser * osc_parser)460 ags_osc_parser_read_gfloat(AgsOscParser *osc_parser)
461 {
462   char str[4];
463   union{
464     guint32 val;
465     GFloatIEEE754 ieee_float;
466   }data;
467 
468   str[0] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
469   str[1] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
470   str[2] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
471   str[3] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
472 
473   data.val = (str[0] & 0xff);
474   data.val = (data.val<<8) + (str[1] & 0xff);
475   data.val = (data.val<<8) + (str[2] & 0xff);
476   data.val = (data.val<<8) + (str[3] & 0xff);
477 
478   return(data.ieee_float.v_float);
479 }
480 
481 /**
482  * ags_osc_parser_read_gdouble:
483  * @osc_parser: the #AgsOscParser
484  *
485  * Read double precision floating point value.
486  *
487  * Returns: the gdouble read
488  *
489  * Since: 3.0.0
490  */
491 gdouble
ags_osc_parser_read_gdouble(AgsOscParser * osc_parser)492 ags_osc_parser_read_gdouble(AgsOscParser *osc_parser)
493 {
494   char str[8];
495   union{
496     guint64 val;
497     GDoubleIEEE754 ieee_double;
498   }data;
499 
500   str[0] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
501   str[1] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
502   str[2] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
503   str[3] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
504   str[4] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
505   str[5] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
506   str[6] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
507   str[7] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
508 
509   data.val = (str[0] & 0xff);
510   data.val = (data.val << 8) + (str[1] & 0xff);
511   data.val = (data.val << 8) + (str[2] & 0xff);
512   data.val = (data.val << 8) + (str[3] & 0xff);
513   data.val = (data.val << 8) + (str[4] & 0xff);
514   data.val = (data.val << 8) + (str[5] & 0xff);
515   data.val = (data.val << 8) + (str[6] & 0xff);
516   data.val = (data.val << 8) + (str[7] & 0xff);
517 
518   return(data.ieee_double.v_double);
519 }
520 
521 /**
522  * ags_osc_parser_read_text:
523  * @osc_parser: the #AgsOscParser
524  * @length: the length
525  *
526  * Read text.
527  *
528  * Returns: the text read as string
529  *
530  * Since: 3.0.0
531  */
532 gchar*
ags_osc_parser_read_text(AgsOscParser * osc_parser,gint length)533 ags_osc_parser_read_text(AgsOscParser *osc_parser,
534 			 gint length)
535 {
536   gchar text[AGS_OSC_PARSER_MAX_TEXT_LENGTH + 1];
537 
538   gchar c;
539   guint i;
540 
541   memset(text, 0, AGS_OSC_PARSER_MAX_TEXT_LENGTH * sizeof(char));
542   i = 0;
543 
544   while((length <= 0 ||
545 	 i < length) &&
546 	(AGS_OSC_PARSER_EOF & (osc_parser->flags)) == 0 &&
547 	i < AGS_OSC_PARSER_MAX_TEXT_LENGTH){
548     (c = (char) 0xff & (ags_osc_parser_osc_getc(osc_parser)));
549 
550     if(c == '\0'){
551       break;
552     }
553 
554     text[i] = c;
555     i++;
556   }
557 
558   text[i] = '\0';
559 
560   return(g_strdup(text));
561 }
562 
563 int
ags_osc_parser_real_osc_getc(AgsOscParser * osc_parser)564 ags_osc_parser_real_osc_getc(AgsOscParser *osc_parser)
565 {
566   int c;
567 
568   if(osc_parser->offset >= osc_parser->file_length){
569     osc_parser->flags |= AGS_OSC_PARSER_EOF;
570 
571     return(-1);
572   }
573 
574   c = (int) osc_parser->buffer[osc_parser->offset];
575   osc_parser->offset += 1;
576 
577   return(c);
578 }
579 
580 /**
581  * ags_osc_parser_osc_getc:
582  * @osc_parser: the #AgsOscParser
583  *
584  * Read byte.
585  *
586  * Returns: the byte read
587  *
588  * Since: 3.0.0
589  */
590 int
ags_osc_parser_osc_getc(AgsOscParser * osc_parser)591 ags_osc_parser_osc_getc(AgsOscParser *osc_parser)
592 {
593   int c;
594 
595   g_return_val_if_fail(AGS_IS_OSC_PARSER(osc_parser), '\0');
596 
597   g_object_ref((GObject *) osc_parser);
598   g_signal_emit(G_OBJECT(osc_parser),
599 		osc_parser_signals[OSC_GETC], 0,
600 		&c);
601   g_object_unref((GObject *) osc_parser);
602 
603   return(c);
604 }
605 
606 void
ags_osc_parser_real_on_error(AgsOscParser * osc_parser,GError ** error)607 ags_osc_parser_real_on_error(AgsOscParser *osc_parser,
608 			     GError **error)
609 {
610   //TODO:JK: implement me
611 }
612 
613 /**
614  * ags_osc_parser_on_error:
615  * @osc_parser: the #AgsOscParser
616  * @error: the #GError-struct return location
617  *
618  * On error event.
619  *
620  * Since: 3.0.0
621  */
622 void
ags_osc_parser_on_error(AgsOscParser * osc_parser,GError ** error)623 ags_osc_parser_on_error(AgsOscParser *osc_parser,
624 			GError **error)
625 {
626   g_return_if_fail(AGS_IS_OSC_PARSER(osc_parser));
627 
628   g_object_ref((GObject *) osc_parser);
629   g_signal_emit(G_OBJECT(osc_parser),
630 		osc_parser_signals[ON_ERROR], 0,
631 		error);
632   g_object_unref((GObject *) osc_parser);
633 }
634 
635 xmlDoc*
ags_osc_parser_real_parse_full(AgsOscParser * osc_parser)636 ags_osc_parser_real_parse_full(AgsOscParser *osc_parser)
637 {
638   xmlDoc *doc;
639   xmlNode *root_node;
640   xmlNode *packets_node;
641   xmlNode *current;
642 
643   /* create xmlDoc and set root node */
644   osc_parser->doc =
645     doc = xmlNewDoc("1.0");
646   root_node = xmlNewNode(NULL, "osc");
647   xmlDocSetRootElement(doc, root_node);
648 
649   /* create packets node */
650   packets_node = xmlNewNode(NULL, "osc-packets");
651 
652   /* parse packets */
653   xmlAddChild(root_node,
654 	      packets_node);
655 
656   osc_parser->offset = 0;
657 
658   while(((AGS_OSC_PARSER_EOF & (osc_parser->flags))) == 0){
659     current = ags_osc_parser_packet(osc_parser);
660 
661     if(current != NULL){
662       xmlAddChild(packets_node,
663 		  current);
664 #ifdef AGS_DEBUG
665       g_message("parsed packet");
666 #endif
667     }else{
668       g_warning("skipped input");
669     }
670   }
671 
672   return(doc);
673 }
674 
675 /**
676  * ags_osc_parser_parse_full:
677  * @osc_parser: the #AgsOscParser
678  *
679  * Parse full document.
680  *
681  * Returns: (transfer none): the parsed XML doc
682  *
683  * Since: 3.0.0
684  */
685 xmlDoc*
ags_osc_parser_parse_full(AgsOscParser * osc_parser)686 ags_osc_parser_parse_full(AgsOscParser *osc_parser)
687 {
688   xmlDoc *doc;
689 
690   g_return_val_if_fail(AGS_IS_OSC_PARSER(osc_parser), NULL);
691 
692   g_object_ref((GObject *) osc_parser);
693   g_signal_emit(G_OBJECT(osc_parser),
694 		osc_parser_signals[PARSE_FULL], 0,
695 		&doc);
696   g_object_unref((GObject *) osc_parser);
697 
698   return(doc);
699 }
700 
701 xmlNode*
ags_osc_parser_real_parse_bytes(AgsOscParser * osc_parser,unsigned char * osc_buffer,guint buffer_length)702 ags_osc_parser_real_parse_bytes(AgsOscParser *osc_parser,
703 				unsigned char *osc_buffer,
704 				guint buffer_length)
705 {
706   xmlNode *node;
707 
708   node = NULL;
709 
710   //TODO:JK: implement me
711 
712   return(node);
713 }
714 
715 /**
716  * ags_osc_parser_parse_bytes:
717  * @osc_parser: the #AgsOscParser
718  * @osc_buffer: the data buffer
719  * @buffer_length: the length of data buffer
720  *
721  * Parse bytes.
722  *
723  * Returns: (transfer none): the parsed XML node
724  *
725  * Since: 3.0.0
726  */
727 xmlNode*
ags_osc_parser_parse_bytes(AgsOscParser * osc_parser,unsigned char * osc_buffer,guint buffer_length)728 ags_osc_parser_parse_bytes(AgsOscParser *osc_parser,
729 			   unsigned char *osc_buffer,
730 			   guint buffer_length)
731 {
732   xmlNode *node;
733 
734   g_return_val_if_fail(AGS_IS_OSC_PARSER(osc_parser), NULL);
735 
736   g_object_ref((GObject *) osc_parser);
737   g_signal_emit(G_OBJECT(osc_parser),
738 		osc_parser_signals[PARSE_BYTES], 0,
739 		&node);
740   g_object_unref((GObject *) osc_parser);
741 
742   return(node);
743 }
744 
745 xmlNode*
ags_osc_parser_real_packet(AgsOscParser * osc_parser)746 ags_osc_parser_real_packet(AgsOscParser *osc_parser)
747 {
748   xmlNode *node, *current;
749 
750   gsize start_offset;
751   gint32 packet_size;
752   gchar current_byte;
753 
754   node = xmlNewNode(NULL, "osc-packet");
755 
756   packet_size =
757     osc_parser->packet_size = ags_osc_parser_read_gint32(osc_parser);
758   xmlNewProp(node,
759 	     "packet-size",
760 	     g_strdup_printf("%u", packet_size));
761 
762   current_byte = ags_osc_parser_osc_getc(osc_parser);
763 
764   start_offset =
765     osc_parser->start_offset = osc_parser->offset;
766 
767   while(osc_parser->offset < start_offset + packet_size){
768     if(current_byte == '#'){
769       current = ags_osc_parser_bundle(osc_parser);
770     }else if(current_byte == '/'){
771       current = ags_osc_parser_message(osc_parser);
772     }else{
773       current = NULL;
774 
775       g_warning("failed to read bundle or message");
776     }
777 
778     if(current != NULL){
779       xmlAddChild(node,
780 		  current);
781     }
782   }
783 
784   return(node);
785 }
786 
787 /**
788  * ags_osc_parser_packet:
789  * @osc_parser: the #AgsOscParser
790  *
791  * Parse OSC packet.
792  *
793  * Returns: (transfer none): the parsed XML node
794  *
795  * Since: 3.0.0
796  */
797 xmlNode*
ags_osc_parser_packet(AgsOscParser * osc_parser)798 ags_osc_parser_packet(AgsOscParser *osc_parser)
799 {
800   xmlNode *node;
801 
802   g_return_val_if_fail(AGS_IS_OSC_PARSER(osc_parser), NULL);
803 
804   g_object_ref((GObject *) osc_parser);
805   g_signal_emit(G_OBJECT(osc_parser),
806 		osc_parser_signals[PACKET], 0,
807 		&node);
808   g_object_unref((GObject *) osc_parser);
809 
810   return(node);
811 }
812 
813 xmlNode*
ags_osc_parser_real_bundle(AgsOscParser * osc_parser)814 ags_osc_parser_real_bundle(AgsOscParser *osc_parser)
815 {
816   xmlNode *node, *current;
817 
818   gint32 tv_secs;
819   gint32 tv_fraction;
820   gboolean immediately;
821   guint i;
822   gchar current_byte;
823 
824   static gchar bundle[] = "#bundle";
825 
826   for(i = 0; i < 7; i++){
827     gchar c;
828 
829     c = ags_osc_parser_osc_getc(osc_parser);
830 
831     if(c != bundle[i + 1]){
832       g_warning("bad byte");
833 
834       return(NULL);
835     }
836   }
837 
838   node = xmlNewNode(NULL,
839 		    "osc-bundle");
840 
841   /* read time tag */
842   tv_secs = ags_osc_parser_read_gint32(osc_parser);
843   tv_fraction = ags_osc_parser_read_gint32(osc_parser);
844 
845   immediately = FALSE;
846 
847   if((0x1 & (tv_fraction)) != 0){
848     immediately = TRUE;
849   }
850 
851   /* add prop */
852   xmlNewProp(node,
853 	     "tv-secs",
854 	     g_strdup_printf("%u", tv_secs));
855 
856   xmlNewProp(node,
857 	     "tv-fraction",
858 	     g_strdup_printf("%u", tv_fraction));
859 
860   xmlNewProp(node,
861 	     "immediately",
862 	     g_strdup_printf("%s", ((immediately) ? "true": "false")));
863 
864   while(osc_parser->offset < osc_parser->start_offset + osc_parser->packet_size){
865     current_byte = ags_osc_parser_osc_getc(osc_parser);
866 
867     if(current_byte == '#'){
868       current = ags_osc_parser_bundle(osc_parser);
869     }else if(current_byte == '/'){
870       current = ags_osc_parser_message(osc_parser);
871     }else{
872       current = NULL;
873 
874       g_warning("failed to read bundle or message");
875     }
876 
877     if(current != NULL){
878       xmlAddChild(node,
879 		  current);
880     }
881   }
882 
883   return(node);
884 }
885 
886 /**
887  * ags_osc_parser_bundle:
888  * @osc_parser: the #AgsOscParser
889  *
890  * Parse OSC bundle.
891  *
892  * Returns: (transfer none): the parsed XML node
893  *
894  * Since: 3.0.0
895  */
896 xmlNode*
ags_osc_parser_bundle(AgsOscParser * osc_parser)897 ags_osc_parser_bundle(AgsOscParser *osc_parser)
898 {
899   xmlNode *node;
900 
901   g_return_val_if_fail(AGS_IS_OSC_PARSER(osc_parser), NULL);
902 
903   g_object_ref((GObject *) osc_parser);
904   g_signal_emit(G_OBJECT(osc_parser),
905 		osc_parser_signals[BUNDLE], 0,
906 		&node);
907   g_object_unref((GObject *) osc_parser);
908 
909   return(node);
910 }
911 
912 xmlNode*
ags_osc_parser_real_message(AgsOscParser * osc_parser)913 ags_osc_parser_real_message(AgsOscParser *osc_parser)
914 {
915   xmlNode *node, *current;
916 
917   gchar *address_pattern;
918   gchar *type_tag;
919   gchar *str;
920   gchar current_byte;
921 
922   node = xmlNewNode(NULL,
923 		    "osc-message");
924 
925   str = ags_osc_parser_read_text(osc_parser,
926 				 -1);
927 
928   address_pattern = g_strdup_printf("/%s", str);
929   g_free(str);
930 
931   xmlNewProp(node,
932 	     "address-pattern",
933 	     address_pattern);
934 
935   current_byte = ags_osc_parser_osc_getc(osc_parser);
936 
937   if(current_byte != ','){
938     unsigned char *blob;
939 
940     char str[4];
941     gint32 value;
942     guint i;
943 
944     /* no type tag - provide blob */
945     str[0] = (char) 0xff & current_byte;
946     str[1] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
947     str[2] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
948     str[3] = (char) 0xff & ags_osc_parser_osc_getc(osc_parser);
949 
950     value = (str[0] & 0xff);
951     value = (value<<8) + (str[1] & 0xff);
952     value = (value<<8) + (str[2] & 0xff);
953     value = (value<<8) + (str[3] & 0xff);
954 
955     current = xmlNewNode(NULL,
956 		      "osc-value");
957 
958     blob = (unsigned char *) malloc(value * sizeof(unsigned char));
959 
960     for(i = 0; i < value; i++){
961       blob[i] = ags_osc_parser_osc_getc(osc_parser);
962     }
963 
964     xmlNodeSetContent(current,
965 		      g_base64_encode(blob,
966 				      value));
967 
968     free(blob);
969 
970     xmlAddChild(node,
971 		current);
972   }else{
973     gchar *iter;
974 
975     /* has got type tag */
976     str = ags_osc_parser_read_text(osc_parser,
977 				   -1);
978 
979     type_tag = g_strdup_printf(",%s", str);
980     g_free(str);
981 
982     xmlNewProp(node,
983 	       "type-tag",
984 	       type_tag);
985 
986     for(iter = type_tag + 1; iter[0] != '\0'; iter++){
987       switch(iter[0]){
988       case AGS_OSC_UTIL_TYPE_TAG_STRING_INT32:
989       case AGS_OSC_UTIL_TYPE_TAG_STRING_FLOAT:
990       case AGS_OSC_UTIL_TYPE_TAG_STRING_STRING:
991       case AGS_OSC_UTIL_TYPE_TAG_STRING_BLOB:
992       case AGS_OSC_UTIL_TYPE_TAG_STRING_INT64:
993       case AGS_OSC_UTIL_TYPE_TAG_STRING_TIMETAG:
994       case AGS_OSC_UTIL_TYPE_TAG_STRING_DOUBLE:
995       case AGS_OSC_UTIL_TYPE_TAG_STRING_SYMBOL:
996       case AGS_OSC_UTIL_TYPE_TAG_STRING_CHAR:
997       case AGS_OSC_UTIL_TYPE_TAG_STRING_RGBA:
998       case AGS_OSC_UTIL_TYPE_TAG_STRING_MIDI:
999 	{
1000 	  current = ags_osc_parser_value(osc_parser,
1001 					 iter[0]);
1002 
1003 	  if(current != NULL){
1004 	    xmlAddChild(node,
1005 			current);
1006 	  }
1007 	}
1008 	break;
1009       case AGS_OSC_UTIL_TYPE_TAG_STRING_TRUE:
1010       case AGS_OSC_UTIL_TYPE_TAG_STRING_FALSE:
1011       case AGS_OSC_UTIL_TYPE_TAG_STRING_INFINITE:
1012       case AGS_OSC_UTIL_TYPE_TAG_STRING_NIL:
1013       case AGS_OSC_UTIL_TYPE_TAG_STRING_ARRAY_START:
1014       case AGS_OSC_UTIL_TYPE_TAG_STRING_ARRAY_END:
1015 	break;
1016       default:
1017 	{
1018 	  g_warning("unknown type");
1019 	}
1020       }
1021     }
1022   }
1023 
1024   return(node);
1025 }
1026 
1027 /**
1028  * ags_osc_parser_message:
1029  * @osc_parser: the #AgsOscParser
1030  *
1031  * Parse OSC message.
1032  *
1033  * Returns: (transfer none): the parsed XML node
1034  *
1035  * Since: 3.0.0
1036  */
1037 xmlNode*
ags_osc_parser_message(AgsOscParser * osc_parser)1038 ags_osc_parser_message(AgsOscParser *osc_parser)
1039 {
1040   xmlNode *node;
1041 
1042   g_return_val_if_fail(AGS_IS_OSC_PARSER(osc_parser), NULL);
1043 
1044   g_object_ref((GObject *) osc_parser);
1045   g_signal_emit(G_OBJECT(osc_parser),
1046 		osc_parser_signals[MESSAGE], 0,
1047 		&node);
1048   g_object_unref((GObject *) osc_parser);
1049 
1050   return(node);
1051 }
1052 
1053 xmlNode*
ags_osc_parser_real_value(AgsOscParser * osc_parser,guint v_type)1054 ags_osc_parser_real_value(AgsOscParser *osc_parser,
1055 			  guint v_type)
1056 {
1057   xmlNode *node;
1058 
1059   node = xmlNewNode(NULL,
1060 		    "osc-value");
1061 
1062   switch(v_type){
1063   case AGS_OSC_UTIL_TYPE_TAG_STRING_INT32:
1064     {
1065       xmlNewProp(node,
1066 		 "int32",
1067 		 g_strdup_printf("%d", ags_osc_parser_read_gint32(osc_parser)));
1068     }
1069     break;
1070   case AGS_OSC_UTIL_TYPE_TAG_STRING_FLOAT:
1071     {
1072       xmlNewProp(node,
1073 		 "float",
1074 		 g_strdup_printf("%f", ags_osc_parser_read_gfloat(osc_parser)));
1075     }
1076     break;
1077   case AGS_OSC_UTIL_TYPE_TAG_STRING_STRING:
1078     {
1079       xmlNewProp(node,
1080 		 "text",
1081 		 ags_osc_parser_read_text(osc_parser,
1082 					  -1));
1083     }
1084     break;
1085   case AGS_OSC_UTIL_TYPE_TAG_STRING_BLOB:
1086     {
1087       unsigned char *blob;
1088 
1089       gint32 data_size;
1090       guint i;
1091 
1092       data_size = ags_osc_parser_read_gint32(osc_parser);
1093 
1094       blob = (unsigned char *) malloc(data_size * sizeof(unsigned char));
1095 
1096       for(i = 0; i < data_size; i++){
1097 	blob[i] = ags_osc_parser_osc_getc(osc_parser);
1098       }
1099 
1100       xmlNodeSetContent(node,
1101 			g_base64_encode(blob,
1102 					data_size));
1103 
1104       free(blob);
1105     }
1106     break;
1107   case AGS_OSC_UTIL_TYPE_TAG_STRING_INT64:
1108     {
1109       xmlNewProp(node,
1110 		 "int64",
1111 		 g_strdup_printf("%ld", ags_osc_parser_read_gint64(osc_parser)));
1112     }
1113     break;
1114   case AGS_OSC_UTIL_TYPE_TAG_STRING_TIMETAG:
1115     {
1116       gint32 tv_secs;
1117       gint32 tv_fraction;
1118       gboolean immediately;
1119 
1120       tv_secs = ags_osc_parser_read_gint32(osc_parser);
1121       tv_fraction = ags_osc_parser_read_gint32(osc_parser);
1122 
1123       immediately = (0x1 & (tv_fraction)) ? TRUE: FALSE;
1124 
1125       xmlNewProp(node,
1126 		 "tv-secs",
1127 		 g_strdup_printf("%d", tv_secs));
1128 
1129       xmlNewProp(node,
1130 		 "tv-fraction",
1131 		 g_strdup_printf("%d", tv_fraction));
1132 
1133       xmlNewProp(node,
1134 		 "immediately",
1135 		 g_strdup_printf("%s", ((immediately) ? "true": "false")));
1136     }
1137     break;
1138   case AGS_OSC_UTIL_TYPE_TAG_STRING_DOUBLE:
1139     {
1140       xmlNewProp(node,
1141 		 "double",
1142 		 g_strdup_printf("%f", ags_osc_parser_read_gdouble(osc_parser)));
1143     }
1144     break;
1145   case AGS_OSC_UTIL_TYPE_TAG_STRING_SYMBOL:
1146     {
1147       xmlNewProp(node,
1148 		 "symbol",
1149 		 ags_osc_parser_read_text(osc_parser,
1150 					  -1));
1151     }
1152     break;
1153   case AGS_OSC_UTIL_TYPE_TAG_STRING_CHAR:
1154     {
1155       gint32 c;
1156 
1157       c = ags_osc_parser_read_gint32(osc_parser);
1158 
1159       xmlNewProp(node,
1160 		 "char",
1161 		 g_strdup_printf("%c", c));
1162     }
1163     break;
1164   case AGS_OSC_UTIL_TYPE_TAG_STRING_RGBA:
1165     {
1166       guint8 r, g, b, a;
1167 
1168       r = 0xff & (ags_osc_parser_osc_getc(osc_parser));
1169       g = 0xff & (ags_osc_parser_osc_getc(osc_parser));
1170       b = 0xff & (ags_osc_parser_osc_getc(osc_parser));
1171       a = 0xff & (ags_osc_parser_osc_getc(osc_parser));
1172 
1173       xmlNewProp(node,
1174 		 "red",
1175 		 g_strdup_printf("%u", r));
1176 
1177       xmlNewProp(node,
1178 		 "green",
1179 		 g_strdup_printf("%u", g));
1180 
1181       xmlNewProp(node,
1182 		 "blue",
1183 		 g_strdup_printf("%u", b));
1184 
1185       xmlNewProp(node,
1186 		 "alpha",
1187 		 g_strdup_printf("%u", a));
1188     }
1189     break;
1190   case AGS_OSC_UTIL_TYPE_TAG_STRING_MIDI:
1191     {
1192       guint8 port;
1193       guint8 status_byte;
1194       guint8 data0, data1;
1195 
1196       port = 0xff & (ags_osc_parser_osc_getc(osc_parser));
1197       status_byte = 0xff & (ags_osc_parser_osc_getc(osc_parser));
1198       data0 = 0xff & (ags_osc_parser_osc_getc(osc_parser));
1199       data1 = 0xff & (ags_osc_parser_osc_getc(osc_parser));
1200 
1201       xmlNewProp(node,
1202 		 "port",
1203 		 g_strdup_printf("%u", port));
1204 
1205       xmlNewProp(node,
1206 		 "status-byte",
1207 		 g_strdup_printf("%u", status_byte));
1208 
1209       xmlNewProp(node,
1210 		 "data0",
1211 		 g_strdup_printf("%u", data0));
1212 
1213       xmlNewProp(node,
1214 		 "data1",
1215 		 g_strdup_printf("%u", data1));
1216     }
1217     break;
1218   }
1219 
1220   return(node);
1221 }
1222 
1223 /**
1224  * ags_osc_parser_value:
1225  * @osc_parser: the #AgsOscParser
1226  * @v_type: value type
1227  *
1228  * Parse OSC value.
1229  *
1230  * Returns: (transfer none): the parsed XML node
1231  *
1232  * Since: 3.0.0
1233  */
1234 xmlNode*
ags_osc_parser_value(AgsOscParser * osc_parser,guint v_type)1235 ags_osc_parser_value(AgsOscParser *osc_parser,
1236 		     guint v_type)
1237 {
1238   xmlNode *node;
1239 
1240   g_return_val_if_fail(AGS_IS_OSC_PARSER(osc_parser), NULL);
1241 
1242   g_object_ref((GObject *) osc_parser);
1243   g_signal_emit(G_OBJECT(osc_parser),
1244 		osc_parser_signals[VALUE], 0,
1245 		v_type,
1246 		&node);
1247   g_object_unref((GObject *) osc_parser);
1248 
1249   return(node);
1250 }
1251 
1252 /**
1253  * ags_osc_parser_new:
1254  *
1255  * Creates a new instance of #AgsOscParser
1256  *
1257  * Returns: the new #AgsOscParser
1258  *
1259  * Since: 3.0.0
1260  */
1261 AgsOscParser*
ags_osc_parser_new()1262 ags_osc_parser_new()
1263 {
1264   AgsOscParser *osc_parser;
1265 
1266   osc_parser = (AgsOscParser *) g_object_new(AGS_TYPE_OSC_PARSER,
1267 					     NULL);
1268 
1269   return(osc_parser);
1270 }
1271