source: roaraudio/libroar/ltm.c @ 4275:2a5ba5fd0120

Last change on this file since 4275:2a5ba5fd0120 was 4275:2a5ba5fd0120, checked in by phi, 14 years ago

corrected client site handling of ltm, should now be complet

File size: 8.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 for (i = 0; i < 8; i++) {
264  d16[i] = ROAR_NET2HOST64(d16[i]);
265 }
266
267 for (i = 2; i < mes.datalen/8; i++) {
268  d64[i] = ROAR_NET2HOST64(d64[i]);
269 }
270
271 needed_structlen = sizeof(struct roar_ltm_result) + mes.datalen - 16;
272
273 if ( oldresult != NULL ) {
274  if ( oldresult->structlen >= needed_structlen ) {
275   res = oldresult;
276   needed_structlen = oldresult->structlen;
277  } else {
278   roar_ltm_freeres(oldresult);
279  }
280 } else {
281  res = roar_mm_malloc(needed_structlen);
282 }
283
284 if ( res == NULL ) {
285  if ( buf != NULL )
286   free(buf);
287  return NULL;
288 }
289
290 memset(res, 0, needed_structlen);
291 res->structlen = needed_structlen;
292
293 res->mt      = mt;
294 res->window  = window;
295 res->streams = slen;
296 res->nummt   = roar_ltm_numbits(mt);
297
298 memcpy(res->data, &(d64[2]), mes.datalen - 16);
299
300 if ( buf != NULL )
301  free(buf);
302 return res;
303}
304
305#define _CKNULL(x) if ( (x) == NULL ) return -1
306#define _RETMEMBERCKED(x,m) _CKNULL(x); return (x)->m
307
308int roar_ltm_get_numstreams(struct roar_ltm_result * res) {
309 _RETMEMBERCKED(res, streams);
310}
311int roar_ltm_get_mt(struct roar_ltm_result * res) {
312 _RETMEMBERCKED(res, mt);
313}
314int roar_ltm_get_window(struct roar_ltm_result * res) {
315 _RETMEMBERCKED(res, window);
316}
317
318static int64_t * roar_ltm_get_streamptr(struct roar_ltm_result * res, int streamidx) {
319 int64_t * ptr;
320 int numchans;
321 int i;
322
323 if ( res == NULL || streamidx < 0 || streamidx >= res->streams )
324  return NULL;
325
326 ptr = res->data;
327
328 for (i = 0; i < streamidx; i++) {
329  numchans = *ptr & 0xFFFF;
330  ptr += res->nummt * numchans;
331  ptr++;
332 }
333
334 return ptr;
335}
336
337int roar_ltm_get_numchans(struct roar_ltm_result * res, int streamidx) {
338 int64_t * ptr = roar_ltm_get_streamptr(res, streamidx);
339
340 if ( ptr == NULL )
341  return -1;
342
343 return *ptr & 0xFFFF;
344}
345
346int64_t roar_ltm_extract(struct roar_ltm_result * res, int mt, int streamidx, int channel) {
347 int64_t * ptr = roar_ltm_get_streamptr(res, streamidx);
348 int numchans;
349 int resmt;
350
351 if ( roar_ltm_numbits(mt) != 1 )
352  return -1;
353
354 if ( ptr == NULL )
355  return -1;
356
357 numchans = *ptr & 0xFFFF;
358
359 if ( channel >= numchans )
360  return -1;
361
362 ptr++;
363
364 ptr += res->nummt * channel;
365
366 // now ptr points to the first mt for the given channel.
367
368 resmt = res->mt;
369
370 while (!(mt & 0x1)) {
371  if ( resmt & 0x1 )
372   ptr++;
373  mt    >>= 1;
374  resmt >>= 1;
375 }
376
377 return *ptr;
378}
379
380//ll
Note: See TracBrowser for help on using the repository browser.