1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2021 Joël Krähemann
3  *
4  * This file is part of GSequencer.
5  *
6  * GSequencer is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSequencer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/audio/osc/ags_osc_util.h>
21 
22 #include <math.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <time.h>
26 
27 #ifdef __APPLE__
28 #include <mach/clock.h>
29 #include <mach/mach.h>
30 #endif
31 
32 gpointer ags_osc_util_copy(gpointer ptr);
33 void ags_osc_util_free(gpointer ptr);
34 
35 /**
36  * SECTION:ags_osc_util
37  * @short_description: OSC util
38  * @title: AgsOscUtil
39  * @section_id:
40  * @include: ags/audio/osc/ags_osc_util.h
41  *
42  * Utility functions for OSC.
43  */
44 
45 GType
ags_osc_util_get_type(void)46 ags_osc_util_get_type(void)
47 {
48   static volatile gsize g_define_type_id__volatile = 0;
49 
50   if(g_once_init_enter (&g_define_type_id__volatile)){
51     GType ags_type_osc_util = 0;
52 
53     ags_type_osc_util =
54       g_boxed_type_register_static("AgsOscUtil",
55 				   (GBoxedCopyFunc) ags_osc_util_copy,
56 				   (GBoxedFreeFunc) ags_osc_util_free);
57 
58     g_once_init_leave(&g_define_type_id__volatile, ags_type_osc_util);
59   }
60 
61   return g_define_type_id__volatile;
62 }
63 
64 gpointer
ags_osc_util_copy(gpointer ptr)65 ags_osc_util_copy(gpointer ptr)
66 {
67   gpointer retval;
68 
69   retval = g_memdup(ptr, sizeof(AgsOscUtil));
70 
71   return(retval);
72 }
73 
74 void
ags_osc_util_free(gpointer ptr)75 ags_osc_util_free(gpointer ptr)
76 {
77   g_free(ptr);
78 }
79 
80 /**
81  * ags_osc_util_type_tag_string_count_type:
82  * @type_tag: the type tag string
83  *
84  * Count types in @type_tag.
85  *
86  * Returns: the count of types specified
87  *
88  * Since: 3.0.0
89  */
90 guint
ags_osc_util_type_tag_string_count_type(gchar * type_tag)91 ags_osc_util_type_tag_string_count_type(gchar *type_tag)
92 {
93   gsize count;
94 
95   if(type_tag == NULL ||
96      type_tag[0] != ','){
97     return(0);
98   }
99 
100   count = strlen(type_tag);
101 
102   if(count <= 0){
103     return(0);
104   }
105 
106   count -= 1;
107 
108   return(count);
109 }
110 
111 /**
112  * ags_osc_util_meta_data:
113  * @uri: the URI
114  * @meta_data_length: the return location of meta data's length
115  *
116  * Get meta data.
117  *
118  * Returns: the byte array containing meta data
119  *
120  * Since: 3.0.0
121  */
122 unsigned char*
ags_osc_util_meta_data(gchar * uri,guint * meta_data_length)123 ags_osc_util_meta_data(gchar *uri,
124 		       guint *meta_data_length)
125 {
126   unsigned char *meta_data;
127 
128   meta_data = g_strdup_printf("framing=slip\nversion=1.0 | 1.1\nuri=%s\ntypes=%s\n",
129 			      uri,
130 			      AGS_OSC_UTIL_TYPE_TAG_STRING_ALL);
131 
132   if(meta_data_length != NULL){
133     *meta_data_length = strlen(meta_data);
134   }
135 
136   return(meta_data);
137 }
138 
139 /**
140  * ags_osc_util_mime_header:
141  * @uri: the URI
142  * @mime_header_length: the return location of MIME header's length
143  *
144  * Get MIME header.
145  *
146  * Returns: the byte array containing MIME header
147  *
148  * Since: 3.0.0
149  */
150 unsigned char*
ags_osc_util_mime_header(gchar * uri,guint * mime_header_length)151 ags_osc_util_mime_header(gchar *uri,
152 			 guint *mime_header_length)
153 {
154   unsigned char *mime_header;
155 
156   mime_header = g_strdup_printf("MIME-Version: 1.0\nContent-type: application/osc;\nframing=slip\nversion=1.0 | 1.1\nuri=%s\ntypes=%s\n",
157 				uri,
158 				AGS_OSC_UTIL_TYPE_TAG_STRING_ALL);
159 
160   if(mime_header_length != NULL){
161     *mime_header_length = strlen(mime_header);
162   }
163 
164   return(mime_header);
165 }
166 
167 /**
168  * ags_osc_util_slip_encode:
169  * @osc_buffer: the OSC buffer
170  * @buffer_length: the OSC buffer's length
171  * @returned_buffer_length: the returned buffer's length
172  *
173  * Encode @osc_buffer to be suitable for network transmission.
174  * See SLIP (RFC1055).
175  *
176  * Returns: the encoded byte array
177  *
178  * Since: 3.0.0
179  */
180 unsigned char*
ags_osc_util_slip_encode(unsigned char * osc_buffer,guint buffer_length,guint * returned_buffer_length)181 ags_osc_util_slip_encode(unsigned char *osc_buffer,
182 			 guint buffer_length,
183 			 guint *returned_buffer_length)
184 {
185   unsigned char *slip_buffer;
186 
187   guint slip_buffer_length;
188   guint i, j;
189 
190   slip_buffer_length = (guint) AGS_OSC_UTIL_SLIP_CHUNK_LENGTH + 2;
191 
192   slip_buffer = (unsigned char *) malloc((slip_buffer_length + 2) * sizeof(unsigned char));
193 
194   slip_buffer[0] = AGS_OSC_UTIL_SLIP_END;
195 
196   for(i = 0, j = 1; i < buffer_length; i++, j++){
197     if(j + 2 >= slip_buffer_length){
198       slip_buffer_length = slip_buffer_length + AGS_OSC_UTIL_SLIP_CHUNK_LENGTH;
199       slip_buffer = (unsigned char *) realloc(slip_buffer,
200 					      (slip_buffer_length + AGS_OSC_UTIL_SLIP_CHUNK_LENGTH) * sizeof(unsigned char));
201     }
202 
203     switch(osc_buffer[i]){
204     case AGS_OSC_UTIL_SLIP_END:
205       {
206 	slip_buffer[j] = AGS_OSC_UTIL_SLIP_ESC;
207 	j++;
208 
209 	slip_buffer[j] = AGS_OSC_UTIL_SLIP_ESC_END;
210       }
211       break;
212     case AGS_OSC_UTIL_SLIP_ESC:
213       {
214 	slip_buffer[j] = AGS_OSC_UTIL_SLIP_ESC;
215 	j++;
216 
217 	slip_buffer[j] = AGS_OSC_UTIL_SLIP_ESC_ESC;
218       }
219       break;
220     default:
221       {
222 	slip_buffer[j] = osc_buffer[i];
223       }
224     }
225   }
226 
227   slip_buffer[j] = AGS_OSC_UTIL_SLIP_END;
228 
229   if(returned_buffer_length != NULL){
230     *returned_buffer_length = j + 1;
231   }
232 
233   return(slip_buffer);
234 }
235 
236 /**
237  * ags_osc_util_slip_decode:
238  * @slip_buffer: the SLIP encoded OSC buffer
239  * @slip_buffer_length: the buffer length of SLIP encoded OSC buffer
240  * @returned_buffer_length: the returned buffer's length
241  *
242  * Decode @slip_buffer from SLIP encoded format.
243  * See SLIP (RFC1055).
244  *
245  * Returns: the OSC buffer as byte array
246  *
247  * Since: 3.0.0
248  */
249 unsigned char*
ags_osc_util_slip_decode(unsigned char * slip_buffer,guint slip_buffer_length,guint * returned_buffer_length)250 ags_osc_util_slip_decode(unsigned char *slip_buffer,
251 			 guint slip_buffer_length,
252 			 guint *returned_buffer_length)
253 {
254   unsigned char *osc_buffer;
255 
256   guint buffer_length;
257   guint i, j;
258 
259   buffer_length = slip_buffer_length;
260 
261   osc_buffer = (unsigned char *) malloc(buffer_length * sizeof(unsigned char));
262 
263   for(i = 0, j = 1; j < slip_buffer_length; i++, j++){
264     switch(slip_buffer[j]){
265     case AGS_OSC_UTIL_SLIP_ESC:
266       {
267 	j++;
268 
269 	if(slip_buffer[j] == AGS_OSC_UTIL_SLIP_ESC_END){
270 	  osc_buffer[i] = AGS_OSC_UTIL_SLIP_END;
271 	}else if(slip_buffer[j] == AGS_OSC_UTIL_SLIP_ESC_ESC){
272 	  osc_buffer[i] = AGS_OSC_UTIL_SLIP_ESC;
273 	}
274       }
275       break;
276     default:
277       {
278 	osc_buffer[i] = slip_buffer[j];
279       }
280     }
281   }
282 
283   if(returned_buffer_length != NULL){
284     *returned_buffer_length = i - 1;
285   }
286 
287   return(osc_buffer);
288 }
289 
290 /**
291  * ags_osc_util_timetag_now:
292  * @tv_sec: the return location of number of seconds since midnight on January 1, 1900
293  * @tv_fraction: the return location of fraction of seconds to a precision of about 200 picoseconds
294  *
295  * Get current time.
296  *
297  * Since: 3.0.0
298  */
299 void
ags_osc_util_timetag_now(gint32 * tv_sec,gint32 * tv_fraction)300 ags_osc_util_timetag_now(gint32 *tv_sec, gint32 *tv_fraction)
301 {
302   struct timespec time_now;
303 
304 #ifdef __APPLE__
305   clock_serv_t cclock;
306   mach_timespec_t mts;
307 #endif
308 
309   static const guint sec_since_1900_to_1970 = 2208988800;
310 
311 #ifdef __APPLE__
312   host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
313 
314   clock_get_time(cclock, &mts);
315   mach_port_deallocate(mach_task_self(), cclock);
316 
317   time_now.tv_sec = mts.tv_sec;
318   time_now.tv_nsec = mts.tv_nsec;
319 #else
320   clock_gettime(CLOCK_MONOTONIC, &time_now);
321 #endif
322 
323   if(tv_sec != NULL){
324     tv_sec[0] = time_now.tv_sec + 2208988800;
325   }
326 
327   if(tv_fraction != NULL){
328     tv_fraction[0] = 0xfffffffe & (guint) (time_now.tv_nsec * 4.294967296);
329   }
330 }
331