1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2004-2009 Lennart Poettering 5 6 PulseAudio is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as published 8 by the Free Software Foundation; either version 2.1 of the License, 9 or (at your option) any later version. 10 11 PulseAudio is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 18***/ 19 20#ifdef HAVE_CONFIG_H 21#include <config.h> 22#endif 23 24#include <pulse/xmalloc.h> 25 26#include <pulsecore/namereg.h> 27#include <pulsecore/sink.h> 28#include <pulsecore/module.h> 29#include <pulsecore/core-util.h> 30#include <pulsecore/modargs.h> 31#include <pulsecore/log.h> 32#include <pulsecore/rtpoll.h> 33 34PA_MODULE_AUTHOR("Lennart Poettering"); 35PA_MODULE_DESCRIPTION("Virtual channel remapping sink"); 36PA_MODULE_VERSION(PACKAGE_VERSION); 37PA_MODULE_LOAD_ONCE(false); 38PA_MODULE_USAGE( 39 "sink_name=<name for the sink> " 40 "sink_properties=<properties for the sink> " 41 "master=<name of sink to remap> " 42 "master_channel_map=<channel map> " 43 "format=<sample format> " 44 "rate=<sample rate> " 45 "channels=<number of channels> " 46 "channel_map=<channel map> " 47 "resample_method=<resampler> " 48 "remix=<remix channels?>"); 49 50struct userdata { 51 pa_module *module; 52 53 pa_sink *sink; 54 pa_sink_input *sink_input; 55 56 bool auto_desc; 57}; 58 59static const char* const valid_modargs[] = { 60 "sink_name", 61 "sink_properties", 62 "master", 63 "master_channel_map", 64 "format", 65 "rate", 66 "channels", 67 "channel_map", 68 "resample_method", 69 "remix", 70 NULL 71}; 72 73/* Called from I/O thread context */ 74static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { 75 struct userdata *u = PA_SINK(o)->userdata; 76 77 switch (code) { 78 79 case PA_SINK_MESSAGE_GET_LATENCY: 80 81 /* The sink is _put() before the sink input is, so let's 82 * make sure we don't access it yet */ 83 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) || 84 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) { 85 *((int64_t*) data) = 0; 86 return 0; 87 } 88 89 *((int64_t*) data) = 90 /* Get the latency of the master sink */ 91 pa_sink_get_latency_within_thread(u->sink_input->sink, true) + 92 93 /* Add the latency internal to our sink input on top */ 94 pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec); 95 96 /* Add resampler latency */ 97 *((int64_t*) data) += pa_resampler_get_delay_usec(u->sink_input->thread_info.resampler); 98 99 return 0; 100 } 101 102 return pa_sink_process_msg(o, code, data, offset, chunk); 103} 104 105/* Called from main context */ 106static int sink_set_state_in_main_thread(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) { 107 struct userdata *u; 108 109 pa_sink_assert_ref(s); 110 pa_assert_se(u = s->userdata); 111 112 if (!PA_SINK_IS_LINKED(state) || 113 !PA_SINK_INPUT_IS_LINKED(u->sink_input->state)) 114 return 0; 115 116 pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED); 117 return 0; 118} 119 120/* Called from the IO thread. */ 121static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) { 122 struct userdata *u; 123 124 pa_assert(s); 125 pa_assert_se(u = s->userdata); 126 127 /* When set to running or idle for the first time, request a rewind 128 * of the master sink to make sure we are heard immediately */ 129 if (PA_SINK_IS_OPENED(new_state) && s->thread_info.state == PA_SINK_INIT) { 130 pa_log_debug("Requesting rewind due to state change."); 131 pa_sink_input_request_rewind(u->sink_input, 0, false, true, true); 132 } 133 134 return 0; 135} 136 137/* Called from I/O thread context */ 138static void sink_request_rewind(pa_sink *s) { 139 struct userdata *u; 140 141 pa_sink_assert_ref(s); 142 pa_assert_se(u = s->userdata); 143 144 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) || 145 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) 146 return; 147 148 pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, true, false, false); 149} 150 151/* Called from I/O thread context */ 152static void sink_update_requested_latency(pa_sink *s) { 153 struct userdata *u; 154 155 pa_sink_assert_ref(s); 156 pa_assert_se(u = s->userdata); 157 158 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) || 159 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) 160 return; 161 162 /* Just hand this one over to the master sink */ 163 pa_sink_input_set_requested_latency_within_thread( 164 u->sink_input, 165 pa_sink_get_requested_latency_within_thread(s)); 166} 167 168/* Called from I/O thread context */ 169static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) { 170 struct userdata *u; 171 172 pa_sink_input_assert_ref(i); 173 pa_assert(chunk); 174 pa_assert_se(u = i->userdata); 175 176 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state)) 177 return -1; 178 179 /* Hmm, process any rewind request that might be queued up */ 180 pa_sink_process_rewind(u->sink, 0); 181 182 pa_sink_render(u->sink, nbytes, chunk); 183 return 0; 184} 185 186/* Called from I/O thread context */ 187static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) { 188 size_t amount = 0; 189 struct userdata *u; 190 191 pa_sink_input_assert_ref(i); 192 pa_assert_se(u = i->userdata); 193 194 /* If the sink is not yet linked, there is nothing to rewind */ 195 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state)) 196 return; 197 198 if (u->sink->thread_info.rewind_nbytes > 0) { 199 amount = PA_MIN(u->sink->thread_info.rewind_nbytes, nbytes); 200 u->sink->thread_info.rewind_nbytes = 0; 201 } 202 203 pa_sink_process_rewind(u->sink, amount); 204} 205 206/* Called from I/O thread context */ 207static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) { 208 struct userdata *u; 209 210 pa_sink_input_assert_ref(i); 211 pa_assert_se(u = i->userdata); 212 213 /* FIXME: Too small max_rewind: 214 * https://bugs.freedesktop.org/show_bug.cgi?id=53709 */ 215 pa_sink_set_max_rewind_within_thread(u->sink, nbytes); 216} 217 218/* Called from I/O thread context */ 219static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) { 220 struct userdata *u; 221 222 pa_sink_input_assert_ref(i); 223 pa_assert_se(u = i->userdata); 224 225 pa_sink_set_max_request_within_thread(u->sink, nbytes); 226} 227 228/* Called from I/O thread context */ 229static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) { 230 struct userdata *u; 231 232 pa_sink_input_assert_ref(i); 233 pa_assert_se(u = i->userdata); 234 235 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency); 236} 237 238/* Called from I/O thread context */ 239static void sink_input_update_sink_fixed_latency_cb(pa_sink_input *i) { 240 struct userdata *u; 241 242 pa_sink_input_assert_ref(i); 243 pa_assert_se(u = i->userdata); 244 245 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency); 246} 247 248/* Called from I/O thread context */ 249static void sink_input_detach_cb(pa_sink_input *i) { 250 struct userdata *u; 251 252 pa_sink_input_assert_ref(i); 253 pa_assert_se(u = i->userdata); 254 255 if (PA_SINK_IS_LINKED(u->sink->thread_info.state)) 256 pa_sink_detach_within_thread(u->sink); 257 258 pa_sink_set_rtpoll(u->sink, NULL); 259} 260 261/* Called from I/O thread context */ 262static void sink_input_attach_cb(pa_sink_input *i) { 263 struct userdata *u; 264 265 pa_sink_input_assert_ref(i); 266 pa_assert_se(u = i->userdata); 267 268 pa_sink_set_rtpoll(u->sink, i->sink->thread_info.rtpoll); 269 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency); 270 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency); 271 pa_sink_set_max_request_within_thread(u->sink, pa_sink_input_get_max_request(i)); 272 273 /* FIXME: Too small max_rewind: 274 * https://bugs.freedesktop.org/show_bug.cgi?id=53709 */ 275 pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i)); 276 277 if (PA_SINK_IS_LINKED(u->sink->thread_info.state)) 278 pa_sink_attach_within_thread(u->sink); 279} 280 281/* Called from main context */ 282static void sink_input_kill_cb(pa_sink_input *i) { 283 struct userdata *u; 284 285 pa_sink_input_assert_ref(i); 286 pa_assert_se(u = i->userdata); 287 288 /* The order here matters! We first kill the sink so that streams 289 * can properly be moved away while the sink input is still connected 290 * to the master. */ 291 pa_sink_input_cork(u->sink_input, true); 292 pa_sink_unlink(u->sink); 293 pa_sink_input_unlink(u->sink_input); 294 295 pa_sink_input_unref(u->sink_input); 296 u->sink_input = NULL; 297 298 pa_sink_unref(u->sink); 299 u->sink = NULL; 300 301 pa_module_unload_request(u->module, true); 302} 303 304/* Called from main context */ 305static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) { 306 struct userdata *u; 307 308 pa_sink_input_assert_ref(i); 309 pa_assert_se(u = i->userdata); 310 311 if (dest) { 312 pa_sink_set_asyncmsgq(u->sink, dest->asyncmsgq); 313 pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags); 314 } else 315 pa_sink_set_asyncmsgq(u->sink, NULL); 316 317 if (u->auto_desc && dest) { 318 const char *k; 319 pa_proplist *pl; 320 321 pl = pa_proplist_new(); 322 k = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION); 323 pa_proplist_setf(pl, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : dest->name); 324 325 pa_sink_update_proplist(u->sink, PA_UPDATE_REPLACE, pl); 326 pa_proplist_free(pl); 327 } 328} 329 330int pa__init(pa_module*m) { 331 struct userdata *u; 332 pa_sample_spec ss; 333 pa_resample_method_t resample_method = PA_RESAMPLER_INVALID; 334 pa_channel_map sink_map, stream_map; 335 pa_modargs *ma; 336 pa_sink *master; 337 pa_sink_input_new_data sink_input_data; 338 pa_sink_new_data sink_data; 339 bool remix = true; 340 341 pa_assert(m); 342 343 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { 344 pa_log("Failed to parse module arguments."); 345 goto fail; 346 } 347 348 if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) { 349 pa_log("Master sink not found"); 350 goto fail; 351 } 352 353 ss = master->sample_spec; 354 sink_map = master->channel_map; 355 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &sink_map, PA_CHANNEL_MAP_DEFAULT) < 0) { 356 pa_log("Invalid sample format specification or channel map"); 357 goto fail; 358 } 359 360 stream_map = sink_map; 361 if (pa_modargs_get_channel_map(ma, "master_channel_map", &stream_map) < 0) { 362 pa_log("Invalid master channel map"); 363 goto fail; 364 } 365 366 if (stream_map.channels != ss.channels) { 367 pa_log("Number of channels doesn't match"); 368 goto fail; 369 } 370 371 if (pa_channel_map_equal(&stream_map, &master->channel_map)) 372 pa_log_warn("No remapping configured, proceeding nonetheless!"); 373 374 if (pa_modargs_get_value_boolean(ma, "remix", &remix) < 0) { 375 pa_log("Invalid boolean remix parameter"); 376 goto fail; 377 } 378 379 if (pa_modargs_get_resample_method(ma, &resample_method) < 0) { 380 pa_log("Invalid resampling method"); 381 goto fail; 382 } 383 384 u = pa_xnew0(struct userdata, 1); 385 u->module = m; 386 m->userdata = u; 387 388 /* Create sink */ 389 pa_sink_new_data_init(&sink_data); 390 sink_data.driver = __FILE__; 391 sink_data.module = m; 392 if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL)))) 393 sink_data.name = pa_sprintf_malloc("%s.remapped", master->name); 394 pa_sink_new_data_set_sample_spec(&sink_data, &ss); 395 pa_sink_new_data_set_channel_map(&sink_data, &sink_map); 396 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name); 397 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter"); 398 399 if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) { 400 pa_log("Invalid properties"); 401 pa_sink_new_data_done(&sink_data); 402 goto fail; 403 } 404 405 if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) { 406 const char *k; 407 408 k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION); 409 pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : master->name); 410 } 411 412 u->sink = pa_sink_new(m->core, &sink_data, master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)); 413 pa_sink_new_data_done(&sink_data); 414 415 if (!u->sink) { 416 pa_log("Failed to create sink."); 417 goto fail; 418 } 419 420 u->sink->parent.process_msg = sink_process_msg; 421 u->sink->set_state_in_main_thread = sink_set_state_in_main_thread; 422 u->sink->set_state_in_io_thread = sink_set_state_in_io_thread_cb; 423 u->sink->update_requested_latency = sink_update_requested_latency; 424 u->sink->request_rewind = sink_request_rewind; 425 u->sink->userdata = u; 426 427 pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq); 428 429 /* Create sink input */ 430 pa_sink_input_new_data_init(&sink_input_data); 431 sink_input_data.driver = __FILE__; 432 sink_input_data.module = m; 433 pa_sink_input_new_data_set_sink(&sink_input_data, master, false, true); 434 sink_input_data.origin_sink = u->sink; 435 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Remapped Stream"); 436 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter"); 437 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss); 438 pa_sink_input_new_data_set_channel_map(&sink_input_data, &stream_map); 439 sink_input_data.flags = (remix ? 0 : PA_SINK_INPUT_NO_REMIX) | PA_SINK_INPUT_START_CORKED; 440 sink_input_data.resample_method = resample_method; 441 442 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data); 443 pa_sink_input_new_data_done(&sink_input_data); 444 445 if (!u->sink_input) 446 goto fail; 447 448 u->sink_input->pop = sink_input_pop_cb; 449 u->sink_input->process_rewind = sink_input_process_rewind_cb; 450 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb; 451 u->sink_input->update_max_request = sink_input_update_max_request_cb; 452 u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb; 453 u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb; 454 u->sink_input->attach = sink_input_attach_cb; 455 u->sink_input->detach = sink_input_detach_cb; 456 u->sink_input->kill = sink_input_kill_cb; 457 u->sink_input->moving = sink_input_moving_cb; 458 u->sink_input->userdata = u; 459 460 u->sink->input_to_master = u->sink_input; 461 462 /* The order here is important. The input must be put first, 463 * otherwise streams might attach to the sink before the sink 464 * input is attached to the master. */ 465 pa_sink_input_put(u->sink_input); 466 pa_sink_put(u->sink); 467 pa_sink_input_cork(u->sink_input, false); 468 469 pa_modargs_free(ma); 470 471 return 0; 472 473fail: 474 if (ma) 475 pa_modargs_free(ma); 476 477 pa__done(m); 478 479 return -1; 480} 481 482int pa__get_n_used(pa_module *m) { 483 struct userdata *u; 484 485 pa_assert(m); 486 pa_assert_se(u = m->userdata); 487 488 return pa_sink_linked_by(u->sink); 489} 490 491void pa__done(pa_module*m) { 492 struct userdata *u; 493 494 pa_assert(m); 495 496 if (!(u = m->userdata)) 497 return; 498 499 /* See comments in sink_input_kill_cb() above regarding 500 * destruction order! */ 501 502 if (u->sink_input) 503 pa_sink_input_cork(u->sink_input, true); 504 505 if (u->sink) 506 pa_sink_unlink(u->sink); 507 508 if (u->sink_input) { 509 pa_sink_input_unlink(u->sink_input); 510 pa_sink_input_unref(u->sink_input); 511 } 512 513 if (u->sink) 514 pa_sink_unref(u->sink); 515 516 pa_xfree(u); 517} 518