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