source: roaraudio/libroar/caps.c @ 4498:1396b66d445d

Last change on this file since 4498:1396b66d445d was 4498:1396b66d445d, checked in by phi, 14 years ago

implemented basic CAPS api for standards

File size: 5.1 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 if ( flags == -1 )
113  flags = 0;
114
115 if ( con == NULL )
116  return -1;
117
118 if ( out != NULL )
119  flags |= ROAR_CF_REQUEST;
120
121 if ( (flags & ROAR_CF_REQUEST) && out == NULL )
122  return -1;
123
124 if ( in != NULL )
125  if ( in->stds_len == 0 )
126   in = NULL;
127
128 memset(&caps, 0, sizeof(caps));
129
130 caps.version = 0;
131 caps.type    = ROAR_CT_STANDARDS;
132 caps.flags   = flags;
133
134 memset(&mes, 0, sizeof(mes));
135
136 if ( in != NULL ) {
137  // we use a hack here to avoid double alloc:
138  // first pass the data in native byte order.
139  // after we got a buffer swap in-buffer.
140  caps.data = in->stds;
141  caps.len  = in->stds_len * 4;
142 }
143
144 if ( roar_caps_to_msg(&mes, &caps, &data) == -1 )
145  return -1;
146
147 if ( in != NULL ) {
148  if ( data == NULL ) {
149   for (i = 0; i < in->stds_len; i++) {
150    ((uint32_t*)mes.data)[i+1] = ROAR_HOST2NET32(((uint32_t*)mes.data)[i+1]);
151   }
152  } else {
153   for (i = 0; i < in->stds_len; i++) {
154    ((uint32_t*)data)[i+1] = ROAR_HOST2NET32(((uint32_t*)data)[i+1]);
155   }
156  }
157 }
158
159 mes.cmd = ROAR_CMD_CAPS;
160
161 if ( roar_req(con, &mes, &data) == -1 )
162  return -1;
163
164 if ( mes.cmd != ROAR_CMD_OK ) {
165  if ( data != NULL )
166   free(data);
167  return -1;
168 }
169
170 if ( roar_caps_from_msg(&caps, &mes, data) == -1 ) {
171  if ( data != NULL )
172   free(data);
173  return -1;
174 }
175
176 // check if response matches the request:
177 if ( caps.version != 0 || caps.type != ROAR_CT_STANDARDS || (caps.len & 0x3) != 0 ) {
178  if ( data != NULL )
179   free(data);
180  return -1;
181 }
182
183 if ( out != NULL ) {
184  *out = roar_stds_new(caps.len/4);
185  if ( *out == NULL ) {
186   if ( data != NULL )
187    free(data);
188   return -1;
189  }
190
191  for (i = 0; i < (*out)->stds_len; i++) {
192   (*out)->stds[i] = ROAR_NET2HOST32(((uint32_t*)caps.data)[i+1]);
193  }
194 }
195
196 if ( data != NULL )
197  free(data);
198
199 return 0;
200}
201
202struct roar_stds * roar_stds_new(size_t len) {
203 struct roar_stds * ret;
204
205 if ( len == 0 )
206  return NULL;
207
208 ret = roar_mm_malloc(sizeof(struct roar_stds));
209
210 if ( ret == NULL )
211  return NULL;
212
213 memset(ret, 0, sizeof(struct roar_stds));
214
215 ret->stds_len = len;
216 ret->stds     = roar_mm_malloc(len*sizeof(uint32_t));
217
218 if ( ret->stds == NULL ) {
219  roar_mm_free(ret);
220  return NULL;
221 }
222
223 memset(ret->stds, 0, len*sizeof(uint32_t));
224
225 return ret;
226}
227
228int roar_stds_free(struct roar_stds * stds) {
229 if ( stds == NULL )
230  return -1;
231
232 if ( stds->stds != NULL )
233  roar_mm_free(stds->stds);
234
235 roar_mm_free(stds);
236
237 return 0;
238}
239
240//ll
Note: See TracBrowser for help on using the repository browser.