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