source: roaraudio/libroar/ltm.c @ 5961:06e7fd9e4c25

Last change on this file since 5961:06e7fd9e4c25 was 5961:06e7fd9e4c25, checked in by phi, 10 years ago

Updates of copyright and license headers

File size: 8.4 KB
Line 
1//ltm.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2014
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 ) {
68  roar_err_set(ROAR_ERROR_INVAL);
69  return -1;
70 }
71
72 if ( streams == NULL || slen == 0 || mes == NULL || buf == NULL ) {
73  roar_err_set(ROAR_ERROR_FAULT);
74  return -1;
75 }
76
77 memset(mes, 0, sizeof(struct roar_message));
78
79 switch (regtype) {
80  case ROAR_LTM_SST_REGISTER:
81  case ROAR_LTM_SST_UNREGISTER:
82    mes->cmd = ROAR_CMD_SET_STREAM_PARA;
83   break;
84  case ROAR_LTM_SST_GET_RAW:
85    mes->cmd = ROAR_CMD_GET_STREAM_PARA;
86   break;
87  default:
88    roar_err_set(ROAR_ERROR_NOTSUP);
89    return -1;
90   break;
91 }
92
93 if ( slen == 1 ) {
94  mes->stream  = *streams;
95  mes->datalen = 6 * 2;
96 } else {
97  mes->stream = -1;
98  mes->datalen = (6 + slen) * 2;
99 }
100
101 if ( mes->datalen > LIBROAR_BUFFER_MSGDATA ) {
102  roar_err_set(ROAR_ERROR_NOTSUP);
103  return -1;
104 }
105
106 *buf = NULL;
107
108 data = (uint16_t*)mes->data;
109
110 data[0] = 0;
111 data[1] = ROAR_STREAM_PARA_LTM;
112 data[2] = regtype;
113 data[3] = window;
114 data[4] = 0;
115 data[5] = mt;
116
117 for (i = 0; i < slen; i++) {
118  data[6+i] = streams[i];
119 }
120
121 for (i = 0; i < (mes->datalen/2); i++) {
122  data[i] = ROAR_HOST2NET16(data[i]);
123 }
124
125 return 0;
126}
127
128static int roar_ltm_regunreg(struct roar_connection * con, int mt, int window, int * streams, size_t slen, int type) {
129 struct roar_message mes;
130 char * buf = NULL;
131 int    ret;
132
133 if ( roar_ltm_pack_req(mt, window, streams, slen, &mes, &buf, type) == -1 )
134  return -1;
135
136 ret = roar_req(con, &mes, &buf);
137
138 if ( buf != NULL )
139  roar_mm_free(buf);
140
141 if ( ret != -1 ) {
142  if ( mes.cmd != ROAR_CMD_OK )
143   ret = -1;
144 }
145
146 return ret;
147}
148
149int roar_ltm_register(struct roar_connection * con, int mt, int window, int * streams, size_t slen) {
150 return roar_ltm_regunreg(con, mt, window, streams, slen, ROAR_LTM_SST_REGISTER);
151}
152int roar_ltm_unregister(struct roar_connection * con, int mt, int window, int * streams, size_t slen) {
153 return roar_ltm_regunreg(con, mt, window, streams, slen, ROAR_LTM_SST_UNREGISTER);
154}
155
156
157#ifdef DEBUG
158#define HEXDUMP64(x) roar_ltm_hexdump64((x))
159static void roar_ltm_hexdump64(void * p) {
160 unsigned char * d = p;
161 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]);
162}
163#else
164#define HEXDUMP64(x)
165#endif
166
167struct roar_ltm_result * roar_ltm_get(struct roar_connection * con,
168                                      int mt, int window,
169                                      int * streams, size_t slen,
170                                      struct roar_ltm_result * oldresult) {
171 struct roar_ltm_result * res = NULL;
172 struct roar_message mes;
173 size_t needed_structlen = 0;
174 int64_t  * d64;
175 char * buf = NULL;
176 int    ret;
177 size_t i;
178
179 if ( con == NULL ) {
180  roar_err_set(ROAR_ERROR_FAULT);
181  return NULL;
182 }
183
184 if ( streams == NULL || slen == 0 ) {
185  roar_err_set(ROAR_ERROR_FAULT);
186  return NULL;
187 }
188
189 if ( roar_ltm_pack_req(mt, window, streams, slen, &mes, &buf, ROAR_LTM_SST_GET_RAW) == -1 )
190  return NULL;
191
192 ret = roar_req(con, &mes, &buf);
193
194 if ( ret == -1 || mes.cmd != ROAR_CMD_OK ) {
195  if ( buf != NULL )
196   roar_mm_free(buf);
197  return NULL;
198 }
199
200 if ( buf == NULL ) {
201  d64 = ( int64_t*)&(mes.data);
202 } else {
203  d64 = ( int64_t*)buf;
204 }
205
206
207 for (i = 0; i < mes.datalen/8; i++) {
208  ROAR_DBG("roar_ltm_get(*): d64[i=%i]=%lli", i, (long long int)d64[i]);
209  HEXDUMP64(&(d64[i]));
210  d64[i] = ROAR_NET2HOST64(d64[i]);
211  HEXDUMP64(&(d64[i]));
212  ROAR_DBG("roar_ltm_get(*): d64[i=%i]=%lli", i, (long long int)d64[i]);
213 }
214
215 needed_structlen = sizeof(struct roar_ltm_result) + mes.datalen;
216
217 if ( oldresult != NULL ) {
218  if ( oldresult->structlen >= needed_structlen ) {
219   res = oldresult;
220   needed_structlen = oldresult->structlen;
221  } else {
222   roar_ltm_freeres(oldresult);
223  }
224 } else {
225  res = roar_mm_malloc(needed_structlen);
226 }
227
228 if ( res == NULL ) {
229  if ( buf != NULL )
230   roar_mm_free(buf);
231  return NULL;
232 }
233
234 memset(res, 0, needed_structlen);
235 res->structlen = needed_structlen;
236
237 res->mt      = mt;
238 res->window  = window;
239 res->streams = slen;
240 res->nummt   = roar_ltm_numbits(mt);
241
242 memcpy(res->data, d64, mes.datalen);
243
244 if ( buf != NULL )
245  roar_mm_free(buf);
246 return res;
247}
248
249#define _CKNULL(x) if ( (x) == NULL ) { roar_err_set(ROAR_ERROR_FAULT); return -1; }
250#define _RETMEMBERCKED(x,m) _CKNULL(x) return (x)->m
251
252int roar_ltm_get_numstreams(struct roar_ltm_result * res) {
253 _RETMEMBERCKED(res, streams);
254}
255int roar_ltm_get_mt(struct roar_ltm_result * res) {
256 _RETMEMBERCKED(res, mt);
257}
258int roar_ltm_get_window(struct roar_ltm_result * res) {
259 _RETMEMBERCKED(res, window);
260}
261
262static int64_t * roar_ltm_get_streamptr(struct roar_ltm_result * res, size_t streamidx) {
263 int64_t * ptr;
264 int numchans;
265 size_t i;
266
267 ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i) = ?", res, streamidx);
268
269 if ( res == NULL || streamidx >= res->streams ) {
270  roar_err_set(ROAR_ERROR_FAULT);
271  return NULL;
272 }
273
274 ptr = res->data;
275
276 ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i): res->data=%p", res, streamidx, res->data);
277
278 for (i = 0; i < streamidx; i++) {
279  numchans = *ptr & 0xFFFF;
280
281  ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i): i=%i, numchans=%i", res, streamidx, i, numchans);
282
283  ptr += res->nummt * numchans;
284  ptr++;
285 }
286
287 ROAR_DBG("roar_ltm_get_streamptr(res=%p, streamidx=%i) = %p", res, streamidx, ptr);
288 return ptr;
289}
290
291int roar_ltm_get_numchans(struct roar_ltm_result * res, size_t streamidx) {
292 int64_t * ptr = roar_ltm_get_streamptr(res, streamidx);
293
294 if ( ptr == NULL )
295  return -1;
296
297 return *ptr & 0xFFFF;
298}
299
300int64_t roar_ltm_extract(struct roar_ltm_result * res, int mt, size_t streamidx, int channel) {
301 int64_t * ptr = roar_ltm_get_streamptr(res, streamidx);
302 int numchans;
303 int resmt;
304
305 ROAR_DBG("roar_ltm_extract(res=%p, mt=0x%.4x, streamidx=%i, channel=%i) = ?", res, mt, streamidx, channel);
306
307 if ( roar_ltm_numbits(mt) != 1 ) {
308  roar_err_set(ROAR_ERROR_INVAL);
309  return -1;
310 }
311
312 ROAR_DBG("roar_ltm_extract(res=%p, mt=0x%.4x, streamidx=%i, channel=%i) = ?", res, mt, streamidx, channel);
313
314 if ( ptr == NULL )
315  return -1;
316
317 numchans = *ptr & 0xFFFF;
318
319 ROAR_DBG("roar_ltm_extract(res=%p, mt=0x%.4x, streamidx=%i, channel=%i): numchans=%i", res, mt, streamidx, channel, numchans);
320
321 if ( channel >= numchans ) {
322  roar_err_set(ROAR_ERROR_RANGE);
323  return -1;
324 }
325
326 ptr++;
327
328 ptr += res->nummt * channel;
329
330 // now ptr points to the first mt for the given channel.
331
332 resmt = res->mt;
333
334 while (!(mt & 0x1)) {
335  if ( resmt & 0x1 )
336   ptr++;
337  mt    >>= 1;
338  resmt >>= 1;
339 }
340
341 ROAR_DBG("roar_ltm_extract(res=%p, mt=?, streamidx=%i, channel=%i): ptr=%p", res, streamidx, channel, ptr);
342 ROAR_DBG("roar_ltm_extract(res=%p, mt=?, streamidx=%i, channel=%i) = %lli", res, streamidx, channel, (long long int)*ptr);
343
344 return *ptr;
345}
346
347//ll
Note: See TracBrowser for help on using the repository browser.