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