ao_portaudio: use new option API

This basically serves as example. All other AOs should be ported as
well.
This commit is contained in:
wm4 2013-07-21 21:35:29 +02:00
parent 7eba27c125
commit 38f712d96d
1 changed files with 35 additions and 32 deletions

View File

@ -26,7 +26,7 @@
#include <portaudio.h>
#include "config.h"
#include "core/subopt-helper.h"
#include "core/m_option.h"
#include "audio/format.h"
#include "core/mp_msg.h"
#include "core/mp_ring.h"
@ -44,6 +44,9 @@ struct priv {
// 0 is N/A (0 is not a valid PA time value)
int play_silence; // play this many bytes of silence, before real data
bool play_remaining;// play what's left in the buffer, then stop stream
// Options
char *cfg_device;
};
struct format_map {
@ -62,18 +65,6 @@ static const struct format_map format_maps[] = {
{AF_FORMAT_UNKNOWN, 0}
};
static void print_help(void)
{
mp_msg(MSGT_AO, MSGL_FATAL,
"\n-ao portaudio commandline help:\n"
"Example: mpv -ao portaudio:device=subdevice\n"
"\nOptions:\n"
" device=subdevice\n"
" Audio device PortAudio should use. Devices can be listed\n"
" with -ao portaudio:device=help\n"
" The subdevice can be passed as index, or as complete name.\n");
}
static bool check_pa_ret(int ret)
{
if (ret < 0) {
@ -102,12 +93,14 @@ static int to_int(const char *s, int return_on_error)
return (s[0] && !endptr[0]) ? res : return_on_error;
}
static int find_device(struct ao *ao, const char *name)
static int find_device(const char *name)
{
int found = paNoDevice;
if (!name)
return found;
int help = strcmp(name, "help") == 0;
int count = Pa_GetDeviceCount();
check_pa_ret(count);
int found = paNoDevice;
int index = to_int(name, -1);
if (help)
mp_msg(MSGT_AO, MSGL_INFO, "PortAudio devices:\n");
@ -128,11 +121,27 @@ static int find_device(struct ao *ao, const char *name)
}
}
if (found == paNoDevice && !help)
mp_msg(MSGT_AO, MSGL_FATAL, "[portaudio] Device '%s' not found!\n",
mp_msg(MSGT_AO, MSGL_WARN, "[portaudio] Device '%s' not found!\n",
name);
return found;
}
static int validate_device_opt(const m_option_t *opt, struct bstr name,
struct bstr param)
{
// Note: we do not check whether the device actually exist, because this
// might break elaborate configs with several AOs trying several
// devices. We do it merely for making "help" special.
if (bstr_equals0(param, "help")) {
if (!check_pa_ret(Pa_Initialize()))
return M_OPT_EXIT;
find_device("help");
Pa_Terminate();
return M_OPT_EXIT - 1;
}
return 0;
}
static void fill_silence(unsigned char *ptr, int len)
{
memset(ptr, 0, len);
@ -207,27 +216,16 @@ static void uninit(struct ao *ao, bool cut_audio)
static int init(struct ao *ao, char *params)
{
struct priv *priv = talloc_zero(ao, struct priv);
ao->priv = priv;
struct priv *priv = ao->priv;
if (!check_pa_ret(Pa_Initialize()))
return -1;
pthread_mutex_init(&priv->ring_mutex, NULL);
char *device = NULL;
const opt_t subopts[] = {
{"device", OPT_ARG_MSTRZ, &device, NULL},
{NULL}
};
if (subopt_parse(params, subopts) != 0) {
print_help();
goto error_exit;
}
int pa_device = Pa_GetDefaultOutputDevice();
if (device)
pa_device = find_device(ao, device);
if (priv->cfg_device && priv->cfg_device[0])
pa_device = find_device(priv->cfg_device);
if (pa_device == paNoDevice)
goto error_exit;
@ -274,12 +272,10 @@ static int init(struct ao *ao, char *params)
priv->ring = mp_ring_new(priv, seconds_to_bytes(ao, 0.5));
free(device);
return 0;
error_exit:
uninit(ao, true);
free(device);
return -1;
}
@ -374,6 +370,8 @@ static void resume(struct ao *ao)
check_pa_ret(Pa_StartStream(priv->stream));
}
#define OPT_BASE_STRUCT struct priv
const struct ao_driver audio_out_portaudio = {
.info = &(const struct ao_info) {
"PortAudio",
@ -389,4 +387,9 @@ const struct ao_driver audio_out_portaudio = {
.get_delay = get_delay,
.pause = pause,
.resume = resume,
.priv_size = sizeof(struct priv),
.options = (const struct m_option[]) {
OPT_STRING_VALIDATE("device", cfg_device, 0, validate_device_opt),
{0}
},
};