mirror of
https://github.com/mpv-player/mpv
synced 2025-05-02 08:09:50 +00:00
ao_oss: remove global variables
This commit is contained in:
parent
15202ebc76
commit
32a898ff5d
@ -50,6 +50,16 @@
|
|||||||
|
|
||||||
#include "ao.h"
|
#include "ao.h"
|
||||||
|
|
||||||
|
struct priv {
|
||||||
|
char *dsp;
|
||||||
|
int audio_fd;
|
||||||
|
int prepause_space;
|
||||||
|
const char *oss_mixer_device;
|
||||||
|
int oss_mixer_channel;
|
||||||
|
audio_buf_info zz;
|
||||||
|
int audio_delay_method;
|
||||||
|
};
|
||||||
|
|
||||||
static int format2oss(int format)
|
static int format2oss(int format)
|
||||||
{
|
{
|
||||||
switch (format) {
|
switch (format) {
|
||||||
@ -130,31 +140,24 @@ static int oss2format(int format)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *dsp = PATH_DEV_DSP;
|
|
||||||
static audio_buf_info zz;
|
|
||||||
static int audio_fd = -1;
|
|
||||||
static int prepause_space;
|
|
||||||
|
|
||||||
static const char *oss_mixer_device = PATH_DEV_MIXER;
|
|
||||||
static int oss_mixer_channel = SOUND_MIXER_PCM;
|
|
||||||
|
|
||||||
#ifdef SNDCTL_DSP_GETPLAYVOL
|
#ifdef SNDCTL_DSP_GETPLAYVOL
|
||||||
static int volume_oss4(ao_control_vol_t *vol, int cmd)
|
static int volume_oss4(ao_control_vol_t *vol, int cmd)
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
|
|
||||||
if (audio_fd < 0)
|
if (p->audio_fd < 0)
|
||||||
return CONTROL_ERROR;
|
return CONTROL_ERROR;
|
||||||
|
|
||||||
if (cmd == AOCONTROL_GET_VOLUME) {
|
if (cmd == AOCONTROL_GET_VOLUME) {
|
||||||
if (ioctl(audio_fd, SNDCTL_DSP_GETPLAYVOL, &v) == -1)
|
if (ioctl(p->audio_fd, SNDCTL_DSP_GETPLAYVOL, &v) == -1)
|
||||||
return CONTROL_ERROR;
|
return CONTROL_ERROR;
|
||||||
vol->right = (v & 0xff00) >> 8;
|
vol->right = (v & 0xff00) >> 8;
|
||||||
vol->left = v & 0x00ff;
|
vol->left = v & 0x00ff;
|
||||||
return CONTROL_OK;
|
return CONTROL_OK;
|
||||||
} else if (cmd == AOCONTROL_SET_VOLUME) {
|
} else if (cmd == AOCONTROL_SET_VOLUME) {
|
||||||
v = ((int) vol->right << 8) | (int) vol->left;
|
v = ((int) vol->right << 8) | (int) vol->left;
|
||||||
if (ioctl(audio_fd, SNDCTL_DSP_SETPLAYVOL, &v) == -1)
|
if (ioctl(p->audio_fd, SNDCTL_DSP_SETPLAYVOL, &v) == -1)
|
||||||
return CONTROL_ERROR;
|
return CONTROL_ERROR;
|
||||||
return CONTROL_OK;
|
return CONTROL_OK;
|
||||||
} else
|
} else
|
||||||
@ -165,6 +168,7 @@ static int volume_oss4(ao_control_vol_t *vol, int cmd)
|
|||||||
// to set/get/query special features/parameters
|
// to set/get/query special features/parameters
|
||||||
static int control(struct ao *ao, enum aocontrol cmd, void *arg)
|
static int control(struct ao *ao, enum aocontrol cmd, void *arg)
|
||||||
{
|
{
|
||||||
|
struct priv *p = ao->priv;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case AOCONTROL_GET_VOLUME:
|
case AOCONTROL_GET_VOLUME:
|
||||||
case AOCONTROL_SET_VOLUME:
|
case AOCONTROL_SET_VOLUME:
|
||||||
@ -181,16 +185,16 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
|
|||||||
if (AF_FORMAT_IS_AC3(ao->format))
|
if (AF_FORMAT_IS_AC3(ao->format))
|
||||||
return CONTROL_TRUE;
|
return CONTROL_TRUE;
|
||||||
|
|
||||||
if ((fd = open(oss_mixer_device, O_RDONLY)) != -1) {
|
if ((fd = open(p->oss_mixer_device, O_RDONLY)) != -1) {
|
||||||
ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devs);
|
ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devs);
|
||||||
if (devs & (1 << oss_mixer_channel)) {
|
if (devs & (1 << p->oss_mixer_channel)) {
|
||||||
if (cmd == AOCONTROL_GET_VOLUME) {
|
if (cmd == AOCONTROL_GET_VOLUME) {
|
||||||
ioctl(fd, MIXER_READ(oss_mixer_channel), &v);
|
ioctl(fd, MIXER_READ(p->oss_mixer_channel), &v);
|
||||||
vol->right = (v & 0xFF00) >> 8;
|
vol->right = (v & 0xFF00) >> 8;
|
||||||
vol->left = v & 0x00FF;
|
vol->left = v & 0x00FF;
|
||||||
} else {
|
} else {
|
||||||
v = ((int)vol->right << 8) | (int)vol->left;
|
v = ((int)vol->right << 8) | (int)vol->left;
|
||||||
ioctl(fd, MIXER_WRITE(oss_mixer_channel), &v);
|
ioctl(fd, MIXER_WRITE(p->oss_mixer_channel), &v);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -217,9 +221,19 @@ static int init(struct ao *ao, char *params)
|
|||||||
mp_msg(MSGT_AO, MSGL_V, "ao2: %d Hz %d chans %s\n", ao->samplerate,
|
mp_msg(MSGT_AO, MSGL_V, "ao2: %d Hz %d chans %s\n", ao->samplerate,
|
||||||
ao->channels.num, af_fmt2str_short(ao->format));
|
ao->channels.num, af_fmt2str_short(ao->format));
|
||||||
|
|
||||||
if (ao_subdevice) {
|
struct priv *p = talloc(ao, struct priv);
|
||||||
|
*p = (struct priv) {
|
||||||
|
.dsp = PATH_DEV_DSP,
|
||||||
|
.audio_fd = -1,
|
||||||
|
.oss_mixer_device = mdev ? mdev : PATH_DEV_MIXER,
|
||||||
|
.oss_mixer_channel = SOUND_MIXER_PCM,
|
||||||
|
.audio_delay_method = 2,
|
||||||
|
};
|
||||||
|
ao->priv = p;
|
||||||
|
|
||||||
|
if (params) {
|
||||||
char *m, *c;
|
char *m, *c;
|
||||||
m = strchr(ao_subdevice, ':');
|
m = strchr(params, ':');
|
||||||
if (m) {
|
if (m) {
|
||||||
c = strchr(m + 1, ':');
|
c = strchr(m + 1, ':');
|
||||||
if (c) {
|
if (c) {
|
||||||
@ -229,21 +243,16 @@ static int init(struct ao *ao, char *params)
|
|||||||
mdev = m + 1;
|
mdev = m + 1;
|
||||||
m[0] = '\0';
|
m[0] = '\0';
|
||||||
}
|
}
|
||||||
dsp = ao_subdevice;
|
p->dsp = talloc_strdup(ao, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mdev)
|
|
||||||
oss_mixer_device = mdev;
|
|
||||||
else
|
|
||||||
oss_mixer_device = PATH_DEV_MIXER;
|
|
||||||
|
|
||||||
if (mchan) {
|
if (mchan) {
|
||||||
int fd, devs, i;
|
int fd, devs, i;
|
||||||
|
|
||||||
if ((fd = open(oss_mixer_device, O_RDONLY)) == -1) {
|
if ((fd = open(p->oss_mixer_device, O_RDONLY)) == -1) {
|
||||||
mp_tmsg(MSGT_AO, MSGL_ERR,
|
mp_tmsg(MSGT_AO, MSGL_ERR,
|
||||||
"[AO OSS] audio_setup: Can't open mixer device %s: %s\n",
|
"[AO OSS] audio_setup: Can't open mixer device %s: %s\n",
|
||||||
oss_mixer_device, strerror(errno));
|
p->oss_mixer_device, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devs);
|
ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devs);
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -257,7 +266,7 @@ static int init(struct ao *ao, char *params)
|
|||||||
i = SOUND_MIXER_NRDEVICES + 1;
|
i = SOUND_MIXER_NRDEVICES + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
oss_mixer_channel = i;
|
p->oss_mixer_channel = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,30 +277,30 @@ static int init(struct ao *ao, char *params)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oss_mixer_channel = SOUND_MIXER_PCM;
|
p->oss_mixer_channel = SOUND_MIXER_PCM;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_msg(MSGT_AO, MSGL_V, "audio_setup: using '%s' dsp device\n", dsp);
|
mp_msg(MSGT_AO, MSGL_V, "audio_setup: using '%s' dsp device\n", p->dsp);
|
||||||
mp_msg(MSGT_AO, MSGL_V, "audio_setup: using '%s' mixer device\n",
|
mp_msg(MSGT_AO, MSGL_V, "audio_setup: using '%s' mixer device\n",
|
||||||
oss_mixer_device);
|
p->oss_mixer_device);
|
||||||
mp_msg(MSGT_AO, MSGL_V, "audio_setup: using '%s' mixer device\n",
|
mp_msg(MSGT_AO, MSGL_V, "audio_setup: using '%s' mixer device\n",
|
||||||
mixer_channels[oss_mixer_channel]);
|
mixer_channels[p->oss_mixer_channel]);
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
audio_fd = open(dsp, O_WRONLY | O_NONBLOCK);
|
p->audio_fd = open(p->dsp, O_WRONLY | O_NONBLOCK);
|
||||||
#else
|
#else
|
||||||
audio_fd = open(dsp, O_WRONLY);
|
p->audio_fd = open(p->dsp, O_WRONLY);
|
||||||
#endif
|
#endif
|
||||||
if (audio_fd < 0) {
|
if (p->audio_fd < 0) {
|
||||||
mp_tmsg(MSGT_AO, MSGL_ERR,
|
mp_tmsg(MSGT_AO, MSGL_ERR,
|
||||||
"[AO OSS] audio_setup: Can't open audio device %s: %s\n",
|
"[AO OSS] audio_setup: Can't open audio device %s: %s\n",
|
||||||
dsp, strerror(errno));
|
p->dsp, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
/* Remove the non-blocking flag */
|
/* Remove the non-blocking flag */
|
||||||
if (fcntl(audio_fd, F_SETFL, 0) < 0) {
|
if (fcntl(p->audio_fd, F_SETFL, 0) < 0) {
|
||||||
mp_tmsg(MSGT_AO, MSGL_ERR, "[AO OSS] audio_setup: Can't make file "
|
mp_tmsg(MSGT_AO, MSGL_ERR, "[AO OSS] audio_setup: Can't make file "
|
||||||
"descriptor blocking: %s\n", strerror(errno));
|
"descriptor blocking: %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
@ -299,11 +308,11 @@ static int init(struct ao *ao, char *params)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(FD_CLOEXEC) && defined(F_SETFD)
|
#if defined(FD_CLOEXEC) && defined(F_SETFD)
|
||||||
fcntl(audio_fd, F_SETFD, FD_CLOEXEC);
|
fcntl(p->audio_fd, F_SETFD, FD_CLOEXEC);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (AF_FORMAT_IS_AC3(ao->format)) {
|
if (AF_FORMAT_IS_AC3(ao->format)) {
|
||||||
ioctl(audio_fd, SNDCTL_DSP_SPEED, &ao->samplerate);
|
ioctl(p->audio_fd, SNDCTL_DSP_SPEED, &ao->samplerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
ac3_retry:
|
ac3_retry:
|
||||||
@ -318,11 +327,11 @@ ac3_retry:
|
|||||||
#endif
|
#endif
|
||||||
ao->format = AF_FORMAT_S16_NE;
|
ao->format = AF_FORMAT_S16_NE;
|
||||||
}
|
}
|
||||||
if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &oss_format) < 0 ||
|
if (ioctl(p->audio_fd, SNDCTL_DSP_SETFMT, &oss_format) < 0 ||
|
||||||
oss_format != format2oss(ao->format))
|
oss_format != format2oss(ao->format))
|
||||||
{
|
{
|
||||||
mp_tmsg(MSGT_AO, MSGL_WARN, "[AO OSS] Can't set audio device %s to %s "
|
mp_tmsg(MSGT_AO, MSGL_WARN, "[AO OSS] Can't set audio device %s to %s "
|
||||||
"output, trying %s...\n", dsp, af_fmt2str_short(ao->format),
|
"output, trying %s...\n", p->dsp, af_fmt2str_short(ao->format),
|
||||||
af_fmt2str_short(AF_FORMAT_S16_NE));
|
af_fmt2str_short(AF_FORMAT_S16_NE));
|
||||||
ao->format = AF_FORMAT_S16_NE;
|
ao->format = AF_FORMAT_S16_NE;
|
||||||
goto ac3_retry;
|
goto ac3_retry;
|
||||||
@ -344,7 +353,7 @@ ac3_retry:
|
|||||||
// We only use SNDCTL_DSP_CHANNELS for >2 channels, in case some drivers don't have it
|
// We only use SNDCTL_DSP_CHANNELS for >2 channels, in case some drivers don't have it
|
||||||
if (reqchannels > 2) {
|
if (reqchannels > 2) {
|
||||||
int nchannels = reqchannels;
|
int nchannels = reqchannels;
|
||||||
if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &nchannels) == -1 ||
|
if (ioctl(p->audio_fd, SNDCTL_DSP_CHANNELS, &nchannels) == -1 ||
|
||||||
nchannels != reqchannels)
|
nchannels != reqchannels)
|
||||||
{
|
{
|
||||||
mp_tmsg(MSGT_AO, MSGL_ERR, "[AO OSS] audio_setup: Failed to "
|
mp_tmsg(MSGT_AO, MSGL_ERR, "[AO OSS] audio_setup: Failed to "
|
||||||
@ -353,7 +362,7 @@ ac3_retry:
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int c = reqchannels - 1;
|
int c = reqchannels - 1;
|
||||||
if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &c) == -1) {
|
if (ioctl(p->audio_fd, SNDCTL_DSP_STEREO, &c) == -1) {
|
||||||
mp_tmsg(MSGT_AO, MSGL_ERR, "[AO OSS] audio_setup: Failed to "
|
mp_tmsg(MSGT_AO, MSGL_ERR, "[AO OSS] audio_setup: Failed to "
|
||||||
"set audio device to %d channels.\n", reqchannels);
|
"set audio device to %d channels.\n", reqchannels);
|
||||||
return -1;
|
return -1;
|
||||||
@ -365,16 +374,16 @@ ac3_retry:
|
|||||||
"audio_setup: using %d channels (requested: %d)\n",
|
"audio_setup: using %d channels (requested: %d)\n",
|
||||||
ao->channels.num, reqchannels);
|
ao->channels.num, reqchannels);
|
||||||
// set rate
|
// set rate
|
||||||
ioctl(audio_fd, SNDCTL_DSP_SPEED, &ao->samplerate);
|
ioctl(p->audio_fd, SNDCTL_DSP_SPEED, &ao->samplerate);
|
||||||
mp_msg(MSGT_AO, MSGL_V, "audio_setup: using %d Hz samplerate\n",
|
mp_msg(MSGT_AO, MSGL_V, "audio_setup: using %d Hz samplerate\n",
|
||||||
ao->samplerate);
|
ao->samplerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz) == -1) {
|
if (ioctl(p->audio_fd, SNDCTL_DSP_GETOSPACE, &p->zz) == -1) {
|
||||||
int r = 0;
|
int r = 0;
|
||||||
mp_tmsg(MSGT_AO, MSGL_WARN, "[AO OSS] audio_setup: driver doesn't "
|
mp_tmsg(MSGT_AO, MSGL_WARN, "[AO OSS] audio_setup: driver doesn't "
|
||||||
"support SNDCTL_DSP_GETOSPACE\n");
|
"support SNDCTL_DSP_GETOSPACE\n");
|
||||||
if (ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &r) == -1)
|
if (ioctl(p->audio_fd, SNDCTL_DSP_GETBLKSIZE, &r) == -1)
|
||||||
mp_msg(MSGT_AO, MSGL_V, "audio_setup: %d bytes/frag (config.h)\n",
|
mp_msg(MSGT_AO, MSGL_V, "audio_setup: %d bytes/frag (config.h)\n",
|
||||||
ao->outburst);
|
ao->outburst);
|
||||||
else {
|
else {
|
||||||
@ -385,10 +394,10 @@ ac3_retry:
|
|||||||
} else {
|
} else {
|
||||||
mp_msg(MSGT_AO, MSGL_V,
|
mp_msg(MSGT_AO, MSGL_V,
|
||||||
"audio_setup: frags: %3d/%d (%d bytes/frag) free: %6d\n",
|
"audio_setup: frags: %3d/%d (%d bytes/frag) free: %6d\n",
|
||||||
zz.fragments, zz.fragstotal, zz.fragsize, zz.bytes);
|
p->zz.fragments, p->zz.fragstotal, p->zz.fragsize, p->zz.bytes);
|
||||||
if (ao->buffersize == -1)
|
if (ao->buffersize == -1)
|
||||||
ao->buffersize = zz.bytes;
|
ao->buffersize = p->zz.bytes;
|
||||||
ao->outburst = zz.fragsize;
|
ao->outburst = p->zz.fragsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ao->buffersize == -1) {
|
if (ao->buffersize == -1) {
|
||||||
@ -402,12 +411,12 @@ ac3_retry:
|
|||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
FD_SET(audio_fd, &rfds);
|
FD_SET(p->audio_fd, &rfds);
|
||||||
tv.tv_sec = 0;
|
tv.tv_sec = 0;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
if (!select(audio_fd + 1, NULL, &rfds, NULL, &tv))
|
if (!select(p->audio_fd + 1, NULL, &rfds, NULL, &tv))
|
||||||
break;
|
break;
|
||||||
write(audio_fd, data, ao->outburst);
|
write(p->audio_fd, data, ao->outburst);
|
||||||
ao->buffersize += ao->outburst;
|
ao->buffersize += ao->outburst;
|
||||||
}
|
}
|
||||||
free(data);
|
free(data);
|
||||||
@ -430,61 +439,74 @@ ac3_retry:
|
|||||||
// close audio device
|
// close audio device
|
||||||
static void uninit(struct ao *ao, bool immed)
|
static void uninit(struct ao *ao, bool immed)
|
||||||
{
|
{
|
||||||
if (audio_fd == -1)
|
struct priv *p = ao->priv;
|
||||||
|
if (p->audio_fd == -1)
|
||||||
return;
|
return;
|
||||||
#ifdef SNDCTL_DSP_SYNC
|
#ifdef SNDCTL_DSP_SYNC
|
||||||
// to get the buffer played
|
// to get the buffer played
|
||||||
if (!immed)
|
if (!immed)
|
||||||
ioctl(audio_fd, SNDCTL_DSP_SYNC, NULL);
|
ioctl(p->audio_fd, SNDCTL_DSP_SYNC, NULL);
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNDCTL_DSP_RESET
|
#ifdef SNDCTL_DSP_RESET
|
||||||
if (immed)
|
if (immed)
|
||||||
ioctl(audio_fd, SNDCTL_DSP_RESET, NULL);
|
ioctl(p->audio_fd, SNDCTL_DSP_RESET, NULL);
|
||||||
#endif
|
#endif
|
||||||
close(audio_fd);
|
close(p->audio_fd);
|
||||||
audio_fd = -1;
|
p->audio_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void close_device(struct ao *ao)
|
||||||
|
{
|
||||||
|
struct priv *p = ao->priv;
|
||||||
|
#ifdef SNDCTL_DSP_RESET
|
||||||
|
ioctl(p->audio_fd, SNDCTL_DSP_RESET, NULL);
|
||||||
|
#endif
|
||||||
|
close(p->audio_fd);
|
||||||
|
p->audio_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop playing and empty buffers (for seeking/pause)
|
// stop playing and empty buffers (for seeking/pause)
|
||||||
static void reset(struct ao *ao)
|
static void reset(struct ao *ao)
|
||||||
{
|
{
|
||||||
|
struct priv *p = ao->priv;
|
||||||
int oss_format;
|
int oss_format;
|
||||||
uninit(ao, true);
|
close_device(ao);
|
||||||
audio_fd = open(dsp, O_WRONLY);
|
p->audio_fd = open(p->dsp, O_WRONLY);
|
||||||
if (audio_fd < 0) {
|
if (p->audio_fd < 0) {
|
||||||
mp_tmsg(MSGT_AO, MSGL_ERR, "[AO OSS]\nFatal error: *** CANNOT "
|
mp_tmsg(MSGT_AO, MSGL_ERR, "[AO OSS]\nFatal error: *** CANNOT "
|
||||||
"RE-OPEN / RESET AUDIO DEVICE *** %s\n", strerror(errno));
|
"RE-OPEN / RESET AUDIO DEVICE *** %s\n", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(FD_CLOEXEC) && defined(F_SETFD)
|
#if defined(FD_CLOEXEC) && defined(F_SETFD)
|
||||||
fcntl(audio_fd, F_SETFD, FD_CLOEXEC);
|
fcntl(p->audio_fd, F_SETFD, FD_CLOEXEC);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
oss_format = format2oss(ao->format);
|
oss_format = format2oss(ao->format);
|
||||||
if (AF_FORMAT_IS_AC3(ao->format))
|
if (AF_FORMAT_IS_AC3(ao->format))
|
||||||
ioctl(audio_fd, SNDCTL_DSP_SPEED, &ao->samplerate);
|
ioctl(p->audio_fd, SNDCTL_DSP_SPEED, &ao->samplerate);
|
||||||
ioctl(audio_fd, SNDCTL_DSP_SETFMT, &oss_format);
|
ioctl(p->audio_fd, SNDCTL_DSP_SETFMT, &oss_format);
|
||||||
if (!AF_FORMAT_IS_AC3(ao->format)) {
|
if (!AF_FORMAT_IS_AC3(ao->format)) {
|
||||||
if (ao->channels.num > 2)
|
if (ao->channels.num > 2)
|
||||||
ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &ao->channels.num);
|
ioctl(p->audio_fd, SNDCTL_DSP_CHANNELS, &ao->channels.num);
|
||||||
else {
|
else {
|
||||||
int c = ao->channels.num - 1;
|
int c = ao->channels.num - 1;
|
||||||
ioctl(audio_fd, SNDCTL_DSP_STEREO, &c);
|
ioctl(p->audio_fd, SNDCTL_DSP_STEREO, &c);
|
||||||
}
|
}
|
||||||
ioctl(audio_fd, SNDCTL_DSP_SPEED, &ao->samplerate);
|
ioctl(p->audio_fd, SNDCTL_DSP_SPEED, &ao->samplerate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return: how many bytes can be played without blocking
|
// return: how many bytes can be played without blocking
|
||||||
static int get_space(struct ao *ao)
|
static int get_space(struct ao *ao)
|
||||||
{
|
{
|
||||||
|
struct priv *p = ao->priv;
|
||||||
int playsize = ao->outburst;
|
int playsize = ao->outburst;
|
||||||
|
|
||||||
#ifdef SNDCTL_DSP_GETOSPACE
|
#ifdef SNDCTL_DSP_GETOSPACE
|
||||||
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz) != -1) {
|
if (ioctl(p->audio_fd, SNDCTL_DSP_GETOSPACE, &p->zz) != -1) {
|
||||||
// calculate exact buffer space:
|
// calculate exact buffer space:
|
||||||
playsize = zz.fragments * zz.fragsize;
|
playsize = p->zz.fragments * p->zz.fragsize;
|
||||||
return playsize;
|
return playsize;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -495,10 +517,10 @@ static int get_space(struct ao *ao)
|
|||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
FD_SET(audio_fd, &rfds);
|
FD_SET(p->audio_fd, &rfds);
|
||||||
tv.tv_sec = 0;
|
tv.tv_sec = 0;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
if (!select(audio_fd + 1, NULL, &rfds, NULL, &tv))
|
if (!select(p->audio_fd + 1, NULL, &rfds, NULL, &tv))
|
||||||
return 0; // not block!
|
return 0; // not block!
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -509,8 +531,9 @@ static int get_space(struct ao *ao)
|
|||||||
// stop playing, keep buffers (for pause)
|
// stop playing, keep buffers (for pause)
|
||||||
static void audio_pause(struct ao *ao)
|
static void audio_pause(struct ao *ao)
|
||||||
{
|
{
|
||||||
prepause_space = get_space(ao);
|
struct priv *p = ao->priv;
|
||||||
uninit(ao, true);
|
p->prepause_space = get_space(ao);
|
||||||
|
close_device(ao);
|
||||||
}
|
}
|
||||||
|
|
||||||
// plays 'len' bytes of 'data'
|
// plays 'len' bytes of 'data'
|
||||||
@ -518,22 +541,24 @@ static void audio_pause(struct ao *ao)
|
|||||||
// return: number of bytes played
|
// return: number of bytes played
|
||||||
static int play(struct ao *ao, void *data, int len, int flags)
|
static int play(struct ao *ao, void *data, int len, int flags)
|
||||||
{
|
{
|
||||||
|
struct priv *p = ao->priv;
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return len;
|
return len;
|
||||||
if (len > ao->outburst || !(flags & AOPLAY_FINAL_CHUNK)) {
|
if (len > ao->outburst || !(flags & AOPLAY_FINAL_CHUNK)) {
|
||||||
len /= ao->outburst;
|
len /= ao->outburst;
|
||||||
len *= ao->outburst;
|
len *= ao->outburst;
|
||||||
}
|
}
|
||||||
len = write(audio_fd, data, len);
|
len = write(p->audio_fd, data, len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// resume playing, after audio_pause()
|
// resume playing, after audio_pause()
|
||||||
static void audio_resume(struct ao *ao)
|
static void audio_resume(struct ao *ao)
|
||||||
{
|
{
|
||||||
|
struct priv *p = ao->priv;
|
||||||
int fillcnt;
|
int fillcnt;
|
||||||
reset(ao);
|
reset(ao);
|
||||||
fillcnt = get_space(ao) - prepause_space;
|
fillcnt = get_space(ao) - p->prepause_space;
|
||||||
if (fillcnt > 0 && !(ao->format & AF_FORMAT_SPECIAL_MASK)) {
|
if (fillcnt > 0 && !(ao->format & AF_FORMAT_SPECIAL_MASK)) {
|
||||||
void *silence = calloc(fillcnt, 1);
|
void *silence = calloc(fillcnt, 1);
|
||||||
play(ao, silence, fillcnt, 0);
|
play(ao, silence, fillcnt, 0);
|
||||||
@ -541,27 +566,26 @@ static void audio_resume(struct ao *ao)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int audio_delay_method = 2;
|
|
||||||
|
|
||||||
// return: delay in seconds between first and last sample in buffer
|
// return: delay in seconds between first and last sample in buffer
|
||||||
static float get_delay(struct ao *ao)
|
static float get_delay(struct ao *ao)
|
||||||
{
|
{
|
||||||
|
struct priv *p = ao->priv;
|
||||||
/* Calculate how many bytes/second is sent out */
|
/* Calculate how many bytes/second is sent out */
|
||||||
if (audio_delay_method == 2) {
|
if (p->audio_delay_method == 2) {
|
||||||
#ifdef SNDCTL_DSP_GETODELAY
|
#ifdef SNDCTL_DSP_GETODELAY
|
||||||
int r = 0;
|
int r = 0;
|
||||||
if (ioctl(audio_fd, SNDCTL_DSP_GETODELAY, &r) != -1)
|
if (ioctl(p->audio_fd, SNDCTL_DSP_GETODELAY, &r) != -1)
|
||||||
return ((float)r) / (float)ao->bps;
|
return ((float)r) / (float)ao->bps;
|
||||||
#endif
|
#endif
|
||||||
audio_delay_method = 1; // fallback if not supported
|
p->audio_delay_method = 1; // fallback if not supported
|
||||||
}
|
}
|
||||||
if (audio_delay_method == 1) {
|
if (p->audio_delay_method == 1) {
|
||||||
// SNDCTL_DSP_GETOSPACE
|
// SNDCTL_DSP_GETOSPACE
|
||||||
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz) != -1) {
|
if (ioctl(p->audio_fd, SNDCTL_DSP_GETOSPACE, &p->zz) != -1) {
|
||||||
return ((float)(ao->buffersize -
|
return ((float)(ao->buffersize -
|
||||||
zz.bytes)) / (float)ao->bps;
|
p->zz.bytes)) / (float)ao->bps;
|
||||||
}
|
}
|
||||||
audio_delay_method = 0; // fallback if not supported
|
p->audio_delay_method = 0; // fallback if not supported
|
||||||
}
|
}
|
||||||
return ((float)ao->buffersize) / (float)ao->bps;
|
return ((float)ao->buffersize) / (float)ao->bps;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user