Subversion Repositories svn.mios32

Rev

Rev 1003 | Rev 1005 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1003 tk 1
/* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
2
// $Id: OscHelper.cpp 1004 2010-04-22 07:42:28Z philetaylor $
3
/*
4
 * OSC Help Routines
5
 * (taken from MIOS32_OSC)
6
 * Documentation: see there
7
 *
8
 * ==========================================================================
9
 *
10
 *  Copyright (C) 2010 Thorsten Klose (tk@midibox.org)
11
 *  Licensed for personal non-commercial use only.
12
 *  All other rights reserved.
13
 *
14
 * ==========================================================================
15
 */
16
 
17
#include "OscHelper.h"
18
#include <string.h>
19
 
1004 philetaylo 20
 
1003 tk 21
//==============================================================================
22
OscHelper::OscHelper()
23
{
24
}
25
 
26
OscHelper::~OscHelper()
27
{
28
}
29
 
30
 
31
//==============================================================================
32
// strnlen() not available for all libc's, therefore we use a local solution here
33
static size_t my_strnlen(char *str, size_t max_len)
34
{
35
  size_t len = 0;
36
 
37
  while( *str++ && (len < max_len) )
38
    ++len;
39
 
40
  return len;
41
}
42
 
43
//==============================================================================
1004 philetaylo 44
// stpcpy is not available in windows, therefore we use a local solution here
45
#ifdef WIN32
46
static char *stpcpy(char *dest, const char *src){strcpy(dest,src);return dest +strlen(dest);}
47
#endif
48
 
49
//==============================================================================
1003 tk 50
/////////////////////////////////////////////////////////////////////////////
51
// Gets a word (4 bytes) from buffer
52
// \param[in] buffer pointer to OSC message buffer 
53
// \return 32bit unsigned integer
54
/////////////////////////////////////////////////////////////////////////////
55
unsigned OscHelper::getWord(unsigned char *buffer)
56
{
57
  // taking endianess into account
58
  return
59
    (((unsigned)*(buffer+0)) << 24) | (((unsigned)*(buffer+1)) << 16) |
60
    (((unsigned)*(buffer+2)) <<  8) | (((unsigned)*(buffer+3)) <<  0);
61
}
62
 
63
/////////////////////////////////////////////////////////////////////////////
64
// Puts a word (4 bytes) into buffer
65
// \param[in] buffer pointer to OSC message buffer 
66
// \param[in] word 32bit word
67
// \return buffer pointer behind the inserted entry
68
/////////////////////////////////////////////////////////////////////////////
69
unsigned char *OscHelper::putWord(unsigned char *buffer, unsigned word)
70
{
71
  *buffer++ = (word >> 24) & 0xff;
72
  *buffer++ = (word >> 16) & 0xff;
73
  *buffer++ = (word >>  8) & 0xff;
74
  *buffer++ = (word >>  0) & 0xff;
75
  return buffer;
76
}
77
 
78
/////////////////////////////////////////////////////////////////////////////
79
// Gets a timetag (8 bytes) from buffer
80
// \param[in] buffer pointer to OSC message buffer 
81
// \return timetag (seconds and fraction part)
82
/////////////////////////////////////////////////////////////////////////////
83
OscHelper::OscTimetagT OscHelper::getTimetag(unsigned char *buffer)
84
{
85
  OscTimetagT timetag;
86
  timetag.seconds = getWord(buffer);
87
  timetag.fraction = getWord(buffer+4);
88
  return timetag;
89
}
90
 
91
/////////////////////////////////////////////////////////////////////////////
92
// Puts a timetag (8 bytes) into buffer
93
// \param[in] buffer pointer to OSC message buffer 
94
// \param[in] timetag the timetag which should be inserted
95
// \return buffer pointer behind the inserted entry
96
/////////////////////////////////////////////////////////////////////////////
97
unsigned char *OscHelper::putTimetag(unsigned char *buffer, OscTimetagT timetag)
98
{
99
  buffer = putWord(buffer, timetag.seconds);
100
  buffer = putWord(buffer, timetag.fraction);
101
  return buffer;
102
}
103
 
104
/////////////////////////////////////////////////////////////////////////////
105
// Gets a word (4 bytes) from buffer and converts it to a 32bit signed integer.
106
// \param[in] buffer pointer to OSC message buffer 
107
// \return 32bit signed integer
108
/////////////////////////////////////////////////////////////////////////////
109
int OscHelper::getInt(unsigned char *buffer)
110
{
111
  return (int)getWord(buffer);
112
}
113
 
