2 This file is part of PulseAudio.
4 Copyright 2006 Lennart Poettering
5 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 Copyright 2009 Finn Thain
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.
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.
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
35 #include <sys/ioctl.h>
37 #include <sys/types.h>
42 #include <sys/audio.h>
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>
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 #include <pulsecore/time-smoother.h>
65 #include "module-solaris-symdef.h"
67 PA_MODULE_AUTHOR("Pierre Ossman");
68 PA_MODULE_DESCRIPTION("Solaris Sink/Source");
69 PA_MODULE_VERSION(PACKAGE_VERSION
);
71 "sink_name=<name for the sink> "
72 "sink_properties=<properties for the sink> "
73 "source_name=<name for the source> "
74 "source_properties=<properties for the source> "
75 "device=<audio device file name> "
76 "record=<enable source?> "
77 "playback=<enable sink?> "
78 "format=<sample format> "
79 "channels=<number of channels> "
81 "buffer_length=<milliseconds> "
82 "channel_map=<channel map>");
83 PA_MODULE_LOAD_ONCE(FALSE
);
91 pa_thread_mq thread_mq
;
100 uint64_t written_bytes
, read_bytes
;
105 pa_rtpoll_item
*rtpoll_item
;
108 pa_bool_t sink_suspended
, source_suspended
;
110 uint32_t play_samples_msw
, record_samples_msw
;
111 uint32_t prev_playback_samples
, prev_record_samples
;
113 int32_t minimum_request
;
115 pa_smoother
*smoother
;
118 static const char* const valid_modargs
[] = {
134 #define DEFAULT_DEVICE "/dev/audio"
136 #define MAX_RENDER_HZ (300)
137 /* This render rate limit imposes a minimum latency, but without it we waste too much CPU time. */
139 #define MAX_BUFFER_SIZE (128 * 1024)
140 /* An attempt to buffer more than 128 KB causes write() to fail with errno == EAGAIN. */
142 static uint64_t get_playback_buffered_bytes(struct userdata
*u
) {
144 uint64_t played_bytes
;
149 err
= ioctl(u
->fd
, AUDIO_GETINFO
, &info
);
152 /* Handle wrap-around of the device's sample counter, which is a uint_32. */
153 if (u
->prev_playback_samples
> info
.play
.samples
) {
155 * Unfortunately info.play.samples can sometimes go backwards, even before it wraps!
156 * The bug seems to be absent on Solaris x86 nv117 with audio810 driver, at least on this (UP) machine.
157 * The bug is present on a different (SMP) machine running Solaris x86 nv103 with audioens driver.
158 * An earlier revision of this file mentions the same bug independently (unknown configuration).
160 if (u
->prev_playback_samples
+ info
.play
.samples
< 240000) {
161 ++u
->play_samples_msw
;
163 pa_log_debug("play.samples went backwards %d bytes", u
->prev_playback_samples
- info
.play
.samples
);
166 u
->prev_playback_samples
= info
.play
.samples
;
167 played_bytes
= (((uint64_t)u
->play_samples_msw
<< 32) + info
.play
.samples
) * u
->frame_size
;
169 pa_smoother_put(u
->smoother
, pa_rtclock_now(), pa_bytes_to_usec(played_bytes
, &u
->sink
->sample_spec
));
171 return u
->written_bytes
- played_bytes
;
174 static pa_usec_t
sink_get_latency(struct userdata
*u
, pa_sample_spec
*ss
) {
181 r
= pa_bytes_to_usec(get_playback_buffered_bytes(u
), ss
);
182 if (u
->memchunk
.memblock
)
183 r
+= pa_bytes_to_usec(u
->memchunk
.length
, ss
);
188 static uint64_t get_recorded_bytes(struct userdata
*u
) {
193 pa_assert(u
->source
);
195 err
= ioctl(u
->fd
, AUDIO_GETINFO
, &info
);
198 if (u
->prev_record_samples
> info
.record
.samples
)
199 ++u
->record_samples_msw
;
200 u
->prev_record_samples
= info
.record
.samples
;
201 result
= (((uint64_t)u
->record_samples_msw
<< 32) + info
.record
.samples
) * u
->frame_size
;
206 static pa_usec_t
source_get_latency(struct userdata
*u
, pa_sample_spec
*ss
) {
214 int err
= ioctl(u
->fd
, AUDIO_GETINFO
, &info
);
217 r
= pa_bytes_to_usec(get_recorded_bytes(u
), ss
) - pa_bytes_to_usec(u
->read_bytes
, ss
);
222 static void build_pollfd(struct userdata
*u
) {
223 struct pollfd
*pollfd
;
226 pa_assert(!u
->rtpoll_item
);
227 u
->rtpoll_item
= pa_rtpoll_item_new(u
->rtpoll
, PA_RTPOLL_NEVER
, 1);
229 pollfd
= pa_rtpoll_item_get_pollfd(u
->rtpoll_item
, NULL
);
235 static int set_buffer(int fd
, int buffer_size
) {
240 AUDIO_INITINFO(&info
);
241 info
.play
.buffer_size
= buffer_size
;
242 info
.record
.buffer_size
= buffer_size
;
244 if (ioctl(fd
, AUDIO_SETINFO
, &info
) < 0) {
246 pa_log("AUDIO_SETINFO: Unsupported buffer size.");
248 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
255 static int auto_format(int fd
, int mode
, pa_sample_spec
*ss
) {
261 AUDIO_INITINFO(&info
);
263 if (mode
!= O_RDONLY
) {
264 info
.play
.sample_rate
= ss
->rate
;
265 info
.play
.channels
= ss
->channels
;
266 switch (ss
->format
) {
268 info
.play
.precision
= 8;
269 info
.play
.encoding
= AUDIO_ENCODING_LINEAR
;
272 info
.play
.precision
= 8;
273 info
.play
.encoding
= AUDIO_ENCODING_ALAW
;
276 info
.play
.precision
= 8;
277 info
.play
.encoding
= AUDIO_ENCODING_ULAW
;
279 case PA_SAMPLE_S16NE
:
280 info
.play
.precision
= 16;
281 info
.play
.encoding
= AUDIO_ENCODING_LINEAR
;
284 pa_log("AUDIO_SETINFO: Unsupported sample format.");
289 if (mode
!= O_WRONLY
) {
290 info
.record
.sample_rate
= ss
->rate
;
291 info
.record
.channels
= ss
->channels
;
292 switch (ss
->format
) {
294 info
.record
.precision
= 8;
295 info
.record
.encoding
= AUDIO_ENCODING_LINEAR
;
298 info
.record
.precision
= 8;
299 info
.record
.encoding
= AUDIO_ENCODING_ALAW
;
302 info
.record
.precision
= 8;
303 info
.record
.encoding
= AUDIO_ENCODING_ULAW
;
305 case PA_SAMPLE_S16NE
:
306 info
.record
.precision
= 16;
307 info
.record
.encoding
= AUDIO_ENCODING_LINEAR
;
310 pa_log("AUDIO_SETINFO: Unsupported sample format.");
315 if (ioctl(fd
, AUDIO_SETINFO
, &info
) < 0) {
317 pa_log("AUDIO_SETINFO: Failed to set sample format.");
319 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
326 static int open_audio_device(struct userdata
*u
, pa_sample_spec
*ss
) {
330 if ((u
->fd
= open(u
->device_name
, u
->mode
| O_NONBLOCK
)) < 0) {
331 pa_log_warn("open %s failed (%s)", u
->device_name
, pa_cstrerror(errno
));
335 pa_log_info("device opened in %s mode.", u
->mode
== O_WRONLY
? "O_WRONLY" : (u
->mode
== O_RDONLY
? "O_RDONLY" : "O_RDWR"));
337 if (auto_format(u
->fd
, u
->mode
, ss
) < 0)
340 if (set_buffer(u
->fd
, u
->buffer_size
) < 0)
343 u
->written_bytes
= u
->read_bytes
= 0;
344 u
->play_samples_msw
= u
->record_samples_msw
= 0;
345 u
->prev_playback_samples
= u
->prev_record_samples
= 0;
350 static int suspend(struct userdata
*u
) {
352 pa_assert(u
->fd
>= 0);
354 pa_log_info("Suspending...");
356 ioctl(u
->fd
, AUDIO_DRAIN
, NULL
);
360 if (u
->rtpoll_item
) {
361 pa_rtpoll_item_free(u
->rtpoll_item
);
362 u
->rtpoll_item
= NULL
;
365 pa_log_info("Device suspended.");
370 static int unsuspend(struct userdata
*u
) {
372 pa_assert(u
->fd
< 0);
374 pa_log_info("Resuming...");
376 if (open_audio_device(u
, u
->sink
? &u
->sink
->sample_spec
: &u
->source
->sample_spec
) < 0)
381 pa_log_info("Device resumed.");
386 static int sink_process_msg(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
387 struct userdata
*u
= PA_SINK(o
)->userdata
;
391 case PA_SINK_MESSAGE_GET_LATENCY
:
392 *((pa_usec_t
*) data
) = sink_get_latency(u
, &PA_SINK(o
)->sample_spec
);
395 case PA_SINK_MESSAGE_SET_STATE
:
397 switch ((pa_sink_state_t
) PA_PTR_TO_UINT(data
)) {
399 case PA_SINK_SUSPENDED
:
401 pa_assert(PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
));
403 pa_smoother_pause(u
->smoother
, pa_rtclock_now());
405 if (!u
->source
|| u
->source_suspended
) {
409 u
->sink_suspended
= TRUE
;
413 case PA_SINK_RUNNING
:
415 if (u
->sink
->thread_info
.state
== PA_SINK_SUSPENDED
) {
416 pa_smoother_resume(u
->smoother
, pa_rtclock_now(), TRUE
);
418 if (!u
->source
|| u
->source_suspended
) {
419 if (unsuspend(u
) < 0)
421 u
->sink
->get_volume(u
->sink
);
422 u
->sink
->get_mute(u
->sink
);
424 u
->sink_suspended
= FALSE
;
428 case PA_SINK_INVALID_STATE
:
429 case PA_SINK_UNLINKED
:
437 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
440 static int source_process_msg(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
441 struct userdata
*u
= PA_SOURCE(o
)->userdata
;
445 case PA_SOURCE_MESSAGE_GET_LATENCY
:
446 *((pa_usec_t
*) data
) = source_get_latency(u
, &PA_SOURCE(o
)->sample_spec
);
449 case PA_SOURCE_MESSAGE_SET_STATE
:
451 switch ((pa_source_state_t
) PA_PTR_TO_UINT(data
)) {
453 case PA_SOURCE_SUSPENDED
:
455 pa_assert(PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
));
457 if (!u
->sink
|| u
->sink_suspended
) {
461 u
->source_suspended
= TRUE
;
465 case PA_SOURCE_RUNNING
:
467 if (u
->source
->thread_info
.state
== PA_SOURCE_SUSPENDED
) {
468 if (!u
->sink
|| u
->sink_suspended
) {
469 if (unsuspend(u
) < 0)
471 u
->source
->get_volume(u
->source
);
473 u
->source_suspended
= FALSE
;
477 case PA_SOURCE_UNLINKED
:
479 case PA_SOURCE_INVALID_STATE
:
487 return pa_source_process_msg(o
, code
, data
, offset
, chunk
);
490 static void sink_set_volume(pa_sink
*s
) {
494 pa_assert_se(u
= s
->userdata
);
497 AUDIO_INITINFO(&info
);
499 info
.play
.gain
= pa_cvolume_max(&s
->real_volume
) * AUDIO_MAX_GAIN
/ PA_VOLUME_NORM
;
500 assert(info
.play
.gain
<= AUDIO_MAX_GAIN
);
502 if (ioctl(u
->fd
, AUDIO_SETINFO
, &info
) < 0) {
504 pa_log("AUDIO_SETINFO: Unsupported volume.");
506 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
511 static void sink_get_volume(pa_sink
*s
) {
515 pa_assert_se(u
= s
->userdata
);
518 if (ioctl(u
->fd
, AUDIO_GETINFO
, &info
) < 0)
519 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
521 pa_cvolume_set(&s
->real_volume
, s
->sample_spec
.channels
, info
.play
.gain
* PA_VOLUME_NORM
/ AUDIO_MAX_GAIN
);
525 static void source_set_volume(pa_source
*s
) {
529 pa_assert_se(u
= s
->userdata
);
532 AUDIO_INITINFO(&info
);
534 info
.play
.gain
= pa_cvolume_max(&s
->volume
) * AUDIO_MAX_GAIN
/ PA_VOLUME_NORM
;
535 assert(info
.play
.gain
<= AUDIO_MAX_GAIN
);
537 if (ioctl(u
->fd
, AUDIO_SETINFO
, &info
) < 0) {
539 pa_log("AUDIO_SETINFO: Unsupported volume.");
541 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
546 static void source_get_volume(pa_source
*s
) {
550 pa_assert_se(u
= s
->userdata
);
553 if (ioctl(u
->fd
, AUDIO_GETINFO
, &info
) < 0)
554 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
556 pa_cvolume_set(&s
->volume
, s
->sample_spec
.channels
, info
.play
.gain
* PA_VOLUME_NORM
/ AUDIO_MAX_GAIN
);
560 static void sink_set_mute(pa_sink
*s
) {
561 struct userdata
*u
= s
->userdata
;
567 AUDIO_INITINFO(&info
);
569 info
.output_muted
= !!s
->muted
;
571 if (ioctl(u
->fd
, AUDIO_SETINFO
, &info
) < 0)
572 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
576 static void sink_get_mute(pa_sink
*s
) {
577 struct userdata
*u
= s
->userdata
;
583 if (ioctl(u
->fd
, AUDIO_GETINFO
, &info
) < 0)
584 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
586 s
->muted
= !!info
.output_muted
;
590 static void process_rewind(struct userdata
*u
) {
591 size_t rewind_nbytes
;
595 /* Figure out how much we shall rewind and reset the counter */
596 rewind_nbytes
= u
->sink
->thread_info
.rewind_nbytes
;
597 u
->sink
->thread_info
.rewind_nbytes
= 0;
599 if (rewind_nbytes
> 0) {
600 pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes
);
601 rewind_nbytes
= PA_MIN(u
->memchunk
.length
, rewind_nbytes
);
602 u
->memchunk
.length
-= rewind_nbytes
;
603 pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes
);
606 pa_sink_process_rewind(u
->sink
, rewind_nbytes
);
609 static void thread_func(void *userdata
) {
610 struct userdata
*u
= userdata
;
611 unsigned short revents
= 0;
617 pa_log_debug("Thread starting up");
619 if (u
->core
->realtime_scheduling
)
620 pa_make_realtime(u
->core
->realtime_priority
);
622 pa_thread_mq_install(&u
->thread_mq
);
624 pa_smoother_set_time_offset(u
->smoother
, pa_rtclock_now());
627 /* Render some data and write it to the dsp */
629 if (u
->sink
&& PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
)) {
630 pa_usec_t xtime0
, ysleep_interval
, xsleep_interval
;
631 uint64_t buffered_bytes
;
633 if (u
->sink
->thread_info
.rewind_requested
)
636 err
= ioctl(u
->fd
, AUDIO_GETINFO
, &info
);
638 pa_log("AUDIO_GETINFO ioctl failed: %s", pa_cstrerror(errno
));
642 if (info
.play
.error
) {
643 pa_log_debug("buffer under-run!");
645 AUDIO_INITINFO(&info
);
647 if (ioctl(u
->fd
, AUDIO_SETINFO
, &info
) < 0)
648 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
650 pa_smoother_reset(u
->smoother
, pa_rtclock_now(), TRUE
);
660 * Since we cannot modify the size of the output buffer we fake it
661 * by not filling it more than u->buffer_size.
663 xtime0
= pa_rtclock_now();
664 buffered_bytes
= get_playback_buffered_bytes(u
);
665 if (buffered_bytes
>= (uint64_t)u
->buffer_size
)
668 len
= u
->buffer_size
- buffered_bytes
;
669 len
-= len
% u
->frame_size
;
671 if (len
< (size_t) u
->minimum_request
)
674 if (u
->memchunk
.length
< len
)
675 pa_sink_render(u
->sink
, len
- u
->memchunk
.length
, &u
->memchunk
);
677 len
= PA_MIN(u
->memchunk
.length
, len
);
679 p
= pa_memblock_acquire(u
->memchunk
.memblock
);
680 w
= pa_write(u
->fd
, (uint8_t*) p
+ u
->memchunk
.index
, len
, &write_type
);
681 pa_memblock_release(u
->memchunk
.memblock
);
684 if (errno
== EINTR
) {
686 } else if (errno
== EAGAIN
) {
687 /* We may have realtime priority so yield the CPU to ensure that fd can become writable again. */
688 pa_log_debug("EAGAIN with %llu bytes buffered.", buffered_bytes
);
691 pa_log("Failed to write data to DSP: %s", pa_cstrerror(errno
));
695 pa_assert(w
% u
->frame_size
== 0);
697 u
->written_bytes
+= w
;
698 u
->memchunk
.index
+= w
;
699 u
->memchunk
.length
-= w
;
700 if (u
->memchunk
.length
<= 0) {
701 pa_memblock_unref(u
->memchunk
.memblock
);
702 pa_memchunk_reset(&u
->memchunk
);
707 ysleep_interval
= pa_bytes_to_usec(buffered_bytes
/ 2, &u
->sink
->sample_spec
);
708 xsleep_interval
= pa_smoother_translate(u
->smoother
, xtime0
, ysleep_interval
);
709 pa_rtpoll_set_timer_absolute(u
->rtpoll
, xtime0
+ PA_MIN(xsleep_interval
, ysleep_interval
));
711 pa_rtpoll_set_timer_disabled(u
->rtpoll
);
713 /* Try to read some data and pass it on to the source driver */
715 if (u
->source
&& PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
) && (revents
& POLLIN
)) {
716 pa_memchunk memchunk
;
721 err
= ioctl(u
->fd
, AUDIO_GETINFO
, &info
);
724 if (info
.record
.error
) {
725 pa_log_debug("buffer overflow!");
727 AUDIO_INITINFO(&info
);
728 info
.record
.error
= 0;
729 if (ioctl(u
->fd
, AUDIO_SETINFO
, &info
) < 0)
730 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
733 err
= ioctl(u
->fd
, I_NREAD
, &len
);
737 memchunk
.memblock
= pa_memblock_new(u
->core
->mempool
, len
);
738 pa_assert(memchunk
.memblock
);
740 p
= pa_memblock_acquire(memchunk
.memblock
);
741 r
= pa_read(u
->fd
, p
, len
, NULL
);
742 pa_memblock_release(memchunk
.memblock
);
745 pa_memblock_unref(memchunk
.memblock
);
749 pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno
));
758 pa_source_post(u
->source
, &memchunk
);
759 pa_memblock_unref(memchunk
.memblock
);
766 if (u
->rtpoll_item
) {
767 struct pollfd
*pollfd
;
769 pa_assert(u
->fd
>= 0);
771 pollfd
= pa_rtpoll_item_get_pollfd(u
->rtpoll_item
, NULL
);
772 pollfd
->events
= (u
->source
&& PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
)) ? POLLIN
: 0;
775 /* Hmm, nothing to do. Let's sleep */
776 if ((ret
= pa_rtpoll_run(u
->rtpoll
, TRUE
)) < 0)
782 if (u
->rtpoll_item
) {
783 struct pollfd
*pollfd
;
785 pollfd
= pa_rtpoll_item_get_pollfd(u
->rtpoll_item
, NULL
);
787 if (pollfd
->revents
& ~(POLLOUT
|POLLIN
)) {
788 pa_log("DSP shutdown.");
792 revents
= pollfd
->revents
;
798 /* We have to continue processing messages until we receive the
799 * SHUTDOWN message */
800 pa_asyncmsgq_post(u
->thread_mq
.outq
, PA_MSGOBJECT(u
->core
), PA_CORE_MESSAGE_UNLOAD_MODULE
, u
->module
, 0, NULL
, NULL
);
801 pa_asyncmsgq_wait_for(u
->thread_mq
.inq
, PA_MESSAGE_SHUTDOWN
);
804 pa_log_debug("Thread shutting down");
807 static void sig_callback(pa_mainloop_api
*api
, pa_signal_event
*e
, int sig
, void *userdata
) {
808 struct userdata
*u
= userdata
;
812 pa_log_debug("caught signal");
815 pa_sink_get_volume(u
->sink
, TRUE
);
816 pa_sink_get_mute(u
->sink
, TRUE
);
820 pa_source_get_volume(u
->source
, TRUE
);
823 int pa__init(pa_module
*m
) {
824 struct userdata
*u
= NULL
;
825 pa_bool_t record
= TRUE
, playback
= TRUE
;
828 pa_modargs
*ma
= NULL
;
829 uint32_t buffer_length_msec
;
831 pa_sink_new_data sink_new_data
;
832 pa_source_new_data source_new_data
;
835 pa_bool_t namereg_fail
;
839 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
840 pa_log("failed to parse module arguments.");
844 if (pa_modargs_get_value_boolean(ma
, "record", &record
) < 0 || pa_modargs_get_value_boolean(ma
, "playback", &playback
) < 0) {
845 pa_log("record= and playback= expect a boolean argument.");
849 if (!playback
&& !record
) {
850 pa_log("neither playback nor record enabled for device.");
854 u
= pa_xnew0(struct userdata
, 1);
856 if (!(u
->smoother
= pa_smoother_new(PA_USEC_PER_SEC
, PA_USEC_PER_SEC
* 2, TRUE
, TRUE
, 10, pa_rtclock_now(), TRUE
)))
860 * For a process (or several processes) to use the same audio device for both
861 * record and playback at the same time, the device's mixer must be enabled.
862 * See mixerctl(1). It may be turned off for playback only or record only.
864 u
->mode
= (playback
&& record
) ? O_RDWR
: (playback
? O_WRONLY
: (record
? O_RDONLY
: 0));
866 ss
= m
->core
->default_sample_spec
;
867 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
868 pa_log("failed to parse sample specification");
871 u
->frame_size
= pa_frame_size(&ss
);
873 u
->minimum_request
= pa_usec_to_bytes(PA_USEC_PER_SEC
/ MAX_RENDER_HZ
, &ss
);
875 buffer_length_msec
= 100;
876 if (pa_modargs_get_value_u32(ma
, "buffer_length", &buffer_length_msec
) < 0) {
877 pa_log("failed to parse buffer_length argument");
880 u
->buffer_size
= pa_usec_to_bytes(1000 * buffer_length_msec
, &ss
);
881 if (u
->buffer_size
< 2 * u
->minimum_request
) {
882 pa_log("buffer_length argument cannot be smaller than %u",
883 (unsigned)(pa_bytes_to_usec(2 * u
->minimum_request
, &ss
) / 1000));
886 if (u
->buffer_size
> MAX_BUFFER_SIZE
) {
887 pa_log("buffer_length argument cannot be greater than %u",
888 (unsigned)(pa_bytes_to_usec(MAX_BUFFER_SIZE
, &ss
) / 1000));
892 u
->device_name
= pa_xstrdup(pa_modargs_get_value(ma
, "device", DEFAULT_DEVICE
));
894 if ((fd
= open_audio_device(u
, &ss
)) < 0)
901 pa_memchunk_reset(&u
->memchunk
);
903 u
->rtpoll
= pa_rtpoll_new();
904 pa_thread_mq_init(&u
->thread_mq
, m
->core
->mainloop
, u
->rtpoll
);
906 u
->rtpoll_item
= NULL
;
909 if (u
->mode
!= O_WRONLY
) {
913 if (!(name
= pa_modargs_get_value(ma
, "source_name", NULL
))) {
914 name
= name_buf
= pa_sprintf_malloc("solaris_input.%s", pa_path_get_filename(u
->device_name
));
915 namereg_fail
= FALSE
;
918 pa_source_new_data_init(&source_new_data
);
919 source_new_data
.driver
= __FILE__
;
920 source_new_data
.module
= m
;
921 pa_source_new_data_set_name(&source_new_data
, name
);
922 source_new_data
.namereg_fail
= namereg_fail
;
923 pa_source_new_data_set_sample_spec(&source_new_data
, &ss
);
924 pa_source_new_data_set_channel_map(&source_new_data
, &map
);
925 pa_proplist_sets(source_new_data
.proplist
, PA_PROP_DEVICE_STRING
, u
->device_name
);
926 pa_proplist_sets(source_new_data
.proplist
, PA_PROP_DEVICE_API
, "solaris");
927 pa_proplist_sets(source_new_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "Solaris PCM source");
928 pa_proplist_sets(source_new_data
.proplist
, PA_PROP_DEVICE_ACCESS_MODE
, "serial");
929 pa_proplist_setf(source_new_data
.proplist
, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE
, "%lu", (unsigned long) u
->buffer_size
);
931 if (pa_modargs_get_proplist(ma
, "source_properties", source_new_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
932 pa_log("Invalid properties");
933 pa_source_new_data_done(&source_new_data
);
937 u
->source
= pa_source_new(m
->core
, &source_new_data
, PA_SOURCE_HARDWARE
|PA_SOURCE_LATENCY
|PA_SOURCE_HW_VOLUME_CTRL
);
938 pa_source_new_data_done(&source_new_data
);
942 pa_log("Failed to create source object");
946 u
->source
->userdata
= u
;
947 u
->source
->parent
.process_msg
= source_process_msg
;
949 pa_source_set_asyncmsgq(u
->source
, u
->thread_mq
.inq
);
950 pa_source_set_rtpoll(u
->source
, u
->rtpoll
);
951 pa_source_set_fixed_latency(u
->source
, pa_bytes_to_usec(u
->buffer_size
, &u
->source
->sample_spec
));
953 u
->source
->get_volume
= source_get_volume
;
954 u
->source
->set_volume
= source_set_volume
;
955 u
->source
->refresh_volume
= TRUE
;
959 if (u
->mode
!= O_RDONLY
) {
962 if (!(name
= pa_modargs_get_value(ma
, "sink_name", NULL
))) {
963 name
= name_buf
= pa_sprintf_malloc("solaris_output.%s", pa_path_get_filename(u
->device_name
));
964 namereg_fail
= FALSE
;
967 pa_sink_new_data_init(&sink_new_data
);
968 sink_new_data
.driver
= __FILE__
;
969 sink_new_data
.module
= m
;
970 pa_sink_new_data_set_name(&sink_new_data
, name
);
971 sink_new_data
.namereg_fail
= namereg_fail
;
972 pa_sink_new_data_set_sample_spec(&sink_new_data
, &ss
);
973 pa_sink_new_data_set_channel_map(&sink_new_data
, &map
);
974 pa_proplist_sets(sink_new_data
.proplist
, PA_PROP_DEVICE_STRING
, u
->device_name
);
975 pa_proplist_sets(sink_new_data
.proplist
, PA_PROP_DEVICE_API
, "solaris");
976 pa_proplist_sets(sink_new_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "Solaris PCM sink");
977 pa_proplist_sets(sink_new_data
.proplist
, PA_PROP_DEVICE_ACCESS_MODE
, "serial");
979 if (pa_modargs_get_proplist(ma
, "sink_properties", sink_new_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
980 pa_log("Invalid properties");
981 pa_sink_new_data_done(&sink_new_data
);
985 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
);
986 pa_sink_new_data_done(&sink_new_data
);
989 u
->sink
->userdata
= u
;
990 u
->sink
->parent
.process_msg
= sink_process_msg
;
992 pa_sink_set_asyncmsgq(u
->sink
, u
->thread_mq
.inq
);
993 pa_sink_set_rtpoll(u
->sink
, u
->rtpoll
);
994 pa_sink_set_fixed_latency(u
->sink
, pa_bytes_to_usec(u
->buffer_size
, &u
->sink
->sample_spec
));
995 pa_sink_set_max_request(u
->sink
, u
->buffer_size
);
996 pa_sink_set_max_rewind(u
->sink
, u
->buffer_size
);
998 u
->sink
->get_volume
= sink_get_volume
;
999 u
->sink
->set_volume
= sink_set_volume
;
1000 u
->sink
->get_mute
= sink_get_mute
;
1001 u
->sink
->set_mute
= sink_set_mute
;
1002 u
->sink
->refresh_volume
= u
->sink
->refresh_muted
= TRUE
;
1006 pa_assert(u
->source
|| u
->sink
);
1008 u
->sig
= pa_signal_new(SIGPOLL
, sig_callback
, u
);
1010 ioctl(u
->fd
, I_SETSIG
, S_MSG
);
1012 pa_log_warn("Could not register SIGPOLL handler");
1014 if (!(u
->thread
= pa_thread_new(thread_func
, u
))) {
1015 pa_log("Failed to create thread.");
1019 /* Read mixer settings */
1021 if (sink_new_data
.volume_is_set
)
1022 u
->sink
->set_volume(u
->sink
);
1024 u
->sink
->get_volume(u
->sink
);
1026 if (sink_new_data
.muted_is_set
)
1027 u
->sink
->set_mute(u
->sink
);
1029 u
->sink
->get_mute(u
->sink
);
1031 pa_sink_put(u
->sink
);
1035 if (source_new_data
.volume_is_set
)
1036 u
->source
->set_volume(u
->source
);
1038 u
->source
->get_volume(u
->source
);
1040 pa_source_put(u
->source
);
1043 pa_modargs_free(ma
);
1054 pa_modargs_free(ma
);
1059 void pa__done(pa_module
*m
) {
1064 if (!(u
= m
->userdata
))
1068 ioctl(u
->fd
, I_SETSIG
, 0);
1069 pa_signal_free(u
->sig
);
1073 pa_sink_unlink(u
->sink
);
1076 pa_source_unlink(u
->source
);
1079 pa_asyncmsgq_send(u
->thread_mq
.inq
, NULL
, PA_MESSAGE_SHUTDOWN
, NULL
, 0, NULL
);
1080 pa_thread_free(u
->thread
);
1083 pa_thread_mq_done(&u
->thread_mq
);
1086 pa_sink_unref(u
->sink
);
1089 pa_source_unref(u
->source
);
1091 if (u
->memchunk
.memblock
)
1092 pa_memblock_unref(u
->memchunk
.memblock
);
1095 pa_rtpoll_item_free(u
->rtpoll_item
);
1098 pa_rtpoll_free(u
->rtpoll
);
1104 pa_smoother_free(u
->smoother
);
1106 pa_xfree(u
->device_name
);