source: mainline/uspace/srv/audio/hound/hound.c@ 1c33539

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

hound: Implement disconnect

  • Property mode set to 100644
File size: 7.0 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_client.h"
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
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
78int hound_init(hound_t *hound)
79{
80 assert(hound);
81 fibril_mutex_initialize(&hound->list_guard);
82 list_initialize(&hound->devices);
83 list_initialize(&hound->sources);
84 list_initialize(&hound->sinks);
85 return EOK;
86}
87
88int hound_add_device(hound_t *hound, service_id_t id, const char *name)
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) {
99 audio_device_t *dev = audio_device_list_instance(it);
100 if (dev->id == id) {
101 log_debug("Device with id %zu is already present", id);
102 return EEXISTS;
103 }
104 }
105
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));
113 if (!dev) {
114 log_debug("Failed to malloc device structure.");
115 return ENOMEM;
116 }
117
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);
127 log_info("Added new device: '%s'", dev->name);
128
129 audio_source_t *source = audio_device_get_source(dev);
130 if (source) {
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 }
138 log_verbose("Added source: '%s'.", source->name);
139 }
140
141 audio_sink_t *sink = audio_device_get_sink(dev);
142 if (sink) {
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 }
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
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
203int hound_connect(hound_t *hound, const char* source_name, const char* sink_name)
204{
205 assert(hound);
206 log_verbose("Connecting '%s' to '%s'.", source_name, sink_name);
207 fibril_mutex_lock(&hound->list_guard);
208 audio_source_t *source =
209 find_source_by_name(&hound->sources, source_name);
210 audio_sink_t *sink = find_sink_by_name(&hound->sinks, sink_name);
211 if (!source || !sink) {
212 fibril_mutex_unlock(&hound->list_guard);
213 log_debug("Source (%p), or sink (%p) not found", source, sink);
214 return ENOENT;
215 }
216 list_remove(&source->link);
217 const int ret = audio_sink_add_source(sink, source);
218 if (ret != EOK) {
219 log_debug("Failed add source to sink list: %s", str_error(ret));
220 list_append(&source->link, &hound->sources);
221 }
222 fibril_mutex_unlock(&hound->list_guard);
223 return EOK;
224}
225
226int hound_disconnect(hound_t *hound, const char* source_name, const char* sink_name)
227{
228 assert(hound);
229 log_verbose("Disconnecting '%s' to '%s'.", source_name, sink_name);
230 fibril_mutex_lock(&hound->list_guard);
231 audio_sink_t *sink = find_sink_by_name(&hound->sinks, sink_name);
232 audio_source_t *source = sink ? find_source_by_name(&sink->sources, source_name) : NULL;
233 if (!source || !sink) {
234 fibril_mutex_unlock(&hound->list_guard);
235 log_debug("Source (%p), or sink (%p) not found", source, sink);
236 return ENOENT;
237 }
238 const int ret = audio_sink_remove_source(sink, source);
239 if (ret != EOK) {
240 log_debug("Failed remove source to sink list: %s", str_error(ret));
241 } else {
242 list_append(&source->link, &hound->sources);
243 }
244 fibril_mutex_unlock(&hound->list_guard);
245 return EOK;
246 return ENOTSUP;
247}
248/**
249 * @}
250 */
Note: See TracBrowser for help on using the repository browser.