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