source: mainline/uspace/srv/audio/hound/main.c@ 92b638c

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

Create libpcm.

Move pcm related functions and definitions there.
Make other stuff use this library.
Rename most of it on the way.

  • 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 <async.h>
38#include <bool.h>
39#include <errno.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <str_error.h>
43#include <hound/server.h>
44
45
46#include "hound.h"
47
48#define NAMESPACE "audio"
49#define NAME "hound"
50#define CATEGORY "audio-pcm"
51
52#include "audio_client.h"
53#include "log.h"
54
55static hound_t hound;
56
57static int device_callback(service_id_t id, const char *name)
58{
59 return hound_add_device(&hound, id, name);
60}
61
62static void scan_for_devices(void)
63{
64 hound_server_devices_iterate(device_callback);
65}
66
67static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
68{
69 async_answer_0(iid, EOK);
70
71 LIST_INITIALIZE(local_playback);
72 LIST_INITIALIZE(local_recording);
73 pcm_format_t format = {0};
74 const char *name = NULL;
75 async_sess_t *sess = NULL;
76
77 while (1) {
78 ipc_call_t call;
79 ipc_callid_t callid = async_get_call(&call);
80 switch (IPC_GET_IMETHOD(call)) {
81 case HOUND_REGISTER_PLAYBACK: {
82 hound_server_get_register_params(&name, &sess,
83 &format.channels, &format.sampling_rate,
84 &format.sample_format);
85 audio_client_t *client =
86 audio_client_get_playback(name, &format, sess);
87 free(name);
88 if (!client) {
89 log_error("Failed to create playback client");
90 async_answer_0(callid, ENOMEM);
91 break;
92 }
93 int ret = hound_add_source(&hound, &client->source);
94 if (ret != EOK){
95 audio_client_destroy(client);
96 log_error("Failed to add audio source: %s",
97 str_error(ret));
98 async_answer_0(callid, ret);
99 break;
100 }
101 log_info("Added audio client %p '%s'",
102 client, client->name);
103 async_answer_0(callid, EOK);
104 list_append(&client->link, &local_playback);
105 break;
106 }
107 case HOUND_REGISTER_RECORDING: {
108 hound_server_get_register_params(&name, &sess,
109 &format.channels, &format.sampling_rate,
110 &format.sample_format);
111 audio_client_t *client =
112 audio_client_get_recording(name, &format, sess);
113 free(name);
114 if (!client) {
115 log_error("Failed to create recording client");
116 async_answer_0(callid, ENOMEM);
117 break;
118 }
119 int ret = hound_add_sink(&hound, &client->sink);
120 if (ret != EOK){
121 audio_client_destroy(client);
122 log_error("Failed to add audio sink: %s",
123 str_error(ret));
124 async_answer_0(callid, ret);
125 break;
126 }
127 async_answer_0(callid, EOK);
128 list_append(&client->link, &local_recording);
129 break;
130 }
131 case HOUND_UNREGISTER_PLAYBACK: {
132 const char *name = NULL;
133 hound_server_get_unregister_params(&name);
134 int ret = ENOENT;
135 list_foreach(local_playback, it) {
136 audio_client_t *client =
137 audio_client_list_instance(it);
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 hound_remove_source(&hound, &client->source);
217 audio_client_destroy(client);
218 }
219 return;
220 }
221 }
222}
223
224int main(int argc, char **argv)
225{
226 printf("%s: HelenOS sound service\n", NAME);
227
228 int ret = hound_init(&hound);
229 if (ret != EOK) {
230 log_fatal("Failed to initialize hound structure: %s",
231 str_error(ret));
232 return -ret;
233 }
234
235 async_set_client_connection(client_connection);
236
237 service_id_t id = 0;
238 ret = hound_server_register(NAME, &id);
239 if (ret != EOK) {
240 log_fatal("Failed to register server: %s", str_error(ret));
241 return -ret;
242 }
243
244 ret = hound_server_set_device_change_callback(scan_for_devices);
245 if (ret != EOK) {
246 log_fatal("Failed to register for device changes: %s",
247 str_error(ret));
248 hound_server_unregister(id);
249 return -ret;
250 }
251 log_info("Running with service id %u", id);
252
253 scan_for_devices();
254
255 async_manager();
256 return 0;
257}
258
259/**
260 * @}
261 */
Note: See TracBrowser for help on using the repository browser.