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