source: roaraudio/libroar/caps.c @ 4502:cee57ed26316

Last change on this file since 4502:cee57ed26316 was 4502:cee57ed26316, checked in by phi, 13 years ago

added functions to look up standards names

File size: 6.2 KB
Line 
1//caps.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
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 char * data = NULL;
110 size_t i;
111
112 ROAR_DBG("roar_caps_stds(con=%p, out=%p, in=%p, flags=0x%.4x) = ?", con, out, in, flags);
113
114 if ( flags == -1 )
115  flags = 0;
116
117 if ( con == NULL )
118  return -1;
119
120 if ( out != NULL )
121  flags |= ROAR_CF_REQUEST;
122
123 if ( (flags & ROAR_CF_REQUEST) && out == NULL )
124  return -1;
125
126 if ( in != NULL )
127  if ( in->stds_len == 0 )
128   in = NULL;
129
130 memset(&caps, 0, sizeof(caps));
131
132 caps.version = 0;
133 caps.type    = ROAR_CT_STANDARDS;
134 caps.flags   = flags;
135
136 memset(&mes, 0, sizeof(mes));
137
138 if ( in != NULL ) {
139  // we use a hack here to avoid double alloc:
140  // first pass the data in native byte order.
141  // after we got a buffer swap in-buffer.
142  caps.data = in->stds;
143  caps.len  = in->stds_len * 4;
144 }
145
146 if ( roar_caps_to_msg(&mes, &caps, &data) == -1 )
147  return -1;
148
149 if ( in != NULL ) {
150  if ( data == NULL ) {
151   for (i = 0; i < in->stds_len; i++) {
152    ((uint32_t*)mes.data)[i] = ROAR_HOST2NET32(((uint32_t*)mes.data)[i]);
153   }
154  } else {
155   for (i = 0; i < in->stds_len; i++) {
156    ((uint32_t*)data)[i] = ROAR_HOST2NET32(((uint32_t*)data)[i]);
157   }
158  }
159 }
160
161 mes.cmd = ROAR_CMD_CAPS;
162
163 if ( roar_req(con, &mes, &data) == -1 )
164  return -1;
165
166 if ( mes.cmd != ROAR_CMD_OK ) {
167  if ( data != NULL )
168   free(data);
169  return -1;
170 }
171
172 if ( roar_caps_from_msg(&caps, &mes, data) == -1 ) {
173  if ( data != NULL )
174   free(data);
175  return -1;
176 }
177
178 // check if response matches the request:
179 if ( caps.version != 0 || caps.type != ROAR_CT_STANDARDS || (caps.len & 0x3) != 0 ) {
180  if ( data != NULL )
181   free(data);
182  return -1;
183 }
184
185 if ( out != NULL ) {
186  *out = roar_stds_new(caps.len/4);
187  if ( *out == NULL ) {
188   if ( data != NULL )
189    free(data);
190   return -1;
191  }
192
193  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);
194
195  for (i = 0; i < (*out)->stds_len; i++) {
196   (*out)->stds[i] = ROAR_NET2HOST32(((uint32_t*)caps.data)[i]);
197   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]);
198  }
199 }
200
201 if ( data != NULL )
202  free(data);
203
204 return 0;
205}
206
207struct roar_stds * roar_stds_new(size_t len) {
208 struct roar_stds * ret;
209
210 if ( len == 0 )
211  return NULL;
212
213 ret = roar_mm_malloc(sizeof(struct roar_stds));
214
215 if ( ret == NULL )
216  return NULL;
217
218 memset(ret, 0, sizeof(struct roar_stds));
219
220 ret->stds_len = len;
221 ret->stds     = roar_mm_malloc(len*sizeof(uint32_t));
222
223 if ( ret->stds == NULL ) {
224  roar_mm_free(ret);
225  return NULL;
226 }
227
228 memset(ret->stds, 0, len*sizeof(uint32_t));
229
230 return ret;
231}
232
233int roar_stds_free(struct roar_stds * stds) {
234 if ( stds == NULL )
235  return -1;
236
237 if ( stds->stds != NULL )
238  roar_mm_free(stds->stds);
239
240 roar_mm_free(stds);
241
242 return 0;
243}
244
245
246static struct {
247 const int    vendor;
248 const char * name;
249} _libroar_std_vendors[] = {
250 {ROAR_STDV_ROARAUDIO, "RoarAudio"},
251 {ROAR_STDV_PROTO,     "Protocols"},
252 {ROAR_STDV_RFC,       "RFC"},
253 {-1, NULL}
254};
255
256int roar_stds_str2vendor(const char * vendor) {
257 int i;
258
259 for (i = 0; _libroar_std_vendors[i].name != NULL; i++)
260  if ( !strcasecmp(_libroar_std_vendors[i].name, vendor) )
261   return _libroar_std_vendors[i].vendor;
262
263 return -1;
264}
265
266const char * roar_stds_vendor2str(const int vendor) {
267 int i;
268
269 for (i = 0; _libroar_std_vendors[i].name != NULL; i++)
270  if ( _libroar_std_vendors[i].vendor == vendor )
271   return _libroar_std_vendors[i].name;
272
273 return NULL;
274}
275
276
277//ll
Note: See TracBrowser for help on using the repository browser.