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>
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>
64 #include "module-solaris-symdef.h"
66 PA_MODULE_AUTHOR("Pierre Ossman");
67 PA_MODULE_DESCRIPTION("Solaris Sink/Source");
68 PA_MODULE_VERSION(PACKAGE_VERSION
);
70 "sink_name=<name for the sink> "
71 "source_name=<name for the source> "
72 "device=<audio device file name> "
73 "record=<enable source?> "
74 "playback=<enable sink?> "
75 "format=<sample format> "
76 "channels=<number of channels> "
78 "buffer_size=<record buffer size> "
79 "channel_map=<channel map>");
80 PA_MODULE_LOAD_ONCE(FALSE
);
88 pa_thread_mq thread_mq
;
97 volatile uint64_t written_bytes
, read_bytes
;
98 pa_mutex
*written_bytes_lock
;
103 pa_rtpoll_item
*rtpoll_item
;
106 pa_bool_t sink_suspended
, source_suspended
;
108 uint32_t play_samples_msw
, record_samples_msw
;
109 uint32_t prev_playback_samples
, prev_record_samples
;
110 pa_mutex
*sample_counter_lock
;
115 static const char* const valid_modargs
[] = {
129 #define DEFAULT_DEVICE "/dev/audio"
130 #define MIN_BUFFER_SIZE (640)
131 #define MAX_RENDER_HZ (300)
133 /* This render rate limit implies a minimum latency, but without it we waste too much CPU time in the
134 * IO thread. The maximum render rate and minimum latency (or minimum buffer size) are unachievable on
135 * common hardware anyway. Note that MIN_BUFFER_SIZE * MAX_RENDER_HZ >= 4 * 48000 Bps.
138 static uint64_t get_playback_buffered_bytes(struct userdata
*u
) {
140 uint64_t played_bytes
;
145 pa_mutex_lock(u
->sample_counter_lock
);
147 err
= ioctl(u
->fd
, AUDIO_GETINFO
, &info
);
150 /* Handle wrap-around of the device's sample counter, which is a uint_32. */
151 if (u
->prev_playback_samples
> info
.play
.samples
) {
152 /* Unfortunately info.play.samples can sometimes go backwards, even before it wraps! */
153 if (u
->prev_playback_samples
+ info
.play
.samples
< 240000) {
154 ++u
->play_samples_msw
;
156 pa_log_debug("play.samples went backwards %d bytes", u
->prev_playback_samples
- info
.play
.samples
);
159 u
->prev_playback_samples
= info
.play
.samples
;
160 played_bytes
= (((uint64_t)u
->play_samples_msw
<< 32) + info
.play
.samples
) * u
->frame_size
;
162 pa_mutex_unlock(u
->sample_counter_lock
);
164 return u
->written_bytes
- played_bytes
;
167 static pa_usec_t
sink_get_latency(struct userdata
*u
, pa_sample_spec
*ss
) {
174 pa_mutex_lock(u
->written_bytes_lock
);
175 r
= pa_bytes_to_usec(get_playback_buffered_bytes(u
), ss
);
176 if (u
->memchunk
.memblock
)
177 r
+= pa_bytes_to_usec(u
->memchunk
.length
, ss
);
178 pa_mutex_unlock(u
->written_bytes_lock
);
183 static uint64_t get_recorded_bytes(struct userdata
*u
) {
188 pa_assert(u
->source
);
190 err
= ioctl(u
->fd
, AUDIO_GETINFO
, &info
);
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
;
201 static pa_usec_t
source_get_latency(struct userdata
*u
, pa_sample_spec
*ss
) {
209 int err
= ioctl(u
->fd
, AUDIO_GETINFO
, &info
);
212 r
= pa_bytes_to_usec(get_recorded_bytes(u
), ss
) - pa_bytes_to_usec(u
->read_bytes
, ss
);
217 static void build_pollfd(struct userdata
*u
) {
218 struct pollfd
*pollfd
;
221 pa_assert(!u
->rtpoll_item
);
222 u
->rtpoll_item
= pa_rtpoll_item_new(u
->rtpoll
, PA_RTPOLL_NEVER
, 1);
224 pollfd
= pa_rtpoll_item_get_pollfd(u
->rtpoll_item
, NULL
);
230 static int set_buffer(int fd
, int buffer_size
) {
235 AUDIO_INITINFO(&info
);
236 info
.play
.buffer_size
= buffer_size
;
237 info
.record
.buffer_size
= buffer_size
;
239 if (ioctl(fd
, AUDIO_SETINFO
, &info
) < 0) {
241 pa_log("AUDIO_SETINFO: Unsupported buffer size.");
243 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
250 static int auto_format(int fd
, int mode
, pa_sample_spec
*ss
) {
256 AUDIO_INITINFO(&info
);
258 if (mode
!= O_RDONLY
) {
259 info
.play
.sample_rate
= ss
->rate
;
260 info
.play
.channels
= ss
->channels
;
261 switch (ss
->format
) {
263 info
.play
.precision
= 8;
264 info
.play
.encoding
= AUDIO_ENCODING_LINEAR
;
267 info
.play
.precision
= 8;
268 info
.play
.encoding
= AUDIO_ENCODING_ALAW
;
271 info
.play
.precision
= 8;
272 info
.play
.encoding
= AUDIO_ENCODING_ULAW
;
274 case PA_SAMPLE_S16NE
:
275 info
.play
.precision
= 16;
276 info
.play
.encoding
= AUDIO_ENCODING_LINEAR
;
279 pa_log("AUDIO_SETINFO: Unsupported sample format.");
284 if (mode
!= O_WRONLY
) {
285 info
.record
.sample_rate
= ss
->rate
;
286 info
.record
.channels
= ss
->channels
;
287 switch (ss
->format
) {
289 info
.record
.precision
= 8;
290 info
.record
.encoding
= AUDIO_ENCODING_LINEAR
;
293 info
.record
.precision
= 8;
294 info
.record
.encoding
= AUDIO_ENCODING_ALAW
;
297 info
.record
.precision
= 8;
298 info
.record
.encoding
= AUDIO_ENCODING_ULAW
;
300 case PA_SAMPLE_S16NE
:
301 info
.record
.precision
= 16;
302 info
.record
.encoding
= AUDIO_ENCODING_LINEAR
;
305 pa_log("AUDIO_SETINFO: Unsupported sample format.");
310 if (ioctl(fd
, AUDIO_SETINFO
, &info
) < 0) {
312 pa_log("AUDIO_SETINFO: Failed to set sample format.");
314 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
321 static int open_audio_device(struct userdata
*u
, pa_sample_spec
*ss
) {
325 if ((u
->fd
= open(u
->device_name
, u
->mode
| O_NONBLOCK
)) < 0) {
326 pa_log_warn("open %s failed (%s)", u
->device_name
, pa_cstrerror(errno
));
330 pa_log_info("device opened in %s mode.", u
->mode
== O_WRONLY
? "O_WRONLY" : (u
->mode
== O_RDONLY
? "O_RDONLY" : "O_RDWR"));
332 if (auto_format(u
->fd
, u
->mode
, ss
) < 0)
335 if (set_buffer(u
->fd
, u
->buffer_size
) < 0)
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;
345 static int suspend(struct userdata
*u
) {
347 pa_assert(u
->fd
>= 0);
349 pa_log_info("Suspending...");
351 ioctl(u
->fd
, AUDIO_DRAIN
, NULL
);
355 if (u
->rtpoll_item
) {
356 pa_rtpoll_item_free(u
->rtpoll_item
);
357 u
->rtpoll_item
= NULL
;
360 pa_log_info("Device suspended.");
365 static int unsuspend(struct userdata
*u
) {
367 pa_assert(u
->fd
< 0);
369 pa_log_info("Resuming...");
371 if (open_audio_device(u
, u
->sink
? &u
->sink
->sample_spec
: &u
->source
->sample_spec
) < 0)
376 pa_log_info("Device resumed.");
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
;
386 case PA_SINK_MESSAGE_GET_LATENCY
:
387 *((pa_usec_t
*) data
) = sink_get_latency(u
, &PA_SINK(o
)->sample_spec
);
390 case PA_SINK_MESSAGE_SET_STATE
:
392 switch ((pa_sink_state_t
) PA_PTR_TO_UINT(data
)) {
394 case PA_SINK_SUSPENDED
:
396 pa_assert(PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
));
398 if (!u
->source
|| u
->source_suspended
) {
402 u
->sink_suspended
= TRUE
;
406 case PA_SINK_RUNNING
:
408 if (u
->sink
->thread_info
.state
== PA_SINK_SUSPENDED
) {
409 if (!u
->source
|| u
->source_suspended
) {
410 if (unsuspend(u
) < 0)
412 u
->sink
->get_volume(u
->sink
);
413 u
->sink
->get_mute(u
->sink
);
415 u
->sink_suspended
= FALSE
;
419 case PA_SINK_INVALID_STATE
:
420 case PA_SINK_UNLINKED
:
428 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
431 static int source_process_msg(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
432 struct userdata
*u
= PA_SOURCE(o
)->userdata
;
436 case PA_SOURCE_MESSAGE_GET_LATENCY
:
437 *((pa_usec_t
*) data
) = source_get_latency(u
, &PA_SOURCE(o
)->sample_spec
);
440 case PA_SOURCE_MESSAGE_SET_STATE
:
442 switch ((pa_source_state_t
) PA_PTR_TO_UINT(data
)) {
444 case PA_SOURCE_SUSPENDED
:
446 pa_assert(PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
));
448 if (!u
->sink
|| u
->sink_suspended
) {
452 u
->source_suspended
= TRUE
;
456 case PA_SOURCE_RUNNING
:
458 if (u
->source
->thread_info
.state
== PA_SOURCE_SUSPENDED
) {
459 if (!u
->sink
|| u
->sink_suspended
) {
460 if (unsuspend(u
) < 0)
462 u
->source
->get_volume(u
->source
);
464 u
->source_suspended
= FALSE
;
468 case PA_SOURCE_UNLINKED
:
470 case PA_SOURCE_INVALID_STATE
:
478 return pa_source_process_msg(o
, code
, data
, offset
, chunk
);
481 static void sink_set_volume(pa_sink
*s
) {
485 pa_assert_se(u
= s
->userdata
);
488 AUDIO_INITINFO(&info
);
490 info
.play
.gain
= pa_cvolume_avg(&s
->virtual_volume
) * AUDIO_MAX_GAIN
/ PA_VOLUME_NORM
;
491 assert(info
.play
.gain
<= AUDIO_MAX_GAIN
);
493 if (ioctl(u
->fd
, AUDIO_SETINFO
, &info
) < 0) {
495 pa_log("AUDIO_SETINFO: Unsupported volume.");
497 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
502 static void sink_get_volume(pa_sink
*s
) {
506 pa_assert_se(u
= s
->userdata
);
509 if (ioctl(u
->fd
, AUDIO_GETINFO
, &info
) < 0)
510 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
512 pa_cvolume_set(&s
->virtual_volume
, s
->sample_spec
.channels
,
513 info
.play
.gain
* PA_VOLUME_NORM
/ AUDIO_MAX_GAIN
);
517 static void source_set_volume(pa_source
*s
) {
521 pa_assert_se(u
= s
->userdata
);
524 AUDIO_INITINFO(&info
);
526 info
.play
.gain
= pa_cvolume_avg(&s
->virtual_volume
) * AUDIO_MAX_GAIN
/ PA_VOLUME_NORM
;
527 assert(info
.play
.gain
<= AUDIO_MAX_GAIN
);
529 if (ioctl(u
->fd
, AUDIO_SETINFO
, &info
) < 0) {
531 pa_log("AUDIO_SETINFO: Unsupported volume.");
533 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
538 static void source_get_volume(pa_source
*s
) {
542 pa_assert_se(u
= s
->userdata
);
545 if (ioctl(u
->fd
, AUDIO_GETINFO
, &info
) < 0)
546 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
548 pa_cvolume_set(&s
->virtual_volume
, s
->sample_spec
.channels
,
549 info
.play
.gain
* PA_VOLUME_NORM
/ AUDIO_MAX_GAIN
);
553 static void sink_set_mute(pa_sink
*s
) {
554 struct userdata
*u
= s
->userdata
;
560 AUDIO_INITINFO(&info
);
562 info
.output_muted
= !!s
->muted
;
564 if (ioctl(u
->fd
, AUDIO_SETINFO
, &info
) < 0)
565 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
569 static void sink_get_mute(pa_sink
*s
) {
570 struct userdata
*u
= s
->userdata
;
576 if (ioctl(u
->fd
, AUDIO_GETINFO
, &info
) < 0)
577 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
579 s
->muted
= !!info
.output_muted
;
583 static void thread_func(void *userdata
) {
584 struct userdata
*u
= userdata
;
585 unsigned short revents
= 0;
591 pa_log_debug("Thread starting up");
593 if (u
->core
->realtime_scheduling
)
594 pa_make_realtime(u
->core
->realtime_priority
);
596 pa_thread_mq_install(&u
->thread_mq
);
597 pa_rtpoll_install(u
->rtpoll
);
600 /* Render some data and write it to the dsp */
602 if (u
->sink
&& PA_SINK_IS_OPENED(u
->sink
->thread_info
.state
)) {
604 uint64_t buffered_bytes
;
606 if (u
->sink
->thread_info
.rewind_requested
)
607 pa_sink_process_rewind(u
->sink
, 0);
609 err
= ioctl(u
->fd
, AUDIO_GETINFO
, &info
);
612 if (info
.play
.error
) {
613 pa_log_debug("buffer under-run!");
615 AUDIO_INITINFO(&info
);
617 if (ioctl(u
->fd
, AUDIO_SETINFO
, &info
) < 0)
618 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
627 * Since we cannot modify the size of the output buffer we fake it
628 * by not filling it more than u->buffer_size.
630 xtime0
= pa_rtclock_usec();
631 buffered_bytes
= get_playback_buffered_bytes(u
);
632 if (buffered_bytes
>= (uint64_t)u
->buffer_size
)
635 len
= u
->buffer_size
- buffered_bytes
;
636 len
-= len
% u
->frame_size
;
638 if (len
< u
->min_request
)
641 if (u
->memchunk
.length
< len
)
642 pa_sink_render(u
->sink
, u
->sink
->thread_info
.max_request
, &u
->memchunk
);
644 p
= pa_memblock_acquire(u
->memchunk
.memblock
);
645 w
= pa_write(u
->fd
, (uint8_t*) p
+ u
->memchunk
.index
, u
->memchunk
.length
, NULL
);
646 pa_memblock_release(u
->memchunk
.memblock
);
653 u
->buffer_size
= u
->buffer_size
* 18 / 25;
654 u
->buffer_size
-= u
->buffer_size
% u
->frame_size
;
655 u
->buffer_size
= PA_MAX(u
->buffer_size
, (int32_t)MIN_BUFFER_SIZE
);
656 pa_sink_set_max_request_within_thread(u
->sink
, u
->buffer_size
);
657 pa_log("EAGAIN. Buffer size is now %u bytes (%llu buffered)", u
->buffer_size
, buffered_bytes
);
660 pa_log("Failed to write data to DSP: %s", pa_cstrerror(errno
));
664 pa_assert(w
% u
->frame_size
== 0);
666 pa_mutex_lock(u
->written_bytes_lock
);
667 u
->written_bytes
+= w
;
668 u
->memchunk
.length
-= w
;
669 pa_mutex_unlock(u
->written_bytes_lock
);
671 u
->memchunk
.index
+= w
;
672 if (u
->memchunk
.length
<= 0) {
673 pa_memblock_unref(u
->memchunk
.memblock
);
674 pa_memchunk_reset(&u
->memchunk
);
679 pa_rtpoll_set_timer_absolute(u
->rtpoll
, xtime0
+ pa_bytes_to_usec(buffered_bytes
/ 2, &u
->sink
->sample_spec
));
681 pa_rtpoll_set_timer_disabled(u
->rtpoll
);
684 /* Try to read some data and pass it on to the source driver */
686 if (u
->source
&& PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
) && (revents
& POLLIN
)) {
687 pa_memchunk memchunk
;
692 err
= ioctl(u
->fd
, AUDIO_GETINFO
, &info
);
695 if (info
.record
.error
) {
696 pa_log_debug("buffer overflow!");
698 AUDIO_INITINFO(&info
);
699 info
.record
.error
= 0;
700 if (ioctl(u
->fd
, AUDIO_SETINFO
, &info
) < 0)
701 pa_log("AUDIO_SETINFO: %s", pa_cstrerror(errno
));
704 err
= ioctl(u
->fd
, I_NREAD
, &len
);
708 memchunk
.memblock
= pa_memblock_new(u
->core
->mempool
, len
);
709 pa_assert(memchunk
.memblock
);
711 p
= pa_memblock_acquire(memchunk
.memblock
);
712 r
= pa_read(u
->fd
, p
, len
, NULL
);
713 pa_memblock_release(memchunk
.memblock
);
716 pa_memblock_unref(memchunk
.memblock
);
720 pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno
));
729 pa_source_post(u
->source
, &memchunk
);
730 pa_memblock_unref(memchunk
.memblock
);
737 if (u
->rtpoll_item
) {
738 struct pollfd
*pollfd
;
740 pa_assert(u
->fd
>= 0);
742 pollfd
= pa_rtpoll_item_get_pollfd(u
->rtpoll_item
, NULL
);
743 pollfd
->events
= (u
->source
&& PA_SOURCE_IS_OPENED(u
->source
->thread_info
.state
)) ? POLLIN
: 0;
746 /* Hmm, nothing to do. Let's sleep */
747 if ((ret
= pa_rtpoll_run(u
->rtpoll
, TRUE
)) < 0)
753 if (u
->rtpoll_item
) {
754 struct pollfd
*pollfd
;
756 pollfd
= pa_rtpoll_item_get_pollfd(u
->rtpoll_item
, NULL
);
758 if (pollfd
->revents
& ~(POLLOUT
|POLLIN
)) {
759 pa_log("DSP shutdown.");
763 revents
= pollfd
->revents
;
769 /* We have to continue processing messages until we receive the
770 * SHUTDOWN message */
771 pa_asyncmsgq_post(u
->thread_mq
.outq
, PA_MSGOBJECT(u
->core
), PA_CORE_MESSAGE_UNLOAD_MODULE
, u
->module
, 0, NULL
, NULL
);
772 pa_asyncmsgq_wait_for(u
->thread_mq
.inq
, PA_MESSAGE_SHUTDOWN
);
775 pa_log_debug("Thread shutting down");
778 static void sig_callback(pa_mainloop_api
*api
, pa_signal_event
*e
, int sig
, void *userdata
) {
779 struct userdata
*u
= userdata
;
783 pa_log_debug("caught signal");
786 pa_sink_get_volume(u
->sink
, TRUE
);
787 pa_sink_get_mute(u
->sink
, TRUE
);
791 pa_source_get_volume(u
->source
, TRUE
);
794 int pa__init(pa_module
*m
) {
795 struct userdata
*u
= NULL
;
796 pa_bool_t record
= TRUE
, playback
= TRUE
;
799 pa_modargs
*ma
= NULL
;
801 pa_sink_new_data sink_new_data
;
802 pa_source_new_data source_new_data
;
805 pa_bool_t namereg_fail
;
809 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
810 pa_log("failed to parse module arguments.");
814 if (pa_modargs_get_value_boolean(ma
, "record", &record
) < 0 || pa_modargs_get_value_boolean(ma
, "playback", &playback
) < 0) {
815 pa_log("record= and playback= expect a boolean argument.");
819 if (!playback
&& !record
) {
820 pa_log("neither playback nor record enabled for device.");
824 u
= pa_xnew0(struct userdata
, 1);
825 u
->sample_counter_lock
= pa_mutex_new(FALSE
, FALSE
);
826 u
->written_bytes_lock
= pa_mutex_new(FALSE
, FALSE
);
829 * For a process (or several processes) to use the same audio device for both
830 * record and playback at the same time, the device's mixer must be enabled.
831 * See mixerctl(1). It may be turned off for playback only or record only.
833 u
->mode
= (playback
&& record
) ? O_RDWR
: (playback
? O_WRONLY
: (record
? O_RDONLY
: 0));
835 ss
= m
->core
->default_sample_spec
;
836 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
837 pa_log("failed to parse sample specification");
840 u
->frame_size
= pa_frame_size(&ss
);
842 u
->buffer_size
= 16384;
843 if (pa_modargs_get_value_s32(ma
, "buffer_size", &u
->buffer_size
) < 0) {
844 pa_log("failed to parse buffer size argument");
847 u
->buffer_size
-= u
->buffer_size
% u
->frame_size
;
848 if (u
->buffer_size
< (int32_t)MIN_BUFFER_SIZE
) {
849 pa_log("supplied buffer size argument is too small");
853 u
->device_name
= pa_xstrdup(pa_modargs_get_value(ma
, "device", DEFAULT_DEVICE
));
855 if ((fd
= open_audio_device(u
, &ss
)) < 0)
862 pa_memchunk_reset(&u
->memchunk
);
864 u
->rtpoll
= pa_rtpoll_new();
865 pa_thread_mq_init(&u
->thread_mq
, m
->core
->mainloop
, u
->rtpoll
);
867 u
->rtpoll_item
= NULL
;
870 if (u
->mode
!= O_WRONLY
) {
874 if (!(name
= pa_modargs_get_value(ma
, "source_name", NULL
))) {
875 name
= name_buf
= pa_sprintf_malloc("solaris_input.%s", pa_path_get_filename(u
->device_name
));
876 namereg_fail
= FALSE
;
879 pa_source_new_data_init(&source_new_data
);
880 source_new_data
.driver
= __FILE__
;
881 source_new_data
.module
= m
;
882 pa_source_new_data_set_name(&source_new_data
, name
);
883 source_new_data
.namereg_fail
= namereg_fail
;
884 pa_source_new_data_set_sample_spec(&source_new_data
, &ss
);
885 pa_source_new_data_set_channel_map(&source_new_data
, &map
);
886 pa_proplist_sets(source_new_data
.proplist
, PA_PROP_DEVICE_STRING
, u
->device_name
);
887 pa_proplist_sets(source_new_data
.proplist
, PA_PROP_DEVICE_API
, "solaris");
888 pa_proplist_setf(source_new_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "Solaris PCM source");
889 pa_proplist_sets(source_new_data
.proplist
, PA_PROP_DEVICE_ACCESS_MODE
, "serial");
890 pa_proplist_setf(source_new_data
.proplist
, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE
, "%lu", (unsigned long) u
->buffer_size
);
892 u
->source
= pa_source_new(m
->core
, &source_new_data
, PA_SOURCE_HARDWARE
|PA_SOURCE_LATENCY
|PA_SOURCE_HW_VOLUME_CTRL
);
893 pa_source_new_data_done(&source_new_data
);
897 pa_log("Failed to create source object");
901 u
->source
->userdata
= u
;
902 u
->source
->parent
.process_msg
= source_process_msg
;
904 pa_source_set_asyncmsgq(u
->source
, u
->thread_mq
.inq
);
905 pa_source_set_rtpoll(u
->source
, u
->rtpoll
);
907 u
->source
->get_volume
= source_get_volume
;
908 u
->source
->set_volume
= source_set_volume
;
909 u
->source
->refresh_volume
= TRUE
;
913 if (u
->mode
!= O_RDONLY
) {
916 if (!(name
= pa_modargs_get_value(ma
, "sink_name", NULL
))) {
917 name
= name_buf
= pa_sprintf_malloc("solaris_output.%s", pa_path_get_filename(u
->device_name
));
918 namereg_fail
= FALSE
;
921 pa_sink_new_data_init(&sink_new_data
);
922 sink_new_data
.driver
= __FILE__
;
923 sink_new_data
.module
= m
;
924 pa_sink_new_data_set_name(&sink_new_data
, name
);
925 sink_new_data
.namereg_fail
= namereg_fail
;
926 pa_sink_new_data_set_sample_spec(&sink_new_data
, &ss
);
927 pa_sink_new_data_set_channel_map(&sink_new_data
, &map
);
928 pa_proplist_sets(sink_new_data
.proplist
, PA_PROP_DEVICE_STRING
, u
->device_name
);
929 pa_proplist_sets(sink_new_data
.proplist
, PA_PROP_DEVICE_API
, "solaris");
930 pa_proplist_setf(sink_new_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "Solaris PCM sink");
931 pa_proplist_sets(sink_new_data
.proplist
, PA_PROP_DEVICE_ACCESS_MODE
, "serial");
933 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
);
934 pa_sink_new_data_done(&sink_new_data
);
937 u
->sink
->userdata
= u
;
938 u
->sink
->parent
.process_msg
= sink_process_msg
;
940 pa_sink_set_asyncmsgq(u
->sink
, u
->thread_mq
.inq
);
941 pa_sink_set_rtpoll(u
->sink
, u
->rtpoll
);
943 u
->sink
->get_volume
= sink_get_volume
;
944 u
->sink
->set_volume
= sink_set_volume
;
945 u
->sink
->get_mute
= sink_get_mute
;
946 u
->sink
->set_mute
= sink_set_mute
;
947 u
->sink
->refresh_volume
= u
->sink
->refresh_muted
= TRUE
;
949 pa_sink_set_max_request(u
->sink
, u
->buffer_size
);
950 u
->min_request
= pa_usec_to_bytes(PA_USEC_PER_SEC
/ MAX_RENDER_HZ
, &ss
);
954 pa_assert(u
->source
|| u
->sink
);
956 u
->sig
= pa_signal_new(SIGPOLL
, sig_callback
, u
);
958 ioctl(u
->fd
, I_SETSIG
, S_MSG
);
960 if (!(u
->thread
= pa_thread_new(thread_func
, u
))) {
961 pa_log("Failed to create thread.");
965 /* Read mixer settings */
967 if (sink_new_data
.volume_is_set
)
968 u
->sink
->set_volume(u
->sink
);
970 u
->sink
->get_volume(u
->sink
);
972 if (sink_new_data
.muted_is_set
)
973 u
->sink
->set_mute(u
->sink
);
975 u
->sink
->get_mute(u
->sink
);
977 pa_sink_put(u
->sink
);
981 if (source_new_data
.volume_is_set
)
982 u
->source
->set_volume(u
->source
);
984 u
->source
->get_volume(u
->source
);
986 pa_source_put(u
->source
);
1000 pa_modargs_free(ma
);
1005 void pa__done(pa_module
*m
) {
1010 if (!(u
= m
->userdata
))
1013 ioctl(u
->fd
, I_SETSIG
, 0);
1014 pa_signal_free(u
->sig
);
1017 pa_sink_unlink(u
->sink
);
1020 pa_source_unlink(u
->source
);
1023 pa_asyncmsgq_send(u
->thread_mq
.inq
, NULL
, PA_MESSAGE_SHUTDOWN
, NULL
, 0, NULL
);
1024 pa_thread_free(u
->thread
);
1027 pa_thread_mq_done(&u
->thread_mq
);
1030 pa_sink_unref(u
->sink
);
1033 pa_source_unref(u
->source
);
1035 if (u
->memchunk
.memblock
)
1036 pa_memblock_unref(u
->memchunk
.memblock
);
1039 pa_rtpoll_item_free(u
->rtpoll_item
);
1042 pa_rtpoll_free(u
->rtpoll
);
1047 pa_mutex_free(u
->written_bytes_lock
);
1048 pa_mutex_free(u
->sample_counter_lock
);
1050 pa_xfree(u
->device_name
);