Commit b1c459e9 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

aout: add distinct start/stop callbacks (refs #4787, refs #7601)

This would enable the input manager to hold an audio output plugin at
all times. Then it would be possible to keep track of output devices,
volume, policy and (JACK) routing continuously. For this to work,
outputs will need to be patched so that device selection and volume
handling works even when playing back.

Note though that this commit only introduces the change in the
audio_output_t interface; it does not implement the features above.
parent 157d4a8b
......@@ -140,10 +140,9 @@ struct audio_output
{
VLC_COMMON_MEMBERS
audio_sample_format_t format; /**< Output format (plugin can modify it
only when succesfully probed and not afterward) */
struct aout_sys_t *sys; /**< Output plugin private data */
int (*start) (audio_output_t *, audio_sample_format_t *);
void (*stop) (audio_output_t *);
void (*play)(audio_output_t *, block_t *, mtime_t *); /**< Play callback
- queue a block for playback */
void (*pause)( audio_output_t *, bool, mtime_t ); /**< Pause/resume
......@@ -277,6 +276,7 @@ struct aout_fifo_t
typedef struct
{
vlc_mutex_t lock;
audio_sample_format_t format;
aout_fifo_t partial; /**< Audio blocks before packetization */
aout_fifo_t fifo; /**< Packetized audio blocks */
mtime_t pause_date; /**< Date when paused or VLC_TS_INVALID */
......@@ -285,7 +285,7 @@ typedef struct
bool starving; /**< Whether currently starving (to limit error messages) */
} aout_packet_t;
VLC_DEPRECATED void aout_PacketInit(audio_output_t *, aout_packet_t *, unsigned);
VLC_DEPRECATED void aout_PacketInit(audio_output_t *, aout_packet_t *, unsigned, const audio_sample_format_t *);
VLC_DEPRECATED void aout_PacketDestroy(audio_output_t *);
VLC_DEPRECATED void aout_PacketPlay(audio_output_t *, block_t *, mtime_t *);
......
......@@ -49,25 +49,30 @@ static void Play( audio_output_t *aout, block_t *block, mtime_t *drift )
(void) drift;
}
static int Open( vlc_object_t * p_this )
static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
{
audio_output_t * p_aout = (audio_output_t *)p_this;
p_aout->play = Play;
p_aout->pause = NULL;
p_aout->flush = NULL;
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
if( AOUT_FMT_SPDIF( &p_aout->format )
&& var_InheritBool( p_this, "spdif" ) )
if (AOUT_FMT_SPDIF(fmt) && var_InheritBool(aout, "spdif"))
{
p_aout->format.i_format = VLC_CODEC_SPDIFL;
p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->format.i_frame_length = A52_FRAME_NB;
fmt->i_format = VLC_CODEC_SPDIFL;
fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
fmt->i_frame_length = A52_FRAME_NB;
}
else
p_aout->format.i_format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
fmt->i_format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
return VLC_SUCCESS;
}
static int Open(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout->start = Start;
aout->play = Play;
aout->pause = NULL;
aout->flush = NULL;
aout->stop = NULL;
aout->volume_set = NULL;
aout->mute_set = NULL;
return VLC_SUCCESS;
}
......@@ -46,6 +46,7 @@ struct aout_sys_t
void (*reorder) (void *, size_t, unsigned);
float soft_gain;
bool soft_mute;
audio_sample_format_t format;
};
#include "volume.h"
......@@ -159,9 +160,9 @@ static void Flush (audio_output_t *, bool);
static void Reorder71 (void *, size_t, unsigned);
/** Initializes an ALSA playback stream */
static int Open (vlc_object_t *obj)
static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
/* Get device name */
char *device = var_InheritString (aout, "alsa-audio-device");
......@@ -169,7 +170,7 @@ static int Open (vlc_object_t *obj)
return VLC_ENOMEM;
snd_pcm_format_t pcm_format; /* ALSA sample format */
vlc_fourcc_t fourcc = aout->format.i_format;
vlc_fourcc_t fourcc = fmt->i_format;
bool spdif = false;
switch (fourcc)
......@@ -223,7 +224,7 @@ static int Open (vlc_object_t *obj)
pcm_format = SND_PCM_FORMAT_U8;
break;
default:
if (AOUT_FMT_SPDIF(&aout->format))
if (AOUT_FMT_SPDIF(fmt))
spdif = var_InheritBool (aout, "spdif");
if (spdif)
{
......@@ -246,14 +247,14 @@ static int Open (vlc_object_t *obj)
/* ALSA channels */
/* XXX: maybe this should be shared with other dumb outputs */
uint32_t map = var_InheritInteger (aout, "alsa-audio-channels");
map &= aout->format.i_physical_channels;
map &= fmt->i_physical_channels;
if (unlikely(map == 0)) /* WTH? */
map = AOUT_CHANS_STEREO;
unsigned channels = popcount (map);
if (channels < aout_FormatNbChannels (&aout->format))
if (channels < aout_FormatNbChannels (fmt))
msg_Dbg (aout, "downmixing from %u to %u channels",
aout_FormatNbChannels (&aout->format), channels);
aout_FormatNbChannels (fmt), channels);
else
msg_Dbg (aout, "keeping %u channels", channels);
......@@ -264,7 +265,7 @@ static int Open (vlc_object_t *obj)
{
unsigned aes3;
switch (aout->format.i_rate)
switch (fmt->i_rate)
{
#define FS(freq) \
case freq: aes3 = IEC958_AES3_CON_FS_ ## freq; break;
......@@ -287,15 +288,6 @@ static int Open (vlc_object_t *obj)
return VLC_ENOMEM;
}
/* Allocate structures */
aout_sys_t *sys = malloc (sizeof (*sys));
if (unlikely(sys == NULL))
{
free (device);
return VLC_ENOMEM;
}
aout->sys = sys;
/* Open the device */
snd_pcm_t *pcm;
/* VLC always has a resampler. No need for ALSA's. */
......@@ -332,7 +324,6 @@ static int Open (vlc_object_t *obj)
_("The audio device \"%s\" could not be used:\n%s."),
device, snd_strerror (val));
free (device);
free (sys);
return VLC_EGENERIC;
}
sys->pcm = pcm;
......@@ -412,16 +403,15 @@ static int Open (vlc_object_t *obj)
}
/* Set sample rate */
unsigned rate = aout->format.i_rate;
unsigned rate = fmt->i_rate;
val = snd_pcm_hw_params_set_rate_near (pcm, hw, &rate, NULL);
if (val)
{
msg_Err (aout, "cannot set sample rate: %s", snd_strerror (val));
goto error;
}
if (aout->format.i_rate != rate)
msg_Dbg (aout, "resampling from %d Hz to %d Hz",
aout->format.i_rate, rate);
if (fmt->i_rate != rate)
msg_Dbg (aout, "resampling from %d Hz to %d Hz", fmt->i_rate, rate);
/* Set buffer size */
param = AOUT_MAX_ADVANCE_TIME;
......@@ -497,29 +487,26 @@ static int Open (vlc_object_t *obj)
}
/* Setup audio_output_t */
aout->format.i_format = fourcc;
aout->format.i_rate = rate;
fmt->i_format = fourcc;
fmt->i_rate = rate;
sys->reorder = NULL;
if (spdif)
{
aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
aout->format.i_frame_length = A52_FRAME_NB;
aout->volume_set = NULL;
aout->mute_set = NULL;
fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
fmt->i_frame_length = A52_FRAME_NB;
}
else
{
aout->format.i_original_channels =
aout->format.i_physical_channels = map;
fmt->i_original_channels =
fmt->i_physical_channels = map;
switch (popcount (map))
{
case 8:
sys->reorder = Reorder71;
break;
}
aout_SoftVolumeInit (aout);
}
sys->format = *fmt;
aout->play = Play;
if (snd_pcm_hw_params_can_pause (hw))
......@@ -535,13 +522,13 @@ static int Open (vlc_object_t *obj)
{
vlc_value_t text;
var_Create (obj, "audio-device", VLC_VAR_STRING | VLC_VAR_HASCHOICE);
var_Create (aout, "audio-device", VLC_VAR_STRING | VLC_VAR_HASCHOICE);
text.psz_string = _("Audio Device");
var_Change (obj, "audio-device", VLC_VAR_SETTEXT, &text, NULL);
var_Change (aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL);
GetDevices (obj, device);
GetDevices (VLC_OBJECT(aout), device);
}
var_AddCallback (obj, "audio-device", DeviceChanged, NULL);
var_AddCallback (aout, "audio-device", DeviceChanged, NULL);
free (device);
return 0;
......@@ -549,7 +536,6 @@ static int Open (vlc_object_t *obj)
error:
snd_pcm_close (pcm);
free (device);
free (sys);
return VLC_EGENERIC;
}
......@@ -563,7 +549,7 @@ static void Play (audio_output_t *aout, block_t *block,
if (sys->reorder != NULL)
sys->reorder (block->p_buffer, block->i_nb_samples,
aout->format.i_bitspersample / 8);
sys->format.i_bitspersample / 8);
snd_pcm_t *pcm = sys->pcm;
snd_pcm_sframes_t frames;
......@@ -571,19 +557,19 @@ static void Play (audio_output_t *aout, block_t *block,
if (snd_pcm_delay (pcm, &frames) == 0)
{
mtime_t delay = frames * CLOCK_FREQ / aout->format.i_rate;
mtime_t delay = frames * CLOCK_FREQ / sys->format.i_rate;
delay += mdate () - block->i_pts;
if (state != SND_PCM_STATE_RUNNING)
{
if (delay < 0)
{
if (aout->format.i_format != VLC_CODEC_SPDIFL)
if (sys->format.i_format != VLC_CODEC_SPDIFL)
{
frames = (delay * aout->format.i_rate) / -CLOCK_FREQ;
frames = (delay * sys->format.i_rate) / -CLOCK_FREQ;
msg_Dbg (aout, "prepending %ld zeroes", frames);
void *z = calloc (frames, aout->format.i_bytes_per_frame);
void *z = calloc (frames, sys->format.i_bytes_per_frame);
if (likely(z != NULL))
{
snd_pcm_writei (pcm, z, frames);
......@@ -677,18 +663,16 @@ static void Flush (audio_output_t *aout, bool wait)
/**
* Releases the audio output.
*/
static void Close (vlc_object_t *obj)
static void Stop (audio_output_t *aout)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
snd_pcm_t *pcm = aout->sys->pcm;
snd_pcm_t *pcm = sys->pcm;
var_DelCallback (obj, "audio-device", DeviceChanged, NULL);
var_Destroy (obj, "audio-device");
var_DelCallback (aout, "audio-device", DeviceChanged, NULL);
var_Destroy (aout, "audio-device");
snd_pcm_drop (pcm);
snd_pcm_close (pcm);
free (sys);
}
/**
......@@ -837,3 +821,25 @@ static void GetDevices(vlc_object_t *obj, const char *prefs_dev)
}
var_Change(obj, "audio-device", VLC_VAR_SETVALUE, &val, NULL);
}
static int Open(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = malloc (sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
aout->sys = sys;
aout->start = Start;
aout->stop = Stop;
aout_SoftVolumeInit (aout);
return VLC_SUCCESS;
}
static void Close(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
free(sys);
}
......@@ -55,13 +55,22 @@ vlc_module_end ()
struct aout_sys_t
{
void *opaque;
int (*setup) (void **, char *, unsigned *, unsigned *);
union
{
void (*cleanup) (void *opaque);
struct
{
unsigned rate:18;
unsigned channels:14;
};
};
void (*play) (void *opaque, const void *data, unsigned count, int64_t pts);
void (*pause) (void *opaque, int64_t pts);
void (*resume) (void *opaque, int64_t pts);
void (*flush) (void *opaque);
void (*drain) (void *opaque);
int (*set_volume) (void *opaque, float vol, bool mute);
void (*cleanup) (void *opaque);
float volume;
bool mute;
};
......@@ -132,109 +141,116 @@ static int SoftMuteSet (audio_output_t *aout, bool mute)
return 0;
}
typedef int (*vlc_audio_format_cb) (void **, char *, unsigned *, unsigned *);
static int Open (vlc_object_t *obj)
static int Start (audio_output_t *aout, audio_sample_format_t *fmt)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = malloc (sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
aout->sys = sys;
sys->opaque = var_InheritAddress (obj, "amem-data");
sys->play = var_InheritAddress (obj, "amem-play");
sys->pause = var_InheritAddress (obj, "amem-pause");
sys->resume = var_InheritAddress (obj, "amem-resume");
sys->flush = var_InheritAddress (obj, "amem-flush");
sys->drain = var_InheritAddress (obj, "amem-drain");
sys->set_volume = var_InheritAddress (obj, "amem-set-volume");
sys->cleanup = NULL; /* defer */
sys->volume = 1.;
sys->mute = false;
if (sys->play == NULL)
goto error;
vlc_audio_format_cb setup = var_InheritAddress (obj, "amem-setup");
aout_sys_t *sys = aout->sys;
char format[5] = "S16N";
unsigned rate, channels;
unsigned channels;
if (setup != NULL)
if (sys->setup != NULL)
{
rate = aout->format.i_rate;
channels = aout_FormatNbChannels(&aout->format);
channels = aout_FormatNbChannels(fmt);
if (setup (&sys->opaque, format, &rate, &channels))
goto error;
/* Only call this callback if setup succeeded */
sys->cleanup = var_InheritAddress (obj, "amem-cleanup");
if (sys->setup (&sys->opaque, format, &fmt->i_rate, &channels))
return VLC_EGENERIC;
}
else
{
rate = var_InheritInteger (obj, "amem-rate");
channels = var_InheritInteger (obj, "amem-channels");
fmt->i_rate = sys->rate;
channels = sys->channels;
}
if (rate == 0 || rate > 192000
if (fmt->i_rate == 0 || fmt->i_rate > 192000
|| channels == 0 || channels > AOUT_CHAN_MAX)
goto error;
return VLC_EGENERIC;
/* TODO: amem-format */
if (strcmp(format, "S16N"))
{
msg_Err (aout, "format not supported");
goto error;
return VLC_EGENERIC;
}
/* channel mapping */
switch (channels)
{
case 1:
aout->format.i_physical_channels = AOUT_CHAN_CENTER;
fmt->i_physical_channels = AOUT_CHAN_CENTER;
break;
case 2:
aout->format.i_physical_channels =
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
fmt->i_physical_channels = AOUT_CHANS_2_0;
break;
case 3:
aout->format.i_physical_channels =
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
fmt->i_physical_channels = AOUT_CHANS_2_1;
break;
case 4:
aout->format.i_physical_channels =
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
fmt->i_physical_channels = AOUT_CHANS_4_0;
break;
case 5:
aout->format.i_physical_channels =
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
fmt->i_physical_channels = AOUT_CHANS_5_0;
break;
case 6:
aout->format.i_physical_channels =
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
fmt->i_physical_channels = AOUT_CHANS_5_1;
break;
case 7:
aout->format.i_physical_channels =
fmt->i_physical_channels =
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT |
AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
break;
case 8:
aout->format.i_physical_channels =
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
fmt->i_physical_channels = AOUT_CHANS_7_1;
break;
default:
assert(0);
}
aout->format.i_format = VLC_CODEC_S16N;
aout->format.i_rate = rate;
aout->format.i_original_channels = aout->format.i_physical_channels;
fmt->i_format = VLC_CODEC_S16N;
fmt->i_original_channels = fmt->i_physical_channels;
return VLC_SUCCESS;
}
static void Stop (audio_output_t *aout)
{
aout_sys_t *sys = aout->sys;
if (sys->cleanup != NULL)
sys->cleanup (sys->opaque);
}
static int Open (vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = malloc (sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
aout->sys = sys;
sys->opaque = var_InheritAddress (obj, "amem-data");
sys->setup = var_InheritAddress (obj, "amem-setup");
if (sys->setup != NULL)
sys->cleanup = var_InheritAddress (obj, "amem-cleanup");
else
{
sys->rate = var_InheritInteger (obj, "amem-rate");
sys->channels = var_InheritInteger (obj, "amem-channels");
}
sys->play = var_InheritAddress (obj, "amem-play");
sys->pause = var_InheritAddress (obj, "amem-pause");
sys->resume = var_InheritAddress (obj, "amem-resume");
sys->flush = var_InheritAddress (obj, "amem-flush");
sys->drain = var_InheritAddress (obj, "amem-drain");
sys->set_volume = var_InheritAddress (obj, "amem-set-volume");
sys->volume = 1.;
sys->mute = false;
if (sys->play == NULL)
{
free (sys);
return VLC_EGENERIC;
}
aout->start = Start;
aout->stop = Stop;
aout->play = Play;
aout->pause = Pause;
aout->flush = Flush;
......@@ -249,10 +265,6 @@ static int Open (vlc_object_t *obj)
aout->mute_set = SoftMuteSet;
}
return VLC_SUCCESS;
error:
Close (obj);
return VLC_EGENERIC;
}
static void Close (vlc_object_t *obj)
......@@ -260,7 +272,5 @@ static void Close (vlc_object_t *obj)
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
if (sys->cleanup != NULL)
sys->cleanup (sys->opaque);
free (sys);
}
......@@ -79,11 +79,10 @@ vlc_module_end ()
* Open: open the audio device
*****************************************************************************/
static int Open ( vlc_object_t *p_this )
static int Start( audio_output_t *aout, audio_sample_format_t *restrict fmt )
{
audio_output_t *p_aout = (audio_output_t *)p_this;
struct aout_sys_t *p_sys = malloc(sizeof(aout_sys_t));
p_aout->sys = p_sys;
aout_sys_t *p_sys = aout->sys;
OSStatus status = 0;
......@@ -120,13 +119,10 @@ static int Open ( vlc_object_t *p_this )
AudioQueueCallback(NULL, p_sys->audioQueue, buffer);
}
/* Volume is entirely done in software. */
aout_SoftVolumeInit( p_aout );
p_aout->format.i_format = VLC_CODEC_S16L;
p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
p_aout->format.i_rate = 44100;
aout_PacketInit(p_aout, &p_sys->packet, FRAME_SIZE);
fmt->i_format = VLC_CODEC_S16L;
fmt->i_physical_channels = AOUT_CHANS_STEREO;
fmt->i_rate = 44100;
aout_PacketInit(p_aout, &p_sys->packet, FRAME_SIZE, fmt);
p_aout->play = aout_PacketPlay;
p_aout->pause = aout_PacketPause;
p_aout->flush = aout_PacketFlush;
......@@ -156,9 +152,8 @@ static block_t *aout_FifoPop2( aout_fifo_t * p_fifo )
/*****************************************************************************
* Close: close the audio device
*****************************************************************************/
static void Close ( vlc_object_t *p_this )
static void Stop ( audio_output_t *p_aout )
{
audio_output_t *p_aout = (audio_output_t *)p_this;
struct aout_sys_t * p_sys = p_aout->sys;
msg_Dbg(p_aout, "Stopping AudioQueue");
......@@ -166,7 +161,6 @@ static void Close ( vlc_object_t *p_this )
msg_Dbg(p_aout, "Disposing of AudioQueue");
AudioQueueDispose(p_sys->audioQueue, false);
aout_PacketDestroy(p_aout);
free (p_sys);
}
void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
......@@ -195,3 +189,25 @@ void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferR
}
AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
}
static int Open(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = malloc(sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
aout->sys = sys;
aout->start = Start;
aout->stop = Stop;
aout_SoftVolumeInit(aout);
return VLC_SUCCESS;
}
static void Close(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
free(sys);
}
......@@ -174,28 +174,16 @@ static void *InitLibrary(struct aout_sys_t *p_sys)
return p_library;
}
static int Open(vlc_object_t *p_this)
static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
{
struct aout_sys_t *p_sys;
audio_output_t *p_aout = (audio_output_t*)(p_this);
struct aout_sys_t *p_sys = aout->sys:
int status, size;
int afSampleRate, afFrameCount, afLatency, minBufCount, minFrameCount;
int stream_type, channel, rate, format;
p_sys = (struct aout_sys_t*) malloc(sizeof(aout_sys_t));
if (!p_sys)
return VLC_ENOMEM;
p_sys->libmedia = InitLibrary(p_sys);
if (!p_sys->libmedia) {
msg_Err(p_aout, "Could not initialize libmedia.so!");
free(p_sys);
return VLC_EGENERIC;
}
/* 4000 <= frequency <= 48000 */
rate = p_aout->format.i_rate;
rate = fmt->i_rate;
if (rate < 4000)
rate = 4000;
if (rate > 48000)
......@@ -204,22 +192,22 @@ static int Open(vlc_object_t *p_this)
stream_type = MUSIC;
/* We can only accept U8 and S16L */
if (p_aout->format.i_format != VLC_CODEC_U8 && p_aout->format.i_format != VLC_CODEC_S16L)
p_aout->format.i_format = VLC_CODEC_S16L;
format = (p_aout->format.i_format == VLC_CODEC_S16L) ? PCM_16_BIT : PCM_8_BIT;
if (fmt->i_format != VLC_CODEC_U8 && fmt->i_format != VLC_CODEC_S16L)
fmt->i_format = VLC_CODEC_S16L;
format = (fmt->i_format == VLC_CODEC_S16L) ? PCM_16_BIT : PCM_8_BIT;
/* TODO: android supports more channels */
p_aout->format.i_original_channels = p_aout->format.i_physical_channels;
switch(aout_FormatNbChannels(&p_aout->format))
fmt->i_original_channels = fmt->i_physical_channels;
switch(aout_FormatNbChannels(fmt))
{
case 1:
channel = CHANNEL_OUT_MONO;
p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
fmt->i_physical_channels = AOUT_CHAN_CENTER;
break;
case 2:
default:
channel = CHANNEL_OUT_STEREO;
p_aout->format.i_physical_channels = AOUT_CHANS_STEREO;
fmt->i_physical_channels = AOUT_CHANS_STEREO;
break;
}
......@@ -230,8 +218,6 @@ static int Open(vlc_object_t *p_this)
status ^= p_sys->as_getOutputLatency((uint32_t*)(&afLatency), stream_type);
if (status != 0) {
msg_Err(p_aout, "Could not query the AudioStream parameters");
dlclose(p_sys->libmedia);
free(p_sys);
return VLC_EGENERIC;
}
minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate);
......@@ -243,8 +229,6 @@ static int Open(vlc_object_t *p_this)
status = p_sys->at_getMinFrameCount(&minFrameCount, stream_type, rate);
if (status != 0) {
msg_Err(p_aout, "Could not query the AudioTrack parameters");
dlclose(p_sys->libmedia);
free(p_sys);
return VLC_EGENERIC;
}
}
......@@ -253,11 +237,8 @@ static int Open(vlc_object_t *p_this)
/* Sizeof(AudioTrack) == 0x58 (not sure) on 2.2.1, this should be enough */
p_sys->AudioTrack = malloc(SIZE_OF_AUDIOTRACK);
if (!p_sys->AudioTrack) {
dlclose(p_sys->libmedia);
free(p_sys);
if (!p_sys->AudioTrack)
return VLC_ENOMEM;
}
*((uint32_t *) ((uint32_t)p_sys->AudioTrack + SIZE_OF_AUDIOTRACK - 4)) = 0xbaadbaad;
// Higher than android 2.2
......@@ -280,9 +261,7 @@ static int Open(vlc_object_t *p_this)
}
if (status != 0) {
msg_Err(p_aout, "Cannot create AudioTrack!");
dlclose(p_sys->libmedia);
free(p_sys->AudioTrack);
free(p_sys);
return VLC_EGENERIC;
}
......@@ -292,7 +271,7 @@ static int Open(vlc_object_t *p_this)
p_sys->at_start(p_sys->AudioTrack);
p_aout->format.i_rate = rate;
fmt->i_rate = rate;
return VLC_SUCCESS;
}
......@@ -306,8 +285,6 @@ static void Close(vlc_object_t *p_this)
p_sys->at_flush(p_sys->AudioTrack);
p_sys->at_dtor(p_sys->AudioTrack);
free(p_sys->AudioTrack);
dlclose(p_sys->libmedia);
free(p_sys);
}
/* FIXME: lipsync */
......@@ -335,3 +312,34 @@ static void Pause(audio_output_t *p_aout, bool pause, mtime_t date)
p_sys->at_start(p_sys->AudioTrack);
}
}
static int Open(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = malloc(sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
sys->libmedia = InitLibrary(sys);
if (sys->libmedia == NULL) {
msg_Err(aout, "Could not initialize libmedia.so!");
free(sys);
return VLC_EGENERIC;
}
aout->sys = sys;
aout->start = Start;
aout->stop = Stop;
//aout_SoftVolumeInit(aout);
return VLC_SUCCESS;
}
static void Close(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
dlclose(sys->libmedia);
free(sys);
}
This diff is collapsed.
This diff is collapsed.
......@@ -71,7 +71,6 @@ static const int pi_channels_maps[CHANNELS_MAX+1] =
* Local prototypes.
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static void Play ( audio_output_t *, block_t *, mtime_t * );
/*****************************************************************************
......@@ -121,21 +120,17 @@ vlc_module_begin ()
set_capability( "audio output", 0 )
add_shortcut( "file", "audiofile" )
set_callbacks( Open, Close )
set_callbacks( Open, NULL )
vlc_module_end ()
/*****************************************************************************
* Open: open a dummy audio device
*****************************************************************************/
static int Open( vlc_object_t * p_this )
static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
{
audio_output_t * p_aout = (audio_output_t *)p_this;
char * psz_name, * psz_format;
const char * const * ppsz_compare = format_list;
int i_channels, i = 0;
psz_name = var_CreateGetString( p_this, "audiofile-file" );
if( !psz_name || !*psz_name )
psz_name = var_InheritString( p_aout, "audiofile-file" );
if( !psz_name )
{
msg_Err( p_aout, "you need to specify an output file name" );
free( psz_name );
......@@ -164,7 +159,8 @@ static int Open( vlc_object_t * p_this )
p_aout->flush = NULL;
/* Audio format */
psz_format = var_CreateGetString( p_this, "audiofile-format" );
psz_format = var_InheritString( p_aout, "audiofile-format" );
if ( !psz_format ) abort(); /* FIXME */
while ( *ppsz_compare != NULL )
{
......@@ -187,28 +183,22 @@ static int Open( vlc_object_t * p_this )
}
free( psz_format );
p_aout->format.i_format = format_int[i];
if ( AOUT_FMT_SPDIF( &p_aout->format ) )
fmt->i_format = format_int[i];
if ( AOUT_FMT_SPDIF( fmt ) )
{
p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->format.i_frame_length = A52_FRAME_NB;
fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
fmt->i_frame_length = A52_FRAME_NB;
}
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
/* Channels number */
i_channels = var_CreateGetInteger( p_this, "audiofile-channels" );
i_channels = var_InheritInteger( p_aout, "audiofile-channels" );
if( i_channels > 0 && i_channels <= CHANNELS_MAX )
{
p_aout->format.i_physical_channels =
pi_channels_maps[i_channels];
fmt->i_physical_channels = pi_channels_maps[i_channels];
}
/* WAV header */
p_aout->sys->b_add_wav_header = var_CreateGetBool( p_this,
"audiofile-wav" );
p_aout->sys->b_add_wav_header = var_InheritBool( p_aout, "audiofile-wav" );
if( p_aout->sys->b_add_wav_header )
{
/* Write wave header */
......@@ -216,7 +206,7 @@ static int Open( vlc_object_t * p_this )
memset( wh, 0, sizeof(*wh) );
switch( p_aout->format.i_format )
switch( fmt->i_format )
{
case VLC_CODEC_FL32:
wh->Format = WAVE_FORMAT_IEEE_FLOAT;
......@@ -239,8 +229,8 @@ static int Open( vlc_object_t * p_this )
wh->SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
wh->SubChunkLength = 16;
wh->Modus = aout_FormatNbChannels( &p_aout->format );
wh->SampleFreq = p_aout->format.i_rate;
wh->Modus = aout_FormatNbChannels( fmt );
wh->SampleFreq = fmt->i_rate;
wh->BytesPerSample = wh->Modus * ( wh->BitsPerSample / 8 );
wh->BytesPerSec = wh->BytesPerSample * wh->SampleFreq;
......@@ -269,10 +259,8 @@ static int Open( vlc_object_t * p_this )
/*****************************************************************************
* Close: close our file
*****************************************************************************/
static void Close( vlc_object_t * p_this )
static void Stop( audio_output_t *p_aout )
{
audio_output_t * p_aout = (audio_output_t *)p_this;
msg_Dbg( p_aout, "closing audio file" );
if( p_aout->sys->b_add_wav_header )
......@@ -326,3 +314,14 @@ static void Play( audio_output_t * p_aout, block_t *p_buffer,
block_Release( p_buffer );
(void) drift;
}
static int Open(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout->start = Start;
aout->stop = Stop;
aout->volume_set = NULL;
aout->mute_set = NULL;
return VLC_SUCCESS;
}
......@@ -99,26 +99,15 @@ vlc_module_begin ()
set_callbacks( Open, Close )
vlc_module_end ()
/*****************************************************************************
* Open: create a JACK client
*****************************************************************************/
static int Open( vlc_object_t *p_this )
static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
{
char psz_name[32];
audio_output_t *p_aout = (audio_output_t *)p_this;
struct aout_sys_t *p_sys = NULL;
struct aout_sys_t *p_sys = p_aout->sys;
int status = VLC_SUCCESS;
unsigned int i;
int i_error;
/* Allocate structure */
p_sys = calloc( 1, sizeof( aout_sys_t ) );
if( p_sys == NULL )
{
status = VLC_ENOMEM;
goto error_out;
}
p_aout->sys = p_sys;
p_sys->latency = 0;
/* Connect to the JACK server */
......@@ -139,18 +128,18 @@ static int Open( vlc_object_t *p_this )
jack_set_graph_order_callback ( p_sys->p_jack_client, GraphChange, p_aout );
/* JACK only supports fl32 format */
p_aout->format.i_format = VLC_CODEC_FL32;
fmt->i_format = VLC_CODEC_FL32;
// TODO add buffer size callback
p_aout->format.i_rate = jack_get_sample_rate( p_sys->p_jack_client );
fmt->i_rate = jack_get_sample_rate( p_sys->p_jack_client );
p_aout->play = aout_PacketPlay;
p_aout->pause = aout_PacketPause;
p_aout->flush = aout_PacketFlush;
aout_PacketInit( p_aout, &p_sys->packet,
jack_get_buffer_size( p_sys->p_jack_client ) );
jack_get_buffer_size( p_sys->p_jack_client ), fmt );
aout_SoftVolumeInit( p_aout );
p_sys->i_channels = aout_FormatNbChannels( &p_aout->format );
p_sys->i_channels = aout_FormatNbChannels( fmt );
p_sys->p_jack_ports = malloc( p_sys->i_channels *
sizeof(jack_port_t *) );
......@@ -231,7 +220,7 @@ static int Open( vlc_object_t *p_this )
}
msg_Dbg( p_aout, "JACK audio output initialized (%d channels, rate=%d)",
p_sys->i_channels, p_aout->format.i_rate );
p_sys->i_channels, fmt->i_rate );
error_out:
/* Clean up, if an error occurred */
......@@ -245,7 +234,6 @@ error_out:
}
free( p_sys->p_jack_ports );
free( p_sys->p_jack_buffers );
free( p_sys );
}
return status;
}
......@@ -338,10 +326,9 @@ static int GraphChange( void *p_arg )
/*****************************************************************************
* Close: close the JACK client
*****************************************************************************/
static void Close( vlc_object_t *p_this )
static void Stop( audio_output_t *p_aout )
{
int i_error;
audio_output_t *p_aout = (audio_output_t *)p_this;
struct aout_sys_t *p_sys = p_aout->sys;
i_error = jack_deactivate( p_sys->p_jack_client );
......@@ -358,5 +345,26 @@ static void Close( vlc_object_t *p_this )
free( p_sys->p_jack_ports );
free( p_sys->p_jack_buffers );
aout_PacketDestroy( p_aout );
free( p_sys );
}
static int Open(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = calloc(1, sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
aout->sys = sys;
aout->start = Start;
aout->stop = Stop;
aout_SoftVolumeInit(aout);
return VLC_SUCCESS;
}
static void Close(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
free(sys);
}
......@@ -55,7 +55,6 @@ struct aout_sys_t
* Local prototypes
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static void Play ( audio_output_t *_p_aout, block_t *block, mtime_t * );
static ULONG APIENTRY KaiCallback ( PVOID, PVOID, ULONG );
......@@ -94,15 +93,14 @@ vlc_module_begin ()
add_bool( "kai-audio-exclusive-mode", false,
KAI_AUDIO_EXCLUSIVE_MODE_TEXT, KAI_AUDIO_EXCLUSIVE_MODE_LONGTEXT,
true )
set_callbacks( Open, Close )
set_callbacks( Open, NULL )
vlc_module_end ()
/*****************************************************************************
* Open: open the audio device
*****************************************************************************/
static int Open ( vlc_object_t *p_this )
static int Start ( audio_output_t *p_aout, audio_sample_format_t *fmt )
{
audio_output_t *p_aout = (audio_output_t *)p_this;
aout_sys_t *p_sys;
char *psz_mode;
ULONG i_kai_mode;
......@@ -110,7 +108,7 @@ static int Open ( vlc_object_t *p_this )
int i_nb_channels;
int i_bytes_per_frame;
vlc_value_t val, text;
audio_format_t format = p_aout->format;
audio_format_t format = *format;
/* Allocate structure */
p_aout->sys = calloc( 1, sizeof( aout_sys_t ) );
......@@ -201,7 +199,7 @@ static int Open ( vlc_object_t *p_this )
msg_Dbg( p_aout, "obtained i_bytes_per_frame = %d",
format.i_bytes_per_frame );
p_aout->format = format;
*fmt = format;
p_aout->play = Play;
p_aout->pause = aout_PacketPause;
......@@ -267,9 +265,8 @@ static void Play (audio_output_t *p_aout, block_t *block,
/*****************************************************************************
* Close: close the audio device
*****************************************************************************/
static void Close ( vlc_object_t *p_this )
static void Stop ( audio_output_t *p_aout )
{
audio_output_t *p_aout = (audio_output_t *)p_this;
aout_sys_t *p_sys = p_aout->sys;
kaiClose( p_sys->hkai );
......@@ -341,3 +338,13 @@ static ULONG APIENTRY KaiCallback( PVOID p_cb_data,
return i_buf_size;
}
static int Open (vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
/* FIXME: set volume/mute here */
aout->start = Start;
aout->stop = Stop;
return VLC_SUCCESS;
}
......@@ -82,7 +82,6 @@ struct aout_sys_t
* Local prototypes.
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
/*****************************************************************************
* Module descriptor
......@@ -96,7 +95,7 @@ vlc_module_begin ()
set_capability( "audio output", 170 )
add_shortcut( "opensles", "android" )
set_callbacks( Open, Close )
set_callbacks( Open, NULL )
vlc_module_end ()
......@@ -235,9 +234,8 @@ static void PlayedCallback (SLAndroidSimpleBufferQueueItf caller, void *pContext
/*****************************************************************************
* Open
*****************************************************************************/
static int Open( vlc_object_t *p_this )
static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
{
audio_output_t *p_aout = (audio_output_t *)p_this;
SLresult result;
SLEngineItf engineEngine;
......@@ -321,7 +319,7 @@ static int Open( vlc_object_t *p_this )
SLDataFormat_PCM format_pcm;
format_pcm.formatType = SL_DATAFORMAT_PCM;
format_pcm.numChannels = 2;
format_pcm.samplesPerSec = ((SLuint32) p_aout->format.i_rate * 1000) ;
format_pcm.samplesPerSec = ((SLuint32) fmt->i_rate * 1000) ;
format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
......@@ -368,13 +366,13 @@ static int Open( vlc_object_t *p_this )
p_sys->pp_last = &p_sys->p_chain;
// we want 16bit signed data little endian.
p_aout->format.i_format = VLC_CODEC_S16L;
p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
p_aout->play = Play;
p_aout->pause = Pause;
p_aout->flush = Flush;
fmt->i_format = VLC_CODEC_S16L;
fmt->i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
p_aout->play = Play;
p_aout->pause = Pause;
p_aout->flush = Flush;
aout_FormatPrepare( &p_aout->format );
aout_FormatPrepare( fmt );
return VLC_SUCCESS;
error:
......@@ -385,9 +383,8 @@ error:
/*****************************************************************************
* Close
*****************************************************************************/
static void Close( vlc_object_t *p_this )
static void Stop( audio_output_t *p_aout )
{
audio_output_t *p_aout = (audio_output_t*)p_this;
aout_sys_t *p_sys = p_aout->sys;
SetPlayState( p_sys->playerPlay, SL_PLAYSTATE_STOPPED );
......@@ -397,3 +394,13 @@ static void Close( vlc_object_t *p_this )
vlc_mutex_destroy( &p_sys->lock );
Clean( p_sys );
}
static int Open (vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
/* FIXME: set volume/mute here */
aout->start = Start;
aout->stop = Stop;
return VLC_SUCCESS;
}
......@@ -59,7 +59,6 @@ struct aout_sys_t
};
static int Open (vlc_object_t *);
static void Close (vlc_object_t *);
#define AUDIO_DEV_TEXT N_("Audio output device")
#define AUDIO_DEV_LONGTEXT N_("OSS device node path.")
......@@ -72,7 +71,7 @@ vlc_module_begin ()
add_string ("oss-audio-device", "",
AUDIO_DEV_TEXT, AUDIO_DEV_LONGTEXT, false)
set_capability( "audio output", 100 )
set_callbacks( Open, Close )
set_callbacks (Open, NULL)
vlc_module_end ()
static void Play (audio_output_t *, block_t *, mtime_t *);
......@@ -93,7 +92,7 @@ static int DeviceChanged (vlc_object_t *obj, const char *varname,
return VLC_SUCCESS;
}
static int Open (vlc_object_t *obj)
static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
{
audio_output_t *aout = (audio_output_t *)obj;
......@@ -124,10 +123,9 @@ static int Open (vlc_object_t *obj)
/* Select audio format */
int format;
vlc_fourcc_t fourcc = aout->format.i_format;
bool spdif = false;
switch (fourcc)
switch (fmt->i_format)
{
#ifdef AFMT_FLOAT
case VLC_CODEC_F64B:
......@@ -154,7 +152,7 @@ static int Open (vlc_object_t *obj)
format = AFMT_U8;
break;
default:
if (AOUT_FMT_SPDIF(&aout->format))
if (AOUT_FMT_SPDIF(fmt))
spdif = var_InheritBool (aout, "spdif");
if (spdif)
format = AFMT_AC3;
......@@ -174,21 +172,21 @@ static int Open (vlc_object_t *obj)
switch (format)
{
case AFMT_S8: fourcc = VLC_CODEC_S8; break;
case AFMT_U8: fourcc = VLC_CODEC_U8; break;
case AFMT_S16_BE: fourcc = VLC_CODEC_S16B; break;
case AFMT_S16_LE: fourcc = VLC_CODEC_S16L; break;
case AFMT_S8: fmt->i_format = VLC_CODEC_S8; break;
case AFMT_U8: fmt->i_format = VLC_CODEC_U8; break;
case AFMT_S16_BE: fmt->i_format = VLC_CODEC_S16B; break;
case AFMT_S16_LE: fmt->i_format = VLC_CODEC_S16L; break;
//case AFMT_S24_BE:
//case AFMT_S24_LE:
case AFMT_S32_BE: fourcc = VLC_CODEC_S32B; break;
case AFMT_S32_LE: fourcc = VLC_CODEC_S32L; break;
case AFMT_S32_BE: fmt->i_format = VLC_CODEC_S32B; break;
case AFMT_S32_LE: fmt->i_format = VLC_CODEC_S32L; break;
#ifdef AFMT_FLOAT
case AFMT_FLOAT: fourcc = VLC_CODEC_FL32; break;
case AFMT_FLOAT: fmt->i_format = VLC_CODEC_FL32; break;
#endif
case AFMT_AC3:
if (spdif)
{
fourcc = VLC_CODEC_SPDIFL;
fmt->i_format = VLC_CODEC_SPDIFL;
break;
}
default:
......@@ -197,7 +195,7 @@ static int Open (vlc_object_t *obj)
}
/* Select channels count */
int channels = spdif ? 2 : aout_FormatNbChannels (&aout->format);
int channels = spdif ? 2 : aout_FormatNbChannels (fmt);
if (ioctl (fd, SNDCTL_DSP_CHANNELS, &channels) < 0)
{
msg_Err (aout, "cannot set %d channels: %m", channels);
......@@ -217,7 +215,7 @@ static int Open (vlc_object_t *obj)
}
/* Select sample rate */
int rate = spdif ? 48000 : aout->format.i_rate;
int rate = spdif ? 48000 : fmt->i_rate;
if (ioctl (fd, SNDCTL_DSP_SPEED, &rate) < 0)
{
msg_Err (aout, "cannot set %d Hz sample rate: %m", rate);
......@@ -225,7 +223,6 @@ static int Open (vlc_object_t *obj)
}
/* Setup audio_output_t */
aout->format.i_format = fourcc;
aout->play = Play;
aout->pause = Pause;
aout->flush = Flush;
......@@ -234,14 +231,14 @@ static int Open (vlc_object_t *obj)
if (spdif)
{
aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
aout->format.i_frame_length = A52_FRAME_NB;
fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
fmt->i_frame_length = A52_FRAME_NB;
}
else
{
aout->format.i_rate = rate;
aout->format.i_original_channels =
aout->format.i_physical_channels = channels;
fmt->i_rate = rate;
fmt->i_original_channels =
fmt->i_physical_channels = channels;
sys->level = 100;
sys->mute = false;
......@@ -303,9 +300,8 @@ error:
/**
* Releases the audio output.
*/
static void Close (vlc_object_t *obj)
static void Stop (audio_output_t *aout)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
int fd = sys->fd;
......@@ -445,3 +441,13 @@ static int MuteSet (audio_output_t *aout, bool mute)
aout_MuteReport (aout, mute);
return 0;
}
static int Open (vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
/* FIXME: set volume/mute here */
aout->start = Start;
aout->stop = Stop;
return VLC_SUCCESS;
}
......@@ -134,13 +134,15 @@ static inline aout_packet_t *aout_packet (audio_output_t *aout)
return (aout_packet_t *)(aout->sys);
}
void aout_PacketInit (audio_output_t *aout, aout_packet_t *p, unsigned samples)
void aout_PacketInit (audio_output_t *aout, aout_packet_t *p, unsigned samples,
const audio_sample_format_t *fmt)
{
assert (p == aout_packet (aout));
vlc_mutex_init (&p->lock);
aout_FifoInit (&p->partial, aout->format.i_rate);
aout_FifoInit (&p->fifo, aout->format.i_rate);
p->format = *fmt;
aout_FifoInit (&p->partial, p->format.i_rate);
aout_FifoInit (&p->fifo, p->format.i_rate);
p->pause_date = VLC_TS_INVALID;
p->time_report = INT64_MIN;
p->samples = samples;
......@@ -253,9 +255,9 @@ static block_t *aout_OutputSlice (audio_output_t *p_aout)
available += p_buffer->i_nb_samples;
}
if( AOUT_FMT_LINEAR( &p_aout->format ) )
if( AOUT_FMT_LINEAR( &p->format ) )
{
const unsigned framesize = p_aout->format.i_bytes_per_frame;
const unsigned framesize = p->format.i_bytes_per_frame;
/* Build packet with adequate number of samples */
unsigned needed = samples * framesize;
......@@ -285,7 +287,7 @@ static block_t *aout_OutputSlice (audio_output_t *p_aout)
needed /= framesize;
p_fifo->p_first->i_nb_samples -= needed;
mtime_t t = needed * CLOCK_FREQ / p_aout->format.i_rate;
mtime_t t = needed * CLOCK_FREQ / p->format.i_rate;
p_fifo->p_first->i_pts += t;
p_fifo->p_first->i_length -= t;
break;
......@@ -322,7 +324,7 @@ block_t *aout_PacketNext (audio_output_t *p_aout, mtime_t start_date)
aout_packet_t *p = aout_packet (p_aout);
aout_fifo_t *p_fifo = &p->fifo;
block_t *p_buffer;
const bool b_can_sleek = !AOUT_FMT_LINEAR(&p_aout->format);
const bool b_can_sleek = !AOUT_FMT_LINEAR(&p->format);
const mtime_t now = mdate ();
const mtime_t threshold =
(b_can_sleek ? start_date : now) - AOUT_MAX_PTS_DELAY;
......
This diff is collapsed.
......@@ -32,7 +32,7 @@
#include <sndio.h>
static int Open (vlc_object_t *);
static void Close (vlc_object_t *);
static void Close (vlc_objec_t *);
vlc_module_begin ()
set_shortname ("sndio")
......@@ -40,7 +40,7 @@ vlc_module_begin ()
set_category (CAT_AUDIO)
set_subcategory (SUBCAT_AUDIO_AOUT)
set_capability ("audio output", 120)
set_callbacks (Open, Close )
set_callbacks (Open, Close)
vlc_module_end ()
static void Play (audio_output_t *, block_t *, mtime_t *);
......@@ -57,12 +57,9 @@ struct aout_sys_t
};
/** Initializes an sndio playback stream */
static int Open (vlc_object_t *obj)
static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = malloc (sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_EGENERIC;
aout_sys_t *sys = aout->sys;
sys->hdl = sio_open (NULL, SIO_PLAY, 0 /* blocking */);
if (sys->hdl == NULL)
......@@ -79,8 +76,8 @@ static int Open (vlc_object_t *obj)
par.bps = par.bits >> 3;
par.sig = 1;
par.le = SIO_LE_NATIVE;
par.pchan = aout_FormatNbChannels (&aout->format);
par.rate = aout->format.i_rate;
par.pchan = aout_FormatNbChannels (fmt);
par.rate = fmt->i_rate;
par.xrun = SIO_SYNC;
if (!sio_setpar (sys->hdl, &par) || !sio_getpar (sys->hdl, &par))
......@@ -96,23 +93,24 @@ static int Open (vlc_object_t *obj)
goto error;
}
audio_format_t f;
switch (par.bits)
{
case 8:
f.i_format = par.sig ? VLC_CODEC_S8 : VLC_CODEC_U8;
fmt->i_format = par.sig ? VLC_CODEC_S8 : VLC_CODEC_U8;
break;
case 16:
f.i_format = par.sig ? (par.le ? VLC_CODEC_S16L : VLC_CODEC_S16B)
fmt->i_format = par.sig
? (par.le ? VLC_CODEC_S16L : VLC_CODEC_S16B)
: (par.le ? VLC_CODEC_U16L : VLC_CODEC_U16B);
break;
case 24:
f.i_format = par.sig ? (par.le ? VLC_CODEC_S24L : VLC_CODEC_S24B)
fmt->i_format = par.sig
? (par.le ? VLC_CODEC_S24L : VLC_CODEC_S24B)
: (par.le ? VLC_CODEC_U24L : VLC_CODEC_U24B);
break;
case 32:
f.i_format = par.sig ? (par.le ? VLC_CODEC_S32L : VLC_CODEC_S32B)
fmt->i_format = par.sig
? (par.le ? VLC_CODEC_S32L : VLC_CODEC_S32B)
: (par.le ? VLC_CODEC_U32L : VLC_CODEC_U32B);
break;
default:
......@@ -121,7 +119,7 @@ static int Open (vlc_object_t *obj)
goto error;
}
f.i_rate = par.rate;
fmt->i_rate = par.rate;
/* Channel map */
unsigned chans;
......@@ -147,10 +145,9 @@ static int Open (vlc_object_t *obj)
goto error;
}
f.i_original_channels = f.i_physical_channels = chans;
aout_FormatPrepare (&f);
fmt->i_original_channels = fmt->i_physical_channels = chans;
aout_FormatPrepare (fmt);
aout->format = f;
aout->sys = sys;
aout->play = Play;
aout->pause = Pause;
......@@ -170,7 +167,7 @@ static int Open (vlc_object_t *obj)
return VLC_SUCCESS;
error:
Close (obj);
sio_close (sys->hdl);
return VLC_EGENERIC;
}
......@@ -180,7 +177,6 @@ static void Close (vlc_object_t *obj)
aout_sys_t *sys = aout->sys;
sio_close (sys->hdl);
free (sys);
}
static void Play (audio_output_t *aout, block_t *block,
......@@ -250,3 +246,26 @@ static int MuteSet (audio_output_t *aout, bool mute)
sys->mute = mute;
return 0;
}
static int Open (vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = malloc (sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
aout->sys = sys;
aout->start = Start;
aout->stop = Stop;
/* FIXME: set volume/mute here */
return VLC_SUCCESS;
}
static int Close (vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
free (sys);
}
......@@ -121,6 +121,8 @@ struct aout_sys_t
struct IAudioSessionEvents events;
LONG refs;
unsigned rate; /**< Sample rate */
unsigned bytes_per_frame;
UINT32 frames; /**< Total buffer size (frames) */
HANDLE ready; /**< Semaphore from MTA thread */
HANDLE done; /**< Semaphore to MTA thread */
......@@ -173,7 +175,7 @@ static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
break;
}
const size_t copy = frames * (size_t)aout->format.i_bytes_per_frame;
const size_t copy = frames * sys->bytes_per_frame;
memcpy(dst, block->p_buffer, copy);
hr = IAudioRenderClient_ReleaseBuffer(sys->render, frames, 0);
......@@ -192,7 +194,7 @@ static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
/* Out of buffer space, sleep */
msleep(AOUT_MIN_PREPARE_TIME
+ block->i_nb_samples * CLOCK_FREQ / aout->format.i_rate);
+ block->i_nb_samples * CLOCK_FREQ / sys->rate);
}
Leave();
......@@ -653,20 +655,11 @@ fail:
ReleaseSemaphore(sys->ready, 1, NULL);
}
static int Open(vlc_object_t *obj)
static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
HRESULT hr;
if (AOUT_FMT_SPDIF(&aout->format) && !aout->b_force
&& var_InheritBool(aout, "spdif"))
/* Fallback to other plugin until pass-through is implemented */
return VLC_EGENERIC;
aout_sys_t *sys = malloc(sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
sys->aout = aout;
sys->client = NULL;
sys->render = NULL;
sys->clock = NULL;
......@@ -674,17 +667,8 @@ static int Open(vlc_object_t *obj)
sys->refs = 1;
sys->ready = NULL;
sys->done = NULL;
aout->sys = sys;
if (TryEnter(aout))
{
free(sys);
return VLC_EGENERIC;
}
retry:
/* Get audio device according to policy */
var_Create (aout, "audio-device", VLC_VAR_STRING|VLC_VAR_HASCHOICE);
Enter();
IMMDeviceEnumerator *devs;
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
&IID_IMMDeviceEnumerator, (void **)&devs);
......@@ -693,6 +677,9 @@ retry:
msg_Dbg(aout, "cannot create device enumerator (error 0x%lx)", hr);
goto error;
}
retry:
/* Get audio device according to policy */
var_Create (aout, "audio-device", VLC_VAR_STRING|VLC_VAR_HASCHOICE);
// Without configuration item, the variable must be created explicitly.
var_Create (aout, "wasapi-audio-device", VLC_VAR_STRING);
......@@ -741,11 +728,10 @@ retry:
}
/* Configure audio stream */
audio_sample_format_t format = aout->format;
WAVEFORMATEXTENSIBLE wf;
WAVEFORMATEX *pwf;
vlc_ToWave(&wf, &format);
vlc_ToWave(&wf, fmt);
hr = IAudioClient_IsFormatSupported(sys->client, AUDCLNT_SHAREMODE_SHARED,
&wf.Format, &pwf);
if (FAILED(hr))
......@@ -757,7 +743,7 @@ retry:
if (hr == S_FALSE)
{
assert(pwf != NULL);
if (vlc_FromWave(pwf, &format))
if (vlc_FromWave(pwf, fmt))
{
CoTaskMemFree(pwf);
msg_Err(aout, "unsupported audio format");
......@@ -799,15 +785,11 @@ retry:
Leave();
aout->format = format;
sys->rate = fmt->i_rate;
sys->bytes_per_frame = fmt->i_bytes_per_frame;
aout->play = Play;
aout->pause = Pause;
aout->flush = Flush;
/*if (AOUT_FMT_LINEAR(&format) && !exclusive)*/
{
aout->volume_set = SimpleVolumeSet;
aout->mute_set = SimpleMuteSet;
}
if (likely(sys->control != NULL))
IAudioSessionControl_RegisterAudioSessionNotification(sys->control,
&sys->events);
......@@ -828,13 +810,11 @@ error:
goto retry;
}
Leave();
free(sys);
return VLC_EGENERIC;
}
static void Close (vlc_object_t *obj)
static void Stop(audio_output_t *aout)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
Enter();
......@@ -852,5 +832,40 @@ static void Close (vlc_object_t *obj)
CloseHandle(sys->done);
CloseHandle(sys->ready);
}
static int Open(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
if (!aout->b_force && var_InheritBool(aout, "spdif"))
/* Fallback to other plugin until pass-through is implemented */
return VLC_EGENERIC;
aout_sys_t *sys = malloc(sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
if (TryEnter(aout))
{
free(sys);
return VLC_EGENERIC;
}
Leave();
sys->aout = aout;
aout->sys = sys;
aout->start = Start;
aout->stop = Stop;
aout->volume_set = SimpleVolumeSet; /* FIXME */
aout->mute_set = SimpleMuteSet;
return VLC_SUCCESS;
}
static void Close(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
free(sys);
}
This diff is collapsed.
......@@ -76,64 +76,71 @@ static int aout_OutputGainRequest (audio_output_t *aout, float gain)
*****************************************************************************
* This function is entered with the mixer lock.
*****************************************************************************/
int aout_OutputNew( audio_output_t *p_aout,
const audio_sample_format_t * p_format )
int aout_OutputNew (audio_output_t *aout, const audio_sample_format_t *fmtp)
{
aout_owner_t *owner = aout_owner (p_aout);
aout_owner_t *owner = aout_owner (aout);
audio_sample_format_t fmt = *fmtp;
aout_FormatPrepare (&fmt);
aout_assert_locked( p_aout );
p_aout->format = *p_format;
aout_FormatPrepare( &p_aout->format );
aout_assert_locked (aout);
p_aout->event.volume_report = aout_OutputVolumeReport;
p_aout->event.mute_report = aout_OutputMuteReport;
p_aout->event.policy_report = aout_OutputPolicyReport;
p_aout->event.gain_request = aout_OutputGainRequest;
aout->event.volume_report = aout_OutputVolumeReport;
aout->event.mute_report = aout_OutputMuteReport;
aout->event.policy_report = aout_OutputPolicyReport;
aout->event.gain_request = aout_OutputGainRequest;
/* Find the best output plug-in. */
owner->module = module_need (p_aout, "audio output", "$aout", false);
owner->module = module_need (aout, "audio output", "$aout", false);
if (owner->module == NULL)
{
msg_Err( p_aout, "no suitable audio output module" );
msg_Err (aout, "no suitable audio output module");
return -1;
}
if (aout->start (aout, &fmt))
{
msg_Err (aout, "module not functional");
module_unneed (aout, owner->module);
owner->module = NULL;
return -1;
}
if (!var_Type (p_aout, "stereo-mode"))
var_Create (p_aout, "stereo-mode",
if (!var_Type (aout, "stereo-mode"))
var_Create (aout, "stereo-mode",
VLC_VAR_INTEGER | VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT);
/* The user may have selected a different channels configuration. */
var_AddCallback (p_aout, "stereo-mode", aout_ChannelsRestart, NULL);
switch (var_GetInteger (p_aout, "stereo-mode"))
var_AddCallback (aout, "stereo-mode", aout_ChannelsRestart, NULL);
switch (var_GetInteger (aout, "stereo-mode"))
{
case AOUT_VAR_CHAN_RSTEREO:
p_aout->format.i_original_channels |= AOUT_CHAN_REVERSESTEREO;
fmt.i_original_channels |= AOUT_CHAN_REVERSESTEREO;
break;
case AOUT_VAR_CHAN_STEREO:
p_aout->format.i_original_channels = AOUT_CHANS_STEREO;
fmt.i_original_channels = AOUT_CHANS_STEREO;
break;
case AOUT_VAR_CHAN_LEFT:
p_aout->format.i_original_channels = AOUT_CHAN_LEFT;
fmt.i_original_channels = AOUT_CHAN_LEFT;
break;
case AOUT_VAR_CHAN_RIGHT:
p_aout->format.i_original_channels = AOUT_CHAN_RIGHT;
fmt.i_original_channels = AOUT_CHAN_RIGHT;
break;
case AOUT_VAR_CHAN_DOLBYS:
p_aout->format.i_original_channels =
AOUT_CHANS_STEREO | AOUT_CHAN_DOLBYSTEREO;
fmt.i_original_channels = AOUT_CHANS_STEREO|AOUT_CHAN_DOLBYSTEREO;
break;
default:
{
if ((p_aout->format.i_original_channels & AOUT_CHAN_PHYSMASK)
if ((fmt.i_original_channels & AOUT_CHAN_PHYSMASK)
!= AOUT_CHANS_STEREO)
break;
vlc_value_t val, txt;
val.i_int = 0;
var_Change (p_aout, "stereo-mode", VLC_VAR_DELCHOICE, &val, NULL);
var_Change (aout, "stereo-mode", VLC_VAR_DELCHOICE, &val, NULL);
txt.psz_string = _("Stereo audio mode");
var_Change (p_aout, "stereo-mode", VLC_VAR_SETTEXT, &txt, NULL);
if (p_aout->format.i_original_channels & AOUT_CHAN_DOLBYSTEREO)
var_Change (aout, "stereo-mode", VLC_VAR_SETTEXT, &txt, NULL);
if (fmt.i_original_channels & AOUT_CHAN_DOLBYSTEREO)
{
val.i_int = AOUT_VAR_CHAN_DOLBYS;
txt.psz_string = _("Dolby Surround");
......@@ -143,33 +150,32 @@ int aout_OutputNew( audio_output_t *p_aout,
val.i_int = AOUT_VAR_CHAN_STEREO;
txt.psz_string = _("Stereo");
}
var_Change (p_aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
var_Change (p_aout, "stereo-mode", VLC_VAR_SETVALUE, &val, NULL);
var_Change (aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
var_Change (aout, "stereo-mode", VLC_VAR_SETVALUE, &val, NULL);
val.i_int = AOUT_VAR_CHAN_LEFT;
txt.psz_string = _("Left");
var_Change (p_aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
if (p_aout->format.i_original_channels & AOUT_CHAN_DUALMONO)
var_Change (aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
if (fmt.i_original_channels & AOUT_CHAN_DUALMONO)
{ /* Go directly to the left channel. */
p_aout->format.i_original_channels = AOUT_CHAN_LEFT;
var_Change (p_aout, "stereo-mode", VLC_VAR_SETVALUE, &val,
NULL);
fmt.i_original_channels = AOUT_CHAN_LEFT;
var_Change (aout, "stereo-mode", VLC_VAR_SETVALUE, &val, NULL);
}
val.i_int = AOUT_VAR_CHAN_RIGHT;
txt.psz_string = _("Right");
var_Change (p_aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
var_Change (aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
val.i_int = AOUT_VAR_CHAN_RSTEREO;
txt.psz_string = _("Reverse stereo");
var_Change (p_aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
var_Change (aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
}
}
aout_FormatPrepare( &p_aout->format );
aout_FormatPrint( p_aout, "output", &p_aout->format );
aout_FormatPrepare (&fmt);
aout_FormatPrint (aout, "output", &fmt );
/* Choose the mixer format. */
owner->mixer_format = p_aout->format;
if (!AOUT_FMT_LINEAR(&p_aout->format))
owner->mixer_format.i_format = p_format->i_format;
owner->mixer_format = fmt;
if (!AOUT_FMT_LINEAR(&fmt))
owner->mixer_format.i_format = fmtp->i_format;
else
/* Most audio filters can only deal with single-precision,
* so lets always use that when hardware supports floating point. */
......@@ -181,16 +187,15 @@ int aout_OutputNew( audio_output_t *p_aout,
owner->mixer_format.i_format = VLC_CODEC_S16N;
aout_FormatPrepare (&owner->mixer_format);
aout_FormatPrint (p_aout, "mixer", &owner->mixer_format);
aout_FormatPrint (aout, "mixer", &owner->mixer_format);
/* Create filters. */
owner->nb_filters = 0;
if (aout_FiltersCreatePipeline (p_aout, owner->filters,
&owner->nb_filters, &owner->mixer_format,
&p_aout->format) < 0)
if (aout_FiltersCreatePipeline (aout, owner->filters, &owner->nb_filters,
&owner->mixer_format, &fmt) < 0)
{
msg_Err( p_aout, "couldn't create audio output pipeline" );
module_unneed (p_aout, owner->module);
msg_Err (aout, "couldn't create audio output pipeline");
module_unneed (aout, owner->module);
owner->module = NULL;
return -1;
}
......@@ -210,6 +215,8 @@ void aout_OutputDelete (audio_output_t *aout)
return;
var_DelCallback (aout, "stereo-mode", aout_ChannelsRestart, NULL);
if (aout->stop != NULL)
aout->stop (aout);
module_unneed (aout, owner->module);
aout->volume_set = NULL;
aout->mute_set = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment