1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2004-2006 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 <stdlib.h> 25#include <stdio.h> 26#include <errno.h> 27#include <string.h> 28#include <unistd.h> 29 30#ifdef HAVE_NETINET_IN_H 31#include <netinet/in.h> 32#endif 33 34#ifdef HAVE_NETINET_TCP_H 35#include <netinet/tcp.h> 36#endif 37 38#ifdef HAVE_SYS_IOCTL_H 39#include <sys/ioctl.h> 40#endif 41 42#ifdef HAVE_LINUX_SOCKIOS_H 43#include <linux/sockios.h> 44#endif 45 46#include <pulse/rtclock.h> 47#include <pulse/timeval.h> 48#include <pulse/xmalloc.h> 49 50#include <pulsecore/socket.h> 51#include <pulsecore/core-error.h> 52#include <pulsecore/iochannel.h> 53#include <pulsecore/sink.h> 54#include <pulsecore/module.h> 55#include <pulsecore/core-util.h> 56#include <pulsecore/modargs.h> 57#include <pulsecore/log.h> 58#include <pulsecore/socket-client.h> 59#include <pulsecore/esound.h> 60#include <pulsecore/authkey.h> 61#include <pulsecore/thread-mq.h> 62#include <pulsecore/thread.h> 63 64#ifdef USE_SMOOTHER_2 65#include <pulsecore/time-smoother_2.h> 66#else 67#include <pulsecore/time-smoother.h> 68#endif 69 70#include <pulsecore/socket-util.h> 71#include <pulsecore/rtpoll.h> 72#include <pulsecore/poll.h> 73 74PA_MODULE_AUTHOR("Lennart Poettering"); 75PA_MODULE_DESCRIPTION("ESOUND Sink"); 76PA_MODULE_VERSION(PACKAGE_VERSION); 77PA_MODULE_LOAD_ONCE(false); 78PA_MODULE_USAGE( 79 "sink_name=<name for the sink> " 80 "sink_properties=<properties for the sink> " 81 "server=<address> cookie=<filename> " 82 "format=<sample format> " 83 "rate=<sample rate> " 84 "channels=<number of channels>"); 85 86#define DEFAULT_SINK_NAME "esound_out" 87 88struct userdata { 89 pa_core *core; 90 pa_module *module; 91 pa_sink *sink; 92 93 pa_thread_mq thread_mq; 94 pa_rtpoll *rtpoll; 95 pa_rtpoll_item *rtpoll_item; 96 pa_thread *thread; 97 98 pa_memchunk memchunk; 99 100 void *write_data; 101 size_t write_length, write_index; 102 103 void *read_data; 104 size_t read_length, read_index; 105 106 enum { 107 STATE_AUTH, 108 STATE_LATENCY, 109 STATE_PREPARE, 110 STATE_RUNNING, 111 STATE_DEAD 112 } state; 113 114 pa_usec_t latency; 115 116 esd_format_t format; 117 int32_t rate; 118 119#ifdef USE_SMOOTHER_2 120 pa_smoother_2 *smoother; 121#else 122 pa_smoother *smoother; 123#endif 124 125 int fd; 126 127 int64_t offset; 128 129 pa_iochannel *io; 130 pa_socket_client *client; 131 132 size_t block_size; 133}; 134 135static const char* const valid_modargs[] = { 136 "sink_name", 137 "sink_properties", 138 "server", 139 "cookie", 140 "format", 141 "rate", 142 "channels", 143 NULL 144}; 145 146enum { 147 SINK_MESSAGE_PASS_SOCKET = PA_SINK_MESSAGE_MAX 148}; 149 150static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { 151 struct userdata *u = PA_SINK(o)->userdata; 152 153 switch (code) { 154 155 case PA_SINK_MESSAGE_GET_LATENCY: { 156#ifdef USE_SMOOTHER_2 157 *((int64_t*) data) = pa_smoother_2_get_delay(u->smoother, pa_rtclock_now(), (uint64_t)u->offset + u->memchunk.length); 158#else 159 pa_usec_t w, r; 160 161 r = pa_smoother_get(u->smoother, pa_rtclock_now()); 162 w = pa_bytes_to_usec((uint64_t) u->offset + u->memchunk.length, &u->sink->sample_spec); 163 164 *((int64_t*) data) = (int64_t)w - r; 165#endif 166 return 0; 167 } 168 169 case SINK_MESSAGE_PASS_SOCKET: { 170 struct pollfd *pollfd; 171 172 pa_assert(!u->rtpoll_item); 173 174 u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); 175 pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); 176 pollfd->fd = u->fd; 177 pollfd->events = pollfd->revents = 0; 178 179 return 0; 180 } 181 } 182 183 return pa_sink_process_msg(o, code, data, offset, chunk); 184} 185 186/* Called from the IO thread. */ 187static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) { 188 struct userdata *u; 189 190 pa_assert(s); 191 pa_assert_se(u = s->userdata); 192 193 /* It may be that only the suspend cause is changing, in which case there's 194 * nothing to do. */ 195 if (new_state == s->thread_info.state) 196 return 0; 197 198 switch (new_state) { 199 200 case PA_SINK_SUSPENDED: 201 pa_assert(PA_SINK_IS_OPENED(s->thread_info.state)); 202 203#ifdef USE_SMOOTHER_2 204 pa_smoother_2_pause(u->smoother, pa_rtclock_now()); 205#else 206 pa_smoother_pause(u->smoother, pa_rtclock_now()); 207#endif 208 break; 209 210 case PA_SINK_IDLE: 211 case PA_SINK_RUNNING: 212 213 if (s->thread_info.state == PA_SINK_SUSPENDED) 214#ifdef USE_SMOOTHER_2 215 pa_smoother_2_resume(u->smoother, pa_rtclock_now()); 216#else 217 pa_smoother_resume(u->smoother, pa_rtclock_now(), true); 218#endif 219 break; 220 221 case PA_SINK_UNLINKED: 222 case PA_SINK_INIT: 223 case PA_SINK_INVALID_STATE: 224 ; 225 } 226 227 return 0; 228} 229 230static void thread_func(void *userdata) { 231 struct userdata *u = userdata; 232 int write_type = 0; 233 234 pa_assert(u); 235 236 pa_log_debug("Thread starting up"); 237 238 pa_thread_mq_install(&u->thread_mq); 239 240#ifdef USE_SMOOTHER_2 241 pa_smoother_2_reset(u->smoother, pa_rtclock_now()); 242#else 243 pa_smoother_set_time_offset(u->smoother, pa_rtclock_now()); 244#endif 245 246 for (;;) { 247 int ret; 248 249 if (PA_UNLIKELY(u->sink->thread_info.rewind_requested)) 250 pa_sink_process_rewind(u->sink, 0); 251 252 if (u->rtpoll_item) { 253 struct pollfd *pollfd; 254 pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); 255 256 /* Render some data and write it to the fifo */ 257 if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) { 258#ifdef USE_SMOOTHER_2 259 size_t bytes; 260#else 261 pa_usec_t usec; 262#endif 263 int64_t n; 264 265 for (;;) { 266 ssize_t l; 267 void *p; 268 269 if (u->memchunk.length <= 0) 270 pa_sink_render(u->sink, u->block_size, &u->memchunk); 271 272 pa_assert(u->memchunk.length > 0); 273 274 p = pa_memblock_acquire(u->memchunk.memblock); 275 l = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &write_type); 276 pa_memblock_release(u->memchunk.memblock); 277 278 pa_assert(l != 0); 279 280 if (l < 0) { 281 282 if (errno == EAGAIN) { 283 284 /* OK, we filled all socket buffers up 285 * now. */ 286 goto filled_up; 287 288 } else { 289 pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno)); 290 goto fail; 291 } 292 293 } else { 294 u->offset += l; 295 296 u->memchunk.index += (size_t) l; 297 u->memchunk.length -= (size_t) l; 298 299 if (u->memchunk.length <= 0) { 300 pa_memblock_unref(u->memchunk.memblock); 301 pa_memchunk_reset(&u->memchunk); 302 } 303 304 pollfd->revents = 0; 305 306 if (u->memchunk.length > 0) 307 308 /* OK, we wrote less that we asked for, 309 * hence we can assume that the socket 310 * buffers are full now */ 311 goto filled_up; 312 } 313 } 314 315 filled_up: 316 317 /* At this spot we know that the socket buffers are 318 * fully filled up. This is the best time to estimate 319 * the playback position of the server */ 320 321 n = u->offset; 322 323#ifdef SIOCOUTQ 324 { 325 int l; 326 if (ioctl(u->fd, SIOCOUTQ, &l) >= 0 && l > 0) 327 n -= l; 328 } 329#endif 330 331#ifdef USE_SMOOTHER_2 332 bytes = pa_usec_to_bytes(u->latency, &u->sink->sample_spec); 333 334 if ((uint64_t)n > bytes) 335 bytes = n - bytes; 336 else 337 bytes = 0; 338 339 pa_smoother_2_put(u->smoother, pa_rtclock_now(), bytes); 340#else 341 usec = pa_bytes_to_usec((uint64_t) n, &u->sink->sample_spec); 342 343 if (usec > u->latency) 344 usec -= u->latency; 345 else 346 usec = 0; 347 348 pa_smoother_put(u->smoother, pa_rtclock_now(), usec); 349#endif 350 } 351 352 /* Hmm, nothing to do. Let's sleep */ 353 pollfd->events = (short) (PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0); 354 } 355 356 if ((ret = pa_rtpoll_run(u->rtpoll)) < 0) 357 goto fail; 358 359 if (ret == 0) 360 goto finish; 361 362 if (u->rtpoll_item) { 363 struct pollfd* pollfd; 364 365 pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); 366 367 if (pollfd->revents & ~POLLOUT) { 368 pa_log("FIFO shutdown."); 369 goto fail; 370 } 371 } 372 } 373 374fail: 375 /* If this was no regular exit from the loop we have to continue 376 * processing messages until we received PA_MESSAGE_SHUTDOWN */ 377 pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL); 378 pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); 379 380finish: 381 pa_log_debug("Thread shutting down"); 382} 383 384static int do_write(struct userdata *u) { 385 ssize_t r; 386 pa_assert(u); 387 388 if (!pa_iochannel_is_writable(u->io)) 389 return 0; 390 391 if (u->write_data) { 392 pa_assert(u->write_index < u->write_length); 393 394 if ((r = pa_iochannel_write(u->io, (uint8_t*) u->write_data + u->write_index, u->write_length - u->write_index)) < 0) { 395 pa_log("write() failed: %s", pa_cstrerror(errno)); 396 return -1; 397 } 398 399 u->write_index += (size_t) r; 400 pa_assert(u->write_index <= u->write_length); 401 402 if (u->write_index == u->write_length) { 403 pa_xfree(u->write_data); 404 u->write_data = NULL; 405 u->write_index = u->write_length = 0; 406 } 407 } 408 409 if (!u->write_data && u->state == STATE_PREPARE) { 410 int so_sndbuf = 0; 411 socklen_t sl = sizeof(int); 412 413 /* OK, we're done with sending all control data we need to, so 414 * let's hand the socket over to the IO thread now */ 415 416 pa_assert(u->fd < 0); 417 u->fd = pa_iochannel_get_send_fd(u->io); 418 419 pa_iochannel_set_noclose(u->io, true); 420 pa_iochannel_free(u->io); 421 u->io = NULL; 422 423 pa_make_tcp_socket_low_delay(u->fd); 424 425 if (getsockopt(u->fd, SOL_SOCKET, SO_SNDBUF, (void *) &so_sndbuf, &sl) < 0) 426 pa_log_warn("getsockopt(SO_SNDBUF) failed: %s", pa_cstrerror(errno)); 427 else { 428 pa_log_debug("SO_SNDBUF is %zu.", (size_t) so_sndbuf); 429 pa_sink_set_max_request(u->sink, PA_MAX((size_t) so_sndbuf, u->block_size)); 430 } 431 432 pa_log_debug("Connection authenticated, handing fd to IO thread..."); 433 434 pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_PASS_SOCKET, NULL, 0, NULL, NULL); 435 u->state = STATE_RUNNING; 436 } 437 438 return 0; 439} 440 441static int handle_response(struct userdata *u) { 442 pa_assert(u); 443 444 switch (u->state) { 445 446 case STATE_AUTH: 447 pa_assert(u->read_length == sizeof(int32_t)); 448 449 /* Process auth data */ 450 if (!*(int32_t*) u->read_data) { 451 pa_log("Authentication failed: %s", pa_cstrerror(errno)); 452 return -1; 453 } 454 455 /* Request latency data */ 456 pa_assert(!u->write_data); 457 *(int32_t*) (u->write_data = pa_xmalloc(u->write_length = sizeof(int32_t))) = ESD_PROTO_LATENCY; 458 459 u->write_index = 0; 460 u->state = STATE_LATENCY; 461 462 /* Space for next response */ 463 pa_assert(u->read_length >= sizeof(int32_t)); 464 u->read_index = 0; 465 u->read_length = sizeof(int32_t); 466 467 break; 468 469 case STATE_LATENCY: { 470 int32_t *p; 471 pa_assert(u->read_length == sizeof(int32_t)); 472 473 /* Process latency info */ 474 u->latency = (pa_usec_t) ((double) (*(int32_t*) u->read_data) * 1000000 / 44100); 475 if (u->latency > 10000000) { 476 pa_log_warn("Invalid latency information received from server"); 477 u->latency = 0; 478 } 479 480 /* Create stream */ 481 pa_assert(!u->write_data); 482 p = u->write_data = pa_xmalloc0(u->write_length = sizeof(int32_t)*3+ESD_NAME_MAX); 483 *(p++) = ESD_PROTO_STREAM_PLAY; 484 *(p++) = u->format; 485 *(p++) = u->rate; 486 pa_strlcpy((char*) p, "PulseAudio Tunnel", ESD_NAME_MAX); 487 488 u->write_index = 0; 489 u->state = STATE_PREPARE; 490 491 /* Don't read any further */ 492 pa_xfree(u->read_data); 493 u->read_data = NULL; 494 u->read_index = u->read_length = 0; 495 496 break; 497 } 498 499 default: 500 pa_assert_not_reached(); 501 } 502 503 return 0; 504} 505 506static int do_read(struct userdata *u) { 507 pa_assert(u); 508 509 if (!pa_iochannel_is_readable(u->io)) 510 return 0; 511 512 if (u->state == STATE_AUTH || u->state == STATE_LATENCY) { 513 ssize_t r; 514 515 if (!u->read_data) 516 return 0; 517 518 pa_assert(u->read_index < u->read_length); 519 520 if ((r = pa_iochannel_read(u->io, (uint8_t*) u->read_data + u->read_index, u->read_length - u->read_index)) <= 0) { 521 pa_log("read() failed: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); 522 return -1; 523 } 524 525 u->read_index += (size_t) r; 526 pa_assert(u->read_index <= u->read_length); 527 528 if (u->read_index == u->read_length) 529 return handle_response(u); 530 } 531 532 return 0; 533} 534 535static void io_callback(pa_iochannel *io, void*userdata) { 536 struct userdata *u = userdata; 537 pa_assert(u); 538 539 if (do_read(u) < 0 || do_write(u) < 0) { 540 541 if (u->io) { 542 pa_iochannel_free(u->io); 543 u->io = NULL; 544 } 545 546 pa_module_unload_request(u->module, true); 547 } 548} 549 550static void on_connection(pa_socket_client *c, pa_iochannel*io, void *userdata) { 551 struct userdata *u = userdata; 552 553 pa_socket_client_unref(u->client); 554 u->client = NULL; 555 556 if (!io) { 557 pa_log("Connection failed: %s", pa_cstrerror(errno)); 558 pa_module_unload_request(u->module, true); 559 return; 560 } 561 562 pa_assert(!u->io); 563 u->io = io; 564 pa_iochannel_set_callback(u->io, io_callback, u); 565 566 pa_log_debug("Connection established, authenticating ..."); 567} 568 569int pa__init(pa_module*m) { 570 struct userdata *u = NULL; 571 pa_sample_spec ss; 572 pa_modargs *ma = NULL; 573 const char *espeaker; 574 uint32_t key; 575 pa_sink_new_data data; 576 char *cookie_path; 577 int r; 578 579 pa_assert(m); 580 581 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { 582 pa_log("failed to parse module arguments"); 583 goto fail; 584 } 585 586 ss = m->core->default_sample_spec; 587 if (pa_modargs_get_sample_spec(ma, &ss) < 0) { 588 pa_log("invalid sample format specification"); 589 goto fail; 590 } 591 592 if ((ss.format != PA_SAMPLE_U8 && ss.format != PA_SAMPLE_S16NE) || 593 (ss.channels > 2)) { 594 pa_log("esound sample type support is limited to mono/stereo and U8 or S16NE sample data"); 595 goto fail; 596 } 597 598 u = pa_xnew0(struct userdata, 1); 599 u->core = m->core; 600 u->module = m; 601 m->userdata = u; 602 u->fd = -1; 603#ifdef USE_SMOOTHER_2 604 u->smoother = pa_smoother_2_new(5*PA_USEC_PER_SEC, pa_rtclock_now(), pa_frame_size(&ss), ss.rate); 605#else 606 u->smoother = pa_smoother_new( 607 PA_USEC_PER_SEC, 608 PA_USEC_PER_SEC*2, 609 true, 610 true, 611 10, 612 0, 613 false); 614#endif 615 pa_memchunk_reset(&u->memchunk); 616 u->offset = 0; 617 618 u->rtpoll = pa_rtpoll_new(); 619 620 if (pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll) < 0) { 621 pa_log("pa_thread_mq_init() failed."); 622 goto fail; 623 } 624 625 u->rtpoll_item = NULL; 626 627 u->format = 628 (ss.format == PA_SAMPLE_U8 ? ESD_BITS8 : ESD_BITS16) | 629 (ss.channels == 2 ? ESD_STEREO : ESD_MONO); 630 u->rate = (int32_t) ss.rate; 631 u->block_size = pa_usec_to_bytes(PA_USEC_PER_SEC/20, &ss); 632 633 u->read_data = u->write_data = NULL; 634 u->read_index = u->write_index = u->read_length = u->write_length = 0; 635 636 u->state = STATE_AUTH; 637 u->latency = 0; 638 639 if (!(espeaker = getenv("ESPEAKER"))) 640 espeaker = ESD_UNIX_SOCKET_NAME; 641 642 espeaker = pa_modargs_get_value(ma, "server", espeaker); 643 644 pa_sink_new_data_init(&data); 645 data.driver = __FILE__; 646 data.module = m; 647 pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME)); 648 pa_sink_new_data_set_sample_spec(&data, &ss); 649 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, espeaker); 650 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "esd"); 651 pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "EsounD Output on %s", espeaker); 652 653 if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) { 654 pa_log("Invalid properties"); 655 pa_sink_new_data_done(&data); 656 goto fail; 657 } 658 659 u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY|PA_SINK_NETWORK); 660 pa_sink_new_data_done(&data); 661 662 if (!u->sink) { 663 pa_log("Failed to create sink."); 664 goto fail; 665 } 666 667 u->sink->parent.process_msg = sink_process_msg; 668 u->sink->set_state_in_io_thread = sink_set_state_in_io_thread_cb; 669 u->sink->userdata = u; 670 671 pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); 672 pa_sink_set_rtpoll(u->sink, u->rtpoll); 673 674 if (!(u->client = pa_socket_client_new_string(u->core->mainloop, true, espeaker, ESD_DEFAULT_PORT))) { 675 pa_log("Failed to connect to server."); 676 goto fail; 677 } 678 679 pa_socket_client_set_callback(u->client, on_connection, u); 680 681 cookie_path = pa_xstrdup(pa_modargs_get_value(ma, "cookie", NULL)); 682 if (!cookie_path) { 683 if (pa_append_to_home_dir(".esd_auth", &cookie_path) < 0) 684 goto fail; 685 } 686 687 /* Prepare the initial request */ 688 u->write_data = pa_xmalloc(u->write_length = ESD_KEY_LEN + sizeof(int32_t)); 689 690 r = pa_authkey_load(cookie_path, true, u->write_data, ESD_KEY_LEN); 691 pa_xfree(cookie_path); 692 if (r < 0) { 693 pa_log("Failed to load cookie"); 694 goto fail; 695 } 696 697 key = ESD_ENDIAN_KEY; 698 memcpy((uint8_t*) u->write_data + ESD_KEY_LEN, &key, sizeof(key)); 699 700 /* Reserve space for the response */ 701 u->read_data = pa_xmalloc(u->read_length = sizeof(int32_t)); 702 703 if (!(u->thread = pa_thread_new("esound-sink", thread_func, u))) { 704 pa_log("Failed to create thread."); 705 goto fail; 706 } 707 708 pa_sink_put(u->sink); 709 710 pa_modargs_free(ma); 711 712 return 0; 713 714fail: 715 if (ma) 716 pa_modargs_free(ma); 717 718 pa__done(m); 719 720 return -1; 721} 722 723int pa__get_n_used(pa_module *m) { 724 struct userdata *u; 725 726 pa_assert(m); 727 pa_assert_se(u = m->userdata); 728 729 return pa_sink_linked_by(u->sink); 730} 731 732void pa__done(pa_module*m) { 733 struct userdata *u; 734 pa_assert(m); 735 736 if (!(u = m->userdata)) 737 return; 738 739 if (u->sink) 740 pa_sink_unlink(u->sink); 741 742 if (u->thread) { 743 pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); 744 pa_thread_free(u->thread); 745 } 746 747 pa_thread_mq_done(&u->thread_mq); 748 749 if (u->sink) 750 pa_sink_unref(u->sink); 751 752 if (u->io) 753 pa_iochannel_free(u->io); 754 755 if (u->rtpoll_item) 756 pa_rtpoll_item_free(u->rtpoll_item); 757 758 if (u->rtpoll) 759 pa_rtpoll_free(u->rtpoll); 760 761 if (u->memchunk.memblock) 762 pa_memblock_unref(u->memchunk.memblock); 763 764 if (u->client) 765 pa_socket_client_unref(u->client); 766 767 pa_xfree(u->read_data); 768 pa_xfree(u->write_data); 769 770 if (u->smoother) 771#ifdef USE_SMOOTHER_2 772 pa_smoother_2_free(u->smoother); 773#else 774 pa_smoother_free(u->smoother); 775#endif 776 777 if (u->fd >= 0) 778 pa_close(u->fd); 779 780 pa_xfree(u); 781} 782