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