1
mirror of https://code.videolan.org/videolan/vlc synced 2024-07-21 07:24:15 +02:00

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.
This commit is contained in:
Rémi Denis-Courmont 2012-10-20 20:27:48 +03:00
parent 157d4a8bf1
commit b1c459e950
19 changed files with 851 additions and 718 deletions

View File

@ -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 *);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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,7 +141,82 @@ static int SoftMuteSet (audio_output_t *aout, bool mute)
return 0;
}
typedef int (*vlc_audio_format_cb) (void **, char *, unsigned *, unsigned *);
static int Start (audio_output_t *aout, audio_sample_format_t *fmt)
{
aout_sys_t *sys = aout->sys;
char format[5] = "S16N";
unsigned channels;
if (sys->setup != NULL)
{
channels = aout_FormatNbChannels(fmt);
if (sys->setup (&sys->opaque, format, &fmt->i_rate, &channels))
return VLC_EGENERIC;
}
else
{
fmt->i_rate = sys->rate;
channels = sys->channels;
}
if (fmt->i_rate == 0 || fmt->i_rate > 192000
|| channels == 0 || channels > AOUT_CHAN_MAX)
return VLC_EGENERIC;
/* TODO: amem-format */
if (strcmp(format, "S16N"))
{
msg_Err (aout, "format not supported");
return VLC_EGENERIC;
}
/* channel mapping */
switch (channels)
{
case 1:
fmt->i_physical_channels = AOUT_CHAN_CENTER;
break;
case 2:
fmt->i_physical_channels = AOUT_CHANS_2_0;
break;
case 3:
fmt->i_physical_channels = AOUT_CHANS_2_1;
break;
case 4:
fmt->i_physical_channels = AOUT_CHANS_4_0;
break;
case 5:
fmt->i_physical_channels = AOUT_CHANS_5_0;
break;
case 6:
fmt->i_physical_channels = AOUT_CHANS_5_1;
break;
case 7:
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:
fmt->i_physical_channels = AOUT_CHANS_7_1;
break;
default:
assert(0);
}
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)
{
@ -143,98 +227,30 @@ static int Open (vlc_object_t *obj)
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->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");
char format[5] = "S16N";
unsigned rate, channels;
if (setup != NULL)
{
rate = aout->format.i_rate;
channels = aout_FormatNbChannels(&aout->format);
if (setup (&sys->opaque, format, &rate, &channels))
goto error;
/* Only call this callback if setup succeeded */
sys->cleanup = var_InheritAddress (obj, "amem-cleanup");
}
else
{
rate = var_InheritInteger (obj, "amem-rate");
channels = var_InheritInteger (obj, "amem-channels");
free (sys);
return VLC_EGENERIC;
}
if (rate == 0 || rate > 192000
|| channels == 0 || channels > AOUT_CHAN_MAX)
goto error;
/* TODO: amem-format */
if (strcmp(format, "S16N"))
{
msg_Err (aout, "format not supported");
goto error;
}
/* channel mapping */
switch (channels)
{
case 1:
aout->format.i_physical_channels = AOUT_CHAN_CENTER;
break;
case 2:
aout->format.i_physical_channels =
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
break;
case 3:
aout->format.i_physical_channels =
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
break;
case 4:
aout->format.i_physical_channels =
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
break;
case 5:
aout->format.i_physical_channels =
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
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;
break;
case 7:
aout->format.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;
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;
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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -145,23 +145,17 @@ vlc_module_end ()
/*****************************************************************************
* Open: open macosx audio output
*****************************************************************************/
static int Open(vlc_object_t * p_this)
static int Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
{
OSStatus err = noErr;
UInt32 i_param_size = 0;
struct aout_sys_t *p_sys = NULL;
vlc_value_t val;
audio_output_t *p_aout = (audio_output_t *)p_this;
/* Use int here, to match kAudioDevicePropertyDeviceIsAlive
* property size */
int b_alive = false;
/* Allocate structure */
p_aout->sys = malloc(sizeof(aout_sys_t));
if (p_aout->sys == NULL)
return VLC_ENOMEM;
p_sys = p_aout->sys;
p_sys->i_default_dev = 0;
p_sys->i_selected_dev = 0;
@ -183,7 +177,7 @@ static int Open(vlc_object_t * p_this)
p_aout->pause = aout_PacketPause;
p_aout->flush = aout_PacketFlush;
aout_FormatPrint(p_aout, "VLC is looking for:", &p_aout->format);
aout_FormatPrint(p_aout, "VLC is looking for:", fmt);
/* Persistent device variable */
if (var_Type(p_aout->p_libvlc, "macosx-audio-device") == 0)
@ -255,7 +249,7 @@ static int Open(vlc_object_t * p_this)
var_AddCallback(p_aout, "audio-device", AudioDeviceCallback, NULL);
/* Check for Digital mode or Analog output mode */
if (AOUT_FMT_SPDIF (&p_aout->format) && b_supports_digital) {
if (AOUT_FMT_SPDIF (fmt) && b_supports_digital) {
if (OpenSPDIF (p_aout)) {
msg_Dbg(p_aout, "digital output successfully opened");
return VLC_SUCCESS;
@ -271,14 +265,13 @@ error:
/* If we reach this, this aout has failed */
msg_Err(p_aout, "opening the auhal output failed");
var_Destroy(p_aout, "audio-device");
free(p_sys);
return VLC_EGENERIC;
}
/*****************************************************************************
* Open: open and setup a HAL AudioUnit to do analog (multichannel) audio output
*****************************************************************************/
static int OpenAnalog(audio_output_t *p_aout)
static int OpenAnalog(audio_output_t *p_aout, audio_sample_format_t *fmt)
{
struct aout_sys_t *p_sys = p_aout->sys;
OSStatus err = noErr;
@ -374,15 +367,15 @@ static int OpenAnalog(audio_output_t *p_aout)
msg_Dbg(p_aout, "layout of AUHAL has %d channels" , (int)layout->mNumberChannelDescriptions);
/* Initialize the VLC core channel count */
p_aout->format.i_physical_channels = 0;
i_original = p_aout->format.i_original_channels & AOUT_CHAN_PHYSMASK;
fmt->i_physical_channels = 0;
i_original = fmt->i_original_channels & AOUT_CHAN_PHYSMASK;
if (i_original == AOUT_CHAN_CENTER || layout->mNumberChannelDescriptions < 2) {
/* We only need Mono or cannot output more than 1 channel */
p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
fmt->i_physical_channels = AOUT_CHAN_CENTER;
} else if (i_original == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) || layout->mNumberChannelDescriptions < 3) {
/* We only need Stereo or cannot output more than 2 channels */
p_aout->format.i_physical_channels = AOUT_CHAN_RIGHT | AOUT_CHAN_LEFT;
fmt->i_physical_channels = AOUT_CHANS_STEREO;
} else {
/* We want more than stereo and we can do that */
for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; i++) {
@ -390,38 +383,38 @@ static int OpenAnalog(audio_output_t *p_aout)
switch(layout->mChannelDescriptions[i].mChannelLabel) {
case kAudioChannelLabel_Left:
p_aout->format.i_physical_channels |= AOUT_CHAN_LEFT;
fmt->i_physical_channels |= AOUT_CHAN_LEFT;
continue;
case kAudioChannelLabel_Right:
p_aout->format.i_physical_channels |= AOUT_CHAN_RIGHT;
fmt->i_physical_channels |= AOUT_CHAN_RIGHT;
continue;
case kAudioChannelLabel_Center:
p_aout->format.i_physical_channels |= AOUT_CHAN_CENTER;
fmt->i_physical_channels |= AOUT_CHAN_CENTER;
continue;
case kAudioChannelLabel_LFEScreen:
p_aout->format.i_physical_channels |= AOUT_CHAN_LFE;
fmt->i_physical_channels |= AOUT_CHAN_LFE;
continue;
case kAudioChannelLabel_LeftSurround:
p_aout->format.i_physical_channels |= AOUT_CHAN_REARLEFT;
fmt->i_physical_channels |= AOUT_CHAN_REARLEFT;
continue;
case kAudioChannelLabel_RightSurround:
p_aout->format.i_physical_channels |= AOUT_CHAN_REARRIGHT;
fmt->i_physical_channels |= AOUT_CHAN_REARRIGHT;
continue;
case kAudioChannelLabel_RearSurroundLeft:
p_aout->format.i_physical_channels |= AOUT_CHAN_MIDDLELEFT;
fmt->i_physical_channels |= AOUT_CHAN_MIDDLELEFT;
continue;
case kAudioChannelLabel_RearSurroundRight:
p_aout->format.i_physical_channels |= AOUT_CHAN_MIDDLERIGHT;
fmt->i_physical_channels |= AOUT_CHAN_MIDDLERIGHT;
continue;
case kAudioChannelLabel_CenterSurround:
p_aout->format.i_physical_channels |= AOUT_CHAN_REARCENTER;
fmt->i_physical_channels |= AOUT_CHAN_REARCENTER;
continue;
default:
msg_Warn(p_aout, "unrecognized channel form provided by driver: %d", (int)layout->mChannelDescriptions[i].mChannelLabel);
}
}
if (p_aout->format.i_physical_channels == 0) {
p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
if (fmt->i_physical_channels == 0) {
fmt->i_physical_channels = AOUT_CHANS_STEREO;
msg_Err(p_aout, "You should configure your speaker layout with Audio Midi Setup Utility in /Applications/Utilities. Now using Stereo mode.");
dialog_Fatal(p_aout, _("Audio device is not configured"), "%s",
_("You should configure your speaker layout with "
@ -432,14 +425,14 @@ static int OpenAnalog(audio_output_t *p_aout)
free(layout);
} else {
msg_Warn(p_aout, "this driver does not support kAudioDevicePropertyPreferredChannelLayout. BAD DRIVER AUTHOR !!!");
p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
fmt->i_physical_channels = AOUT_CHANS_STEREO;
}
msg_Dbg(p_aout, "selected %d physical channels for device output", aout_FormatNbChannels(&p_aout->format));
msg_Dbg(p_aout, "VLC will output: %s", aout_FormatPrintChannels(&p_aout->format));
msg_Dbg(p_aout, "selected %d physical channels for device output", aout_FormatNbChannels(fmt));
msg_Dbg(p_aout, "VLC will output: %s", aout_FormatPrintChannels(fmt));
memset (&new_layout, 0, sizeof(new_layout));
switch(aout_FormatNbChannels(&p_aout->format)) {
switch(aout_FormatNbChannels(fmt)) {
case 1:
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
break;
@ -447,27 +440,27 @@ static int OpenAnalog(audio_output_t *p_aout)
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
break;
case 3:
if (p_aout->format.i_physical_channels & AOUT_CHAN_CENTER)
if (fmt->i_physical_channels & AOUT_CHAN_CENTER)
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_7; // L R C
else if (p_aout->format.i_physical_channels & AOUT_CHAN_LFE)
else if (fmt->i_physical_channels & AOUT_CHAN_LFE)
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_4; // L R LFE
break;
case 4:
if (p_aout->format.i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_LFE))
if (fmt->i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_LFE))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_10; // L R C LFE
else if (p_aout->format.i_physical_channels & (AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT))
else if (fmt->i_physical_channels & (AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_3; // L R Ls Rs
else if (p_aout->format.i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER))
else if (fmt->i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_3; // L R C Cs
break;
case 5:
if (p_aout->format.i_physical_channels & (AOUT_CHAN_CENTER))
if (fmt->i_physical_channels & (AOUT_CHAN_CENTER))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_19; // L R Ls Rs C
else if (p_aout->format.i_physical_channels & (AOUT_CHAN_LFE))
else if (fmt->i_physical_channels & (AOUT_CHAN_LFE))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_18; // L R Ls Rs LFE
break;
case 6:
if (p_aout->format.i_physical_channels & (AOUT_CHAN_LFE))
if (fmt->i_physical_channels & (AOUT_CHAN_LFE))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_20; // L R Ls Rs C LFE
else
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_6_0; // L R Ls Rs C Cs
@ -483,14 +476,14 @@ static int OpenAnalog(audio_output_t *p_aout)
}
/* Set up the format to be used */
DeviceFormat.mSampleRate = p_aout->format.i_rate;
DeviceFormat.mSampleRate = fmt->i_rate;
DeviceFormat.mFormatID = kAudioFormatLinearPCM;
/* We use float 32. It's the best supported format by both VLC and Coreaudio */
p_aout->format.i_format = VLC_CODEC_FL32;
fmt->i_format = VLC_CODEC_FL32;
DeviceFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
DeviceFormat.mBitsPerChannel = 32;
DeviceFormat.mChannelsPerFrame = aout_FormatNbChannels(&p_aout->format);
DeviceFormat.mChannelsPerFrame = aout_FormatNbChannels(fmt);
/* Calculate framesizes and stuff */
DeviceFormat.mFramesPerPacket = 1;
@ -519,10 +512,8 @@ static int OpenAnalog(audio_output_t *p_aout)
msg_Dbg(p_aout, STREAM_FORMAT_MSG("the actual set AU format is " , DeviceFormat));
/* Do the last VLC aout setups */
aout_FormatPrepare(&p_aout->format);
aout_PacketInit(p_aout, &p_sys->packet, FRAMESIZE);
p_aout->volume_set = VolumeSet;
p_aout->mute_set = MuteSet;
aout_FormatPrepare(fmt);
aout_PacketInit(p_aout, &p_sys->packet, FRAMESIZE, fmt);
/* set the IOproc callback */
input.inputProc = (AURenderCallback) RenderCallbackAnalog;
@ -562,7 +553,7 @@ static int OpenAnalog(audio_output_t *p_aout)
/*****************************************************************************
* Setup a encoded digital stream (SPDIF)
*****************************************************************************/
static int OpenSPDIF (audio_output_t * p_aout)
static int OpenSPDIF (audio_output_t * p_aout, audio_sample_format_t *fmt)
{
struct aout_sys_t *p_sys = p_aout->sys;
OSStatus err = noErr;
@ -690,7 +681,7 @@ static int OpenSPDIF (audio_output_t * p_aout)
p_format_list[j].mFormat.mFormatID == 'iac3' ||
p_format_list[j].mFormat.mFormatID == kAudioFormat60958AC3 ||
p_format_list[j].mFormat.mFormatID == kAudioFormatAC3) {
if (p_format_list[j].mFormat.mSampleRate == p_aout->format.i_rate) {
if (p_format_list[j].mFormat.mSampleRate == fmt->i_rate) {
i_requested_rate_format = j;
break;
} else if (p_format_list[j].mFormat.mSampleRate == p_sys->sfmt_revert.mSampleRate)
@ -728,16 +719,14 @@ static int OpenSPDIF (audio_output_t * p_aout)
/* Set the format flags */
if (p_sys->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian)
p_aout->format.i_format = VLC_CODEC_SPDIFB;
fmt->i_format = VLC_CODEC_SPDIFB;
else
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;
p_aout->format.i_rate = (unsigned int)p_sys->stream_format.mSampleRate;
aout_FormatPrepare(&p_aout->format);
aout_PacketInit(p_aout, &p_sys->packet, A52_FRAME_NB);
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
fmt->i_format = VLC_CODEC_SPDIFL;
fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
fmt->i_frame_length = A52_FRAME_NB;
fmt->i_rate = (unsigned int)p_sys->stream_format.mSampleRate;
aout_FormatPrepare(fmt);
aout_PacketInit(p_aout, &p_sys->packet, A52_FRAME_NB, fmt);
/* Add IOProc callback */
err = AudioDeviceCreateIOProcID(p_sys->i_selected_dev,
@ -775,9 +764,8 @@ static int OpenSPDIF (audio_output_t * p_aout)
/*****************************************************************************
* Close: Close HAL AudioUnit
*****************************************************************************/
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;
OSStatus err = noErr;
UInt32 i_param_size = 0;
@ -855,7 +843,6 @@ static void Close(vlc_object_t * p_this)
var_DelCallback(p_aout, "audio-device", AudioDeviceCallback, NULL);
aout_PacketDestroy(p_aout);
free(p_sys);
}
/*****************************************************************************
@ -1215,8 +1202,8 @@ static OSStatus RenderCallbackAnalog(vlc_object_t *_p_aout,
&p_sys->p_remainder_buffer[p_sys->i_read_bytes],
i_mData_bytes);
p_sys->i_read_bytes += i_mData_bytes;
current_date += (mtime_t) ((mtime_t) 1000000 / p_aout->format.i_rate) *
(i_mData_bytes / 4 / aout_FormatNbChannels(&p_aout->format)); // 4 is fl32 specific
current_date += (mtime_t) ((mtime_t) 1000000 / p_sys->packet.format.i_rate) *
(i_mData_bytes / 4 / aout_FormatNbChannels(&p_sys->packet.format)); // 4 is fl32 specific
if (p_sys->i_read_bytes >= p_sys->i_total_bytes)
p_sys->i_read_bytes = p_sys->i_total_bytes = 0;
@ -1245,8 +1232,8 @@ static OSStatus RenderCallbackAnalog(vlc_object_t *_p_aout,
break;
} else
/* update current_date */
current_date += (mtime_t) ((mtime_t) 1000000 / p_aout->format.i_rate) *
(i_second_mData_bytes / 4 / aout_FormatNbChannels(&p_aout->format)); // 4 is fl32 specific
current_date += (mtime_t) ((mtime_t) 1000000 / p_sys->packet.format.i_rate) *
(i_second_mData_bytes / 4 / aout_FormatNbChannels(&p_sys->packet.format)); // 4 is fl32 specific
block_Release(p_buffer);
} else {
memset((uint8_t *)ioData->mBuffers[0].mData +i_mData_bytes,
@ -1398,3 +1385,26 @@ static int MuteSet(audio_output_t * p_aout, bool 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;
aout->volume_set = VolumeSet;
aout->mute_set = MuteSet;
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);
}

View File

@ -39,8 +39,6 @@
#include "windows_audio_common.h"
#define FRAME_SIZE ((int)p_aout->format.i_rate/20) /* Size in samples */
/*****************************************************************************
* notification_thread_t: DirectX event thread
*****************************************************************************/
@ -98,14 +96,15 @@ struct aout_sys_t
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
static int OpenAudio ( vlc_object_t * );
static void CloseAudio ( vlc_object_t * );
static int Open( vlc_object_t * );
static void Close( vlc_object_t * );
static void Stop( audio_output_t * );
static void Play ( audio_output_t *, block_t *, mtime_t * );
static int VolumeSet ( audio_output_t *, float );
static int MuteSet ( audio_output_t *, bool );
/* local functions */
static void Probe ( audio_output_t * );
static void Probe( audio_output_t *, const audio_sample_format_t * );
static int InitDirectSound ( audio_output_t * );
static int CreateDSBuffer ( audio_output_t *, int, int, int, int, int, bool );
static int CreateDSBufferPCM ( audio_output_t *, vlc_fourcc_t*, int, int, bool );
@ -154,7 +153,7 @@ vlc_module_begin ()
VOLUME_TEXT, VOLUME_LONGTEXT, true )
change_integer_range( DSBVOLUME_MIN, DSBVOLUME_MAX )
set_callbacks( OpenAudio, CloseAudio )
set_callbacks( Open, Close )
vlc_module_end ()
/*****************************************************************************
@ -162,9 +161,8 @@ vlc_module_end ()
*****************************************************************************
* This function opens and setups Direct Sound.
*****************************************************************************/
static int OpenAudio( 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;
vlc_value_t val;
char * psz_speaker;
int i = 0;
@ -173,11 +171,6 @@ static int OpenAudio( vlc_object_t *p_this )
msg_Dbg( p_aout, "Opening DirectSound Audio Output" );
/* Allocate structure */
p_aout->sys = calloc( 1, sizeof( aout_sys_t ) );
if( unlikely( p_aout->sys == NULL ) )
return VLC_ENOMEM;
/* Retrieve config values */
var_Create( p_aout, "directx-audio-float32",
VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
@ -210,7 +203,7 @@ static int OpenAudio( vlc_object_t *p_this )
if( var_Type( p_aout, "audio-device" ) == 0 )
{
Probe( p_aout );
Probe( p_aout, fmt );
}
if( var_Get( p_aout, "audio-device", &val ) < 0 )
@ -222,17 +215,16 @@ static int OpenAudio( vlc_object_t *p_this )
/* Open the device */
if( val.i_int == AOUT_VAR_SPDIF )
{
p_aout->format.i_format = VLC_CODEC_SPDIFL;
fmt->i_format = VLC_CODEC_SPDIFL;
/* Calculate the frame size in bytes */
p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->format.i_frame_length = A52_FRAME_NB;
p_aout->sys->i_frame_size = p_aout->format.i_bytes_per_frame;
fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
fmt->i_frame_length = A52_FRAME_NB;
p_aout->sys->i_frame_size = fmt->i_bytes_per_frame;
if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL,
p_aout->format.i_physical_channels,
aout_FormatNbChannels( &p_aout->format ),
p_aout->format.i_rate,
fmt->i_physical_channels,
aout_FormatNbChannels( fmt ), fmt->i_rate,
p_aout->sys->i_frame_size, false )
!= VLC_SUCCESS )
{
@ -240,26 +232,27 @@ static int OpenAudio( vlc_object_t *p_this )
goto error;
}
aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB );
aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB, fmt );
}
else
{
if( val.i_int == AOUT_VAR_5_1 )
p_aout->format.i_physical_channels = AOUT_CHANS_5_0;
fmt->i_physical_channels = AOUT_CHANS_5_0;
else if( val.i_int == AOUT_VAR_7_1 )
p_aout->format.i_physical_channels = AOUT_CHANS_7_1;
fmt->i_physical_channels = AOUT_CHANS_7_1;
else if( val.i_int == AOUT_VAR_3F2R )
p_aout->format.i_physical_channels = AOUT_CHANS_5_0;
fmt->i_physical_channels = AOUT_CHANS_5_0;
else if( val.i_int == AOUT_VAR_2F2R )
p_aout->format.i_physical_channels = AOUT_CHANS_4_0;
fmt->i_physical_channels = AOUT_CHANS_4_0;
else if( val.i_int == AOUT_VAR_MONO )
p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
fmt->i_physical_channels = AOUT_CHAN_CENTER;
else
p_aout->format.i_physical_channels = AOUT_CHANS_2_0;
fmt->i_physical_channels = AOUT_CHANS_2_0;
if( CreateDSBufferPCM( p_aout, &p_aout->format.i_format,
p_aout->format.i_physical_channels,
p_aout->format.i_rate, false )
aout_FormatPrepare( fmt );
if( CreateDSBufferPCM( p_aout, &fmt->i_format,
fmt->i_physical_channels, fmt->i_rate, false )
!= VLC_SUCCESS )
{
msg_Err( p_aout, "cannot open directx audio device" );
@ -267,8 +260,7 @@ static int OpenAudio( vlc_object_t *p_this )
}
/* Calculate the frame size in bytes */
aout_FormatPrepare( &p_aout->format );
aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE );
aout_PacketInit( p_aout, &p_aout->sys->packet, fmt->i_rate / 20, fmt );
}
p_aout->sys->volume.volume = -1;
@ -315,14 +307,14 @@ static int OpenAudio( vlc_object_t *p_this )
return VLC_SUCCESS;
error:
CloseAudio( VLC_OBJECT(p_aout) );
Stop( p_aout );
return VLC_EGENERIC;
}
/*****************************************************************************
* Probe: probe the audio device for available formats and channels
*****************************************************************************/
static void Probe( audio_output_t * p_aout )
static void Probe( audio_output_t * p_aout, const audio_sample_format_t *fmt )
{
vlc_value_t val, text;
vlc_fourcc_t i_format;
@ -334,10 +326,10 @@ static void Probe( audio_output_t * p_aout )
var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
/* Test for 5.1 support */
if( p_aout->format.i_physical_channels == AOUT_CHANS_5_1 )
if( fmt->i_physical_channels == AOUT_CHANS_5_1 )
{
if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHANS_5_1,
p_aout->format.i_rate, true ) == VLC_SUCCESS )
fmt->i_rate, true ) == VLC_SUCCESS )
{
val.i_int = AOUT_VAR_5_1;
text.psz_string = (char*) "5.1";
@ -350,10 +342,10 @@ static void Probe( audio_output_t * p_aout )
}
/* Test for 7.1 support */
if( p_aout->format.i_physical_channels == AOUT_CHANS_7_1 )
if( fmt->i_physical_channels == AOUT_CHANS_7_1 )
{
if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHANS_7_1,
p_aout->format.i_rate, true ) == VLC_SUCCESS )
fmt->i_rate, true ) == VLC_SUCCESS )
{
val.i_int = AOUT_VAR_7_1;
text.psz_string = (char*) "7.1";
@ -366,10 +358,10 @@ static void Probe( audio_output_t * p_aout )
}
/* Test for 3 Front 2 Rear support */
if( p_aout->format.i_physical_channels == AOUT_CHANS_5_0 )
if( fmt->i_physical_channels == AOUT_CHANS_5_0 )
{
if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHANS_5_0,
p_aout->format.i_rate, true ) == VLC_SUCCESS )
fmt->i_rate, true ) == VLC_SUCCESS )
{
val.i_int = AOUT_VAR_3F2R;
text.psz_string = _("3 Front 2 Rear");
@ -385,11 +377,10 @@ static void Probe( audio_output_t * p_aout )
}
/* Test for 2 Front 2 Rear support */
if( ( p_aout->format.i_physical_channels & AOUT_CHANS_4_0 )
== AOUT_CHANS_4_0 )
if( ( fmt->i_physical_channels & AOUT_CHANS_4_0 ) == AOUT_CHANS_4_0 )
{
if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHANS_4_0,
p_aout->format.i_rate, true ) == VLC_SUCCESS )
fmt->i_rate, true ) == VLC_SUCCESS )
{
val.i_int = AOUT_VAR_2F2R;
text.psz_string = _("2 Front 2 Rear");
@ -406,7 +397,7 @@ static void Probe( audio_output_t * p_aout )
/* Test for stereo support */
if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHANS_2_0,
p_aout->format.i_rate, true ) == VLC_SUCCESS )
fmt->i_rate, true ) == VLC_SUCCESS )
{
val.i_int = AOUT_VAR_STEREO;
text.psz_string = _("Stereo");
@ -422,7 +413,7 @@ static void Probe( audio_output_t * p_aout )
/* Test for mono support */
if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHAN_CENTER,
p_aout->format.i_rate, true ) == VLC_SUCCESS )
fmt->i_rate, true ) == VLC_SUCCESS )
{
val.i_int = AOUT_VAR_MONO;
text.psz_string = _("Mono");
@ -503,12 +494,11 @@ static void Probe( audio_output_t * p_aout )
var_Set( p_aout, "audio-device", val );
/* Test for SPDIF support */
if ( AOUT_FMT_SPDIF( &p_aout->format ) )
if ( AOUT_FMT_SPDIF( fmt ) )
{
if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL,
p_aout->format.i_physical_channels,
aout_FormatNbChannels( &p_aout->format ),
p_aout->format.i_rate,
fmt->i_physical_channels,
aout_FormatNbChannels( fmt ), fmt->i_rate,
AOUT_SPDIF_SIZE, true )
== VLC_SUCCESS )
{
@ -603,9 +593,8 @@ static int MuteSet( audio_output_t *p_aout, bool mute )
/*****************************************************************************
* CloseAudio: close the audio device
*****************************************************************************/
static void CloseAudio( 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;
msg_Dbg( p_aout, "closing audio device" );
@ -629,11 +618,7 @@ static void CloseAudio( vlc_object_t *p_this )
/* finally release the DirectSound object */
if( p_sys->p_dsobject ) IDirectSound_Release( p_sys->p_dsobject );
/* free DSOUND.DLL */
if( p_sys->hdsound_dll ) FreeLibrary( p_sys->hdsound_dll );
free( p_aout->sys->p_device_guid );
free( p_sys );
}
/*****************************************************************************
@ -681,13 +666,6 @@ static int InitDirectSound( audio_output_t *p_aout )
HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
HRESULT (WINAPI *OurDirectSoundEnumerate)(LPDSENUMCALLBACKW, LPVOID);
p_aout->sys->hdsound_dll = LoadLibrary("DSOUND.DLL");
if( p_aout->sys->hdsound_dll == NULL )
{
msg_Warn( p_aout, "cannot open DSOUND.DLL" );
goto error;
}
OurDirectSoundCreate = (void *)
GetProcAddress( p_aout->sys->hdsound_dll,
"DirectSoundCreate" );
@ -742,11 +720,6 @@ static int InitDirectSound( audio_output_t *p_aout )
error:
p_aout->sys->p_dsobject = NULL;
if( p_aout->sys->hdsound_dll )
{
FreeLibrary( p_aout->sys->hdsound_dll );
p_aout->sys->hdsound_dll = NULL;
}
return VLC_EGENERIC;
}
@ -903,12 +876,12 @@ static int CreateDSBufferPCM( audio_output_t *p_aout, vlc_fourcc_t *i_format,
i_nb_channels > 2 ||
CreateDSBuffer( p_aout, VLC_CODEC_FL32,
i_channels, i_nb_channels, i_rate,
FRAME_SIZE * 4 * i_nb_channels, b_probe )
(i_rate / 20) * 4 * i_nb_channels, b_probe )
!= VLC_SUCCESS )
{
if ( CreateDSBuffer( p_aout, VLC_CODEC_S16L,
i_channels, i_nb_channels, i_rate,
FRAME_SIZE * 2 * i_nb_channels, b_probe )
(i_rate / 20) * 2 * i_nb_channels, b_probe )
!= VLC_SUCCESS )
{
return VLC_EGENERIC;
@ -1079,15 +1052,15 @@ static void* DirectSoundThread( void *data )
/* Detect underruns */
if( l_queued && mtime - last_time >
INT64_C(1000000) * l_queued / p_aout->format.i_rate )
INT64_C(1000000) * l_queued / p_aout->sys->packet.format.i_rate )
{
msg_Dbg( p_aout, "detected underrun!" );
}
last_time = mtime;
/* Try to fill in as many frame buffers as possible */
l_read /= (p_aout->format.i_bytes_per_frame /
p_aout->format.i_frame_length);
l_read /= (p_aout->sys->packet.format.i_bytes_per_frame /
p_aout->sys->packet.format.i_frame_length);
l_queued = p_notif->i_write_slot * i_frame_siz - l_read;
if( l_queued < 0 ) l_queued += (i_frame_siz * FRAMES_NUM);
l_free_slots = (FRAMES_NUM * i_frame_siz - l_queued) / i_frame_siz;
@ -1096,7 +1069,7 @@ static void* DirectSoundThread( void *data )
{
block_t *p_buffer = aout_PacketNext( p_aout,
mtime + INT64_C(1000000) * (i * i_frame_siz + l_queued) /
p_aout->format.i_rate );
p_aout->sys->packet.format.i_rate );
/* If there is no audio data available and we have some buffered
* already, then just wait for the next time */
@ -1108,7 +1081,7 @@ static void* DirectSoundThread( void *data )
/* Sleep a reasonable amount of time */
l_queued += (i * i_frame_siz);
msleep( INT64_C(1000000) * l_queued / p_aout->format.i_rate / 2 );
msleep( INT64_C(1000000) * l_queued / p_aout->sys->packet.format.i_rate / 2 );
}
/* make sure the buffer isn't playing */
@ -1182,3 +1155,34 @@ error:
return nb_devices;
}
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;
sys->hdsound_dll = LoadLibrary(_T("DSOUND.DLL"));
if (sys->hdsound_dll == NULL)
{
msg_Warn(aout, "cannot open DSOUND.DLL");
free(sys);
return VLC_EGENERIC;
}
aout->sys = sys;
aout->start = Start;
aout->stop = Stop;
aout->volume_set = NULL; /* FIXME */
aout->mute_set = NULL;
return VLC_SUCCESS;
}
static void Close(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
FreeLibrary(sys->hdsound_dll); /* free DSOUND.DLL */
free(sys);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -68,7 +68,8 @@ struct aout_sys_t
mtime_t last_pts; /**< Play time of buffer write offset */
mtime_t paused; /**< Time when (last) paused */
mtime_t desync; /**< Measured desynchronization */
unsigned rate; /**< Current stream sample rate */
unsigned nominal_rate; /**< Nominal stream sample rate */
unsigned actual_rate; /**< Current stream sample rate */
};
static void sink_list_cb(pa_context *, const pa_sink_info *, int, void *);
@ -180,7 +181,7 @@ static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol,
static void stream_reset_sync(pa_stream *s, audio_output_t *aout)
{
aout_sys_t *sys = aout->sys;
const unsigned rate = aout->format.i_rate;
const unsigned rate = sys->nominal_rate;
sys->first_pts = VLC_TS_INVALID;
sys->last_pts = VLC_TS_INVALID;
@ -189,7 +190,7 @@ static void stream_reset_sync(pa_stream *s, audio_output_t *aout)
if (unlikely(op == NULL))
return;
pa_operation_unref(op);
sys->rate = rate;
sys->actual_rate = rate;
}
static void stream_start_now(pa_stream *s, audio_output_t *aout)
@ -302,8 +303,8 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
//msg_Dbg(aout, "desync: %+"PRId64" us (variation: %+"PRId64" us)",
// delta, change);
const unsigned inrate = aout->format.i_rate;
unsigned outrate = sys->rate;
const unsigned inrate = sys->nominal_rate;
unsigned outrate = sys->actual_rate;
bool sync = false;
if (delta < -AOUT_MAX_PTS_DELAY)
@ -325,7 +326,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
int limit = inrate >> 10;
/* However, to improve stability and try to converge, closing to the
* nominal rate is favored over drifting from it. */
if ((adj > 0) == (sys->rate > inrate))
if ((adj > 0) == (sys->actual_rate > inrate))
limit *= 2;
if (adj > +limit)
adj = +limit;
@ -342,7 +343,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
outrate = inrate - limit;
/* Apply adjusted sample rate */
if (outrate == sys->rate)
if (outrate == sys->actual_rate)
return;
pa_operation *op = pa_stream_update_sample_rate(s, outrate, NULL, NULL);
if (unlikely(op == NULL)) {
@ -351,7 +352,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
}
pa_operation_unref(op);
msg_Dbg(aout, "changed sample rate to %u Hz",outrate);
sys->rate = outrate;
sys->actual_rate = outrate;
}
@ -699,36 +700,31 @@ static int StreamMove(vlc_object_t *obj, const char *varname, vlc_value_t old,
return (op != NULL) ? VLC_SUCCESS : VLC_EGENERIC;
}
static void Stop(audio_output_t *);
/**
* Create a PulseAudio playback stream, a.k.a. a sink input.
*/
static int Open(vlc_object_t *obj)
static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
{
#if !PA_CHECK_VERSION(0,9,22)
if (!vlc_xlib_init(obj))
return VLC_EGENERIC;
#endif
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
pa_operation *op;
/* Sample format specification */
struct pa_sample_spec ss;
vlc_fourcc_t format = aout->format.i_format;
#if PA_CHECK_VERSION(1,0,0)
pa_encoding_t encoding = PA_ENCODING_INVALID;
#endif
switch(format)
switch (fmt->i_format)
{
case VLC_CODEC_F64B:
format = VLC_CODEC_F32B;
fmt->i_format = VLC_CODEC_F32B;
case VLC_CODEC_F32B:
ss.format = PA_SAMPLE_FLOAT32BE;
break;
case VLC_CODEC_F64L:
format = VLC_CODEC_F32L;
fmt->i_format = VLC_CODEC_F32L;
case VLC_CODEC_F32L:
ss.format = PA_SAMPLE_FLOAT32LE;
break;
@ -751,28 +747,28 @@ static int Open(vlc_object_t *obj)
ss.format = PA_SAMPLE_S16LE;
break;
case VLC_CODEC_S8:
format = VLC_CODEC_U8;
fmt->i_format = VLC_CODEC_U8;
case VLC_CODEC_U8:
ss.format = PA_SAMPLE_U8;
break;
#if PA_CHECK_VERSION(1,0,0)
case VLC_CODEC_A52:
format = VLC_CODEC_SPDIFL;
fmt->i_format = VLC_CODEC_SPDIFL;
encoding = PA_ENCODING_AC3_IEC61937;
ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
break;
/*case VLC_CODEC_EAC3:
format = VLC_CODEC_SPDIFL FIXME;
fmt->i_format = VLC_CODEC_SPDIFL FIXME;
encoding = PA_ENCODING_EAC3_IEC61937;
ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
break;
case VLC_CODEC_MPGA:
format = VLC_CODEC_SPDIFL FIXME;
fmt->i_format = VLC_CODEC_SPDIFL FIXME;
encoding = PA_ENCODING_MPEG_IEC61937;
ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
break;*/
case VLC_CODEC_DTS:
format = VLC_CODEC_SPDIFL;
fmt->i_format = VLC_CODEC_SPDIFL;
encoding = PA_ENCODING_DTS_IEC61937;
ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
break;
@ -780,19 +776,19 @@ static int Open(vlc_object_t *obj)
default:
if (HAVE_FPU)
{
format = VLC_CODEC_FL32;
fmt->i_format = VLC_CODEC_FL32;
ss.format = PA_SAMPLE_FLOAT32NE;
}
else
{
format = VLC_CODEC_S16N;
fmt->i_format = VLC_CODEC_S16N;
ss.format = PA_SAMPLE_S16NE;
}
break;
}
ss.rate = aout->format.i_rate;
ss.channels = aout_FormatNbChannels(&aout->format);
ss.rate = fmt->i_rate;
ss.channels = aout_FormatNbChannels(fmt);
if (!pa_sample_spec_valid(&ss)) {
msg_Err(aout, "unsupported sample specification");
return VLC_EGENERIC;
@ -802,28 +798,28 @@ static int Open(vlc_object_t *obj)
struct pa_channel_map map;
map.channels = 0;
if (aout->format.i_physical_channels & AOUT_CHAN_LEFT)
if (fmt->i_physical_channels & AOUT_CHAN_LEFT)
map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
if (aout->format.i_physical_channels & AOUT_CHAN_RIGHT)
if (fmt->i_physical_channels & AOUT_CHAN_RIGHT)
map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
if (aout->format.i_physical_channels & AOUT_CHAN_MIDDLELEFT)
if (fmt->i_physical_channels & AOUT_CHAN_MIDDLELEFT)
map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
if (aout->format.i_physical_channels & AOUT_CHAN_MIDDLERIGHT)
if (fmt->i_physical_channels & AOUT_CHAN_MIDDLERIGHT)
map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
if (aout->format.i_physical_channels & AOUT_CHAN_REARLEFT)
if (fmt->i_physical_channels & AOUT_CHAN_REARLEFT)
map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
if (aout->format.i_physical_channels & AOUT_CHAN_REARRIGHT)
if (fmt->i_physical_channels & AOUT_CHAN_REARRIGHT)
map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
if (aout->format.i_physical_channels & AOUT_CHAN_REARCENTER)
if (fmt->i_physical_channels & AOUT_CHAN_REARCENTER)
map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
if (aout->format.i_physical_channels & AOUT_CHAN_CENTER)
if (fmt->i_physical_channels & AOUT_CHAN_CENTER)
{
if (ss.channels == 1)
map.map[map.channels++] = PA_CHANNEL_POSITION_MONO;
else
map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
}
if (aout->format.i_physical_channels & AOUT_CHAN_LFE)
if (fmt->i_physical_channels & AOUT_CHAN_LFE)
map.map[map.channels++] = PA_CHANNEL_POSITION_LFE;
for (unsigned i = 0; map.channels < ss.channels; i++) {
@ -859,27 +855,14 @@ static int Open(vlc_object_t *obj)
attr.minreq = -1;
attr.fragsize = 0; /* not used for output */
/* Allocate structures */
aout_sys_t *sys = malloc(sizeof(*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
pa_context *ctx = vlc_pa_connect(obj, &sys->mainloop);
if (ctx == NULL)
{
free (sys);
return VLC_EGENERIC;
}
aout->sys = sys;
sys->stream = NULL;
sys->context = ctx;
sys->trigger = NULL;
sys->first_pts = VLC_TS_INVALID;
sys->last_pts = VLC_TS_INVALID;
sys->paused = VLC_TS_INVALID;
sys->desync = 0;
sys->rate = ss.rate;
sys->nominal_rate = ss.rate;
sys->actual_rate = ss.rate;
/* Channel volume */
sys->base_volume = PA_VOLUME_NORM;
@ -916,7 +899,8 @@ static int Open(vlc_object_t *obj)
pa_proplist_sets (props, PA_PROP_MEDIA_ROLE, "video");
pa_threaded_mainloop_lock(sys->mainloop);
s = pa_stream_new_extended(ctx, "audio stream", formatv, formatc, props);
s = pa_stream_new_extended(sys->context, "audio stream", formatv, formatc,
props);
if (likely(props != NULL))
pa_proplist_free(props);
@ -924,11 +908,12 @@ static int Open(vlc_object_t *obj)
pa_format_info_free(formatv[i]);
#else
pa_threaded_mainloop_lock(sys->mainloop);
pa_stream *s = pa_stream_new(ctx, "audio stream", &ss, &map);
pa_stream *s = pa_stream_new(sys->context, "audio stream", &ss, &map);
#endif
if (s == NULL) {
vlc_pa_error(obj, "stream creation failure", ctx);
goto fail;
pa_threaded_mainloop_unlock(sys->mainloop);
vlc_pa_error(aout, "stream creation failure", sys->context);
return VLC_EGENERIC;
}
sys->stream = s;
pa_stream_set_state_callback(s, stream_state_cb, sys->mainloop);
@ -943,7 +928,7 @@ static int Open(vlc_object_t *obj)
if (pa_stream_connect_playback(s, NULL, &attr, flags, NULL, NULL) < 0
|| stream_wait(s, sys->mainloop)) {
vlc_pa_error(obj, "stream connection failure", ctx);
vlc_pa_error(aout, "stream connection failure", sys->context);
goto fail;
}
@ -954,7 +939,7 @@ static int Open(vlc_object_t *obj)
assert (info != NULL);
if (pa_format_info_is_pcm (info)) {
msg_Dbg(aout, "digital pass-through not available");
format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
fmt->i_format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
} else {
msg_Dbg(aout, "digital pass-through enabled");
pa_stream_set_latency_update_callback(s, NULL, NULL);
@ -968,7 +953,7 @@ static int Open(vlc_object_t *obj)
&(vlc_value_t){ .psz_string = (char *)_("Audio device") },
NULL);
var_AddCallback (aout, "audio-device", StreamMove, s);
op = pa_context_get_sink_info_list(ctx, sink_list_cb, aout);
op = pa_context_get_sink_info_list(sys->context, sink_list_cb, aout);
/* We may need to wait for completion... once LibVLC supports this */
if (op != NULL)
pa_operation_unref(op);
@ -977,61 +962,90 @@ static int Open(vlc_object_t *obj)
/* Context events */
const pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SINK
| PA_SUBSCRIPTION_MASK_SINK_INPUT;
pa_context_set_subscribe_callback(ctx, context_cb, aout);
op = pa_context_subscribe(ctx, mask, NULL, NULL);
pa_context_set_subscribe_callback(sys->context, context_cb, aout);
op = pa_context_subscribe(sys->context, mask, NULL, NULL);
if (likely(op != NULL))
pa_operation_unref(op);
pa_threaded_mainloop_unlock(sys->mainloop);
aout->format.i_format = format;
aout->play = Play;
aout->pause = Pause;
aout->flush = Flush;
aout->volume_set = VolumeSet;
aout->mute_set = MuteSet;
return VLC_SUCCESS;
fail:
pa_threaded_mainloop_unlock(sys->mainloop);
Close(obj);
Stop(aout);
return VLC_EGENERIC;
}
/**
* Removes a PulseAudio playback stream
*/
static void Close (vlc_object_t *obj)
static void Stop(audio_output_t *aout)
{
aout_sys_t *sys = aout->sys;
pa_stream *s = sys->stream;
/* The callback takes mainloop lock, so it CANNOT be held here! */
var_DelCallback (aout, "audio-device", StreamMove, s);
var_Destroy (aout, "audio-device");
pa_threaded_mainloop_lock(sys->mainloop);
if (unlikely(sys->trigger != NULL))
vlc_pa_rttime_free(sys->mainloop, sys->trigger);
pa_stream_disconnect(s);
/* Clear all callbacks */
pa_stream_set_state_callback(s, NULL, NULL);
pa_stream_set_buffer_attr_callback(s, NULL, NULL);
pa_stream_set_event_callback(s, NULL, NULL);
pa_stream_set_latency_update_callback(s, NULL, NULL);
pa_stream_set_moved_callback(s, NULL, NULL);
pa_stream_set_overflow_callback(s, NULL, NULL);
pa_stream_set_started_callback(s, NULL, NULL);
pa_stream_set_suspended_callback(s, NULL, NULL);
pa_stream_set_underflow_callback(s, NULL, NULL);
pa_context_set_subscribe_callback(sys->context, NULL, NULL);
pa_stream_unref(s);
pa_threaded_mainloop_unlock(sys->mainloop);
}
static int Open(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = malloc(sizeof (*sys));
#if !PA_CHECK_VERSION(0,9,22)
if (!vlc_xlib_init(obj))
return VLC_EGENERIC;
#endif
if (unlikely(sys == NULL))
return VLC_ENOMEM;
/* Allocate structures */
pa_context *ctx = vlc_pa_connect(obj, &sys->mainloop);
if (ctx == NULL)
{
free(sys);
return VLC_EGENERIC;
}
sys->context = ctx;
aout->sys = sys;
aout->start = Start;
aout->stop = Stop;
aout->play = Play;
aout->pause = Pause;
aout->flush = Flush;
aout->volume_set = VolumeSet;
aout->mute_set = MuteSet;
return VLC_SUCCESS;
}
static void Close(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
pa_context *ctx = sys->context;
pa_stream *s = sys->stream;
if (s != NULL) {
/* The callback takes mainloop lock, so it CANNOT be held here! */
var_DelCallback (aout, "audio-device", StreamMove, s);
var_Destroy (aout, "audio-device");
pa_threaded_mainloop_lock(sys->mainloop);
if (unlikely(sys->trigger != NULL))
vlc_pa_rttime_free(sys->mainloop, sys->trigger);
pa_stream_disconnect(s);
/* Clear all callbacks */
pa_stream_set_state_callback(s, NULL, NULL);
pa_stream_set_buffer_attr_callback(s, NULL, NULL);
pa_stream_set_event_callback(s, NULL, NULL);
pa_stream_set_latency_update_callback(s, NULL, NULL);
pa_stream_set_moved_callback(s, NULL, NULL);
pa_stream_set_overflow_callback(s, NULL, NULL);
pa_stream_set_started_callback(s, NULL, NULL);
pa_stream_set_suspended_callback(s, NULL, NULL);
pa_stream_set_underflow_callback(s, NULL, NULL);
pa_context_set_subscribe_callback(ctx, NULL, NULL);
pa_stream_unref(s);
pa_threaded_mainloop_unlock(sys->mainloop);
}
vlc_pa_disconnect(obj, ctx, sys->mainloop);
free(sys);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -57,7 +57,7 @@ static void Play ( audio_output_t *, block_t *, mtime_t * );
* notification_thread_t: waveOut event thread
*****************************************************************************/
/* local functions */
static void Probe ( audio_output_t * );
static void Probe ( audio_output_t *, const audio_sample_format_t * );
static int OpenWaveOut ( audio_output_t *, uint32_t,
int, int, int, int, bool );
static int OpenWaveOutPCM( audio_output_t *, uint32_t,
@ -153,21 +153,14 @@ vlc_module_begin ()
vlc_module_end ()
/*****************************************************************************
* Open: open the audio device
* Opens the audio device
*****************************************************************************
* This function opens and setups Win32 waveOut
*****************************************************************************/
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;
vlc_value_t val;
/* Allocate structure */
p_aout->sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->sys == NULL )
return VLC_ENOMEM;
p_aout->play = Play;
p_aout->pause = aout_PacketPause;
p_aout->flush = aout_PacketFlush;
@ -211,7 +204,7 @@ static int Open( vlc_object_t *p_this )
if( var_Type( p_aout, "audio-device" ) == 0 )
{
Probe( p_aout );
Probe( p_aout, fmt );
}
if( var_Get( p_aout, "audio-device", &val ) < 0 )
@ -226,14 +219,11 @@ static int Open( vlc_object_t *p_this )
/* Open the device */
if( val.i_int == AOUT_VAR_SPDIF )
{
p_aout->format.i_format = VLC_CODEC_SPDIFL;
fmt->i_format = VLC_CODEC_SPDIFL;
if( OpenWaveOut( p_aout,
p_aout->sys->i_wave_device_id,
VLC_CODEC_SPDIFL,
p_aout->format.i_physical_channels,
aout_FormatNbChannels( &p_aout->format ),
p_aout->format.i_rate, false )
if( OpenWaveOut( p_aout, p_aout->sys->i_wave_device_id,
VLC_CODEC_SPDIFL, fmt->i_physical_channels,
aout_FormatNbChannels( fmt ), fmt->i_rate, false )
!= VLC_SUCCESS )
{
msg_Err( p_aout, "cannot open waveout audio device" );
@ -242,14 +232,11 @@ static int Open( vlc_object_t *p_this )
}
/* Calculate the frame size in bytes */
p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->format.i_frame_length = A52_FRAME_NB;
p_aout->sys->i_buffer_size =
p_aout->format.i_bytes_per_frame;
fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
fmt->i_frame_length = A52_FRAME_NB;
p_aout->sys->i_buffer_size = fmt->i_bytes_per_frame;
aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB );
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB, fmt );
}
else
{
@ -258,30 +245,26 @@ static int Open( vlc_object_t *p_this )
switch( val.i_int )
{
case AOUT_VAR_5_1:
p_aout->format.i_physical_channels
fmt->i_physical_channels
= AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
| AOUT_CHAN_LFE;
break;
case AOUT_VAR_2F2R:
p_aout->format.i_physical_channels
fmt->i_physical_channels
= AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
break;
case AOUT_VAR_MONO:
p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
fmt->i_physical_channels = AOUT_CHAN_CENTER;
break;
default:
p_aout->format.i_physical_channels
= AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
fmt->i_physical_channels = AOUT_CHANS_STEREO;
}
if( OpenWaveOutPCM( p_aout,
p_aout->sys->i_wave_device_id,
&p_aout->format.i_format,
p_aout->format.i_physical_channels,
aout_FormatNbChannels( &p_aout->format ),
p_aout->format.i_rate, false )
if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
&fmt->i_format, fmt->i_physical_channels,
aout_FormatNbChannels( fmt ), fmt->i_rate, false )
!= VLC_SUCCESS )
{
msg_Err( p_aout, "cannot open waveout audio device" );
@ -290,17 +273,16 @@ static int Open( vlc_object_t *p_this )
}
/* Calculate the frame size in bytes */
aout_FormatPrepare( &p_aout->format );
p_aout->sys->i_buffer_size = FRAME_SIZE *
p_aout->format.i_bytes_per_frame;
aout_FormatPrepare( fmt );
p_aout->sys->i_buffer_size = FRAME_SIZE * fmt->i_bytes_per_frame;
aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE );
aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE, fmt );
/* Check for hardware volume support */
if( waveOutGetDevCaps( (UINT_PTR)p_aout->sys->h_waveout,
&wocaps, sizeof(wocaps) ) == MMSYSERR_NOERROR
&& (wocaps.dwSupport & WAVECAPS_VOLUME) )
{
{ /* FIXME: this needs to be moved to Open() */
p_aout->volume_set = VolumeSet;
p_aout->mute_set = MuteSet;
p_aout->sys->volume = 0xffff.fp0;
@ -360,7 +342,7 @@ static int Open( vlc_object_t *p_this )
/*****************************************************************************
* Probe: probe the audio device for available formats and channels
*****************************************************************************/
static void Probe( audio_output_t * p_aout )
static void Probe( audio_output_t * p_aout, const audio_sample_format_t *fmt )
{
vlc_value_t val, text;
vlc_fourcc_t i_format;
@ -374,13 +356,11 @@ static void Probe( audio_output_t * p_aout )
i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
if( p_aout->format.i_physical_channels == i_physical_channels )
if( fmt->i_physical_channels == i_physical_channels )
{
if( OpenWaveOutPCM( p_aout,
p_aout->sys->i_wave_device_id,
&i_format,
i_physical_channels, 6,
p_aout->format.i_rate, true )
if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
&i_format, i_physical_channels, 6,
fmt->i_rate, true )
== VLC_SUCCESS )
{
val.i_int = AOUT_VAR_5_1;
@ -394,14 +374,12 @@ static void Probe( audio_output_t * p_aout )
/* Test for 2 Front 2 Rear support */
i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
if( ( p_aout->format.i_physical_channels & i_physical_channels )
if( ( fmt->i_physical_channels & i_physical_channels )
== i_physical_channels )
{
if( OpenWaveOutPCM( p_aout,
p_aout->sys->i_wave_device_id,
&i_format,
i_physical_channels, 4,
p_aout->format.i_rate, true )
if( OpenWaveOutPCM( p_aout,p_aout->sys->i_wave_device_id,
&i_format, i_physical_channels, 4,
fmt->i_rate, true )
== VLC_SUCCESS )
{
val.i_int = AOUT_VAR_2F2R;
@ -414,11 +392,9 @@ static void Probe( audio_output_t * p_aout )
/* Test for stereo support */
i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
if( OpenWaveOutPCM( p_aout,
p_aout->sys->i_wave_device_id,
&i_format,
i_physical_channels, 2,
p_aout->format.i_rate, true )
if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
&i_format,i_physical_channels, 2,
fmt->i_rate, true )
== VLC_SUCCESS )
{
val.i_int = AOUT_VAR_STEREO;
@ -429,11 +405,8 @@ static void Probe( audio_output_t * p_aout )
/* Test for mono support */
i_physical_channels = AOUT_CHAN_CENTER;
if( OpenWaveOutPCM( p_aout,
p_aout->sys->i_wave_device_id,
&i_format,
i_physical_channels, 1,
p_aout->format.i_rate, true )
if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
&i_format, i_physical_channels, 1, fmt->i_rate, true )
== VLC_SUCCESS )
{
val.i_int = AOUT_VAR_MONO;
@ -443,14 +416,11 @@ static void Probe( audio_output_t * p_aout )
}
/* Test for SPDIF support */
if ( AOUT_FMT_SPDIF( &p_aout->format ) )
if ( AOUT_FMT_SPDIF( fmt ) )
{
if( OpenWaveOut( p_aout,
p_aout->sys->i_wave_device_id,
VLC_CODEC_SPDIFL,
p_aout->format.i_physical_channels,
aout_FormatNbChannels( &p_aout->format ),
p_aout->format.i_rate, true )
if( OpenWaveOut( p_aout, p_aout->sys->i_wave_device_id,
VLC_CODEC_SPDIFL, fmt->i_physical_channels,
aout_FormatNbChannels( fmt ), fmt->i_rate, true )
== VLC_SUCCESS )
{
msg_Dbg( p_aout, "device supports A/52 over S/PDIF" );
@ -504,9 +474,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;
/* Before calling waveOutClose we must reset the device */
@ -575,7 +544,6 @@ static void Close( vlc_object_t *p_this )
free( p_sys->p_silence_buffer );
aout_PacketDestroy( p_aout );
free( p_sys );
}
/*****************************************************************************
@ -886,7 +854,7 @@ static void* WaveOutThread( void *data )
int canc = vlc_savecancel ();
/* We don't want any resampling when using S/PDIF */
b_sleek = p_aout->format.i_format == VLC_CODEC_SPDIFL;
b_sleek = p_sys->packet.format.i_format == VLC_CODEC_SPDIFL;
// wait for first call to "play()"
while( !p_sys->start_date && !vlc_atomic_get(&p_aout->sys->abort) )
@ -1099,3 +1067,25 @@ static uint32_t findDeviceID(char *psz_device_name)
return WAVE_MAPPER;
}
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: volume handlers */
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);
}

View File

@ -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);
aout_assert_locked( p_aout );
p_aout->format = *p_format;
aout_FormatPrepare( &p_aout->format );
audio_sample_format_t fmt = *fmtp;
aout_FormatPrepare (&fmt);
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_assert_locked (aout);
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 (!var_Type (p_aout, "stereo-mode"))
var_Create (p_aout, "stereo-mode",
if (aout->start (aout, &fmt))
{
msg_Err (aout, "module not functional");
module_unneed (aout, owner->module);
owner->module = NULL;
return -1;
}
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;