output/{alsa,oss}: convert to C++
This commit is contained in:
parent
76417d4446
commit
26a9ce7b29
@ -809,7 +809,8 @@ libmixer_plugins_a_CPPFLAGS = $(AM_CPPFLAGS) \
|
|||||||
|
|
||||||
if HAVE_ALSA
|
if HAVE_ALSA
|
||||||
liboutput_plugins_a_SOURCES += \
|
liboutput_plugins_a_SOURCES += \
|
||||||
src/output/alsa_output_plugin.c src/output/alsa_output_plugin.h
|
src/output/AlsaOutputPlugin.cxx \
|
||||||
|
src/output/AlsaOutputPlugin.hxx
|
||||||
libmixer_plugins_a_SOURCES += src/mixer/AlsaMixerPlugin.cxx
|
libmixer_plugins_a_SOURCES += src/mixer/AlsaMixerPlugin.cxx
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -851,8 +852,9 @@ endif
|
|||||||
|
|
||||||
if HAVE_OSS
|
if HAVE_OSS
|
||||||
liboutput_plugins_a_SOURCES += \
|
liboutput_plugins_a_SOURCES += \
|
||||||
src/output/oss_output_plugin.c src/output/oss_output_plugin.h
|
src/output/OssOutputPlugin.cxx \
|
||||||
libmixer_plugins_a_SOURCES += src/mixer/oss_mixer_plugin.c
|
src/output/OssOutputPlugin.hxx
|
||||||
|
libmixer_plugins_a_SOURCES += src/mixer/OssMixerPlugin.cxx
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_OPENAL
|
if HAVE_OPENAL
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "OutputList.hxx"
|
#include "OutputList.hxx"
|
||||||
#include "output_api.h"
|
#include "output_api.h"
|
||||||
#include "output/alsa_output_plugin.h"
|
#include "output/AlsaOutputPlugin.hxx"
|
||||||
#include "output/ao_output_plugin.h"
|
#include "output/ao_output_plugin.h"
|
||||||
#include "output/ffado_output_plugin.h"
|
#include "output/ffado_output_plugin.h"
|
||||||
#include "output/fifo_output_plugin.h"
|
#include "output/fifo_output_plugin.h"
|
||||||
@ -29,7 +29,7 @@
|
|||||||
#include "output/mvp_output_plugin.h"
|
#include "output/mvp_output_plugin.h"
|
||||||
#include "output/null_output_plugin.h"
|
#include "output/null_output_plugin.h"
|
||||||
#include "output/openal_output_plugin.h"
|
#include "output/openal_output_plugin.h"
|
||||||
#include "output/oss_output_plugin.h"
|
#include "output/OssOutputPlugin.hxx"
|
||||||
#include "output/osx_output_plugin.h"
|
#include "output/osx_output_plugin.h"
|
||||||
#include "output/pipe_output_plugin.h"
|
#include "output/pipe_output_plugin.h"
|
||||||
#include "output/pulse_output_plugin.h"
|
#include "output/pulse_output_plugin.h"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2011 The Music Player Daemon Project
|
* Copyright (C) 2003-2013 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -206,11 +206,11 @@ oss_mixer_set_volume(struct mixer *mixer, unsigned volume, GError **error_r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const struct mixer_plugin oss_mixer_plugin = {
|
const struct mixer_plugin oss_mixer_plugin = {
|
||||||
.init = oss_mixer_init,
|
oss_mixer_init,
|
||||||
.finish = oss_mixer_finish,
|
oss_mixer_finish,
|
||||||
.open = oss_mixer_open,
|
oss_mixer_open,
|
||||||
.close = oss_mixer_close,
|
oss_mixer_close,
|
||||||
.get_volume = oss_mixer_get_volume,
|
oss_mixer_get_volume,
|
||||||
.set_volume = oss_mixer_set_volume,
|
oss_mixer_set_volume,
|
||||||
.global = true,
|
true,
|
||||||
};
|
};
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2011 The Music Player Daemon Project
|
* Copyright (C) 2003-2013 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "alsa_output_plugin.h"
|
#include "AlsaOutputPlugin.hxx"
|
||||||
#include "output_api.h"
|
#include "output_api.h"
|
||||||
#include "mixer_list.h"
|
#include "mixer_list.h"
|
||||||
#include "pcm_export.h"
|
#include "pcm_export.h"
|
||||||
@ -26,6 +26,8 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#undef G_LOG_DOMAIN
|
#undef G_LOG_DOMAIN
|
||||||
#define G_LOG_DOMAIN "alsa"
|
#define G_LOG_DOMAIN "alsa"
|
||||||
|
|
||||||
@ -43,14 +45,16 @@ enum {
|
|||||||
typedef snd_pcm_sframes_t alsa_writei_t(snd_pcm_t * pcm, const void *buffer,
|
typedef snd_pcm_sframes_t alsa_writei_t(snd_pcm_t * pcm, const void *buffer,
|
||||||
snd_pcm_uframes_t size);
|
snd_pcm_uframes_t size);
|
||||||
|
|
||||||
struct alsa_data {
|
struct AlsaOutput {
|
||||||
struct audio_output base;
|
struct audio_output base;
|
||||||
|
|
||||||
struct pcm_export_state export;
|
struct pcm_export_state pcm_export;
|
||||||
|
|
||||||
/** the configured name of the ALSA device; NULL for the
|
/**
|
||||||
default device */
|
* The configured name of the ALSA device; empty for the
|
||||||
char *device;
|
* default device
|
||||||
|
*/
|
||||||
|
std::string device;
|
||||||
|
|
||||||
/** use memory mapped I/O? */
|
/** use memory mapped I/O? */
|
||||||
bool use_mmap;
|
bool use_mmap;
|
||||||
@ -101,6 +105,18 @@ struct alsa_data {
|
|||||||
* The number of frames written in the current period.
|
* The number of frames written in the current period.
|
||||||
*/
|
*/
|
||||||
snd_pcm_uframes_t period_position;
|
snd_pcm_uframes_t period_position;
|
||||||
|
|
||||||
|
AlsaOutput():mode(0), writei(snd_pcm_writei) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Init(const config_param *param, GError **error_r) {
|
||||||
|
return ao_base_init(&base, &alsa_output_plugin,
|
||||||
|
param, error_r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Deinit() {
|
||||||
|
ao_base_finish(&base);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,24 +129,13 @@ alsa_output_quark(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
alsa_device(const struct alsa_data *ad)
|
alsa_device(const AlsaOutput *ad)
|
||||||
{
|
{
|
||||||
return ad->device != NULL ? ad->device : default_device;
|
return ad->device.empty() ? default_device : ad->device.c_str();
|
||||||
}
|
|
||||||
|
|
||||||
static struct alsa_data *
|
|
||||||
alsa_data_new(void)
|
|
||||||
{
|
|
||||||
struct alsa_data *ret = g_new(struct alsa_data, 1);
|
|
||||||
|
|
||||||
ret->mode = 0;
|
|
||||||
ret->writei = snd_pcm_writei;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
alsa_configure(struct alsa_data *ad, const struct config_param *param)
|
alsa_configure(AlsaOutput *ad, const struct config_param *param)
|
||||||
{
|
{
|
||||||
ad->device = config_dup_block_string(param, "device", NULL);
|
ad->device = config_dup_block_string(param, "device", NULL);
|
||||||
|
|
||||||
@ -161,10 +166,10 @@ alsa_configure(struct alsa_data *ad, const struct config_param *param)
|
|||||||
static struct audio_output *
|
static struct audio_output *
|
||||||
alsa_init(const struct config_param *param, GError **error_r)
|
alsa_init(const struct config_param *param, GError **error_r)
|
||||||
{
|
{
|
||||||
struct alsa_data *ad = alsa_data_new();
|
AlsaOutput *ad = new AlsaOutput();
|
||||||
|
|
||||||
if (!ao_base_init(&ad->base, &alsa_output_plugin, param, error_r)) {
|
if (!ad->Init(param, error_r)) {
|
||||||
g_free(ad);
|
delete ad;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,12 +181,10 @@ alsa_init(const struct config_param *param, GError **error_r)
|
|||||||
static void
|
static void
|
||||||
alsa_finish(struct audio_output *ao)
|
alsa_finish(struct audio_output *ao)
|
||||||
{
|
{
|
||||||
struct alsa_data *ad = (struct alsa_data *)ao;
|
AlsaOutput *ad = (AlsaOutput *)ao;
|
||||||
|
|
||||||
ao_base_finish(&ad->base);
|
ad->Deinit();
|
||||||
|
delete ad;
|
||||||
g_free(ad->device);
|
|
||||||
g_free(ad);
|
|
||||||
|
|
||||||
/* free libasound's config cache */
|
/* free libasound's config cache */
|
||||||
snd_config_update_free_global();
|
snd_config_update_free_global();
|
||||||
@ -190,18 +193,18 @@ alsa_finish(struct audio_output *ao)
|
|||||||
static bool
|
static bool
|
||||||
alsa_output_enable(struct audio_output *ao, G_GNUC_UNUSED GError **error_r)
|
alsa_output_enable(struct audio_output *ao, G_GNUC_UNUSED GError **error_r)
|
||||||
{
|
{
|
||||||
struct alsa_data *ad = (struct alsa_data *)ao;
|
AlsaOutput *ad = (AlsaOutput *)ao;
|
||||||
|
|
||||||
pcm_export_init(&ad->export);
|
pcm_export_init(&ad->pcm_export);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
alsa_output_disable(struct audio_output *ao)
|
alsa_output_disable(struct audio_output *ao)
|
||||||
{
|
{
|
||||||
struct alsa_data *ad = (struct alsa_data *)ao;
|
AlsaOutput *ad = (AlsaOutput *)ao;
|
||||||
|
|
||||||
pcm_export_deinit(&ad->export);
|
pcm_export_deinit(&ad->pcm_export);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -349,7 +352,8 @@ alsa_output_setup_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
|
|||||||
{
|
{
|
||||||
/* try the input format first */
|
/* try the input format first */
|
||||||
|
|
||||||
int err = alsa_output_try_format(pcm, hwparams, audio_format->format,
|
int err = alsa_output_try_format(pcm, hwparams,
|
||||||
|
sample_format(audio_format->format),
|
||||||
packed_r, reverse_endian_r);
|
packed_r, reverse_endian_r);
|
||||||
|
|
||||||
/* if unsupported by the hardware, try other formats */
|
/* if unsupported by the hardware, try other formats */
|
||||||
@ -383,15 +387,11 @@ alsa_output_setup_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
|
|||||||
* the configured settings and the audio format.
|
* the configured settings and the audio format.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
alsa_setup(struct alsa_data *ad, struct audio_format *audio_format,
|
alsa_setup(AlsaOutput *ad, struct audio_format *audio_format,
|
||||||
bool *packed_r, bool *reverse_endian_r, GError **error)
|
bool *packed_r, bool *reverse_endian_r, GError **error)
|
||||||
{
|
{
|
||||||
snd_pcm_hw_params_t *hwparams;
|
|
||||||
snd_pcm_sw_params_t *swparams;
|
|
||||||
unsigned int sample_rate = audio_format->sample_rate;
|
unsigned int sample_rate = audio_format->sample_rate;
|
||||||
unsigned int channels = audio_format->channels;
|
unsigned int channels = audio_format->channels;
|
||||||
snd_pcm_uframes_t alsa_buffer_size;
|
|
||||||
snd_pcm_uframes_t alsa_period_size;
|
|
||||||
int err;
|
int err;
|
||||||
const char *cmd = NULL;
|
const char *cmd = NULL;
|
||||||
int retry = MPD_ALSA_RETRY_NR;
|
int retry = MPD_ALSA_RETRY_NR;
|
||||||
@ -401,6 +401,7 @@ alsa_setup(struct alsa_data *ad, struct audio_format *audio_format,
|
|||||||
period_time_ro = period_time = ad->period_time;
|
period_time_ro = period_time = ad->period_time;
|
||||||
configure_hw:
|
configure_hw:
|
||||||
/* configure HW params */
|
/* configure HW params */
|
||||||
|
snd_pcm_hw_params_t *hwparams;
|
||||||
snd_pcm_hw_params_alloca(&hwparams);
|
snd_pcm_hw_params_alloca(&hwparams);
|
||||||
cmd = "snd_pcm_hw_params_any";
|
cmd = "snd_pcm_hw_params_any";
|
||||||
err = snd_pcm_hw_params_any(ad->pcm, hwparams);
|
err = snd_pcm_hw_params_any(ad->pcm, hwparams);
|
||||||
@ -434,7 +435,7 @@ configure_hw:
|
|||||||
g_set_error(error, alsa_output_quark(), err,
|
g_set_error(error, alsa_output_quark(), err,
|
||||||
"ALSA device \"%s\" does not support format %s: %s",
|
"ALSA device \"%s\" does not support format %s: %s",
|
||||||
alsa_device(ad),
|
alsa_device(ad),
|
||||||
sample_format_to_string(audio_format->format),
|
sample_format_to_string(sample_format(audio_format->format)),
|
||||||
snd_strerror(-err));
|
snd_strerror(-err));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -525,11 +526,13 @@ configure_hw:
|
|||||||
if (retry != MPD_ALSA_RETRY_NR)
|
if (retry != MPD_ALSA_RETRY_NR)
|
||||||
g_debug("ALSA period_time set to %d\n", period_time);
|
g_debug("ALSA period_time set to %d\n", period_time);
|
||||||
|
|
||||||
|
snd_pcm_uframes_t alsa_buffer_size;
|
||||||
cmd = "snd_pcm_hw_params_get_buffer_size";
|
cmd = "snd_pcm_hw_params_get_buffer_size";
|
||||||
err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size);
|
err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
snd_pcm_uframes_t alsa_period_size;
|
||||||
cmd = "snd_pcm_hw_params_get_period_size";
|
cmd = "snd_pcm_hw_params_get_period_size";
|
||||||
err = snd_pcm_hw_params_get_period_size(hwparams, &alsa_period_size,
|
err = snd_pcm_hw_params_get_period_size(hwparams, &alsa_period_size,
|
||||||
NULL);
|
NULL);
|
||||||
@ -537,6 +540,7 @@ configure_hw:
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* configure SW params */
|
/* configure SW params */
|
||||||
|
snd_pcm_sw_params_t *swparams;
|
||||||
snd_pcm_sw_params_alloca(&swparams);
|
snd_pcm_sw_params_alloca(&swparams);
|
||||||
|
|
||||||
cmd = "snd_pcm_sw_params_current";
|
cmd = "snd_pcm_sw_params_current";
|
||||||
@ -586,7 +590,7 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
alsa_setup_dsd(struct alsa_data *ad, struct audio_format *audio_format,
|
alsa_setup_dsd(AlsaOutput *ad, struct audio_format *audio_format,
|
||||||
bool *shift8_r, bool *packed_r, bool *reverse_endian_r,
|
bool *shift8_r, bool *packed_r, bool *reverse_endian_r,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
@ -626,7 +630,7 @@ alsa_setup_dsd(struct alsa_data *ad, struct audio_format *audio_format,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
alsa_setup_or_dsd(struct alsa_data *ad, struct audio_format *audio_format,
|
alsa_setup_or_dsd(AlsaOutput *ad, struct audio_format *audio_format,
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
bool shift8 = false, packed, reverse_endian;
|
bool shift8 = false, packed, reverse_endian;
|
||||||
@ -642,8 +646,9 @@ alsa_setup_or_dsd(struct alsa_data *ad, struct audio_format *audio_format,
|
|||||||
if (!success)
|
if (!success)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pcm_export_open(&ad->export,
|
pcm_export_open(&ad->pcm_export,
|
||||||
audio_format->format, audio_format->channels,
|
sample_format(audio_format->format),
|
||||||
|
audio_format->channels,
|
||||||
dsd_usb, shift8, packed, reverse_endian);
|
dsd_usb, shift8, packed, reverse_endian);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -651,12 +656,10 @@ alsa_setup_or_dsd(struct alsa_data *ad, struct audio_format *audio_format,
|
|||||||
static bool
|
static bool
|
||||||
alsa_open(struct audio_output *ao, struct audio_format *audio_format, GError **error)
|
alsa_open(struct audio_output *ao, struct audio_format *audio_format, GError **error)
|
||||||
{
|
{
|
||||||
struct alsa_data *ad = (struct alsa_data *)ao;
|
AlsaOutput *ad = (AlsaOutput *)ao;
|
||||||
int err;
|
|
||||||
bool success;
|
|
||||||
|
|
||||||
err = snd_pcm_open(&ad->pcm, alsa_device(ad),
|
int err = snd_pcm_open(&ad->pcm, alsa_device(ad),
|
||||||
SND_PCM_STREAM_PLAYBACK, ad->mode);
|
SND_PCM_STREAM_PLAYBACK, ad->mode);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
g_set_error(error, alsa_output_quark(), err,
|
g_set_error(error, alsa_output_quark(), err,
|
||||||
"Failed to open ALSA device \"%s\": %s",
|
"Failed to open ALSA device \"%s\": %s",
|
||||||
@ -667,20 +670,20 @@ alsa_open(struct audio_output *ao, struct audio_format *audio_format, GError **e
|
|||||||
g_debug("opened %s type=%s", snd_pcm_name(ad->pcm),
|
g_debug("opened %s type=%s", snd_pcm_name(ad->pcm),
|
||||||
snd_pcm_type_name(snd_pcm_type(ad->pcm)));
|
snd_pcm_type_name(snd_pcm_type(ad->pcm)));
|
||||||
|
|
||||||
success = alsa_setup_or_dsd(ad, audio_format, error);
|
if (!alsa_setup_or_dsd(ad, audio_format, error)) {
|
||||||
if (!success) {
|
|
||||||
snd_pcm_close(ad->pcm);
|
snd_pcm_close(ad->pcm);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ad->in_frame_size = audio_format_frame_size(audio_format);
|
ad->in_frame_size = audio_format_frame_size(audio_format);
|
||||||
ad->out_frame_size = pcm_export_frame_size(&ad->export, audio_format);
|
ad->out_frame_size = pcm_export_frame_size(&ad->pcm_export,
|
||||||
|
audio_format);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
alsa_recover(struct alsa_data *ad, int err)
|
alsa_recover(AlsaOutput *ad, int err)
|
||||||
{
|
{
|
||||||
if (err == -EPIPE) {
|
if (err == -EPIPE) {
|
||||||
g_debug("Underrun on ALSA device \"%s\"\n", alsa_device(ad));
|
g_debug("Underrun on ALSA device \"%s\"\n", alsa_device(ad));
|
||||||
@ -719,7 +722,7 @@ alsa_recover(struct alsa_data *ad, int err)
|
|||||||
static void
|
static void
|
||||||
alsa_drain(struct audio_output *ao)
|
alsa_drain(struct audio_output *ao)
|
||||||
{
|
{
|
||||||
struct alsa_data *ad = (struct alsa_data *)ao;
|
AlsaOutput *ad = (AlsaOutput *)ao;
|
||||||
|
|
||||||
if (snd_pcm_state(ad->pcm) != SND_PCM_STATE_RUNNING)
|
if (snd_pcm_state(ad->pcm) != SND_PCM_STATE_RUNNING)
|
||||||
return;
|
return;
|
||||||
@ -753,7 +756,7 @@ alsa_drain(struct audio_output *ao)
|
|||||||
static void
|
static void
|
||||||
alsa_cancel(struct audio_output *ao)
|
alsa_cancel(struct audio_output *ao)
|
||||||
{
|
{
|
||||||
struct alsa_data *ad = (struct alsa_data *)ao;
|
AlsaOutput *ad = (AlsaOutput *)ao;
|
||||||
|
|
||||||
ad->period_position = 0;
|
ad->period_position = 0;
|
||||||
|
|
||||||
@ -763,7 +766,7 @@ alsa_cancel(struct audio_output *ao)
|
|||||||
static void
|
static void
|
||||||
alsa_close(struct audio_output *ao)
|
alsa_close(struct audio_output *ao)
|
||||||
{
|
{
|
||||||
struct alsa_data *ad = (struct alsa_data *)ao;
|
AlsaOutput *ad = (AlsaOutput *)ao;
|
||||||
|
|
||||||
snd_pcm_close(ad->pcm);
|
snd_pcm_close(ad->pcm);
|
||||||
}
|
}
|
||||||
@ -772,11 +775,11 @@ static size_t
|
|||||||
alsa_play(struct audio_output *ao, const void *chunk, size_t size,
|
alsa_play(struct audio_output *ao, const void *chunk, size_t size,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
struct alsa_data *ad = (struct alsa_data *)ao;
|
AlsaOutput *ad = (AlsaOutput *)ao;
|
||||||
|
|
||||||
assert(size % ad->in_frame_size == 0);
|
assert(size % ad->in_frame_size == 0);
|
||||||
|
|
||||||
chunk = pcm_export(&ad->export, chunk, size, &size);
|
chunk = pcm_export(&ad->pcm_export, chunk, size, &size);
|
||||||
|
|
||||||
assert(size % ad->out_frame_size == 0);
|
assert(size % ad->out_frame_size == 0);
|
||||||
|
|
||||||
@ -789,7 +792,7 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size,
|
|||||||
% ad->period_frames;
|
% ad->period_frames;
|
||||||
|
|
||||||
size_t bytes_written = ret * ad->out_frame_size;
|
size_t bytes_written = ret * ad->out_frame_size;
|
||||||
return pcm_export_source_size(&ad->export,
|
return pcm_export_source_size(&ad->pcm_export,
|
||||||
bytes_written);
|
bytes_written);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,17 +806,20 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const struct audio_output_plugin alsa_output_plugin = {
|
const struct audio_output_plugin alsa_output_plugin = {
|
||||||
.name = "alsa",
|
"alsa",
|
||||||
.test_default_device = alsa_test_default_device,
|
alsa_test_default_device,
|
||||||
.init = alsa_init,
|
alsa_init,
|
||||||
.finish = alsa_finish,
|
alsa_finish,
|
||||||
.enable = alsa_output_enable,
|
alsa_output_enable,
|
||||||
.disable = alsa_output_disable,
|
alsa_output_disable,
|
||||||
.open = alsa_open,
|
alsa_open,
|
||||||
.play = alsa_play,
|
alsa_close,
|
||||||
.drain = alsa_drain,
|
nullptr,
|
||||||
.cancel = alsa_cancel,
|
nullptr,
|
||||||
.close = alsa_close,
|
alsa_play,
|
||||||
|
alsa_drain,
|
||||||
|
alsa_cancel,
|
||||||
|
nullptr,
|
||||||
|
|
||||||
.mixer_plugin = &alsa_mixer_plugin,
|
&alsa_mixer_plugin,
|
||||||
};
|
};
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2011 The Music Player Daemon Project
|
* Copyright (C) 2003-2013 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -17,8 +17,8 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MPD_ALSA_OUTPUT_PLUGIN_H
|
#ifndef MPD_ALSA_OUTPUT_PLUGIN_HXX
|
||||||
#define MPD_ALSA_OUTPUT_PLUGIN_H
|
#define MPD_ALSA_OUTPUT_PLUGIN_HXX
|
||||||
|
|
||||||
extern const struct audio_output_plugin alsa_output_plugin;
|
extern const struct audio_output_plugin alsa_output_plugin;
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2011 The Music Player Daemon Project
|
* Copyright (C) 2003-2013 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "oss_output_plugin.h"
|
#include "OssOutputPlugin.hxx"
|
||||||
#include "output_api.h"
|
#include "output_api.h"
|
||||||
#include "mixer_list.h"
|
#include "mixer_list.h"
|
||||||
#include "fd_util.h"
|
#include "fd_util.h"
|
||||||
@ -60,7 +60,7 @@ struct oss_data {
|
|||||||
struct audio_output base;
|
struct audio_output base;
|
||||||
|
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
struct pcm_export_state export;
|
struct pcm_export_state pcm_export;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
@ -163,11 +163,10 @@ oss_output_test_default_device(void)
|
|||||||
static struct audio_output *
|
static struct audio_output *
|
||||||
oss_open_default(GError **error)
|
oss_open_default(GError **error)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int err[G_N_ELEMENTS(default_devices)];
|
int err[G_N_ELEMENTS(default_devices)];
|
||||||
enum oss_stat ret[G_N_ELEMENTS(default_devices)];
|
enum oss_stat ret[G_N_ELEMENTS(default_devices)];
|
||||||
|
|
||||||
for (i = G_N_ELEMENTS(default_devices); --i >= 0; ) {
|
for (int i = G_N_ELEMENTS(default_devices); --i >= 0; ) {
|
||||||
ret[i] = oss_stat_device(default_devices[i], &err[i]);
|
ret[i] = oss_stat_device(default_devices[i], &err[i]);
|
||||||
if (ret[i] == OSS_STAT_NO_ERROR) {
|
if (ret[i] == OSS_STAT_NO_ERROR) {
|
||||||
struct oss_data *od = oss_data_new();
|
struct oss_data *od = oss_data_new();
|
||||||
@ -182,7 +181,7 @@ oss_open_default(GError **error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = G_N_ELEMENTS(default_devices); --i >= 0; ) {
|
for (int i = G_N_ELEMENTS(default_devices); --i >= 0; ) {
|
||||||
const char *dev = default_devices[i];
|
const char *dev = default_devices[i];
|
||||||
switch(ret[i]) {
|
switch(ret[i]) {
|
||||||
case OSS_STAT_NO_ERROR:
|
case OSS_STAT_NO_ERROR:
|
||||||
@ -243,7 +242,7 @@ oss_output_enable(struct audio_output *ao, G_GNUC_UNUSED GError **error_r)
|
|||||||
{
|
{
|
||||||
struct oss_data *od = (struct oss_data *)ao;
|
struct oss_data *od = (struct oss_data *)ao;
|
||||||
|
|
||||||
pcm_export_init(&od->export);
|
pcm_export_init(&od->pcm_export);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +251,7 @@ oss_output_disable(struct audio_output *ao)
|
|||||||
{
|
{
|
||||||
struct oss_data *od = (struct oss_data *)ao;
|
struct oss_data *od = (struct oss_data *)ao;
|
||||||
|
|
||||||
pcm_export_deinit(&od->export);
|
pcm_export_deinit(&od->pcm_export);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -504,7 +503,7 @@ oss_probe_sample_format(int fd, enum sample_format sample_format,
|
|||||||
enum sample_format *sample_format_r,
|
enum sample_format *sample_format_r,
|
||||||
int *oss_format_r,
|
int *oss_format_r,
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
struct pcm_export_state *export,
|
struct pcm_export_state *pcm_export,
|
||||||
#endif
|
#endif
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
@ -539,7 +538,7 @@ oss_probe_sample_format(int fd, enum sample_format sample_format,
|
|||||||
*oss_format_r = oss_format;
|
*oss_format_r = oss_format;
|
||||||
|
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
pcm_export_open(export, sample_format, 0, false, false,
|
pcm_export_open(pcm_export, sample_format, 0, false, false,
|
||||||
oss_format == AFMT_S24_PACKED,
|
oss_format == AFMT_S24_PACKED,
|
||||||
oss_format == AFMT_S24_PACKED &&
|
oss_format == AFMT_S24_PACKED &&
|
||||||
G_BYTE_ORDER != G_LITTLE_ENDIAN);
|
G_BYTE_ORDER != G_LITTLE_ENDIAN);
|
||||||
@ -556,16 +555,16 @@ static bool
|
|||||||
oss_setup_sample_format(int fd, struct audio_format *audio_format,
|
oss_setup_sample_format(int fd, struct audio_format *audio_format,
|
||||||
int *oss_format_r,
|
int *oss_format_r,
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
struct pcm_export_state *export,
|
struct pcm_export_state *pcm_export,
|
||||||
#endif
|
#endif
|
||||||
GError **error_r)
|
GError **error_r)
|
||||||
{
|
{
|
||||||
enum sample_format mpd_format;
|
enum sample_format mpd_format;
|
||||||
enum oss_setup_result result =
|
enum oss_setup_result result =
|
||||||
oss_probe_sample_format(fd, audio_format->format,
|
oss_probe_sample_format(fd, sample_format(audio_format->format),
|
||||||
&mpd_format, oss_format_r,
|
&mpd_format, oss_format_r,
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
export,
|
pcm_export,
|
||||||
#endif
|
#endif
|
||||||
error_r);
|
error_r);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
@ -603,7 +602,7 @@ oss_setup_sample_format(int fd, struct audio_format *audio_format,
|
|||||||
result = oss_probe_sample_format(fd, mpd_format,
|
result = oss_probe_sample_format(fd, mpd_format,
|
||||||
&mpd_format, oss_format_r,
|
&mpd_format, oss_format_r,
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
export,
|
pcm_export,
|
||||||
#endif
|
#endif
|
||||||
error_r);
|
error_r);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
@ -635,7 +634,7 @@ oss_setup(struct oss_data *od, struct audio_format *audio_format,
|
|||||||
oss_setup_sample_rate(od->fd, audio_format, error_r) &&
|
oss_setup_sample_rate(od->fd, audio_format, error_r) &&
|
||||||
oss_setup_sample_format(od->fd, audio_format, &od->oss_format,
|
oss_setup_sample_format(od->fd, audio_format, &od->oss_format,
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
&od->export,
|
&od->pcm_export,
|
||||||
#endif
|
#endif
|
||||||
error_r);
|
error_r);
|
||||||
}
|
}
|
||||||
@ -749,14 +748,14 @@ oss_output_play(struct audio_output *ao, const void *chunk, size_t size,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
chunk = pcm_export(&od->export, chunk, size, &size);
|
chunk = pcm_export(&od->pcm_export, chunk, size, &size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
ret = write(od->fd, chunk, size);
|
ret = write(od->fd, chunk, size);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
ret = pcm_export_source_size(&od->export, ret);
|
ret = pcm_export_source_size(&od->pcm_export, ret);
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -771,18 +770,25 @@ oss_output_play(struct audio_output *ao, const void *chunk, size_t size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const struct audio_output_plugin oss_output_plugin = {
|
const struct audio_output_plugin oss_output_plugin = {
|
||||||
.name = "oss",
|
"oss",
|
||||||
.test_default_device = oss_output_test_default_device,
|
oss_output_test_default_device,
|
||||||
.init = oss_output_init,
|
oss_output_init,
|
||||||
.finish = oss_output_finish,
|
oss_output_finish,
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
.enable = oss_output_enable,
|
oss_output_enable,
|
||||||
.disable = oss_output_disable,
|
oss_output_disable,
|
||||||
|
#else
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
#endif
|
#endif
|
||||||
.open = oss_output_open,
|
oss_output_open,
|
||||||
.close = oss_output_close,
|
oss_output_close,
|
||||||
.play = oss_output_play,
|
nullptr,
|
||||||
.cancel = oss_output_cancel,
|
nullptr,
|
||||||
|
oss_output_play,
|
||||||
|
nullptr,
|
||||||
|
oss_output_cancel,
|
||||||
|
nullptr,
|
||||||
|
|
||||||
.mixer_plugin = &oss_mixer_plugin,
|
&oss_mixer_plugin,
|
||||||
};
|
};
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2011 The Music Player Daemon Project
|
* Copyright (C) 2003-2013 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -17,8 +17,8 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MPD_OSS_OUTPUT_PLUGIN_H
|
#ifndef MPD_OSS_OUTPUT_PLUGIN_HXX
|
||||||
#define MPD_OSS_OUTPUT_PLUGIN_H
|
#define MPD_OSS_OUTPUT_PLUGIN_HXX
|
||||||
|
|
||||||
extern const struct audio_output_plugin oss_output_plugin;
|
extern const struct audio_output_plugin oss_output_plugin;
|
||||||
|
|
@ -87,6 +87,10 @@ struct pcm_export_state {
|
|||||||
uint8_t reverse_endian;
|
uint8_t reverse_endian;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a #pcm_export_state object.
|
* Initialize a #pcm_export_state object.
|
||||||
*/
|
*/
|
||||||
@ -144,4 +148,8 @@ G_GNUC_PURE
|
|||||||
size_t
|
size_t
|
||||||
pcm_export_source_size(const struct pcm_export_state *state, size_t dest_size);
|
pcm_export_source_size(const struct pcm_export_state *state, size_t dest_size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user