source: roaraudio/libroar/caps.c @ 4944:97c58eba6db9

Last change on this file since 4944:97c58eba6db9 was 4944:97c58eba6db9, checked in by phi, 13 years ago

work around small API inconsistency ((void*) vs. (char*))

File size: 6.2 KB
Line 
1//caps.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2011
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
38int roar_caps_to_msg(struct roar_message * mes,  struct roar_caps    * caps, void ** data) {
39 char * datap;
40 size_t needlen = 4;
41
42 if ( mes == NULL || caps == NULL )
43  return -1;
44
45 needlen += caps->len;
46
47 if ( needlen > sizeof(mes->data) ) {
48  if ( data == NULL )
49   return -1;
50
51  if ( (*data = malloc(needlen)) == NULL )
52   return -1;
53
54  datap = *data;
55 } else {
56  datap = mes->data;
57 }
58
59 datap[0] = caps->version;
60 datap[1] = caps->type;
61 datap[2] = (caps->flags & 0xFF00) >> 8;
62 datap[3] = caps->flags & 0xFF;
63
64 if ( caps->len != 0 ) {
65  memcpy(&(datap[4]), caps->data, caps->len);
66 }
67
68 mes->datalen = needlen;
69
70 return 0;
71}
72
73int roar_caps_from_msg(struct roar_caps  * caps, struct roar_message * mes,  void  * data) {
74 char * datap;
75
76 if ( mes == NULL || caps == NULL )
77  return -1;
78
79 if ( data != NULL ) {
80  datap = data;
81 } else {
82  datap = mes->data;
83 }
84
85 // versin check.
86 if ( datap[0] != 0 || mes->datalen < 4 )
87  return -1;
88
89 memset(caps, 0, sizeof(struct roar_caps));
90
91 caps->version = datap[0];
92 caps->type    = datap[1];
93 caps->flags   = (datap[2] << 8) | datap[3];
94
95 if ( mes->datalen == 4 ) {
96  caps->data    = NULL;
97  caps->len     = 0;
98 } else {
99  caps->data    = &(datap[4]);
100  caps->len     = mes->datalen - 4;
101 }
102
103 return 0;
104}
105
106int roar_caps_stds(struct roar_connection * con, struct roar_stds ** out, struct roar_stds * in, int flags) {
107 struct roar_message mes;
108 struct roar_caps caps;
109 void * data = NULL;
110 char * data_char;
111 size_t i;
112
113 ROAR_DBG("roar_caps_stds(con=%p, out=%p, in=%p, flags=0x%.4x) = ?", con, out, in, flags);
114
115 if ( flags == -1 )
116  flags = 0;
117
118 if ( con == NULL )
119  return -1;
120
121 if ( out != NULL )
122  flags |= ROAR_CF_REQUEST;
123
124 if ( (flags & ROAR_CF_REQUEST) && out == NULL )
125  return -1;
126
127 if ( in != NULL )
128  if ( in->stds_len == 0 )
129   in = NULL;
130
131 memset(&caps, 0, sizeof(caps));
132
133 caps.version = 0;
134 caps.type    = ROAR_CT_STANDARDS;
135 caps.flags   = flags;
136
137 memset(&mes, 0, sizeof(mes));
138
139 if ( in != NULL ) {
140  // we use a hack here to avoid double alloc:
141  // first pass the data in native byte order.
142  // after we got a buffer swap in-buffer.
143  caps.data = in->stds;
144  caps.len  = in->stds_len * 4;
145 }
146
147 if ( roar_caps_to_msg(&mes, &caps, &data) == -1 )
148  return -1;
149
150 if ( in != NULL ) {
151  if ( data == NULL ) {
152   for (i = 0; i < in->stds_len; i++) {
153    ((uint32_t*)mes.data)[i] = ROAR_HOST2NET32(((uint32_t*)mes.data)[i]);
154   }
155  } else {
156   for (i = 0; i < in->stds_len; i++) {
157    ((uint32_t*)data)[i] = ROAR_HOST2NET32(((uint32_t*)data)[i]);
158   }
159  }
160 }
161
162 mes.cmd = ROAR_CMD_CAPS;
163
164 data_char = data;
165 if ( roar_req(con, &mes, &data_char) == -1 )
166  return -1;
167 data = data_char;
168
169 if ( mes.cmd != ROAR_CMD_OK ) {
170  if ( data != NULL )
171   free(data);
172  return -1;
173 }
174
175 if ( roar_caps_from_msg(&caps, &mes, data) == -1 ) {
176  if ( data != NULL )
177   free(data);
178  return -1;
179 }
180
181 // check if response matches the request:
182 if ( caps.version != 0 || caps.type != ROAR_CT_STANDARDS || (caps.len & 0x3) != 0 ) {
183  if ( data != NULL )
184   free(data);
185  return -1;
186 }
187
188 if ( out != NULL ) {
189  *out = roar_stds_new(caps.len/4);
190  if ( *out == NULL ) {
191   if ( data != NULL )
192    free(data);
193   return -1;
194  }
195
196  ROAR_DBG("roar_caps_stds(con=%p, out=%p, in=%p, flags=0x%.4x): (*out)->stds_len=%llu", con, out, in, flags, (long long unsigned int)(*out)->stds_len);
197
198  for (i = 0; i < (*out)->stds_len; i++) {
199   (*out)->stds[i] = ROAR_NET2HOST32(((uint32_t*)caps.data)[i]);
200   ROAR_DBG("roar_caps_stds(con=%p, out=%p, in=%p, flags=0x%.4x): (*out)->stds[%llu] = 0x%.8x", con, out, in, flags, (long long unsigned int)i, (*out)->stds[i]);
201  }
202 }
203
204 if ( data != NULL )
205  free(data);
206
207 return 0;
208}
209
210struct roar_stds * roar_stds_new(size_t len) {
211 struct roar_stds * ret;
212
213 if ( len == 0 )
214  return NULL;
215
216 ret = roar_mm_malloc(sizeof(struct roar_stds));
217
218 if ( ret == NULL )
219  return NULL;
220
221 memset(ret, 0, sizeof(struct roar_stds));
222
223 ret->stds_len = len;
224 ret->stds     = roar_mm_malloc(len*sizeof(uint32_t));
225
226 if ( ret->stds == NULL ) {
227  roar_mm_free(ret);
228  return NULL;
229 }
230
231 memset(ret->stds, 0, len*sizeof(uint32_t));
232
233 return ret;
234}
235
236int roar_stds_free(struct roar_stds * stds) {
237 if ( stds == NULL )
238  return -1;
239
240 if ( stds->stds != NULL )
241  roar_mm_free(stds->stds);
242
243 roar_mm_free(stds);
244
245 return 0;
246}
247
248
249static struct {
250 const int    vendor;
251 const char * name;
252} _libroar_std_vendors[] = {
253 {ROAR_STDV_ROARAUDIO, "RoarAudio"},
254 {ROAR_STDV_PROTO,     "Protocols"},
255 {ROAR_STDV_RFC,       "RFC"},
256 {-1, NULL}
257};
258
259int roar_stds_str2vendor(const char * vendor) {
260 int i;
261
262 for (i = 0; _libroar_std_vendors[i].name != NULL; i++)
263  if ( !strcasecmp(_libroar_std_vendors[i].name, vendor) )
264   return _libroar_std_vendors[i].vendor;
265
266 return -1;
267}
268
269const char * roar_stds_vendor2str(const int vendor) {
270 int i;
271
272 for (i = 0; _libroar_std_vendors[i].name != NULL; i++)
273  if ( _libroar_std_vendors[i].vendor == vendor )
274   return _libroar_std_vendors[i].name;
275
276 return NULL;
277}
278
279
280//ll
Note: See TracBrowser for help on using the repository browser.