source: roaraudio/libroar/ltm.c @ 4285:9da711b5213a

Last change on this file since 4285:9da711b5213a was 4285:9da711b5213a, checked in by phi, 14 years ago

added more debug lions

File size: 9.7 KB
Line 
1//ltm.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38struct roar_ltm_result {
39 int mt;
40 int window;
41 size_t streams;
42 size_t nummt;
43 size_t structlen;
44 int64_t data[1];
45};
46
47static int roar_ltm_numbits(int f) {
48 int found = 0;
49
50 while (f) {
51  if ( f & 0x1 )
52   found++;
53
54  f >>= 1;
55 }
56
57 return found;
58}
59
60static int roar_ltm_pack_req(int mt, int window,
61                             int * streams, size_t slen,
62                             struct roar_message * mes, char ** buf,
63                             int regtype) {
64 uint16_t * data;
65 size_t i;
66
67 if ( mt == 0 || streams == NULL || slen == 0 || mes == NULL || buf == NULL ) {
68  roar_errno = ROAR_ERROR_INVAL;
69  return -1;
70 }
71
72 memset(mes, 0, sizeof(struct roar_message));
73
74 switch (regtype) {
75  case ROAR_LTM_SST_REGISTER:
76  case ROAR_LTM_SST_UNREGISTER:
77    mes->cmd = ROAR_CMD_SET_STREAM_PARA;
78   break;
79  case ROAR_LTM_SST_GET_RAW:
80    mes->cmd = ROAR_CMD_GET_STREAM_PARA;
81   break;
82  default:
83    roar_errno = ROAR_ERROR_NOTSUP;
84    return -1;
85   break;
86 }
87
88 if ( slen == 1 ) {
89  mes->stream  = *streams;
90  mes->datalen = 6 * 2;
91 } else {
92  mes->stream = -1;
93  mes->datalen = (6 + slen) * 2;
94 }
95
96 if ( mes->datalen > LIBROAR_BUFFER_MSGDATA ) {
97  roar_errno = ROAR_ERROR_NOTSUP;
98  return -1;
99 }
100
101 *buf = NULL;
102
103 data = (uint16_t*)mes->data;
104
105 data[0] = 0;
106 data[1] = ROAR_STREAM_PARA_LTM;
107 data[2] = regtype;
108 data[3] = window;
109 data[4] = 0;
110 data[5] = mt;
111
112 for (i = 0; i < slen; i++) {
113  data[6+i] = streams[i];
114 }
115
116 for (i = 0; i < (mes->datalen/2); i++) {
117  data[i] = ROAR_HOST2NET16(data[i]);
118 }
119
120 return 0;
121}
122
123static int roar_ltm_regunreg(struct roar_connection * con, int mt, int window, int * streams, size_t slen, int type) {
124 struct roar_message mes;
125 char * buf = NULL;
126 int    ret;
127
128 if ( roar_ltm_pack_req(mt, window, streams, slen, &mes, &buf, type) == -1 )
129  return -1;
130
131 ret = roar_req(con, &mes, &buf);
132
133 if ( buf != NULL )
134  free(buf);
135
136 if ( ret != -1 ) {
137  if ( mes.cmd != ROAR_CMD_OK )
138   ret = -1;
139 }
140
141 return ret;
142}
143
144int roar_ltm_register(struct roar_connection * con, int mt, int window, int * streams, size_t slen) {
145 return roar_ltm_regunreg(con, mt, window, streams, slen, ROAR_LTM_SST_REGISTER);
146}
147int roar_ltm_unregister(struct roar_connection * con, int mt, int window, int * streams, size_t slen) {
148 return roar_ltm_regunreg(con, mt, window, streams, slen, ROAR_LTM_SST_UNREGISTER);
149}
150
151/*
152ssize_t roar_ltm_get_raw(struct roar_connection * con,
153                         int mt, int window,
154                         int * streams, size_t slen,
155                         void * buf, size_t * buflen, int64_t ** array) {
156 int bits = roar_ltm_numbits(mt);
157 int64_t * buffer = buf;
158 size_t i;
159
160 if ( buflen == NULL ) {
161  roar_errno = ROAR_ERROR_INVAL;
162  return -1;
163 }
164
165 if ( slen == 0 ) {
166  *buflen = 0;
167  return bits;
168 }
169
170 if ( con == NULL || streams == NULL || buf == NULL || array == NULL ) {
171  roar_errno = ROAR_ERROR_INVAL;
172  return -1;
173 }
174
175 if ( *buflen < (bits * slen) ) {
176  roar_errno = ROAR_ERROR_INVAL;
177  return -1;
178 }
179
180 for (i = 0; i < slen; i++) {
181  array[i] = &(buffer[bits*i]);
182 }
183
184 roar_errno = ROAR_ERROR_NOSYS;
185 return -1;
186}
187
188int64_t roar_ltm_extract(int64_t * buf, size_t len, int mt, int req) {
189 int have, need;
190
191 roar_err_clear();
192
193 have = roar_ltm_numbits(req);
194
195 need = roar_ltm_numbits(mt);
196
197 if ( have != 1 || (mt & req) != req || len != (size_t)need || buf == NULL ) {
198  roar_errno = ROAR_ERROR_INVAL;
199  return 0;
200 }
201
202 while (req && (req & 0x1) == 0) {
203  if ( mt & 0x1 )
204   buf++;
205
206  mt  <<= 1;
207  req <<= 1;
208 }
209
210 return *buf;
211}
212
213int64_t roar_ltm_extract1(int64_t * buf, size_t len, int mt, int req) {
214 roar_err_clear();
215
216 if ( buf == NULL || len != 1 || mt != req ) {
217  roar_errno = ROAR_ERROR_INVAL;
218  return 0;
219 }
220
221 return *buf;
222}
223*/
224
225#ifdef DEBUG
226#define HEXDUMP64(x) roar_ltm_hexdump64((x))
227static void roar_ltm_hexdump64(void * p) {
228 unsigned char * d = p;
229 ROAR_DBG("roar_ltm_hexdump64(p=%p): hex: %.2x%.2x %.2x%.2x %.2x%.2x %.2x%.2x", p, d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]);
230}
231#else
232#define HEXDUMP64(x)
233#endif
234
235struct roar_ltm_result * roar_ltm_get(struct roar_connection * con,
236                                      int mt, int window,
237                                      int * streams, size_t slen,
238                                      struct roar_ltm_result * oldresult) {
239 struct roar_ltm_result * res = NULL;
240 struct roar_message mes;
241 size_t needed_structlen = 0;
242 uint16_t * d16;
243 int64_t  * d64;
244 char * buf = NULL;
245 int    ret;
246 int    i;
247
248 if ( con == NULL )
249  return NULL;
250
251 if ( streams == NULL || slen == 0 )
252  return NULL;
253
254 if ( roar_ltm_pack_req(mt, window, streams, slen, &mes, &buf, ROAR_LTM_SST_GET_RAW) == -1 )
255  return NULL;
256
257 ret = roar_req(con, &mes, &buf);
258
259 if ( ret == -1 || mes.cmd != ROAR_CMD_OK ) {
260  if ( buf != NULL )
261   free(buf);
262  return NULL;
263 }
264
265 if ( buf == NULL ) {
266  d16 = (uint16_t*)&(mes.data);
267  d64 = ( int64_t*)&(mes.data);
268 } else {
269  d16 = (uint16_t*)buf;
270  d64 = ( int64_t*)buf;
271 }
272
273 // TODO: do we need this block?
274 for (i = 0; i < 8; i++) {
275  d16[i] = ROAR_NET2HOST64(d16[i]);
276  ROAR_DBG("roar_ltm_get(*): d16[i=%i]=%i", i, (unsigned int)d16[i]);
277 }
278
279 for (i = 2; i < mes.datalen/8; i++) {
280  ROAR_DBG("roar_ltm_get(*): d64[i=%i]=%lli", i, (long long int)d64[i]);
281  HEXDUMP64(&(d64[i]));
282  d64[i] = ROAR_NET2HOST64(d64[i]);
283  HEXDUMP64(&(d64[i]));
284  ROAR_DBG("roar_ltm_get(*): d64[i=%i]=%lli", i, (long long int)d64[i]);
285 }
286
287 needed_structlen = sizeof(struct roar_ltm_result) + mes.datalen - 16;
288
289 if ( oldresult != NULL ) {
290  if ( oldresult->structlen >= needed_structlen ) {
291   res = oldresult;
292   needed_structlen = oldresult->structlen;
293  } else {
294   roar_ltm_freeres(oldresult);
295  }
296 } else {
297  res = roar_mm_malloc(needed_structlen);
298 }
299
300 if ( res == NULL ) {
301  if ( buf != NULL )
302   free(buf);
303  return NULL;
304 }
305
306 memset(res, 0, needed_structlen);
307 res->structlen = needed_structlen;
308
309 res->mt      = mt;
310 res->window  = window;
311 res->streams = slen;
312 res->nummt   = roar_ltm_numbits(mt);
313
314 memcpy(res->data, &(d64[2]), mes.datalen - 16);
315
316 if ( buf != NULL )
317  free(buf);
318 return res;
319}
320
321#define _CKNULL(x) if ( (x) == NULL ) return -1
322#define _RETMEMBERCKED(x,m) _CKNULL(x); return (x)->m
323
324int roar_ltm_get_numstreams(struct roar_ltm_result * res) {
325 _RETMEMBERCKED(res, streams);
326}
327int roar_ltm_get_mt(struct roar_ltm_result * res) {
328 _RETMEMBERCKED(res, mt);
329}
330int roar_ltm_get_window(struct roar_ltm_result * res) {
331 _RETMEMBERCKED(res, window);
332}
333
334static int64_t * roar_ltm_get_streamptr(struct roar_ltm_result * res, int streamidx) {
335 int64_t * ptr;
336 int numchans;
337 int i;
338
339 ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i) = ?", res, streamidx);
340
341 if ( res == NULL || streamidx < 0 || streamidx >= res->streams )
342  return NULL;
343
344 ptr = res->data;
345
346 ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i): res->data=%p", res, streamidx, res->data);
347
348 for (i = 0; i < streamidx; i++) {
349  numchans = *ptr & 0xFFFF;
350
351  ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i): i=%i, numchans=%i", res, streamidx, i, numchans);
352
353  ptr += res->nummt * numchans;
354  ptr++;
355 }
356
357 ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i) = %p", res, streamidx, ptr);
358 return ptr;
359}
360
361int roar_ltm_get_numchans(struct roar_ltm_result * res, int streamidx) {
362 int64_t * ptr = roar_ltm_get_streamptr(res, streamidx);
363
364 if ( ptr == NULL )
365  return -1;
366
367 return *ptr & 0xFFFF;
368}
369
370int64_t roar_ltm_extract(struct roar_ltm_result * res, int mt, int streamidx, int channel) {
371 int64_t * ptr = roar_ltm_get_streamptr(res, streamidx);
372 int numchans;
373 int resmt;
374
375 ROAR_DBG("roar_ltm_extract(res=%p, mt=0x%.4x, streamidx=%i, channel=%i) = ?", res, mt, streamidx, channel);
376
377 if ( roar_ltm_numbits(mt) != 1 )
378  return -1;
379
380 ROAR_DBG("roar_ltm_extract(res=%p, mt=0x%.4x, streamidx=%i, channel=%i) = ?", res, mt, streamidx, channel);
381
382 if ( ptr == NULL )
383  return -1;
384
385 numchans = *ptr & 0xFFFF;
386
387 ROAR_DBG("roar_ltm_extract(res=%p, mt=0x%.4x, streamidx=%i, channel=%i): numchans=%i", res, mt, streamidx, channel, numchans);
388
389 if ( channel >= numchans )
390  return -1;
391
392 ptr++;
393
394 ptr += res->nummt * channel;
395
396 // now ptr points to the first mt for the given channel.
397
398 resmt = res->mt;
399
400 while (!(mt & 0x1)) {
401  if ( resmt & 0x1 )
402   ptr++;
403  mt    >>= 1;
404  resmt >>= 1;
405 }
406
407 ROAR_DBG("roar_ltm_extract(res=%p, mt=?, streamidx=%i, channel=%i): ptr=%p", res, streamidx, channel, ptr);
408 ROAR_DBG("roar_ltm_extract(res=%p, mt=?, streamidx=%i, channel=%i) = %lli", res, streamidx, channel, (long long int)*ptr);
409
410 return *ptr;
411}
412
413//ll
Note: See TracBrowser for help on using the repository browser.