source: mainline/uspace/srv/audio/hound/hound.c@ 98af9cc

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

hound: remove unused audio_client code

  • Property mode set to 100644
File size: 11.9 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/**
30 * @addtogroup audio
31 * @brief HelenOS sound server.
32 * @{
33 */
34/** @file
35 */
36
37#include <assert.h>
38#include <stdlib.h>
39
40#include "hound.h"
41#include "audio_device.h"
42#include "audio_sink.h"
43#include "audio_source.h"
44#include "connection.h"
45#include "log.h"
46#include "errno.h"
47#include "str_error.h"
48
49#define FIND_BY_NAME(type) \
50do { \
51 assert(list); \
52 assert(name); \
53 list_foreach(*list, it) { \
54 audio_ ## type ## _t *dev = \
55 audio_ ## type ## _list_instance(it); \
56 if (str_cmp(name, dev->name) == 0) { \
57 log_debug("%s with name '%s' is in the list", \
58 #type, name); \
59 return dev; \
60 } \
61 } \
62 return NULL; \
63} while (0)
64
65static audio_device_t * find_device_by_name(list_t *list, const char *name)
66{
67 FIND_BY_NAME(device);
68}
69static audio_source_t * find_source_by_name(list_t *list, const char *name)
70{
71 FIND_BY_NAME(source);
72}
73static audio_sink_t * find_sink_by_name(list_t *list, const char *name)
74{
75 FIND_BY_NAME(sink);
76}
77
78static int hound_disconnect_internal(hound_t *hound, const char* source_name, const char* sink_name);
79
80static void hound_remove_sink_internal(hound_t *hound, audio_sink_t *sink)
81{
82 assert(hound);
83 assert(sink);
84 log_verbose("Removing sink '%s'.", sink->name);
85 if (!list_empty(&sink->connections))
86 log_warning("Removing sink '%s' while still connected.", sink->name);
87 while (!list_empty(&sink->connections)) {
88 connection_t *conn =
89 connection_from_sink_list(list_first(&sink->connections));
90 list_remove(&conn->hound_link);
91 connection_destroy(conn);
92 }
93 list_remove(&sink->link);
94}
95
96static void hound_remove_source_internal(hound_t *hound, audio_source_t *source)
97{
98 assert(hound);
99 assert(source);
100 log_verbose("Removing source '%s'.", source->name);
101 if (!list_empty(&source->connections))
102 log_warning("Removing source '%s' while still connected.", source->name);
103 while (!list_empty(&source->connections)) {
104 connection_t *conn =
105 connection_from_source_list(list_first(&source->connections));
106 assert(conn);
107 list_remove(&conn->hound_link);
108 connection_destroy(conn);
109 }
110 list_remove(&source->link);
111}
112
113int hound_init(hound_t *hound)
114{
115 assert(hound);
116 fibril_mutex_initialize(&hound->list_guard);
117 list_initialize(&hound->devices);
118 list_initialize(&hound->contexts);
119 list_initialize(&hound->sources);
120 list_initialize(&hound->sinks);
121 list_initialize(&hound->connections);
122 return EOK;
123}
124
125int hound_add_ctx(hound_t *hound, hound_ctx_t *ctx)
126{
127 log_info("Trying to add context %p", ctx);
128 assert(hound);
129 if (!ctx)
130 return EINVAL;
131 fibril_mutex_lock(&hound->list_guard);
132 list_append(&ctx->link, &hound->contexts);
133 fibril_mutex_unlock(&hound->list_guard);
134 int ret = EOK;
135 if (ret == EOK && ctx->source)
136 ret = hound_add_source(hound, ctx->source);
137 if (ret == EOK && ctx->sink)
138 ret = hound_add_sink(hound, ctx->sink);
139 if (ret != EOK)
140 hound_ctx_destroy(ctx);
141 return ret;
142}
143
144int hound_remove_ctx(hound_t *hound, hound_ctx_t *ctx)
145{
146 assert(hound);
147 if (!ctx)
148 return EINVAL;
149 if (!list_empty(&ctx->streams))
150 return EBUSY;
151 fibril_mutex_lock(&hound->list_guard);
152 list_remove(&ctx->link);
153 if (ctx->source)
154 hound_remove_source_internal(hound, ctx->source);
155 if (ctx->sink)
156 hound_remove_sink_internal(hound, ctx->sink);
157 fibril_mutex_unlock(&hound->list_guard);
158 return EOK;
159}
160
161hound_ctx_t *hound_get_ctx_by_id(hound_t *hound, hound_context_id_t id)
162{
163 assert(hound);
164
165 fibril_mutex_lock(&hound->list_guard);
166 hound_ctx_t *res = NULL;
167 list_foreach(hound->contexts, it) {
168 hound_ctx_t *ctx = hound_ctx_from_link(it);
169 if (hound_ctx_get_id(ctx) == id) {
170 res = ctx;
171 break;
172 }
173 }
174 fibril_mutex_unlock(&hound->list_guard);
175 return res;
176}
177
178int hound_add_device(hound_t *hound, service_id_t id, const char *name)
179{
180 log_verbose("Adding device \"%s\", service: %zu", name, id);
181
182 assert(hound);
183 if (!name || !id) {
184 log_debug("Incorrect parameters.");
185 return EINVAL;
186 }
187
188 list_foreach(hound->devices, it) {
189 audio_device_t *dev = audio_device_list_instance(it);
190 if (dev->id == id) {
191 log_debug("Device with id %zu is already present", id);
192 return EEXISTS;
193 }
194 }
195
196 audio_device_t *dev = find_device_by_name(&hound->devices, name);
197 if (dev) {
198 log_debug("Device with name %s is already present", name);
199 return EEXISTS;
200 }
201
202 dev = malloc(sizeof(audio_device_t));
203 if (!dev) {
204 log_debug("Failed to malloc device structure.");
205 return ENOMEM;
206 }
207
208 const int ret = audio_device_init(dev, id, name);
209 if (ret != EOK) {
210 log_debug("Failed to initialize new audio device: %s",
211 str_error(ret));
212 free(dev);
213 return ret;
214 }
215
216 list_append(&dev->link, &hound->devices);
217 log_info("Added new device: '%s'", dev->name);
218
219 audio_source_t *source = audio_device_get_source(dev);
220 if (source) {
221 const int ret = hound_add_source(hound, source);
222 if (ret != EOK) {
223 log_debug("Failed to add device source: %s",
224 str_error(ret));
225 audio_device_fini(dev);
226 return ret;
227 }
228 log_verbose("Added source: '%s'.", source->name);
229 }
230
231 audio_sink_t *sink = audio_device_get_sink(dev);
232 if (sink) {
233 const int ret = hound_add_sink(hound, sink);
234 if (ret != EOK) {
235 log_debug("Failed to add device sink: %s",
236 str_error(ret));
237 audio_device_fini(dev);
238 return ret;
239 }
240 log_verbose("Added sink: '%s'.", sink->name);
241 }
242
243 if (!source && !sink)
244 log_warning("Neither sink nor source on device '%s'.", name);
245
246 return ret;
247}
248
249int hound_add_source(hound_t *hound, audio_source_t *source)
250{
251 assert(hound);
252 if (!source || !source->name || str_cmp(source->name, "default") == 0) {
253 log_debug("Invalid source specified.");
254 return EINVAL;
255 }
256 fibril_mutex_lock(&hound->list_guard);
257 if (find_source_by_name(&hound->sources, source->name)) {
258 log_debug("Source by that name already exists");
259 fibril_mutex_unlock(&hound->list_guard);
260 return EEXISTS;
261 }
262 list_append(&source->link, &hound->sources);
263 fibril_mutex_unlock(&hound->list_guard);
264 return EOK;
265}
266
267int hound_add_sink(hound_t *hound, audio_sink_t *sink)
268{
269 assert(hound);
270 if (!sink || !sink->name || str_cmp(sink->name, "default") == 0) {
271 log_debug("Invalid source specified.");
272 return EINVAL;
273 }
274 fibril_mutex_lock(&hound->list_guard);
275 if (find_sink_by_name(&hound->sinks, sink->name)) {
276 log_debug("Sink by that name already exists");
277 fibril_mutex_unlock(&hound->list_guard);
278 return EEXISTS;
279 }
280 list_append(&sink->link, &hound->sinks);
281 fibril_mutex_unlock(&hound->list_guard);
282 return EOK;
283}
284
285int hound_remove_source(hound_t *hound, audio_source_t *source)
286{
287 assert(hound);
288 if (!source)
289 return EINVAL;
290 fibril_mutex_lock(&hound->list_guard);
291 hound_remove_source_internal(hound, source);
292 fibril_mutex_unlock(&hound->list_guard);
293 return EOK;
294}
295
296
297int hound_remove_sink(hound_t *hound, audio_sink_t *sink)
298{
299 assert(hound);
300 if (!sink)
301 return EINVAL;
302 fibril_mutex_lock(&hound->list_guard);
303 hound_remove_sink_internal(hound, sink);
304 fibril_mutex_unlock(&hound->list_guard);
305 return EOK;
306}
307
308int hound_list_sources(hound_t *hound, const char ***list, size_t *size)
309{
310 assert(hound);
311 if (!list || !size)
312 return EINVAL;
313
314 fibril_mutex_lock(&hound->list_guard);
315 const size_t count = list_count(&hound->sources);
316 if (count == 0) {
317 *list = NULL;
318 *size = 0;
319 fibril_mutex_unlock(&hound->list_guard);
320 return EOK;
321 }
322 const char **names = calloc(count, sizeof(char *));
323 int ret = names ? EOK : ENOMEM;
324 for (size_t i = 0; i < count && ret == EOK; ++i) {
325 link_t *slink = list_nth(&hound->sources, i);
326 audio_source_t *source = audio_source_list_instance(slink);
327 names[i] = str_dup(source->name);
328 if (names[i])
329 ret = ENOMEM;
330 }
331 if (ret == EOK) {
332 *size = count;
333 *list = names;
334 } else {
335 for (size_t i = 0; i < count; ++i)
336 free(names[i]);
337 free(names);
338 }
339 fibril_mutex_unlock(&hound->list_guard);
340 return ret;
341}
342
343int hound_list_sinks(hound_t *hound, const char ***list, size_t *size)
344{
345 assert(hound);
346 if (!list || !size)
347 return EINVAL;
348
349 fibril_mutex_lock(&hound->list_guard);
350 const size_t count = list_count(&hound->sinks);
351 if (count == 0) {
352 *list = NULL;
353 *size = 0;
354 fibril_mutex_unlock(&hound->list_guard);
355 return EOK;
356 }
357 const char **names = calloc(count, sizeof(char *));
358 int ret = names ? EOK : ENOMEM;
359 for (size_t i = 0; i < count && ret == EOK; ++i) {
360 link_t *slink = list_nth(&hound->sinks, i);
361 audio_sink_t *sink = audio_sink_list_instance(slink);
362 names[i] = str_dup(sink->name);
363 if (!names[i])
364 ret = ENOMEM;
365 }
366 if (ret == EOK) {
367 *size = count;
368 *list = names;
369 } else {
370 for (size_t i = 0; i < count; ++i)
371 free(names[i]);
372 free(names);
373 }
374 fibril_mutex_unlock(&hound->list_guard);
375 return ret;
376}
377
378int hound_list_connections(hound_t *hound, const char ***sources,
379 const char ***sinks, size_t *size)
380{
381 fibril_mutex_lock(&hound->list_guard);
382 fibril_mutex_unlock(&hound->list_guard);
383 return ENOTSUP;
384}
385
386int hound_connect(hound_t *hound, const char* source_name, const char* sink_name)
387{
388 assert(hound);
389 log_verbose("Connecting '%s' to '%s'.", source_name, sink_name);
390 fibril_mutex_lock(&hound->list_guard);
391
392 audio_source_t *source =
393 audio_source_list_instance(list_first(&hound->sources));
394 if (str_cmp(source_name, "default") != 0)
395 source = find_source_by_name(&hound->sources, source_name);
396
397 audio_sink_t *sink =
398 audio_sink_list_instance(list_first(&hound->sinks));
399 if (str_cmp(sink_name, "default") != 0)
400 sink = find_sink_by_name(&hound->sinks, sink_name);
401
402 if (!source || !sink) {
403 fibril_mutex_unlock(&hound->list_guard);
404 log_debug("Source (%p), or sink (%p) not found", source, sink);
405 return ENOENT;
406 }
407 connection_t *conn = connection_create(source, sink);
408 if (!conn) {
409 fibril_mutex_unlock(&hound->list_guard);
410 log_debug("Failed to create connection");
411 return ENOMEM;
412 }
413 list_append(&conn->hound_link, &hound->connections);
414 fibril_mutex_unlock(&hound->list_guard);
415 return EOK;
416}
417
418int hound_disconnect(hound_t *hound, const char* source_name, const char* sink_name)
419{
420 assert(hound);
421 fibril_mutex_lock(&hound->list_guard);
422 const int ret = hound_disconnect_internal(hound, source_name, sink_name);
423 fibril_mutex_unlock(&hound->list_guard);
424 return ret;
425}
426
427static int hound_disconnect_internal(hound_t *hound, const char* source_name,
428 const char* sink_name)
429{
430 assert(hound);
431 assert(fibril_mutex_is_locked(&hound->list_guard));
432 log_debug("Disconnecting '%s' to '%s'.", source_name, sink_name);
433
434 list_foreach_safe(hound->connections, it, next) {
435 connection_t *conn = connection_from_hound_list(it);
436 if (str_cmp(connection_source_name(conn), source_name) == 0 ||
437 str_cmp(connection_sink_name(conn), sink_name) == 0) {
438 log_debug("Removing %s -> %s", connection_source_name(conn),
439 connection_sink_name(conn));
440 list_remove(it);
441 connection_destroy(conn);
442 }
443 }
444
445 return EOK;
446}
447/**
448 * @}
449 */
Note: See TracBrowser for help on using the repository browser.