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