114
/////////////////////////////////////////////////////////////////////////////
115
// Puts a 32bit signed integer into buffer
116
// \param[in] buffer pointer to OSC message buffer 
117
// \param[in] value the integer value which should be inserted
118
// \return buffer pointer behind the inserted entry
119
/////////////////////////////////////////////////////////////////////////////
120
unsigned char *OscHelper::putInt(unsigned char *buffer, int value)
121
{
122
  return putWord(buffer, (unsigned)value);
123
}
124
 
125
/////////////////////////////////////////////////////////////////////////////
126
// Gets a word (4 bytes) from buffer and converts it to a float with 
127
// normal precession
128
// \param[in] buffer pointer to OSC message buffer 
129
// \return float with normal procession
130
/////////////////////////////////////////////////////////////////////////////
131
float OscHelper::getFloat(unsigned char *buffer)
132
{
133
#if 0
134
  unsigned word = getWord(buffer);
135
  return *(float *)(&word);
136
#else
137
  // TK: doesn't work with my gcc installation (i686-apple-darwin9-gcc-4.0.1):
138
  // float not converted correctly - it works when optimisation is disabled!
139
  // according to http://gcc.gnu.org/ml/gcc-bugs/2003-02/msg01128.html this isn't a bug...
140
  // workaround:
141
  union { unsigned word; float f; } converted;
142
  converted.word = getWord(buffer);
143
  return converted.f;
144
#endif
145
}
146
 
147
 
148
/////////////////////////////////////////////////////////////////////////////
149
// Puts a float with normal precission into buffer
150
// \param[in] buffer pointer to OSC message buffer 
151
// \param[in] value the float value which should be inserted
152
// \return buffer pointer behind the inserted entry
153
/////////////////////////////////////////////////////////////////////////////
154
unsigned char *OscHelper::putFloat(unsigned char *buffer, float value)
155
{
156
  union { unsigned word; float f; } converted;
157
  converted.f = value;
158
  return putWord(buffer, converted.word);
159
}
160
 
161
/////////////////////////////////////////////////////////////////////////////
162
// Returns pointer to a string in message buffer
163
// \param[in] buffer pointer to OSC message buffer 
164
// \return zero-terminated string
165
/////////////////////////////////////////////////////////////////////////////
166
char *OscHelper::getString(unsigned char *buffer)
167
{
168
  return (char *)buffer; // OSC protocol ensures zero termination (checked in MIOS32_OSC_SearchElement)
169
}
170
 
171
/////////////////////////////////////////////////////////////////////////////
172
// Puts a string into buffer and pads with 0 until word boundary has been reached
173
// \param[in] buffer pointer to OSC message buffer 
174
// \param[in] value the string which should be inserted
175
// \return buffer pointer behind the inserted entry
176
/////////////////////////////////////////////////////////////////////////////
177
unsigned char *OscHelper::putString(unsigned char *buffer, char *str)
178
{
179
  unsigned char *buffer_start = buffer;
180
 
181
  buffer = (unsigned char *)stpcpy((char *)buffer, str);
182
  *buffer++ = 0;
183
 
184
  // pad with zeroes until word boundary is reached
185
  while( (unsigned)(buffer-buffer_start) % 4 )
186
    *buffer++ = 0;
187
 
188
  return buffer;
189
}
190
 
191
/////////////////////////////////////////////////////////////////////////////
192
// Returns the length of a Blob
193
// \param[in] buffer pointer to OSC message buffer 
194
// \return blob length
195
/////////////////////////////////////////////////////////////////////////////
196
unsigned OscHelper::getBlobLength(unsigned char *buffer)
197
{
198
  return *buffer;
199
}
200
 
201
/////////////////////////////////////////////////////////////////////////////
202
// Returns the data part of a Blob
203
// \param[in] buffer pointer to OSC message buffer 
204
// \return pointer to data part of a Blob
205
/////////////////////////////////////////////////////////////////////////////
206
unsigned char *OscHelper::getBlobData(unsigned char *buffer)
207
{
208
  return buffer+4;
209
}
210
 
211
 
212
/////////////////////////////////////////////////////////////////////////////
213
// Puts an OSC-Blob into buffer and pads with 0 until word boundary has been reached
214
// \param[in] buffer pointer to OSC message buffer 
215
// \param[in] data blob data
216
// \param[in] len blob size
217
// \return buffer pointer behind the inserted entry
218
/////////////////////////////////////////////////////////////////////////////
219
unsigned char *OscHelper::putBlob(unsigned char *buffer, unsigned char *data, unsigned len)
220
{
221
  // ensure that length considers word alignment
222
  unsigned aligned_len = (len+3) & 0xfffffffc;
223
 
224
  // add length
225
  buffer = putWord(buffer, aligned_len);
226
 
227
  // add bytes
228
  int i;
229
  for(i=0; i<len; ++i)
230
    *buffer++ = *data++;
231
 
232
  // pad with zeroes
233
  while( i % 4 )
234
    *buffer++ = 0;
235
 
236
  return buffer;
237
}
238
 
