]> code.delx.au - pulseaudio/blob - src/modules/module-solaris.c
solaris, tunnel: Remove some redundant boolean conversions
[pulseaudio] / src / modules / module-solaris.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2006 Lennart Poettering
5 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 Copyright 2009 Finn Thain
7
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published
10 by the Free Software Foundation; either version 2.1 of the License,
11 or (at your option) any later version.
12
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 USA.
22 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <sys/ioctl.h>
34 #include <sys/types.h>
35
36 #include <signal.h>
37 #include <stropts.h>
38 #include <sys/conf.h>
39 #include <sys/audio.h>
40
41 #include <pulse/mainloop-signal.h>
42 #include <pulse/xmalloc.h>
43 #include <pulse/timeval.h>
44 #include <pulse/util.h>
45 #include <pulse/rtclock.h>
46
47 #include <pulsecore/sink.h>
48 #include <pulsecore/source.h>
49 #include <pulsecore/module.h>
50 #include <pulsecore/sample-util.h>
51 #include <pulsecore/core-util.h>
52 #include <pulsecore/modargs.h>
53 #include <pulsecore/log.h>
54 #include <pulsecore/core-error.h>
55 #include <pulsecore/thread-mq.h>
56 #include <pulsecore/rtpoll.h>
57 #include <pulsecore/thread.h>
58 #include <pulsecore/time-smoother.h>
59
60 #include "module-solaris-symdef.h"
61
62 PA_MODULE_AUTHOR("Pierre Ossman");
63 PA_MODULE_DESCRIPTION("Solaris Sink/Source");
64 PA_MODULE_VERSION(PACKAGE_VERSION);
65 PA_MODULE_USAGE(
66 "sink_name=<name for the sink> "
67 "sink_properties=<properties for the sink> "
68 "source_name=<name for the source> "
69 "source_properties=<properties for the source> "
70 "device=<audio device file name> "
71 "record=<enable source?> "
72 "playback=<enable sink?> "
73 "format=<sample format> "
74 "channels=<number of channels> "
75 "rate=<sample rate> "
76 "buffer_length=<milliseconds> "
77 "channel_map=<channel map>");
78 PA_MODULE_LOAD_ONCE(false);
79
80 struct userdata {
81 pa_core *core;
82 pa_sink *sink;
83 pa_source *source;
84
85 pa_thread *thread;
86 pa_thread_mq thread_mq;
87 pa_rtpoll *rtpoll;
88
89 pa_signal_event *sig;
90
91 pa_memchunk memchunk;
92
93 uint32_t frame_size;
94 int32_t buffer_size;
95 uint64_t written_bytes, read_bytes;
96
97 char *device_name;
98 int mode;
99 int fd;
100 pa_rtpoll_item *rtpoll_item;
101 pa_module *module;
102
103 bool sink_suspended, source_suspended;
104
105 uint32_t play_samples_msw, record_samples_msw;
106 uint32_t prev_playback_samples, prev_record_samples;
107
108 int32_t minimum_request;
109
110 pa_smoother *smoother;
111 };
112
113 static const char* const valid_modargs[] = {
114 "sink_name",
115 "sink_properties",
116 "source_name",
117 "source_properties",
118 "device",
119 "record",
120 "playback",
121 "buffer_length",
122 "format",
123 "rate",
124 "channels",
125 "channel_map",
126 NULL
127 };
128
129 #define DEFAULT_DEVICE "/dev/audio"
130
131 #define MAX_RENDER_HZ (300)
132 /* This render rate limit imposes a minimum latency, but without it we waste too much CPU time. */
133
134 #define MAX_BUFFER_SIZE (128 * 1024)
135 /* An attempt to buffer more than 128 KB causes write() to fail with errno == EAGAIN. */
136
137 static uint64_t get_playback_buffered_bytes(struct userdata *u) {
138 audio_info_t info;
139 uint64_t played_bytes;
140 int err;
141
142 pa_assert(u->sink);
143
144 err = ioctl(u->fd, AUDIO_GETINFO, &info);
145 pa_assert(err >= 0);
146
147 /* Handle wrap-around of the device's sample counter, which is a uint_32. */
148 if (u->prev_playback_samples > info.play.samples) {
149 /*
150 * Unfortunately info.play.samples can sometimes go backwards, even before it wraps!
151 * The bug seems to be absent on Solaris x86 nv117 with audio810 driver, at least on this (UP) machine.
152 * The bug is present on a different (SMP) machine running Solaris x86 nv103 with audioens driver.
153 * An earlier revision of this file mentions the same bug independently (unknown configuration).
154 */
155 if (u->prev_playback_samples + info.play.samples < 240000) {
156 ++u->play_samples_msw;
157 } else {
158 pa_log_debug("play.samples went backwards %d bytes", u->prev_playback_samples - info.play.samples);
159 }
160 }
161 u->prev_playback_samples = info.play.samples;
162 played_bytes = (((uint64_t)u->play_samples_msw << 32) + info.play.samples) * u->frame_size;
163
164 pa_smoother_put(u->smoother, pa_rtclock_now(), pa_bytes_to_usec(played_bytes, &u->sink->sample_spec));
165
166 if (u->written_bytes > played_bytes)
167 return u->written_bytes - played_bytes;
168 else
169 return 0;
170 }
171
172 static pa_usec_t sink_get_latency(struct userdata *u, pa_sample_spec *ss) {
173 pa_usec_t r = 0;
174
175 pa_assert(u);
176 pa_assert(ss);
177
178 if (u->fd >= 0) {
179 r = pa_bytes_to_usec(get_playback_buffered_bytes(u), ss);
180 if (u->memchunk.memblock)
181 r += pa_bytes_to_usec(u->memchunk.length, ss);
182 }
183 return r;
184 }
185
186 static uint64_t get_recorded_bytes(struct userdata *u) {
187 audio_info_t info;
188 uint64_t result;
189 int err;
190
191 pa_assert(u->source);
192
193 err = ioctl(u->fd, AUDIO_GETINFO, &info);
194 pa_assert(err >= 0);
195
196 if (u->prev_record_samples > info.record.samples)
197 ++u->record_samples_msw;
198 u->prev_record_samples = info.record.samples;
199 result = (((uint64_t)u->record_samples_msw << 32) + info.record.samples) * u->frame_size;
200
201 return result;
202 }
203
204 static pa_usec_t source_get_latency(struct userdata *u, pa_sample_spec *ss) {
205 pa_usec_t r = 0;
206 audio_info_t info;
207
208 pa_assert(u);
209 pa_assert(ss);
210
211 if (u->fd) {
212 int err = ioctl(u->fd, AUDIO_GETINFO, &info);
213 pa_assert(err >= 0);
214
215 r = pa_bytes_to_usec(get_recorded_bytes(u), ss) - pa_bytes_to_usec(u->read_bytes, ss);
216 }
217 return r;
218 }
219
220 static void build_pollfd(struct userdata *u) {
221 struct pollfd *pollfd;
222
223 pa_assert(u);
224 pa_assert(!u->rtpoll_item);
225 u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
226
227 pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
228 pollfd->fd = u->fd;
229 pollfd->events = 0;
230 pollfd->revents = 0;
231 }
232
233 static int set_buffer(int fd, int buffer_size) {
234 audio_info_t info;
235
236 pa_assert(fd >= 0);
237
238 AUDIO_INITINFO(&info);
239 info.play.buffer_size = buffer_size;
240 info.record.buffer_size = buffer_size;
241
242 if (ioctl(fd, AUDIO_SETINFO, &info) < 0) {
243 if (errno == EINVAL)
244 pa_log("AUDIO_SETINFO: Unsupported buffer size.");
245 else
246 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
247 return -1;
248 }
249
250 return 0;
251 }
252
253 static int auto_format(int fd, int mode, pa_sample_spec *ss) {
254 audio_info_t info;
255
256 pa_assert(fd >= 0);
257 pa_assert(ss);
258
259 AUDIO_INITINFO(&info);
260
261 if (mode != O_RDONLY) {
262 info.play.sample_rate = ss->rate;
263 info.play.channels = ss->channels;
264 switch (ss->format) {
265 case PA_SAMPLE_U8:
266 info.play.precision = 8;
267 info.play.encoding = AUDIO_ENCODING_LINEAR;
268 break;
269 case PA_SAMPLE_ALAW:
270 info.play.precision = 8;
271 info.play.encoding = AUDIO_ENCODING_ALAW;
272 break;
273 case PA_SAMPLE_ULAW:
274 info.play.precision = 8;
275 info.play.encoding = AUDIO_ENCODING_ULAW;
276 break;
277 case PA_SAMPLE_S16NE:
278 info.play.precision = 16;
279 info.play.encoding = AUDIO_ENCODING_LINEAR;
280 break;
281 default:
282 pa_log("AUDIO_SETINFO: Unsupported sample format.");
283 return -1;
284 }
285 }
286
287 if (mode != O_WRONLY) {
288 info.record.sample_rate = ss->rate;
289 info.record.channels = ss->channels;
290 switch (ss->format) {
291 case PA_SAMPLE_U8:
292 info.record.precision = 8;
293 info.record.encoding = AUDIO_ENCODING_LINEAR;
294 break;
295 case PA_SAMPLE_ALAW:
296 info.record.precision = 8;
297 info.record.encoding = AUDIO_ENCODING_ALAW;
298 break;
299 case PA_SAMPLE_ULAW:
300 info.record.precision = 8;
301 info.record.encoding = AUDIO_ENCODING_ULAW;
302 break;
303 case PA_SAMPLE_S16NE:
304 info.record.precision = 16;
305 info.record.encoding = AUDIO_ENCODING_LINEAR;
306 break;
307 default:
308 pa_log("AUDIO_SETINFO: Unsupported sample format.");
309 return -1;
310 }
311 }
312
313 if (ioctl(fd, AUDIO_SETINFO, &info) < 0) {
314 if (errno == EINVAL)
315 pa_log("AUDIO_SETINFO: Failed to set sample format.");
316 else
317 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
318 return -1;
319 }
320
321 return 0;
322 }
323
324 static int open_audio_device(struct userdata *u, pa_sample_spec *ss) {
325 pa_assert(u);
326 pa_assert(ss);
327
328 if ((u->fd = pa_open_cloexec(u->device_name, u->mode | O_NONBLOCK, 0)) < 0) {
329 pa_log_warn("open %s failed (%s)", u->device_name, pa_cstrerror(errno));
330 return -1;
331 }
332
333 pa_log_info("device opened in %s mode.", u->mode == O_WRONLY ? "O_WRONLY" : (u->mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
334
335 if (auto_format(u->fd, u->mode, ss) < 0)
336 return -1;
337
338 if (set_buffer(u->fd, u->buffer_size) < 0)
339 return -1;
340
341 u->written_bytes = u->read_bytes = 0;
342 u->play_samples_msw = u->record_samples_msw = 0;
343 u->prev_playback_samples = u->prev_record_samples = 0;
344
345 return u->fd;
346 }
347
348 static int suspend(struct userdata *u) {
349 pa_assert(u);
350 pa_assert(u->fd >= 0);
351
352 pa_log_info("Suspending...");
353
354 ioctl(u->fd, I_FLUSH, FLUSHRW);
355 pa_close(u->fd);
356 u->fd = -1;
357
358 if (u->rtpoll_item) {
359 pa_rtpoll_item_free(u->rtpoll_item);
360 u->rtpoll_item = NULL;
361 }
362
363 pa_log_info("Device suspended.");
364
365 return 0;
366 }
367
368 static int unsuspend(struct userdata *u) {
369 pa_assert(u);
370 pa_assert(u->fd < 0);
371
372 pa_log_info("Resuming...");
373
374 if (open_audio_device(u, u->sink ? &u->sink->sample_spec : &u->source->sample_spec) < 0)
375 return -1;
376
377 build_pollfd(u);
378
379 pa_log_info("Device resumed.");
380
381 return 0;
382 }
383
384 static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
385 struct userdata *u = PA_SINK(o)->userdata;
386
387 switch (code) {
388
389 case PA_SINK_MESSAGE_GET_LATENCY:
390 *((pa_usec_t*) data) = sink_get_latency(u, &PA_SINK(o)->sample_spec);
391 return 0;
392
393 case PA_SINK_MESSAGE_SET_STATE:
394
395 switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
396
397 case PA_SINK_SUSPENDED:
398
399 pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
400
401 pa_smoother_pause(u->smoother, pa_rtclock_now());
402
403 if (!u->source || u->source_suspended) {
404 if (suspend(u) < 0)
405 return -1;
406 }
407 u->sink_suspended = true;
408 break;
409
410 case PA_SINK_IDLE:
411 case PA_SINK_RUNNING:
412
413 if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
414 pa_smoother_resume(u->smoother, pa_rtclock_now(), true);
415
416 if (!u->source || u->source_suspended) {
417 if (unsuspend(u) < 0)
418 return -1;
419 u->sink->get_volume(u->sink);
420 u->sink->get_mute(u->sink);
421 }
422 u->sink_suspended = false;
423 }
424 break;
425
426 case PA_SINK_INVALID_STATE:
427 case PA_SINK_UNLINKED:
428 case PA_SINK_INIT:
429 ;
430 }
431
432 break;
433 }
434
435 return pa_sink_process_msg(o, code, data, offset, chunk);
436 }
437
438 static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
439 struct userdata *u = PA_SOURCE(o)->userdata;
440
441 switch (code) {
442
443 case PA_SOURCE_MESSAGE_GET_LATENCY:
444 *((pa_usec_t*) data) = source_get_latency(u, &PA_SOURCE(o)->sample_spec);
445 return 0;
446
447 case PA_SOURCE_MESSAGE_SET_STATE:
448
449 switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
450
451 case PA_SOURCE_SUSPENDED:
452
453 pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
454
455 if (!u->sink || u->sink_suspended) {
456 if (suspend(u) < 0)
457 return -1;
458 }
459 u->source_suspended = true;
460 break;
461
462 case PA_SOURCE_IDLE:
463 case PA_SOURCE_RUNNING:
464
465 if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
466 if (!u->sink || u->sink_suspended) {
467 if (unsuspend(u) < 0)
468 return -1;
469 u->source->get_volume(u->source);
470 }
471 u->source_suspended = false;
472 }
473 break;
474
475 case PA_SOURCE_UNLINKED:
476 case PA_SOURCE_INIT:
477 case PA_SOURCE_INVALID_STATE:
478 ;
479
480 }
481 break;
482
483 }
484
485 return pa_source_process_msg(o, code, data, offset, chunk);
486 }
487
488 static void sink_set_volume(pa_sink *s) {
489 struct userdata *u;
490 audio_info_t info;
491
492 pa_assert_se(u = s->userdata);
493
494 if (u->fd >= 0) {
495 AUDIO_INITINFO(&info);
496
497 info.play.gain = pa_cvolume_max(&s->real_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM;
498 assert(info.play.gain <= AUDIO_MAX_GAIN);
499
500 if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) {
501 if (errno == EINVAL)
502 pa_log("AUDIO_SETINFO: Unsupported volume.");
503 else
504 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
505 }
506 }
507 }
508
509 static void sink_get_volume(pa_sink *s) {
510 struct userdata *u;
511 audio_info_t info;
512
513 pa_assert_se(u = s->userdata);
514
515 if (u->fd >= 0) {
516 if (ioctl(u->fd, AUDIO_GETINFO, &info) < 0)
517 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
518 else
519 pa_cvolume_set(&s->real_volume, s->sample_spec.channels, info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);
520 }
521 }
522
523 static void source_set_volume(pa_source *s) {
524 struct userdata *u;
525 audio_info_t info;
526
527 pa_assert_se(u = s->userdata);
528
529 if (u->fd >= 0) {
530 AUDIO_INITINFO(&info);
531
532 info.play.gain = pa_cvolume_max(&s->real_volume) * AUDIO_MAX_GAIN / PA_VOLUME_NORM;
533 assert(info.play.gain <= AUDIO_MAX_GAIN);
534
535 if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0) {
536 if (errno == EINVAL)
537 pa_log("AUDIO_SETINFO: Unsupported volume.");
538 else
539 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
540 }
541 }
542 }
543
544 static void source_get_volume(pa_source *s) {
545 struct userdata *u;
546 audio_info_t info;
547
548 pa_assert_se(u = s->userdata);
549
550 if (u->fd >= 0) {
551 if (ioctl(u->fd, AUDIO_GETINFO, &info) < 0)
552 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
553 else
554 pa_cvolume_set(&s->real_volume, s->sample_spec.channels, info.play.gain * PA_VOLUME_NORM / AUDIO_MAX_GAIN);
555 }
556 }
557
558 static void sink_set_mute(pa_sink *s) {
559 struct userdata *u = s->userdata;
560 audio_info_t info;
561
562 pa_assert(u);
563
564 if (u->fd >= 0) {
565 AUDIO_INITINFO(&info);
566
567 info.output_muted = s->muted;
568
569 if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
570 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
571 }
572 }
573
574 static int sink_get_mute(pa_sink *s, bool *mute) {
575 struct userdata *u = s->userdata;
576 audio_info_t info;
577
578 pa_assert(u);
579
580 if (u->fd < 0)
581 return -1;
582
583 if (ioctl(u->fd, AUDIO_GETINFO, &info) < 0) {
584 pa_log("AUDIO_GETINFO: %s", pa_cstrerror(errno));
585 return -1;
586 }
587
588 *mute = info.output_muted;
589
590 return 0;
591 }
592
593 static void process_rewind(struct userdata *u) {
594 size_t rewind_nbytes;
595
596 pa_assert(u);
597
598 if (!PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
599 pa_sink_process_rewind(u->sink, 0);
600 return;
601 }
602
603 rewind_nbytes = u->sink->thread_info.rewind_nbytes;
604
605 if (rewind_nbytes > 0) {
606 pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
607 rewind_nbytes = PA_MIN(u->memchunk.length, rewind_nbytes);
608 u->memchunk.length -= rewind_nbytes;
609 if (u->memchunk.length <= 0 && u->memchunk.memblock) {
610 pa_memblock_unref(u->memchunk.memblock);
611 pa_memchunk_reset(&u->memchunk);
612 }
613 pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes);
614 }
615
616 pa_sink_process_rewind(u->sink, rewind_nbytes);
617 }
618
619 static void thread_func(void *userdata) {
620 struct userdata *u = userdata;
621 unsigned short revents = 0;
622 int ret, err;
623 audio_info_t info;
624
625 pa_assert(u);
626
627 pa_log_debug("Thread starting up");
628
629 if (u->core->realtime_scheduling)
630 pa_make_realtime(u->core->realtime_priority);
631
632 pa_thread_mq_install(&u->thread_mq);
633
634 pa_smoother_set_time_offset(u->smoother, pa_rtclock_now());
635
636 for (;;) {
637 /* Render some data and write it to the dsp */
638
639 if (PA_UNLIKELY(u->sink->thread_info.rewind_requested))
640 process_rewind(u);
641
642 if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
643 pa_usec_t xtime0, ysleep_interval, xsleep_interval;
644 uint64_t buffered_bytes;
645
646 err = ioctl(u->fd, AUDIO_GETINFO, &info);
647 if (err < 0) {
648 pa_log("AUDIO_GETINFO ioctl failed: %s", pa_cstrerror(errno));
649 goto fail;
650 }
651
652 if (info.play.error) {
653 pa_log_debug("buffer under-run!");
654
655 AUDIO_INITINFO(&info);
656 info.play.error = 0;
657 if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
658 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
659
660 pa_smoother_reset(u->smoother, pa_rtclock_now(), true);
661 }
662
663 for (;;) {
664 void *p;
665 ssize_t w;
666 size_t len;
667 int write_type = 1;
668
669 /*
670 * Since we cannot modify the size of the output buffer we fake it
671 * by not filling it more than u->buffer_size.
672 */
673 xtime0 = pa_rtclock_now();
674 buffered_bytes = get_playback_buffered_bytes(u);
675 if (buffered_bytes >= (uint64_t)u->buffer_size)
676 break;
677
678 len = u->buffer_size - buffered_bytes;
679 len -= len % u->frame_size;
680
681 if (len < (size_t) u->minimum_request)
682 break;
683
684 if (!u->memchunk.length)
685 pa_sink_render(u->sink, u->sink->thread_info.max_request, &u->memchunk);
686
687 len = PA_MIN(u->memchunk.length, len);
688
689 p = pa_memblock_acquire(u->memchunk.memblock);
690 w = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, len, &write_type);
691 pa_memblock_release(u->memchunk.memblock);
692
693 if (w <= 0) {
694 if (errno == EINTR) {
695 continue;
696 } else if (errno == EAGAIN) {
697 /* We may have realtime priority so yield the CPU to ensure that fd can become writable again. */
698 pa_log_debug("EAGAIN with %llu bytes buffered.", buffered_bytes);
699 break;
700 } else {
701 pa_log("Failed to write data to DSP: %s", pa_cstrerror(errno));
702 goto fail;
703 }
704 } else {
705 pa_assert(w % u->frame_size == 0);
706
707 u->written_bytes += w;
708 u->memchunk.index += w;
709 u->memchunk.length -= w;
710 if (u->memchunk.length <= 0) {
711 pa_memblock_unref(u->memchunk.memblock);
712 pa_memchunk_reset(&u->memchunk);
713 }
714 }
715 }
716
717 ysleep_interval = pa_bytes_to_usec(buffered_bytes / 2, &u->sink->sample_spec);
718 xsleep_interval = pa_smoother_translate(u->smoother, xtime0, ysleep_interval);
719 pa_rtpoll_set_timer_absolute(u->rtpoll, xtime0 + PA_MIN(xsleep_interval, ysleep_interval));
720 } else
721 pa_rtpoll_set_timer_disabled(u->rtpoll);
722
723 /* Try to read some data and pass it on to the source driver */
724
725 if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state) && (revents & POLLIN)) {
726 pa_memchunk memchunk;
727 void *p;
728 ssize_t r;
729 size_t len;
730
731 err = ioctl(u->fd, AUDIO_GETINFO, &info);
732 pa_assert(err >= 0);
733
734 if (info.record.error) {
735 pa_log_debug("buffer overflow!");
736
737 AUDIO_INITINFO(&info);
738 info.record.error = 0;
739 if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
740 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
741 }
742
743 err = ioctl(u->fd, I_NREAD, &len);
744 pa_assert(err >= 0);
745
746 if (len > 0) {
747 memchunk.memblock = pa_memblock_new(u->core->mempool, len);
748 pa_assert(memchunk.memblock);
749
750 p = pa_memblock_acquire(memchunk.memblock);
751 r = pa_read(u->fd, p, len, NULL);
752 pa_memblock_release(memchunk.memblock);
753
754 if (r < 0) {
755 pa_memblock_unref(memchunk.memblock);
756 if (errno == EAGAIN)
757 break;
758 else {
759 pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno));
760 goto fail;
761 }
762 } else {
763 u->read_bytes += r;
764
765 memchunk.index = 0;
766 memchunk.length = r;
767
768 pa_source_post(u->source, &memchunk);
769 pa_memblock_unref(memchunk.memblock);
770
771 revents &= ~POLLIN;
772 }
773 }
774 }
775
776 if (u->rtpoll_item) {
777 struct pollfd *pollfd;
778
779 pa_assert(u->fd >= 0);
780
781 pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
782 pollfd->events = (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) ? POLLIN : 0;
783 }
784
785 /* Hmm, nothing to do. Let's sleep */
786 if ((ret = pa_rtpoll_run(u->rtpoll, true)) < 0)
787 goto fail;
788
789 if (ret == 0)
790 goto finish;
791
792 if (u->rtpoll_item) {
793 struct pollfd *pollfd;
794
795 pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
796
797 if (pollfd->revents & ~(POLLOUT|POLLIN)) {
798 pa_log("DSP shutdown.");
799 goto fail;
800 }
801
802 revents = pollfd->revents;
803 } else
804 revents = 0;
805 }
806
807 fail:
808 /* We have to continue processing messages until we receive the
809 * SHUTDOWN message */
810 pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
811 pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
812
813 finish:
814 pa_log_debug("Thread shutting down");
815 }
816
817 static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) {
818 struct userdata *u = userdata;
819
820 assert(u);
821
822 pa_log_debug("caught signal");
823
824 if (u->sink) {
825 pa_sink_get_volume(u->sink, true);
826 pa_sink_get_mute(u->sink, true);
827 }
828
829 if (u->source)
830 pa_source_get_volume(u->source, true);
831 }
832
833 int pa__init(pa_module *m) {
834 struct userdata *u = NULL;
835 bool record = true, playback = true;
836 pa_sample_spec ss;
837 pa_channel_map map;
838 pa_modargs *ma = NULL;
839 uint32_t buffer_length_msec;
840 int fd = -1;
841 pa_sink_new_data sink_new_data;
842 pa_source_new_data source_new_data;
843 char const *name;
844 char *name_buf;
845 bool namereg_fail;
846
847 pa_assert(m);
848
849 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
850 pa_log("failed to parse module arguments.");
851 goto fail;
852 }
853
854 if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
855 pa_log("record= and playback= expect a boolean argument.");
856 goto fail;
857 }
858
859 if (!playback && !record) {
860 pa_log("neither playback nor record enabled for device.");
861 goto fail;
862 }
863
864 u = pa_xnew0(struct userdata, 1);
865
866 if (!(u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC * 2, true, true, 10, pa_rtclock_now(), true)))
867 goto fail;
868
869 /*
870 * For a process (or several processes) to use the same audio device for both
871 * record and playback at the same time, the device's mixer must be enabled.
872 * See mixerctl(1). It may be turned off for playback only or record only.
873 */
874 u->mode = (playback && record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
875
876 ss = m->core->default_sample_spec;
877 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
878 pa_log("failed to parse sample specification");
879 goto fail;
880 }
881 u->frame_size = pa_frame_size(&ss);
882
883 u->minimum_request = pa_usec_to_bytes(PA_USEC_PER_SEC / MAX_RENDER_HZ, &ss);
884
885 buffer_length_msec = 100;
886 if (pa_modargs_get_value_u32(ma, "buffer_length", &buffer_length_msec) < 0) {
887 pa_log("failed to parse buffer_length argument");
888 goto fail;
889 }
890 u->buffer_size = pa_usec_to_bytes(1000 * buffer_length_msec, &ss);
891 if (u->buffer_size < 2 * u->minimum_request) {
892 pa_log("buffer_length argument cannot be smaller than %u",
893 (unsigned)(pa_bytes_to_usec(2 * u->minimum_request, &ss) / 1000));
894 goto fail;
895 }
896 if (u->buffer_size > MAX_BUFFER_SIZE) {
897 pa_log("buffer_length argument cannot be greater than %u",
898 (unsigned)(pa_bytes_to_usec(MAX_BUFFER_SIZE, &ss) / 1000));
899 goto fail;
900 }
901
902 u->device_name = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE));
903
904 if ((fd = open_audio_device(u, &ss)) < 0)
905 goto fail;
906
907 u->core = m->core;
908 u->module = m;
909 m->userdata = u;
910
911 pa_memchunk_reset(&u->memchunk);
912
913 u->rtpoll = pa_rtpoll_new();
914 pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
915
916 u->rtpoll_item = NULL;
917 build_pollfd(u);
918
919 if (u->mode != O_WRONLY) {
920 name_buf = NULL;
921 namereg_fail = true;
922
923 if (!(name = pa_modargs_get_value(ma, "source_name", NULL))) {
924 name = name_buf = pa_sprintf_malloc("solaris_input.%s", pa_path_get_filename(u->device_name));
925 namereg_fail = false;
926 }
927
928 pa_source_new_data_init(&source_new_data);
929 source_new_data.driver = __FILE__;
930 source_new_data.module = m;
931 pa_source_new_data_set_name(&source_new_data, name);
932 source_new_data.namereg_fail = namereg_fail;
933 pa_source_new_data_set_sample_spec(&source_new_data, &ss);
934 pa_source_new_data_set_channel_map(&source_new_data, &map);
935 pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
936 pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_API, "solaris");
937 pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Solaris PCM source");
938 pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_ACCESS_MODE, "serial");
939 pa_proplist_setf(source_new_data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) u->buffer_size);
940
941 if (pa_modargs_get_proplist(ma, "source_properties", source_new_data.proplist, PA_UPDATE_REPLACE) < 0) {
942 pa_log("Invalid properties");
943 pa_source_new_data_done(&source_new_data);
944 goto fail;
945 }
946
947 u->source = pa_source_new(m->core, &source_new_data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
948 pa_source_new_data_done(&source_new_data);
949 pa_xfree(name_buf);
950
951 if (!u->source) {
952 pa_log("Failed to create source object");
953 goto fail;
954 }
955
956 u->source->userdata = u;
957 u->source->parent.process_msg = source_process_msg;
958
959 pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
960 pa_source_set_rtpoll(u->source, u->rtpoll);
961 pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(u->buffer_size, &u->source->sample_spec));
962
963 pa_source_set_get_volume_callback(u->source, source_get_volume);
964 pa_source_set_set_volume_callback(u->source, source_set_volume);
965 u->source->refresh_volume = true;
966 } else
967 u->source = NULL;
968
969 if (u->mode != O_RDONLY) {
970 name_buf = NULL;
971 namereg_fail = true;
972 if (!(name = pa_modargs_get_value(ma, "sink_name", NULL))) {
973 name = name_buf = pa_sprintf_malloc("solaris_output.%s", pa_path_get_filename(u->device_name));
974 namereg_fail = false;
975 }
976
977 pa_sink_new_data_init(&sink_new_data);
978 sink_new_data.driver = __FILE__;
979 sink_new_data.module = m;
980 pa_sink_new_data_set_name(&sink_new_data, name);
981 sink_new_data.namereg_fail = namereg_fail;
982 pa_sink_new_data_set_sample_spec(&sink_new_data, &ss);
983 pa_sink_new_data_set_channel_map(&sink_new_data, &map);
984 pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
985 pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_API, "solaris");
986 pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Solaris PCM sink");
987 pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_ACCESS_MODE, "serial");
988
989 if (pa_modargs_get_proplist(ma, "sink_properties", sink_new_data.proplist, PA_UPDATE_REPLACE) < 0) {
990 pa_log("Invalid properties");
991 pa_sink_new_data_done(&sink_new_data);
992 goto fail;
993 }
994
995 u->sink = pa_sink_new(m->core, &sink_new_data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
996 pa_sink_new_data_done(&sink_new_data);
997
998 pa_assert(u->sink);
999 u->sink->userdata = u;
1000 u->sink->parent.process_msg = sink_process_msg;
1001
1002 pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
1003 pa_sink_set_rtpoll(u->sink, u->rtpoll);
1004 pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->buffer_size, &u->sink->sample_spec));
1005 pa_sink_set_max_request(u->sink, u->buffer_size);
1006 pa_sink_set_max_rewind(u->sink, u->buffer_size);
1007
1008 pa_sink_set_get_volume_callback(u->sink, sink_get_volume);
1009 pa_sink_set_set_volume_callback(u->sink, sink_set_volume);
1010 pa_sink_set_get_mute_callback(u->sink, sink_get_mute);
1011 pa_sink_set_set_mute_callback(u->sink, sink_set_mute);
1012 u->sink->refresh_volume = u->sink->refresh_muted = true;
1013 } else
1014 u->sink = NULL;
1015
1016 pa_assert(u->source || u->sink);
1017
1018 u->sig = pa_signal_new(SIGPOLL, sig_callback, u);
1019 if (u->sig)
1020 ioctl(u->fd, I_SETSIG, S_MSG);
1021 else
1022 pa_log_warn("Could not register SIGPOLL handler");
1023
1024 if (!(u->thread = pa_thread_new("solaris", thread_func, u))) {
1025 pa_log("Failed to create thread.");
1026 goto fail;
1027 }
1028
1029 /* Read mixer settings */
1030 if (u->sink) {
1031 if (sink_new_data.volume_is_set)
1032 u->sink->set_volume(u->sink);
1033 else
1034 u->sink->get_volume(u->sink);
1035
1036 if (sink_new_data.muted_is_set)
1037 u->sink->set_mute(u->sink);
1038 else
1039 u->sink->get_mute(u->sink);
1040
1041 pa_sink_put(u->sink);
1042 }
1043
1044 if (u->source) {
1045 if (source_new_data.volume_is_set)
1046 u->source->set_volume(u->source);
1047 else
1048 u->source->get_volume(u->source);
1049
1050 pa_source_put(u->source);
1051 }
1052
1053 pa_modargs_free(ma);
1054
1055 return 0;
1056
1057 fail:
1058 if (u)
1059 pa__done(m);
1060 else if (fd >= 0)
1061 close(fd);
1062
1063 if (ma)
1064 pa_modargs_free(ma);
1065
1066 return -1;
1067 }
1068
1069 void pa__done(pa_module *m) {
1070 struct userdata *u;
1071
1072 pa_assert(m);
1073
1074 if (!(u = m->userdata))
1075 return;
1076
1077 if (u->sig) {
1078 ioctl(u->fd, I_SETSIG, 0);
1079 pa_signal_free(u->sig);
1080 }
1081
1082 if (u->sink)
1083 pa_sink_unlink(u->sink);
1084
1085 if (u->source)
1086 pa_source_unlink(u->source);
1087
1088 if (u->thread) {
1089 pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
1090 pa_thread_free(u->thread);
1091 }
1092
1093 pa_thread_mq_done(&u->thread_mq);
1094
1095 if (u->sink)
1096 pa_sink_unref(u->sink);
1097
1098 if (u->source)
1099 pa_source_unref(u->source);
1100
1101 if (u->memchunk.memblock)
1102 pa_memblock_unref(u->memchunk.memblock);
1103
1104 if (u->rtpoll_item)
1105 pa_rtpoll_item_free(u->rtpoll_item);
1106
1107 if (u->rtpoll)
1108 pa_rtpoll_free(u->rtpoll);
1109
1110 if (u->fd >= 0)
1111 close(u->fd);
1112
1113 if (u->smoother)
1114 pa_smoother_free(u->smoother);
1115
1116 pa_xfree(u->device_name);
1117
1118 pa_xfree(u);
1119 }