source: mainline/uspace/srv/audio/hound/main.c@ 5029c788

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

hound: add connection class

This will enable N to M routing in the future

  • Property mode set to 100644
File size: 7.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/**
30 * @addtogroup audio
31 * @brief HelenOS sound server.
32 * @{
33 */
34/** @file
35 */
36
37#include <async.h>
38#include <errno.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <str_error.h>
42#include <hound/server.h>
43
44
45#include "hound.h"
46
47#define NAMESPACE "audio"
48#define NAME "hound"
49#define CATEGORY "audio-pcm"
50
51#include "audio_client.h"
52#include "log.h"
53
54static hound_t hound;
55
56static int device_callback(service_id_t id, const char *name)
57{
58 return hound_add_device(&hound, id, name);
59}
60
61static void scan_for_devices(void)
62{
63 hound_server_devices_iterate(device_callback);
64}
65
66static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
67{
68 async_answer_0(iid, EOK);
69
70 LIST_INITIALIZE(local_playback);
71 LIST_INITIALIZE(local_recording);
72 pcm_format_t format = {0};
73 const char *name = NULL;
74 async_sess_t *sess = NULL;
75
76 while (1) {
77 ipc_call_t call;
78 ipc_callid_t callid = async_get_call(&call);
79 switch (IPC_GET_IMETHOD(call)) {
80 case HOUND_REGISTER_PLAYBACK: {
81 hound_server_get_register_params(&name, &sess,
82 &format.channels, &format.sampling_rate,
83 &format.sample_format);
84 audio_client_t *client =
85 audio_client_get_playback(name, &format, sess);
86 free(name);
87 if (!client) {
88 log_error("Failed to create playback client");
89 async_answer_0(callid, ENOMEM);
90 break;
91 }
92 int ret = hound_add_source(&hound, &client->source);
93 if (ret != EOK){
94 audio_client_destroy(client);
95 log_error("Failed to add audio source: %s",
96 str_error(ret));
97 async_answer_0(callid, ret);
98 break;
99 }
100 log_info("Added audio client %p '%s'",
101 client, client->name);
102 async_answer_0(callid, EOK);
103 list_append(&client->link, &local_playback);
104 break;
105 }
106 case HOUND_REGISTER_RECORDING: {
107 hound_server_get_register_params(&name, &sess,
108 &format.channels, &format.sampling_rate,
109 &format.sample_format);
110 audio_client_t *client =
111 audio_client_get_recording(name, &format, sess);
112 free(name);
113 if (!client) {
114 log_error("Failed to create recording client");
115 async_answer_0(callid, ENOMEM);
116 break;
117 }
118 int ret = hound_add_sink(&hound, &client->sink);
119 if (ret != EOK){
120 audio_client_destroy(client);
121 log_error("Failed to add audio sink: %s",
122 str_error(ret));
123 async_answer_0(callid, ret);
124 break;
125 }
126 async_answer_0(callid, EOK);
127 list_append(&client->link, &local_recording);
128 break;
129 }
130 case HOUND_UNREGISTER_PLAYBACK: {
131 const char *name = NULL;
132 hound_server_get_unregister_params(&name);
133 int ret = ENOENT;
134 list_foreach_safe(local_playback, it, next) {
135 audio_client_t *client =
136 audio_client_list_instance(it);
137 log_fatal("UNREGISTER_PLAYBACK %p", client);
138 if (str_cmp(client->name, name) == 0) {
139 ret = hound_remove_source(&hound,
140 &client->source);
141 if (ret == EOK) {
142 list_remove(&client->link);
143 audio_client_destroy(client);
144 }
145 break;
146 }
147 }
148 free(name);
149 async_answer_0(callid, ret);
150 break;
151 }
152 case HOUND_UNREGISTER_RECORDING: {
153 const char *name = NULL;
154 hound_server_get_unregister_params(&name);
155 int ret = ENOENT;
156 list_foreach(local_recording, it) {
157 audio_client_t *client =
158 audio_client_list_instance(it);
159 if (str_cmp(client->name, name) == 0) {
160 ret = hound_remove_sink(&hound,
161 &client->sink);
162 if (ret == EOK) {
163 list_remove(&client->link);
164 audio_client_destroy(client);
165 }
166 break;
167 }
168 }
169 free(name);
170 async_answer_0(callid, ret);
171 break;
172 }
173 case HOUND_CONNECT: {
174 const char *source = NULL, *sink = NULL;
175 hound_server_get_connection_params(&source, &sink);
176 const int ret = hound_connect(&hound, source, sink);
177 if (ret != EOK)
178 log_error("Failed to connect '%s' to '%s': %s",
179 source, sink, str_error(ret));
180 free(source);
181 free(sink);
182 async_answer_0(callid, ret);
183 break;
184 }
185 case HOUND_DISCONNECT: {
186 const char *source = NULL, *sink = NULL;
187 hound_server_get_connection_params(&source, &sink);
188 const int ret = hound_disconnect(&hound, source, sink);
189 if (ret != EOK)
190 log_error("Failed to disconnect '%s' from '%s'"
191 ": %s", source, sink, str_error(ret));
192 free(source);
193 free(sink);
194 async_answer_0(callid, ret);
195 break;
196 }
197 default:
198 log_debug("Got unknown method %u",
199 IPC_GET_IMETHOD(call));
200 async_answer_0(callid, ENOTSUP);
201 break;
202 case 0:
203 while(!list_empty(&local_recording)) {
204 audio_client_t *client =
205 audio_client_list_instance(
206 list_first(&local_recording));
207 list_remove(&client->link);
208 hound_remove_sink(&hound, &client->sink);
209 audio_client_destroy(client);
210 }
211 while(!list_empty(&local_playback)) {
212 audio_client_t *client =
213 audio_client_list_instance(
214 list_first(&local_playback));
215 list_remove(&client->link);
216 log_fatal("CASE 0 %p", client);
217 hound_remove_source(&hound, &client->source);
218 audio_client_destroy(client);
219 }
220 return;
221 }
222 }
223}
224
225int main(int argc, char **argv)
226{
227 printf("%s: HelenOS sound service\n", NAME);
228
229 int ret = hound_init(&hound);
230 if (ret != EOK) {
231 log_fatal("Failed to initialize hound structure: %s",
232 str_error(ret));
233 return -ret;
234 }
235
236 async_set_client_connection(client_connection);
237
238 service_id_t id = 0;
239 ret = hound_server_register(NAME, &id);
240 if (ret != EOK) {
241 log_fatal("Failed to register server: %s", str_error(ret));
242 return -ret;
243 }
244
245 ret = hound_server_set_device_change_callback(scan_for_devices);
246 if (ret != EOK) {
247 log_fatal("Failed to register for device changes: %s",
248 str_error(ret));
249 hound_server_unregister(id);
250 return -ret;
251 }
252 log_info("Running with service id %u", id);
253
254 scan_for_devices();
255
256 async_manager();
257 return 0;
258}
259
260/**
261 * @}
262 */
Note: See TracBrowser for help on using the repository browser.