source: roaraudio/libroar/ltm.c @ 4282:96355d721ce0

Last change on this file since 4282:96355d721ce0 was 4282:96355d721ce0, checked in by phi, 14 years ago

more debug lions...

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