239
 
240
/////////////////////////////////////////////////////////////////////////////
241
// Gets two words (8 bytes) from buffer and converts them to a 64bit signed integer.
242
// \param[in] buffer pointer to OSC message buffer 
243
// \return 64bit signed integer
244
/////////////////////////////////////////////////////////////////////////////
245
long long OscHelper::getLongLong(unsigned char *buffer)
246
{
247
  return ((long long)getWord(buffer) << 32) | getWord(buffer+4);
248
}
249
 
250
/////////////////////////////////////////////////////////////////////////////
251
// Puts a 64bit signed integer into buffer
252
// \param[in] buffer pointer to OSC message buffer 
253
// \param[in] value the "long long" value which should be inserted
254
// \return buffer pointer behind the inserted entry
255
/////////////////////////////////////////////////////////////////////////////
256
unsigned char *OscHelper::putLongLong(unsigned char *buffer, long long value)
257
{
258
  buffer = putWord(buffer, (unsigned)(value >> 32));
259
  buffer = putWord(buffer, (unsigned)value);
260
  return buffer;
261
}
262
 
263
 
264
/////////////////////////////////////////////////////////////////////////////
265
// Gets two words (8 bytes) from buffer and converts them to a float with 
266
// double precession
267
// \param[in] buffer pointer to OSC message buffer 
268
// \return float with double procession
269
/////////////////////////////////////////////////////////////////////////////
270
double OscHelper::getDouble(unsigned char *buffer)
271
{
272
#if 0
273
  long long word = ((long long)getWord(buffer) << 32) | getWord(buffer+4);
274
  return *(double *)(&word);
275
#else
276
  // TK: doesn't work with my gcc installation (i686-apple-darwin9-gcc-4.0.1):
277
  // float not converted correctly - it works when optimisation is disabled!
278
  // according to http://gcc.gnu.org/ml/gcc-bugs/2003-02/msg01128.html this isn't a bug...
279
  // workaround:
280
  union { long long word; double d; } converted;
281
  converted.word = getLongLong(buffer);
282
  return converted.d;
283
#endif
284
}
285
 
286
/////////////////////////////////////////////////////////////////////////////
287
// Puts a float with double precission into buffer
288
// \param[in] buffer pointer to OSC message buffer 
289
// \param[in] value the double value which should be inserted
290
// \return buffer pointer behind the inserted entry
291
/////////////////////////////////////////////////////////////////////////////
292
unsigned char *OscHelper::putDouble(unsigned char *buffer, double value)
293
{
294
  union { long long word; double d; } converted;
295
  converted.d = value;
296
  return putLongLong(buffer, converted.word);
297
}
298
 
299
 
300
/////////////////////////////////////////////////////////////////////////////
301
// Returns a character
302
// \param[in] buffer pointer to OSC message buffer 
303
// \return a single character
304
/////////////////////////////////////////////////////////////////////////////
305
char OscHelper::getChar(unsigned char *buffer)
306
{
307
  return *buffer; // just for completeness..
308
}
309
 
310
/////////////////////////////////////////////////////////////////////////////
311
// Puts a character into buffer and pads with 3 zeros (word aligned)
312
// \param[in] buffer pointer to OSC message buffer 
313
// \param[in] c the character which should be inserted
314
// \return buffer pointer behind the inserted entry
315
/////////////////////////////////////////////////////////////////////////////
316
unsigned char *OscHelper::putChar(unsigned char *buffer, char c)
317
{
318
  return putWord(buffer, (unsigned)c);
319
}
320
 
321
 
322
 
323
/////////////////////////////////////////////////////////////////////////////
324
// Returns a MIDI package
325
// \param[in] buffer pointer to OSC message buffer 
326
// \return a MIOS32 compliant MIDI package
327
/////////////////////////////////////////////////////////////////////////////
328
unsigned OscHelper::getMIDI(unsigned char *buffer)
329
{
330
    // note: no extra conversion to MIOS32 MIDI package format
331
    return getWord(buffer);
332
}
333
 
334
/////////////////////////////////////////////////////////////////////////////
335
// Puts a MIDI package into buffer
336
// \param[in] buffer pointer to OSC message buffer 
337
// \param[in] p the MIDI package which should be inserted
338
// \return buffer pointer behind the inserted entry
339
/////////////////////////////////////////////////////////////////////////////
340
unsigned char *OscHelper::putMIDI(unsigned char *buffer, unsigned p)
341
{
342
    // note: no extra conversion to MIOS32 MIDI package format
343
    return putWord(buffer, p);
344
}