source: roaraudio/libroar/ltm.c @ 4291:7a9728ff6900

Last change on this file since 4291:7a9728ff6900 was 4291:7a9728ff6900, checked in by phi, 14 years ago

killed 16 useless bytes

File size: 9.4 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 int64_t  * d64;
243 char * buf = NULL;
244 int    ret;
245 int    i;
246
247 if ( con == NULL )
248  return NULL;
249
250 if ( streams == NULL || slen == 0 )
251  return NULL;
252
253 if ( roar_ltm_pack_req(mt, window, streams, slen, &mes, &buf, ROAR_LTM_SST_GET_RAW) == -1 )
254  return NULL;
255
256 ret = roar_req(con, &mes, &buf);
257
258 if ( ret == -1 || mes.cmd != ROAR_CMD_OK ) {
259  if ( buf != NULL )
260   free(buf);
261  return NULL;
262 }
263
264 if ( buf == NULL ) {
265  d64 = ( int64_t*)&(mes.data);
266 } else {
267  d64 = ( int64_t*)buf;
268 }
269
270
271 for (i = 0; i < mes.datalen/8; i++) {
272  ROAR_DBG("roar_ltm_get(*): d64[i=%i]=%lli", i, (long long int)d64[i]);
273  HEXDUMP64(&(d64[i]));
274  d64[i] = ROAR_NET2HOST64(d64[i]);
275  HEXDUMP64(&(d64[i]));
276  ROAR_DBG("roar_ltm_get(*): d64[i=%i]=%lli", i, (long long int)d64[i]);
277 }
278
279 needed_structlen = sizeof(struct roar_ltm_result) + mes.datalen;
280
281 if ( oldresult != NULL ) {
282  if ( oldresult->structlen >= needed_structlen ) {
283   res = oldresult;
284   needed_structlen = oldresult->structlen;
285  } else {
286   roar_ltm_freeres(oldresult);
287  }
288 } else {
289  res = roar_mm_malloc(needed_structlen);
290 }
291
292 if ( res == NULL ) {
293  if ( buf != NULL )
294   free(buf);
295  return NULL;
296 }
297
298 memset(res, 0, needed_structlen);
299 res->structlen = needed_structlen;
300
301 res->mt      = mt;
302 res->window  = window;
303 res->streams = slen;
304 res->nummt   = roar_ltm_numbits(mt);
305
306 memcpy(res->data, d64, mes.datalen);
307
308 if ( buf != NULL )
309  free(buf);
310 return res;
311}
312
313#define _CKNULL(x) if ( (x) == NULL ) return -1
314#define _RETMEMBERCKED(x,m) _CKNULL(x); return (x)->m
315
316int roar_ltm_get_numstreams(struct roar_ltm_result * res) {
317 _RETMEMBERCKED(res, streams);
318}
319int roar_ltm_get_mt(struct roar_ltm_result * res) {
320 _RETMEMBERCKED(res, mt);
321}
322int roar_ltm_get_window(struct roar_ltm_result * res) {
323 _RETMEMBERCKED(res, window);
324}
325
326static int64_t * roar_ltm_get_streamptr(struct roar_ltm_result * res, int streamidx) {
327 int64_t * ptr;
328 int numchans;
329 int i;
330
331 ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i) = ?", res, streamidx);
332
333 if ( res == NULL || streamidx < 0 || streamidx >= res->streams )
334  return NULL;
335
336 ptr = res->data;
337
338 ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i): res->data=%p", res, streamidx, res->data);
339
340 for (i = 0; i < streamidx; i++) {
341  numchans = *ptr & 0xFFFF;
342
343  ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i): i=%i, numchans=%i", res, streamidx, i, numchans);
344
345  ptr += res->nummt * numchans;
346  ptr++;
347 }
348
349 ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i) = %p", res, streamidx, ptr);
350 return ptr;
351}
352
353int roar_ltm_get_numchans(struct roar_ltm_result * res, int streamidx) {
354 int64_t * ptr = roar_ltm_get_streamptr(res, streamidx);
355
356 if ( ptr == NULL )
357  return -1;
358
359 return *ptr & 0xFFFF;
360}
361
362int64_t roar_ltm_extract(struct roar_ltm_result * res, int mt, int streamidx, int channel) {
363 int64_t * ptr = roar_ltm_get_streamptr(res, streamidx);
364 int numchans;
365 int resmt;
366
367 ROAR_DBG("roar_ltm_extract(res=%p, mt=0x%.4x, streamidx=%i, channel=%i) = ?", res, mt, streamidx, channel);
368
369 if ( roar_ltm_numbits(mt) != 1 )
370  return -1;
371
372 ROAR_DBG("roar_ltm_extract(res=%p, mt=0x%.4x, streamidx=%i, channel=%i) = ?", res, mt, streamidx, channel);
373
374 if ( ptr == NULL )
375  return -1;
376
377 numchans = *ptr & 0xFFFF;
378
379 ROAR_DBG("roar_ltm_extract(res=%p, mt=0x%.4x, streamidx=%i, channel=%i): numchans=%i", res, mt, streamidx, channel, numchans);
380
381 if ( channel >= numchans )
382  return -1;
383
384 ptr++;
385
386 ptr += res->nummt * channel;
387
388 // now ptr points to the first mt for the given channel.
389
390 resmt = res->mt;
391
392 while (!(mt & 0x1)) {
393  if ( resmt & 0x1 )
394   ptr++;
395  mt    >>= 1;
396  resmt >>= 1;
397 }
398
399 ROAR_DBG("roar_ltm_extract(res=%p, mt=?, streamidx=%i, channel=%i): ptr=%p", res, streamidx, channel, ptr);
400 ROAR_DBG("roar_ltm_extract(res=%p, mt=?, streamidx=%i, channel=%i) = %lli", res, streamidx, channel, (long long int)*ptr);
401
402 return *ptr;
403}
404
405//ll
Note: See TracBrowser for help on using the repository browser.