aboutsummaryrefslogtreecommitdiffstats
path: root/src/output/winmm_output_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/output/winmm_output_plugin.c')
-rw-r--r--src/output/winmm_output_plugin.c85
1 files changed, 54 insertions, 31 deletions
diff --git a/src/output/winmm_output_plugin.c b/src/output/winmm_output_plugin.c
index 4312c635e..4d95834b9 100644
--- a/src/output/winmm_output_plugin.c
+++ b/src/output/winmm_output_plugin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2010 The Music Player Daemon Project
+ * Copyright (C) 2003-2011 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -18,6 +18,7 @@
*/
#include "config.h"
+#include "winmm_output_plugin.h"
#include "output_api.h"
#include "pcm_buffer.h"
#include "mixer_list.h"
@@ -37,6 +38,8 @@ struct winmm_buffer {
};
struct winmm_output {
+ struct audio_output base;
+
UINT device_id;
HWAVEOUT handle;
@@ -71,59 +74,80 @@ winmm_output_test_default_device(void)
return waveOutGetNumDevs() > 0;
}
-static UINT
-get_device_id(const char *device_name)
+static bool
+get_device_id(const char *device_name, UINT *device_id, GError **error_r)
{
/* if device is not specified use wave mapper */
- if (device_name == NULL)
- return WAVE_MAPPER;
+ if (device_name == NULL) {
+ *device_id = WAVE_MAPPER;
+ return true;
+ }
+
+ UINT numdevs = waveOutGetNumDevs();
/* check for device id */
char *endptr;
UINT id = strtoul(device_name, &endptr, 0);
- if (endptr > device_name && *endptr == 0)
- return id;
+ if (endptr > device_name && *endptr == 0) {
+ if (id >= numdevs)
+ goto fail;
+ *device_id = id;
+ return true;
+ }
/* check for device name */
- for (UINT i = 0; i < waveOutGetNumDevs(); i++) {
+ for (UINT i = 0; i < numdevs; i++) {
WAVEOUTCAPS caps;
MMRESULT result = waveOutGetDevCaps(i, &caps, sizeof(caps));
if (result != MMSYSERR_NOERROR)
continue;
/* szPname is only 32 chars long, so it is often truncated.
Use partial match to work around this. */
- if (strstr(device_name, caps.szPname) == device_name)
- return i;
+ if (strstr(device_name, caps.szPname) == device_name) {
+ *device_id = i;
+ return true;
+ }
}
- /* fallback to wave mapper */
- return WAVE_MAPPER;
+fail:
+ g_set_error(error_r, winmm_output_quark(), 0,
+ "device \"%s\" is not found", device_name);
+ return false;
}
-static void *
-winmm_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
- G_GNUC_UNUSED const struct config_param *param,
- G_GNUC_UNUSED GError **error)
+static struct audio_output *
+winmm_output_init(const struct config_param *param, GError **error_r)
{
struct winmm_output *wo = g_new(struct winmm_output, 1);
+ if (!ao_base_init(&wo->base, &winmm_output_plugin, param, error_r)) {
+ g_free(wo);
+ return NULL;
+ }
+
const char *device = config_get_block_string(param, "device", NULL);
- wo->device_id = get_device_id(device);
- return wo;
+ if (!get_device_id(device, &wo->device_id, error_r)) {
+ ao_base_finish(&wo->base);
+ g_free(wo);
+ return NULL;
+ }
+
+ return &wo->base;
}
static void
-winmm_output_finish(void *data)
+winmm_output_finish(struct audio_output *ao)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
+ ao_base_finish(&wo->base);
g_free(wo);
}
static bool
-winmm_output_open(void *data, struct audio_format *audio_format,
+winmm_output_open(struct audio_output *ao, struct audio_format *audio_format,
GError **error_r)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
wo->event = CreateEvent(NULL, false, false, NULL);
if (wo->event == NULL) {
@@ -137,7 +161,6 @@ winmm_output_open(void *data, struct audio_format *audio_format,
case SAMPLE_FORMAT_S16:
break;
- case SAMPLE_FORMAT_S24:
case SAMPLE_FORMAT_S24_P32:
case SAMPLE_FORMAT_S32:
case SAMPLE_FORMAT_UNDEFINED:
@@ -179,9 +202,9 @@ winmm_output_open(void *data, struct audio_format *audio_format,
}
static void
-winmm_output_close(void *data)
+winmm_output_close(struct audio_output *ao)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
for (unsigned i = 0; i < G_N_ELEMENTS(wo->buffers); ++i)
pcm_buffer_deinit(&wo->buffers[i].buffer);
@@ -248,9 +271,9 @@ winmm_drain_buffer(struct winmm_output *wo, struct winmm_buffer *buffer,
}
static size_t
-winmm_output_play(void *data, const void *chunk, size_t size, GError **error_r)
+winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GError **error_r)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
/* get the next buffer from the ring and prepare it */
struct winmm_buffer *buffer = &wo->buffers[wo->next_buffer];
@@ -303,18 +326,18 @@ winmm_stop(struct winmm_output *wo)
}
static void
-winmm_output_drain(void *data)
+winmm_output_drain(struct audio_output *ao)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
if (!winmm_drain_all_buffers(wo, NULL))
winmm_stop(wo);
}
static void
-winmm_output_cancel(void *data)
+winmm_output_cancel(struct audio_output *ao)
{
- struct winmm_output *wo = data;
+ struct winmm_output *wo = (struct winmm_output *)ao;
winmm_stop(wo);
}