#include <windows.h>
#include <mmsystem.h>
-#include <pulse/mainloop-api.h>
-
#include <pulse/xmalloc.h>
#include <pulse/timeval.h>
-#include <pulse/rtclock.h>
#include <pulsecore/sink.h>
#include <pulsecore/source.h>
"record=<enable source?> "
"playback=<enable sink?> "
"format=<sample format> "
- "channels=<number of channels> "
"rate=<sample rate> "
+ "channels=<number of channels> "
+ "channel_map=<channel map> "
"fragments=<number of fragments> "
- "fragment_size=<fragment size> "
- "channel_map=<channel map>");
+ "fragment_size=<fragment size>");
#define DEFAULT_SINK_NAME "wave_output"
#define DEFAULT_SOURCE_NAME "wave_input"
for (;;) {
int ret;
+ pa_bool_t need_timer = FALSE;
- if (PA_SINK_IS_OPENED(u->sink->thread_info.state) ||
- PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
-
+ if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
if (u->sink->thread_info.rewind_requested)
pa_sink_process_rewind(u->sink, 0);
- if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
- do_write(u);
- if (PA_SOURCE_IS_OPENED(u->source->thread_info.state))
- do_read(u);
+ do_write(u);
+ need_timer = TRUE;
+ }
+ if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
+ do_read(u);
+ need_timer = TRUE;
+ }
+ if (need_timer)
pa_rtpoll_set_timer_relative(u->rtpoll, u->poll_timeout);
- } else
+ else
pa_rtpoll_set_timer_disabled(u->rtpoll);
/* Hmm, nothing to do. Let's sleep */
static void sink_get_volume_cb(pa_sink *s) {
struct userdata *u = s->userdata;
+ WAVEOUTCAPS caps;
DWORD vol;
pa_volume_t left, right;
+ if (waveOutGetDevCaps(u->hwo, &caps, sizeof(caps)) != MMSYSERR_NOERROR)
+ return;
+ if (!(caps.dwSupport & WAVECAPS_VOLUME))
+ return;
+
if (waveOutGetVolume(u->hwo, &vol) != MMSYSERR_NOERROR)
return;
left = PA_CLAMP_VOLUME((vol & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME);
- right = PA_CLAMP_VOLUME(((vol >> 16) & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME);
+ if (caps.dwSupport & WAVECAPS_LRVOLUME)
+ right = PA_CLAMP_VOLUME(((vol >> 16) & 0xFFFF) * PA_VOLUME_NORM / WAVEOUT_MAX_VOLUME);
+ else
+ right = left;
/* Windows supports > 2 channels, except for volume control */
if (s->real_volume.channels > 2)
static void sink_set_volume_cb(pa_sink *s) {
struct userdata *u = s->userdata;
+ WAVEOUTCAPS caps;
DWORD vol;
- vol = s->real_volume.values[0] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM;
- if (s->real_volume.channels > 1)
- vol |= (s->real_volume.values[1] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM) << 16;
+ if (waveOutGetDevCaps(u->hwo, &caps, sizeof(caps)) != MMSYSERR_NOERROR)
+ return;
+ if (!(caps.dwSupport & WAVECAPS_VOLUME))
+ return;
+
+ if (s->real_volume.channels == 2 && caps.dwSupport & WAVECAPS_LRVOLUME) {
+ vol = (s->real_volume.values[0] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM)
+ | (s->real_volume.values[1] * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM) << 16;
+ } else {
+ vol = (pa_cvolume_avg(&(s->real_volume)) * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM)
+ | (pa_cvolume_avg(&(s->real_volume)) * WAVEOUT_MAX_VOLUME / PA_VOLUME_NORM) << 16;
+ }
if (waveOutSetVolume(u->hwo, vol) != MMSYSERR_NOERROR)
return;
pa_sink_new_data_done(&data);
pa_assert(u->sink);
- u->sink->get_volume = sink_get_volume_cb;
- u->sink->set_volume = sink_set_volume_cb;
+ pa_sink_set_get_volume_callback(u->sink, sink_get_volume_cb);
+ pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
u->sink->userdata = u;
pa_sink_set_description(u->sink, description);
u->sink->parent.process_msg = process_msg;
u->sink_underflow = 1;
u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 10, &ss);
+ pa_log_debug("Poll timeout = %.1f ms", (double) u->poll_timeout / PA_USEC_PER_MSEC);
u->cur_ihdr = 0;
u->cur_ohdr = 0;