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

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

hound: Only few more TODOs left

  • Property mode set to 100644
File size: 6.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 <async.h>
38#include <bool.h>
39#include <errno.h>
40#include <loc.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <str_error.h>
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#include "protocol.h"
54
55static hound_t hound;
56
57static inline audio_format_t read_format(const ipc_call_t *call)
58{
59 audio_format_t format = {
60 .channels = IPC_GET_ARG1(*call),
61 .sampling_rate = IPC_GET_ARG2(*call),
62 .sample_format = IPC_GET_ARG3(*call),
63 };
64 return format;
65}
66static inline const char *get_name()
67{
68 size_t size = 0;
69 ipc_callid_t callid;
70 async_data_read_receive(&callid, &size);
71 char *buffer = malloc(size);
72 if (buffer) {
73 async_data_read_finalize(callid, buffer, size);
74 buffer[size - 1] = 0;
75 log_verbose("Got name from client: %s", buffer);
76 }
77 return buffer;
78}
79static inline async_sess_t *get_session()
80{
81 ipc_call_t call;
82 ipc_callid_t callid = async_get_call(&call);
83 async_sess_t *s = async_callback_receive_start(EXCHANGE_ATOMIC, &call);
84 async_answer_0(callid, s ? EOK : ENOMEM);
85 log_verbose("Received callback session");
86 return s;
87}
88
89
90static void scan_for_devices(void)
91{
92 static bool cat_resolved = false;
93 static category_id_t cat;
94
95 if (!cat_resolved) {
96 log_verbose("Resolving category \"%s\".", CATEGORY);
97 const int ret = loc_category_get_id(CATEGORY, &cat,
98 IPC_FLAG_BLOCKING);
99 if (ret != EOK) {
100 log_error("Failed to get category: %s", str_error(ret));
101 return;
102 }
103 cat_resolved = true;
104 }
105
106 log_verbose("Getting available services in category.");
107
108 service_id_t *svcs = NULL;
109 size_t count = 0;
110 const int ret = loc_category_get_svcs(cat, &svcs, &count);
111 if (ret != EOK) {
112 log_error("Failed to get audio devices: %s", str_error(ret));
113 return;
114 }
115
116 for (unsigned i = 0; i < count; ++i) {
117 char *name = NULL;
118 int ret = loc_service_get_name(svcs[i], &name);
119 if (ret != EOK) {
120 log_error("Failed to get dev name: %s", str_error(ret));
121 continue;
122 }
123 ret = hound_add_device(&hound, svcs[i], name);
124 if (ret != EOK && ret != EEXISTS) {
125 log_error("Failed to add audio device \"%s\": %s",
126 name, str_error(ret));
127 }
128 free(name);
129 }
130
131 free(svcs);
132}
133
134static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
135{
136 async_answer_0(iid, EOK);
137
138 LIST_INITIALIZE(local_playback);
139 LIST_INITIALIZE(local_recording);
140
141 while (1) {
142 ipc_call_t call;
143 ipc_callid_t callid = async_get_call(&call);
144 log_debug("Got method %u", IPC_GET_IMETHOD(call));
145 switch (IPC_GET_IMETHOD(call)) {
146 case HOUND_REGISTER_PLAYBACK: {
147 const audio_format_t format = read_format(&call);
148 const char *name = get_name();
149 async_sess_t *sess = get_session();
150 audio_client_t * client =
151 audio_client_get_playback(name, &format, sess);
152 if (!client) {
153 log_error("Failed to create playback client");
154 async_answer_0(callid, ENOMEM);
155 }
156 int ret = hound_add_source(&hound, &client->source);
157 if (ret != EOK){
158 audio_client_destroy(client);
159 log_error("Failed to add audio source: %s",
160 str_error(ret));
161 async_answer_0(callid, ret);
162 break;
163 }
164 async_answer_0(callid, EOK);
165 list_append(&client->link, &local_playback);
166 break;
167 }
168 case HOUND_REGISTER_RECORDING: {
169 const audio_format_t format = read_format(&call);
170 const char *name = get_name();
171 async_sess_t *sess = get_session();
172 audio_client_t * client =
173 audio_client_get_recording(name, &format, sess);
174 if (!client) {
175 log_error("Failed to create recording client");
176 async_answer_0(callid, ENOMEM);
177 break;
178 }
179 int ret = hound_add_sink(&hound, &client->sink);
180 if (ret != EOK){
181 audio_client_destroy(client);
182 log_error("Failed to add audio sink: %s",
183 str_error(ret));
184 async_answer_0(callid, ret);
185 break;
186 }
187 async_answer_0(callid, EOK);
188 list_append(&client->link, &local_recording);
189 break;
190 }
191 case HOUND_UNREGISTER_PLAYBACK: {
192 //const char *name = get_name();
193 //TODO unregister in hound
194 //TODO remove from local
195 break;
196 }
197 case HOUND_UNREGISTER_RECORDING: {
198 //TODO Get Name
199 //TODO unregister in hound
200 //TODO remove from local
201 break;
202 }
203 case HOUND_CONNECT: {
204 //TODO Get Name
205 //TODO Get Name
206 //TODO connect in hound
207 break;
208 }
209 case HOUND_DISCONNECT: {
210 //TODO Get Name
211 //TODO Get Name
212 //TODO disconnect in hound
213 break;
214 }
215 default:
216 async_answer_0(callid, ENOTSUP);
217 break;
218 case 0:
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 ret = loc_server_register(NAME);
237 if (ret != EOK) {
238 log_fatal("Failed to register sound server: %s",
239 str_error(ret));
240 return -ret;
241 }
242
243 char fqdn[LOC_NAME_MAXLEN + 1];
244 snprintf(fqdn, LOC_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
245 service_id_t id = 0;
246 ret = loc_service_register(fqdn, &id);
247 if (ret != EOK) {
248 log_fatal("Failed to register sound service: %s",
249 str_error(ret));
250 return -ret;
251 }
252
253 ret = loc_register_cat_change_cb(scan_for_devices);
254 if (ret != EOK) {
255 log_fatal("Failed to register for category changes: %s",
256 str_error(ret));
257 loc_service_unregister(id);
258 return -ret;
259 }
260 log_info("Running with service id %u", id);
261
262 scan_for_devices();
263
264 async_manager();
265 return 0;
266}
267
268/**
269 * @}
270 */
Note: See TracBrowser for help on using the repository browser.