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