source: mainline/uspace/lib/hound/src/client.c@ ec81221

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ec81221 was ec81221, checked in by Jan Vesely <jano.vesely@…>, 12 years ago

libhound: Handle default target

  • Property mode set to 100644
File size: 8.1 KB
Line 
1/*
2 * Copyright (c) 2012 Jan Vesely
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libhound
30 * @addtogroup audio
31 * @{
32 */
33/** @file
34 * Common USB functions.
35 */
36#include <adt/list.h>
37#include <errno.h>
38#include <loc.h>
39#include <str.h>
40#include <stdlib.h>
41#include <stdio.h>
42#include <libarch/types.h>
43
44#include "protocol.h"
45#include "client.h"
46
47/***
48 * CLIENT SIDE
49 ***/
50
51typedef struct hound_stream {
52 link_t link;
53 pcm_format_t format;
54 async_exch_t *exch;
55 hound_context_t *context;
56} hound_stream_t;
57
58typedef struct hound_context {
59 hound_sess_t *session;
60 const char *name;
61 bool record;
62 list_t stream_list;
63 struct {
64 hound_stream_t *stream;
65 pcm_format_t format;
66 size_t bsize;
67 } main;
68 hound_context_id_t id;
69} hound_context_t;
70
71
72static hound_context_t *hound_context_create(const char *name, bool record,
73 pcm_format_t format, size_t bsize)
74{
75 hound_context_t *new_context = malloc(sizeof(hound_context_t));
76 if (new_context) {
77 char *cont_name;
78 int ret = asprintf(&cont_name, "%llu:%s", task_get_id(), name);
79 if (ret < 0) {
80 free(new_context);
81 return NULL;
82 }
83 list_initialize(&new_context->stream_list);
84 new_context->name = cont_name;
85 new_context->record = record;
86 new_context->session = hound_service_connect(HOUND_SERVICE);
87 new_context->main.stream = NULL;
88 new_context->main.format = format;
89 new_context->main.bsize = bsize;
90 if (!new_context->session) {
91 free(new_context->name);
92 free(new_context);
93 return NULL;
94 }
95 new_context->id = hound_service_register_context(
96 new_context->session, new_context->name, record);
97 if (hound_context_id_err(new_context->id) != EOK) {
98 free(new_context->name);
99 free(new_context);
100 return NULL;
101 }
102 }
103 return new_context;
104}
105
106hound_context_t * hound_context_create_playback(const char *name,
107 pcm_format_t format, size_t bsize)
108{
109 return hound_context_create(name, false, format, bsize);
110}
111
112hound_context_t * hound_context_create_capture(const char *name,
113 pcm_format_t format, size_t bsize)
114{
115 return hound_context_create(name, true, format, bsize);
116}
117
118void hound_context_destroy(hound_context_t *hound)
119{
120 assert(hound);
121 hound_service_unregister_context(hound->session, hound->id);
122 hound_service_disconnect(hound->session);
123 free(hound->name);
124 free(hound);
125}
126
127int hound_context_enable(hound_context_t *hound)
128{
129 assert(hound);
130 return ENOTSUP;
131}
132int hound_context_disable(hound_context_t *hound)
133{
134 assert(hound);
135 return ENOTSUP;
136}
137
138int hound_context_get_available_targets(hound_context_t *hound,
139 const char ***names, size_t *count)
140{
141 assert(hound);
142 assert(names);
143 assert(count);
144 return hound_service_get_list_all(hound->session, names, count,
145 hound->record ? HOUND_SOURCE_DEVS : HOUND_SINK_DEVS);
146}
147
148int hound_context_get_connected_targets(hound_context_t *hound,
149 const char ***names, size_t *count)
150{
151 assert(hound);
152 assert(names);
153 assert(count);
154 return hound_service_get_list(hound->session, names, count,
155 HOUND_CONNECTED | (hound->record ?
156 HOUND_SOURCE_DEVS : HOUND_SINK_DEVS), hound->name);
157}
158
159int hound_context_connect_target(hound_context_t *hound, const char* target)
160{
161 assert(hound);
162 assert(target);
163
164 const char **tgt = NULL;
165 size_t count = 1;
166 int ret = EOK;
167 if (str_cmp(target, HOUND_DEFAULT_TARGET) == 0) {
168 ret = hound_context_get_available_targets(hound, &tgt, &count);
169 if (ret != EOK)
170 return ret;
171 target = tgt[0];
172 }
173 //TODO handle all-targets
174
175 if (hound->record) {
176 ret = hound_service_connect_source_sink(
177 hound->session, target, hound->name);
178 } else {
179 ret = hound_service_connect_source_sink(
180 hound->session, hound->name, target);
181 }
182 if (tgt)
183 free(tgt[0]);
184 free(tgt);
185 return ret;
186}
187
188int hound_context_disconnect_target(hound_context_t *hound, const char* target)
189{
190 assert(hound);
191 assert(target);
192 if (hound->record) {
193 return hound_service_disconnect_source_sink(
194 hound->session, target, hound->name);
195 } else {
196 return hound_service_disconnect_source_sink(
197 hound->session, hound->name, target);
198 }
199}
200
201hound_stream_t *hound_stream_create(hound_context_t *hound, unsigned flags,
202 pcm_format_t format, size_t bsize)
203{
204 assert(hound);
205 async_exch_t *stream_exch = async_exchange_begin(hound->session);
206 if (!stream_exch)
207 return NULL;
208 hound_stream_t *new_stream = malloc(sizeof(hound_stream_t));
209 if (new_stream) {
210 link_initialize(&new_stream->link);
211 new_stream->exch = stream_exch;
212 new_stream->format = format;
213 new_stream->context = hound;
214 int ret = hound_service_stream_enter(new_stream->exch,
215 hound->id, flags, format, bsize);
216 if (ret != EOK) {
217 async_exchange_end(new_stream->exch);
218 free(new_stream);
219 return NULL;
220 }
221 list_append(&new_stream->link, &hound->stream_list);
222 }
223 return new_stream;
224}
225
226void hound_stream_destroy(hound_stream_t *stream)
227{
228 if (stream) {
229 // TODO drain?
230 hound_service_stream_exit(stream->exch);
231 async_exchange_end(stream->exch);
232 list_remove(&stream->link);
233 free(stream);
234 }
235}
236
237int hound_stream_write(hound_stream_t *stream, const void *data, size_t size)
238{
239 assert(stream);
240 if (!data || size == 0)
241 return EBADMEM;
242 return hound_service_stream_write(stream->exch, data, size);
243}
244
245int hound_stream_read(hound_stream_t *stream, void *data, size_t size)
246{
247 assert(stream);
248 if (!data || size == 0)
249 return EBADMEM;
250 return hound_service_stream_read(stream->exch, data, size);
251}
252
253static hound_stream_t * hound_get_main_stream(hound_context_t *hound)
254{
255 assert(hound);
256 if (!hound->main.stream)
257 hound->main.stream = hound_stream_create(hound, 0,
258 hound->main.format, hound->main.bsize);
259 return hound->main.stream;
260}
261
262int hound_write_main_stream(hound_context_t *hound,
263 const void *data, size_t size)
264{
265 assert(hound);
266 hound_stream_t *mstream = hound_get_main_stream(hound);
267 if (!mstream)
268 return ENOMEM;
269 return hound_stream_write(mstream, data, size);
270}
271
272int hound_read_main_stream(hound_context_t *hound, void *data, size_t size)
273{
274 assert(hound);
275 hound_stream_t *mstream = hound_get_main_stream(hound);
276 if (!mstream)
277 return ENOMEM;
278 return hound_stream_read(mstream, data, size);
279}
280
281int hound_write_replace_main_stream(hound_context_t *hound,
282 const void *data, size_t size)
283{
284 assert(hound);
285 if (!data || size == 0)
286 return EBADMEM;
287 // TODO implement
288 return ENOTSUP;
289}
290
291int hound_context_set_main_stream_format(hound_context_t *hound,
292 unsigned channels, unsigned rate, pcm_sample_format_t format)
293{
294 assert(hound);
295 // TODO implement
296 return ENOTSUP;
297}
298
299int hound_write_immediate(hound_context_t *hound, pcm_format_t format,
300 const void *data, size_t size)
301{
302 assert(hound);
303 hound_stream_t *tmpstream = hound_stream_create(hound, 0, format, size);
304 if (!tmpstream)
305 return ENOMEM;
306 const int ret = hound_stream_write(tmpstream, data, size);
307 if (ret == EOK) {
308 //TODO drain?
309 hound_service_stream_drain(tmpstream->exch);
310 }
311 hound_stream_destroy(tmpstream);
312 return ret;
313}
314
315
316/**
317 * @}
318 */
Note: See TracBrowser for help on using the repository browser.