source: mainline/uspace/srv/audio/hound/hound.c@ ab07cf0

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

hound: Implement client removal

  • Property mode set to 100644
File size: 7.8 KB
RevLine 
[737b4c0]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"
[1df3018a]41#include "audio_client.h"
[737b4c0]42#include "audio_device.h"
43#include "audio_sink.h"
44#include "audio_source.h"
45#include "log.h"
46#include "errno.h"
47#include "str_error.h"
48
[1df3018a]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) { \
[f3fced0]57 log_debug("%s with name '%s' is in the list", \
[1df3018a]58 #type, name); \
[63d6ff9]59 return dev; \
[1df3018a]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
[737b4c0]78int hound_init(hound_t *hound)
79{
80 assert(hound);
[1df3018a]81 fibril_mutex_initialize(&hound->list_guard);
[737b4c0]82 list_initialize(&hound->devices);
[1df3018a]83 list_initialize(&hound->sources);
[737b4c0]84 list_initialize(&hound->sinks);
85 return EOK;
86}
87
[1df3018a]88int hound_add_device(hound_t *hound, service_id_t id, const char *name)
[737b4c0]89{
90 log_verbose("Adding device \"%s\", service: %zu", name, id);
91
92 assert(hound);
93 if (!name || !id) {
94 log_debug("Incorrect parameters.");
95 return EINVAL;
96 }
97
98 list_foreach(hound->devices, it) {
[1df3018a]99 audio_device_t *dev = audio_device_list_instance(it);
[737b4c0]100 if (dev->id == id) {
101 log_debug("Device with id %zu is already present", id);
102 return EEXISTS;
103 }
104 }
105
[1df3018a]106 audio_device_t *dev = find_device_by_name(&hound->devices, name);
107 if (dev) {
108 log_debug("Device with name %s is already present", name);
109 return EEXISTS;
110 }
111
112 dev = malloc(sizeof(audio_device_t));
[737b4c0]113 if (!dev) {
114 log_debug("Failed to malloc device structure.");
115 return ENOMEM;
116 }
[d93a5a6f]117
[737b4c0]118 const int ret = audio_device_init(dev, id, name);
119 if (ret != EOK) {
120 log_debug("Failed to initialize new audio device: %s",
121 str_error(ret));
122 free(dev);
123 return ret;
124 }
125
126 list_append(&dev->link, &hound->devices);
[1df3018a]127 log_info("Added new device: '%s'", dev->name);
[737b4c0]128
129 audio_source_t *source = audio_device_get_source(dev);
130 if (source) {
[1df3018a]131 const int ret = hound_add_source(hound, source);
132 if (ret != EOK) {
133 log_debug("Failed to add device source: %s",
134 str_error(ret));
135 audio_device_fini(dev);
136 return ret;
137 }
[737b4c0]138 log_verbose("Added source: '%s'.", source->name);
139 }
140
141 audio_sink_t *sink = audio_device_get_sink(dev);
142 if (sink) {
[1df3018a]143 const int ret = hound_add_sink(hound, sink);
144 if (ret != EOK) {
145 log_debug("Failed to add device sink: %s",
146 str_error(ret));
147 audio_device_fini(dev);
148 return ret;
149 }
[737b4c0]150 log_verbose("Added sink: '%s'.", sink->name);
151 }
152
153 if (!source && !sink)
154 log_warning("Neither sink nor source on device '%s'.", name);
155
156 return ret;
157}
158
[1df3018a]159int hound_add_source(hound_t *hound, audio_source_t *source)
160{
161 assert(hound);
162 if (!source || !source->name) {
163 log_debug("Invalid source specified.");
164 return EINVAL;
165 }
166 fibril_mutex_lock(&hound->list_guard);
167 if (find_source_by_name(&hound->sources, source->name)) {
168 log_debug("Source by that name already exists");
169 fibril_mutex_unlock(&hound->list_guard);
170 return EEXISTS;
171 }
172 list_foreach(hound->sinks, it) {
173 audio_sink_t *sink = audio_sink_list_instance(it);
174 if (find_source_by_name(&sink->sources, source->name)) {
175 log_debug("Source by that name already exists");
176 fibril_mutex_unlock(&hound->list_guard);
177 return EEXISTS;
178 }
179 }
180 list_append(&source->link, &hound->sources);
181 fibril_mutex_unlock(&hound->list_guard);
182 return EOK;
183}
184
185int hound_add_sink(hound_t *hound, audio_sink_t *sink)
186{
187 assert(hound);
188 if (!sink || !sink->name) {
189 log_debug("Invalid source specified.");
190 return EINVAL;
191 }
192 fibril_mutex_lock(&hound->list_guard);
193 if (find_sink_by_name(&hound->sinks, sink->name)) {
194 log_debug("Sink by that name already exists");
195 fibril_mutex_unlock(&hound->list_guard);
196 return EEXISTS;
197 }
198 list_append(&sink->link, &hound->sinks);
199 fibril_mutex_unlock(&hound->list_guard);
200 return EOK;
201}
202
[6424800]203int hound_remove_source(hound_t *hound, audio_source_t *source)
204{
205 assert(hound);
206 if (!source)
207 return EINVAL;
208 log_verbose("Removing source '%s'.", source->name);
209 fibril_mutex_lock(&hound->list_guard);
210 if (!list_member(&source->link, &hound->sources)) {
211 fibril_mutex_unlock(&hound->list_guard);
212 return EBUSY;
213 }
214 list_remove(&source->link);
215 fibril_mutex_unlock(&hound->list_guard);
216 return EOK;
217}
218
219int hound_remove_sink(hound_t *hound, audio_sink_t *sink)
220{
221 assert(hound);
222 if (!sink)
223 return EINVAL;
224 log_verbose("Removing sink '%s'.", sink->name);
225 fibril_mutex_lock(&hound->list_guard);
226 if (!list_empty(&sink->sources)) {
227 fibril_mutex_unlock(&hound->list_guard);
228 return EBUSY;
229 }
230 list_remove(&sink->link);
231 fibril_mutex_unlock(&hound->list_guard);
232 return EOK;
233}
234
[f3fced0]235int hound_connect(hound_t *hound, const char* source_name, const char* sink_name)
236{
237 assert(hound);
238 log_verbose("Connecting '%s' to '%s'.", source_name, sink_name);
239 fibril_mutex_lock(&hound->list_guard);
240 audio_source_t *source =
241 find_source_by_name(&hound->sources, source_name);
242 audio_sink_t *sink = find_sink_by_name(&hound->sinks, sink_name);
243 if (!source || !sink) {
244 fibril_mutex_unlock(&hound->list_guard);
[1c33539]245 log_debug("Source (%p), or sink (%p) not found", source, sink);
[f3fced0]246 return ENOENT;
247 }
248 list_remove(&source->link);
249 const int ret = audio_sink_add_source(sink, source);
250 if (ret != EOK) {
251 log_debug("Failed add source to sink list: %s", str_error(ret));
252 list_append(&source->link, &hound->sources);
253 }
254 fibril_mutex_unlock(&hound->list_guard);
255 return EOK;
256}
257
258int hound_disconnect(hound_t *hound, const char* source_name, const char* sink_name)
259{
[1c33539]260 assert(hound);
261 log_verbose("Disconnecting '%s' to '%s'.", source_name, sink_name);
262 fibril_mutex_lock(&hound->list_guard);
263 audio_sink_t *sink = find_sink_by_name(&hound->sinks, sink_name);
264 audio_source_t *source = sink ? find_source_by_name(&sink->sources, source_name) : NULL;
265 if (!source || !sink) {
266 fibril_mutex_unlock(&hound->list_guard);
267 log_debug("Source (%p), or sink (%p) not found", source, sink);
268 return ENOENT;
269 }
270 const int ret = audio_sink_remove_source(sink, source);
271 if (ret != EOK) {
272 log_debug("Failed remove source to sink list: %s", str_error(ret));
273 } else {
274 list_append(&source->link, &hound->sources);
275 }
276 fibril_mutex_unlock(&hound->list_guard);
277 return EOK;
[f3fced0]278 return ENOTSUP;
279}
[737b4c0]280/**
281 * @}
282 */
Note: See TracBrowser for help on using the repository browser.