Subversion Repositories svn.mios32

Rev

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