]> code.delx.au - pulseaudio/blob - src/modules/module-solaris.c
Merge branch 'master' of git://0pointer.de/pulseaudio into dbus-work
[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 = open(u->device_name, u->mode | O_NONBLOCK)) < 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 pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes);
604 }
605
606 pa_sink_process_rewind(u->sink, rewind_nbytes);
607 }
608
609 static void thread_func(void *userdata) {
610 struct userdata *u = userdata;
611 unsigned short revents = 0;
612 int ret, err;
613 audio_info_t info;
614
615 pa_assert(u);
616
617 pa_log_debug("Thread starting up");
618
619 if (u->core->realtime_scheduling)
620 pa_make_realtime(u->core->realtime_priority);
621
622 pa_thread_mq_install(&u->thread_mq);
623
624 pa_smoother_set_time_offset(u->smoother, pa_rtclock_now());
625
626 for (;;) {
627 /* Render some data and write it to the dsp */
628
629 if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
630 pa_usec_t xtime0, ysleep_interval, xsleep_interval;
631 uint64_t buffered_bytes;
632
633 if (u->sink->thread_info.rewind_requested)
634 process_rewind(u);
635
636 err = ioctl(u->fd, AUDIO_GETINFO, &info);
637 if (err < 0) {
638 pa_log("AUDIO_GETINFO ioctl failed: %s", pa_cstrerror(errno));
639 goto fail;
640 }
641
642 if (info.play.error) {
643 pa_log_debug("buffer under-run!");
644
645 AUDIO_INITINFO(&info);
646 info.play.error = 0;
647 if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
648 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
649
650 pa_smoother_reset(u->smoother, pa_rtclock_now(), TRUE);
651 }
652
653 for (;;) {
654 void *p;
655 ssize_t w;
656 size_t len;
657 int write_type = 1;
658
659 /*
660 * Since we cannot modify the size of the output buffer we fake it
661 * by not filling it more than u->buffer_size.
662 */
663 xtime0 = pa_rtclock_now();
664 buffered_bytes = get_playback_buffered_bytes(u);
665 if (buffered_bytes >= (uint64_t)u->buffer_size)
666 break;
667
668 len = u->buffer_size - buffered_bytes;
669 len -= len % u->frame_size;
670
671 if (len < (size_t) u->minimum_request)
672 break;
673
674 if (u->memchunk.length < len)
675 pa_sink_render(u->sink, len - u->memchunk.length, &u->memchunk);
676
677 len = PA_MIN(u->memchunk.length, len);
678
679 p = pa_memblock_acquire(u->memchunk.memblock);
680 w = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, len, &write_type);
681 pa_memblock_release(u->memchunk.memblock);
682
683 if (w <= 0) {
684 if (errno == EINTR) {
685 continue;
686 } else if (errno == EAGAIN) {
687 /* We may have realtime priority so yield the CPU to ensure that fd can become writable again. */
688 pa_log_debug("EAGAIN with %llu bytes buffered.", buffered_bytes);
689 break;
690 } else {
691 pa_log("Failed to write data to DSP: %s", pa_cstrerror(errno));
692 goto fail;
693 }
694 } else {
695 pa_assert(w % u->frame_size == 0);
696
697 u->written_bytes += w;
698 u->memchunk.index += w;
699 u->memchunk.length -= w;
700 if (u->memchunk.length <= 0) {
701 pa_memblock_unref(u->memchunk.memblock);
702 pa_memchunk_reset(&u->memchunk);
703 }
704 }
705 }
706
707 ysleep_interval = pa_bytes_to_usec(buffered_bytes / 2, &u->sink->sample_spec);
708 xsleep_interval = pa_smoother_translate(u->smoother, xtime0, ysleep_interval);
709 pa_rtpoll_set_timer_absolute(u->rtpoll, xtime0 + PA_MIN(xsleep_interval, ysleep_interval));
710 } else
711 pa_rtpoll_set_timer_disabled(u->rtpoll);
712
713 /* Try to read some data and pass it on to the source driver */
714
715 if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state) && (revents & POLLIN)) {
716 pa_memchunk memchunk;
717 void *p;
718 ssize_t r;
719 size_t len;
720
721 err = ioctl(u->fd, AUDIO_GETINFO, &info);
722 pa_assert(err >= 0);
723
724 if (info.record.error) {
725 pa_log_debug("buffer overflow!");
726
727 AUDIO_INITINFO(&info);
728 info.record.error = 0;
729 if (ioctl(u->fd, AUDIO_SETINFO, &info) < 0)
730 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno));
731 }
732
733 err = ioctl(u->fd, I_NREAD, &len);
734 pa_assert(err >= 0);
735
736 if (len > 0) {
737 memchunk.memblock = pa_memblock_new(u->core->mempool, len);
738 pa_assert(memchunk.memblock);
739
740 p = pa_memblock_acquire(memchunk.memblock);
741 r = pa_read(u->fd, p, len, NULL);
742 pa_memblock_release(memchunk.memblock);
743
744 if (r < 0) {
745 pa_memblock_unref(memchunk.memblock);
746 if (errno == EAGAIN)
747 break;
748 else {
749 pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno));
750 goto fail;
751 }
752 } else {
753 u->read_bytes += r;
754
755 memchunk.index = 0;
756 memchunk.length = r;
757
758 pa_source_post(u->source, &memchunk);
759 pa_memblock_unref(memchunk.memblock);
760
761 revents &= ~POLLIN;
762 }
763 }
764 }
765
766 if (u->rtpoll_item) {
767 struct pollfd *pollfd;
768
769 pa_assert(u->fd >= 0);
770
771 pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
772 pollfd->events = (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) ? POLLIN : 0;
773 }
774
775 /* Hmm, nothing to do. Let's sleep */
776 if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
777 goto fail;
778
779 if (ret == 0)
780 goto finish;
781
782 if (u->rtpoll_item) {
783 struct pollfd *pollfd;
784
785 pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
786
787 if (pollfd->revents & ~(POLLOUT|POLLIN)) {
788 pa_log("DSP shutdown.");
789 goto fail;
790 }
791
792 revents = pollfd->revents;
793 } else
794 revents = 0;
795 }
796
797 fail:
798 /* We have to continue processing messages until we receive the
799 * SHUTDOWN message */
800 pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
801 pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
802
803 finish:
804 pa_log_debug("Thread shutting down");
805 }
806
807 static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) {
808 struct userdata *u = userdata;
809
810 assert(u);
811
812 pa_log_debug("caught signal");
813
814 if (u->sink) {
815 pa_sink_get_volume(u->sink, TRUE);
816 pa_sink_get_mute(u->sink, TRUE);
817 }
818
819 if (u->source)
820 pa_source_get_volume(u->source, TRUE);
821 }
822
823 int pa__init(pa_module *m) {
824 struct userdata *u = NULL;
825 pa_bool_t record = TRUE, playback = TRUE;
826 pa_sample_spec ss;
827 pa_channel_map map;
828 pa_modargs *ma = NULL;
829 uint32_t buffer_length_msec;
830 int fd = -1;
831 pa_sink_new_data sink_new_data;
832 pa_source_new_data source_new_data;
833 char const *name;
834 char *name_buf;
835 pa_bool_t namereg_fail;
836
837 pa_assert(m);
838
839 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
840 pa_log("failed to parse module arguments.");
841 goto fail;
842 }
843
844 if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
845 pa_log("record= and playback= expect a boolean argument.");
846 goto fail;
847 }
848
849 if (!playback && !record) {
850 pa_log("neither playback nor record enabled for device.");
851 goto fail;
852 }
853
854 u = pa_xnew0(struct userdata, 1);
855
856 if (!(u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC * 2, TRUE, TRUE, 10, pa_rtclock_now(), TRUE)))
857 goto fail;
858
859 /*
860 * For a process (or several processes) to use the same audio device for both
861 * record and playback at the same time, the device's mixer must be enabled.
862 * See mixerctl(1). It may be turned off for playback only or record only.
863 */
864 u->mode = (playback && record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
865
866 ss = m->core->default_sample_spec;
867 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
868 pa_log("failed to parse sample specification");
869 goto fail;
870 }
871 u->frame_size = pa_frame_size(&ss);
872
873 u->minimum_request = pa_usec_to_bytes(PA_USEC_PER_SEC / MAX_RENDER_HZ, &ss);
874
875 buffer_length_msec = 100;
876 if (pa_modargs_get_value_u32(ma, "buffer_length", &buffer_length_msec) < 0) {
877 pa_log("failed to parse buffer_length argument");
878 goto fail;
879 }
880 u->buffer_size = pa_usec_to_bytes(1000 * buffer_length_msec, &ss);
881 if (u->buffer_size < 2 * u->minimum_request) {
882 pa_log("buffer_length argument cannot be smaller than %u",
883 (unsigned)(pa_bytes_to_usec(2 * u->minimum_request, &ss) / 1000));
884 goto fail;
885 }
886 if (u->buffer_size > MAX_BUFFER_SIZE) {
887 pa_log("buffer_length argument cannot be greater than %u",
888 (unsigned)(pa_bytes_to_usec(MAX_BUFFER_SIZE, &ss) / 1000));
889 goto fail;
890 }
891
892 u->device_name = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE));
893
894 if ((fd = open_audio_device(u, &ss)) < 0)
895 goto fail;
896
897 u->core = m->core;
898 u->module = m;
899 m->userdata = u;
900
901 pa_memchunk_reset(&u->memchunk);
902
903 u->rtpoll = pa_rtpoll_new();
904 pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
905
906 u->rtpoll_item = NULL;
907 build_pollfd(u);
908
909 if (u->mode != O_WRONLY) {
910 name_buf = NULL;
911 namereg_fail = TRUE;
912
913 if (!(name = pa_modargs_get_value(ma, "source_name", NULL))) {
914 name = name_buf = pa_sprintf_malloc("solaris_input.%s", pa_path_get_filename(u->device_name));
915 namereg_fail = FALSE;
916 }
917
918 pa_source_new_data_init(&source_new_data);
919 source_new_data.driver = __FILE__;
920 source_new_data.module = m;
921 pa_source_new_data_set_name(&source_new_data, name);
922 source_new_data.namereg_fail = namereg_fail;
923 pa_source_new_data_set_sample_spec(&source_new_data, &ss);
924 pa_source_new_data_set_channel_map(&source_new_data, &map);
925 pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
926 pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_API, "solaris");
927 pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Solaris PCM source");
928 pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_ACCESS_MODE, "serial");
929 pa_proplist_setf(source_new_data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) u->buffer_size);
930
931 if (pa_modargs_get_proplist(ma, "source_properties", source_new_data.proplist, PA_UPDATE_REPLACE) < 0) {
932 pa_log("Invalid properties");
933 pa_source_new_data_done(&source_new_data);
934 goto fail;
935 }
936
937 u->source = pa_source_new(m->core, &source_new_data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL);
938 pa_source_new_data_done(&source_new_data);
939 pa_xfree(name_buf);
940
941 if (!u->source) {
942 pa_log("Failed to create source object");
943 goto fail;
944 }
945
946 u->source->userdata = u;
947 u->source->parent.process_msg = source_process_msg;
948
949 pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
950 pa_source_set_rtpoll(u->source, u->rtpoll);
951 pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(u->buffer_size, &u->source->sample_spec));
952
953 u->source->get_volume = source_get_volume;
954 u->source->set_volume = source_set_volume;
955 u->source->refresh_volume = TRUE;
956 } else
957 u->source = NULL;
958
959 if (u->mode != O_RDONLY) {
960 name_buf = NULL;
961 namereg_fail = TRUE;
962 if (!(name = pa_modargs_get_value(ma, "sink_name", NULL))) {
963 name = name_buf = pa_sprintf_malloc("solaris_output.%s", pa_path_get_filename(u->device_name));
964 namereg_fail = FALSE;
965 }
966
967 pa_sink_new_data_init(&sink_new_data);
968 sink_new_data.driver = __FILE__;
969 sink_new_data.module = m;
970 pa_sink_new_data_set_name(&sink_new_data, name);
971 sink_new_data.namereg_fail = namereg_fail;
972 pa_sink_new_data_set_sample_spec(&sink_new_data, &ss);
973 pa_sink_new_data_set_channel_map(&sink_new_data, &map);
974 pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
975 pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_API, "solaris");
976 pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Solaris PCM sink");
977 pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_ACCESS_MODE, "serial");
978
979 if (pa_modargs_get_proplist(ma, "sink_properties", sink_new_data.proplist, PA_UPDATE_REPLACE) < 0) {
980 pa_log("Invalid properties");
981 pa_sink_new_data_done(&sink_new_data);
982 goto fail;
983 }
984
985 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);
986 pa_sink_new_data_done(&sink_new_data);
987
988 pa_assert(u->sink);
989 u->sink->userdata = u;
990 u->sink->parent.process_msg = sink_process_msg;
991
992 pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
993 pa_sink_set_rtpoll(u->sink, u->rtpoll);
994 pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->buffer_size, &u->sink->sample_spec));
995 pa_sink_set_max_request(u->sink, u->buffer_size);
996 pa_sink_set_max_rewind(u->sink, u->buffer_size);
997
998 u->sink->get_volume = sink_get_volume;
999 u->sink->set_volume = sink_set_volume;
1000 u->sink->get_mute = sink_get_mute;
1001 u->sink->set_mute = sink_set_mute;
1002 u->sink->refresh_volume = u->sink->refresh_muted = TRUE;
1003 } else
1004 u->sink = NULL;
1005
1006 pa_assert(u->source || u->sink);
1007
1008 u->sig = pa_signal_new(SIGPOLL, sig_callback, u);
1009 if (u->sig)
1010 ioctl(u->fd, I_SETSIG, S_MSG);
1011 else
1012 pa_log_warn("Could not register SIGPOLL handler");
1013
1014 if (!(u->thread = pa_thread_new(thread_func, u))) {
1015 pa_log("Failed to create thread.");
1016 goto fail;
1017 }
1018
1019 /* Read mixer settings */
1020 if (u->sink) {
1021 if (sink_new_data.volume_is_set)
1022 u->sink->set_volume(u->sink);
1023 else
1024 u->sink->get_volume(u->sink);
1025
1026 if (sink_new_data.muted_is_set)
1027 u->sink->set_mute(u->sink);
1028 else
1029 u->sink->get_mute(u->sink);
1030
1031 pa_sink_put(u->sink);
1032 }
1033
1034 if (u->source) {
1035 if (source_new_data.volume_is_set)
1036 u->source->set_volume(u->source);
1037 else
1038 u->source->get_volume(u->source);
1039
1040 pa_source_put(u->source);
1041 }
1042
1043 pa_modargs_free(ma);
1044
1045 return 0;
1046
1047 fail:
1048 if (u)
1049 pa__done(m);
1050 else if (fd >= 0)
1051 close(fd);
1052
1053 if (ma)
1054 pa_modargs_free(ma);
1055
1056 return -1;
1057 }
1058
1059 void pa__done(pa_module *m) {
1060 struct userdata *u;
1061
1062 pa_assert(m);
1063
1064 if (!(u = m->userdata))
1065 return;
1066
1067 if (u->sig) {
1068 ioctl(u->fd, I_SETSIG, 0);
1069 pa_signal_free(u->sig);
1070 }
1071
1072 if (u->sink)
1073 pa_sink_unlink(u->sink);
1074
1075 if (u->source)
1076 pa_source_unlink(u->source);
1077
1078 if (u->thread) {
1079 pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
1080 pa_thread_free(u->thread);
1081 }
1082
1083 pa_thread_mq_done(&u->thread_mq);
1084
1085 if (u->sink)
1086 pa_sink_unref(u->sink);
1087
1088 if (u->source)
1089 pa_source_unref(u->source);
1090
1091 if (u->memchunk.memblock)
1092 pa_memblock_unref(u->memchunk.memblock);
1093
1094 if (u->rtpoll_item)
1095 pa_rtpoll_item_free(u->rtpoll_item);
1096
1097 if (u->rtpoll)
1098 pa_rtpoll_free(u->rtpoll);
1099
1100 if (u->fd >= 0)
1101 close(u->fd);
1102
1103 if (u->smoother)
1104 pa_smoother_free(u->smoother);
1105
1106 pa_xfree(u->device_name);
1107
1108 pa_xfree(u);
1109 }