1
mirror of https://code.videolan.org/videolan/vlc synced 2024-09-04 09:11:33 +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 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 */ 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 void (*play)(audio_output_t *, block_t *, mtime_t *); /**< Play callback
- queue a block for playback */ - queue a block for playback */
void (*pause)( audio_output_t *, bool, mtime_t ); /**< Pause/resume void (*pause)( audio_output_t *, bool, mtime_t ); /**< Pause/resume
@ -277,6 +276,7 @@ struct aout_fifo_t
typedef struct typedef struct
{ {
vlc_mutex_t lock; vlc_mutex_t lock;
audio_sample_format_t format;
aout_fifo_t partial; /**< Audio blocks before packetization */ aout_fifo_t partial; /**< Audio blocks before packetization */
aout_fifo_t fifo; /**< Packetized audio blocks */ aout_fifo_t fifo; /**< Packetized audio blocks */
mtime_t pause_date; /**< Date when paused or VLC_TS_INVALID */ 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) */ bool starving; /**< Whether currently starving (to limit error messages) */
} aout_packet_t; } 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_PacketDestroy(audio_output_t *);
VLC_DEPRECATED void aout_PacketPlay(audio_output_t *, block_t *, mtime_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; (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; if (AOUT_FMT_SPDIF(fmt) && var_InheritBool(aout, "spdif"))
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" ) )
{ {
p_aout->format.i_format = VLC_CODEC_SPDIFL; fmt->i_format = VLC_CODEC_SPDIFL;
p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE; fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->format.i_frame_length = A52_FRAME_NB; fmt->i_frame_length = A52_FRAME_NB;
} }
else 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; 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); void (*reorder) (void *, size_t, unsigned);
float soft_gain; float soft_gain;
bool soft_mute; bool soft_mute;
audio_sample_format_t format;
}; };
#include "volume.h" #include "volume.h"
@ -159,9 +160,9 @@ static void Flush (audio_output_t *, bool);
static void Reorder71 (void *, size_t, unsigned); static void Reorder71 (void *, size_t, unsigned);
/** Initializes an ALSA playback stream */ /** 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 */ /* Get device name */
char *device = var_InheritString (aout, "alsa-audio-device"); char *device = var_InheritString (aout, "alsa-audio-device");
@ -169,7 +170,7 @@ static int Open (vlc_object_t *obj)
return VLC_ENOMEM; return VLC_ENOMEM;
snd_pcm_format_t pcm_format; /* ALSA sample format */ 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; bool spdif = false;
switch (fourcc) switch (fourcc)
@ -223,7 +224,7 @@ static int Open (vlc_object_t *obj)
pcm_format = SND_PCM_FORMAT_U8; pcm_format = SND_PCM_FORMAT_U8;
break; break;
default: default:
if (AOUT_FMT_SPDIF(&aout->format)) if (AOUT_FMT_SPDIF(fmt))
spdif = var_InheritBool (aout, "spdif"); spdif = var_InheritBool (aout, "spdif");
if (spdif) if (spdif)
{ {
@ -246,14 +247,14 @@ static int Open (vlc_object_t *obj)
/* ALSA channels */ /* ALSA channels */
/* XXX: maybe this should be shared with other dumb outputs */ /* XXX: maybe this should be shared with other dumb outputs */
uint32_t map = var_InheritInteger (aout, "alsa-audio-channels"); 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? */ if (unlikely(map == 0)) /* WTH? */
map = AOUT_CHANS_STEREO; map = AOUT_CHANS_STEREO;
unsigned channels = popcount (map); unsigned channels = popcount (map);
if (channels < aout_FormatNbChannels (&aout->format)) if (channels < aout_FormatNbChannels (fmt))
msg_Dbg (aout, "downmixing from %u to %u channels", msg_Dbg (aout, "downmixing from %u to %u channels",
aout_FormatNbChannels (&aout->format), channels); aout_FormatNbChannels (fmt), channels);
else else
msg_Dbg (aout, "keeping %u channels", channels); msg_Dbg (aout, "keeping %u channels", channels);
@ -264,7 +265,7 @@ static int Open (vlc_object_t *obj)
{ {
unsigned aes3; unsigned aes3;
switch (aout->format.i_rate) switch (fmt->i_rate)
{ {
#define FS(freq) \ #define FS(freq) \
case freq: aes3 = IEC958_AES3_CON_FS_ ## freq; break; case freq: aes3 = IEC958_AES3_CON_FS_ ## freq; break;
@ -287,15 +288,6 @@ static int Open (vlc_object_t *obj)
return VLC_ENOMEM; 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 */ /* Open the device */
snd_pcm_t *pcm; snd_pcm_t *pcm;
/* VLC always has a resampler. No need for ALSA's. */ /* 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."), _("The audio device \"%s\" could not be used:\n%s."),
device, snd_strerror (val)); device, snd_strerror (val));
free (device); free (device);
free (sys);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
sys->pcm = pcm; sys->pcm = pcm;
@ -412,16 +403,15 @@ static int Open (vlc_object_t *obj)
} }
/* Set sample rate */ /* 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); val = snd_pcm_hw_params_set_rate_near (pcm, hw, &rate, NULL);
if (val) if (val)
{ {
msg_Err (aout, "cannot set sample rate: %s", snd_strerror (val)); msg_Err (aout, "cannot set sample rate: %s", snd_strerror (val));
goto error; goto error;
} }
if (aout->format.i_rate != rate) if (fmt->i_rate != rate)
msg_Dbg (aout, "resampling from %d Hz to %d Hz", msg_Dbg (aout, "resampling from %d Hz to %d Hz", fmt->i_rate, rate);
aout->format.i_rate, rate);
/* Set buffer size */ /* Set buffer size */
param = AOUT_MAX_ADVANCE_TIME; param = AOUT_MAX_ADVANCE_TIME;
@ -497,29 +487,26 @@ static int Open (vlc_object_t *obj)
} }
/* Setup audio_output_t */ /* Setup audio_output_t */
aout->format.i_format = fourcc; fmt->i_format = fourcc;
aout->format.i_rate = rate; fmt->i_rate = rate;
sys->reorder = NULL; sys->reorder = NULL;
if (spdif) if (spdif)
{ {
aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE; fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
aout->format.i_frame_length = A52_FRAME_NB; fmt->i_frame_length = A52_FRAME_NB;
aout->volume_set = NULL;
aout->mute_set = NULL;
} }
else else
{ {
aout->format.i_original_channels = fmt->i_original_channels =
aout->format.i_physical_channels = map; fmt->i_physical_channels = map;
switch (popcount (map)) switch (popcount (map))
{ {
case 8: case 8:
sys->reorder = Reorder71; sys->reorder = Reorder71;
break; break;
} }
aout_SoftVolumeInit (aout);
} }
sys->format = *fmt;
aout->play = Play; aout->play = Play;
if (snd_pcm_hw_params_can_pause (hw)) if (snd_pcm_hw_params_can_pause (hw))
@ -535,13 +522,13 @@ static int Open (vlc_object_t *obj)
{ {
vlc_value_t text; 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"); 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); free (device);
return 0; return 0;
@ -549,7 +536,6 @@ static int Open (vlc_object_t *obj)
error: error:
snd_pcm_close (pcm); snd_pcm_close (pcm);
free (device); free (device);
free (sys);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
@ -563,7 +549,7 @@ static void Play (audio_output_t *aout, block_t *block,
if (sys->reorder != NULL) if (sys->reorder != NULL)
sys->reorder (block->p_buffer, block->i_nb_samples, 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_t *pcm = sys->pcm;
snd_pcm_sframes_t frames; 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) 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; delay += mdate () - block->i_pts;
if (state != SND_PCM_STATE_RUNNING) if (state != SND_PCM_STATE_RUNNING)
{ {
if (delay < 0) 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); 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)) if (likely(z != NULL))
{ {
snd_pcm_writei (pcm, z, frames); snd_pcm_writei (pcm, z, frames);
@ -677,18 +663,16 @@ static void Flush (audio_output_t *aout, bool wait)
/** /**
* Releases the audio output. * 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; 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_DelCallback (aout, "audio-device", DeviceChanged, NULL);
var_Destroy (obj, "audio-device"); var_Destroy (aout, "audio-device");
snd_pcm_drop (pcm); snd_pcm_drop (pcm);
snd_pcm_close (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); 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 struct aout_sys_t
{ {
void *opaque; 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 (*play) (void *opaque, const void *data, unsigned count, int64_t pts);
void (*pause) (void *opaque, int64_t pts); void (*pause) (void *opaque, int64_t pts);
void (*resume) (void *opaque, int64_t pts); void (*resume) (void *opaque, int64_t pts);
void (*flush) (void *opaque); void (*flush) (void *opaque);
void (*drain) (void *opaque); void (*drain) (void *opaque);
int (*set_volume) (void *opaque, float vol, bool mute); int (*set_volume) (void *opaque, float vol, bool mute);
void (*cleanup) (void *opaque);
float volume; float volume;
bool mute; bool mute;
}; };
@ -132,7 +141,82 @@ static int SoftMuteSet (audio_output_t *aout, bool mute)
return 0; 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) static int Open (vlc_object_t *obj)
{ {
@ -143,98 +227,30 @@ static int Open (vlc_object_t *obj)
aout->sys = sys; aout->sys = sys;
sys->opaque = var_InheritAddress (obj, "amem-data"); 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->play = var_InheritAddress (obj, "amem-play");
sys->pause = var_InheritAddress (obj, "amem-pause"); sys->pause = var_InheritAddress (obj, "amem-pause");
sys->resume = var_InheritAddress (obj, "amem-resume"); sys->resume = var_InheritAddress (obj, "amem-resume");
sys->flush = var_InheritAddress (obj, "amem-flush"); sys->flush = var_InheritAddress (obj, "amem-flush");
sys->drain = var_InheritAddress (obj, "amem-drain"); sys->drain = var_InheritAddress (obj, "amem-drain");
sys->set_volume = var_InheritAddress (obj, "amem-set-volume"); sys->set_volume = var_InheritAddress (obj, "amem-set-volume");
sys->cleanup = NULL; /* defer */
sys->volume = 1.; sys->volume = 1.;
sys->mute = false; sys->mute = false;
if (sys->play == NULL) 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; free (sys);
channels = aout_FormatNbChannels(&aout->format); return VLC_EGENERIC;
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");
} }
if (rate == 0 || rate > 192000 aout->start = Start;
|| channels == 0 || channels > AOUT_CHAN_MAX) aout->stop = Stop;
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->play = Play; aout->play = Play;
aout->pause = Pause; aout->pause = Pause;
aout->flush = Flush; aout->flush = Flush;
@ -249,10 +265,6 @@ static int Open (vlc_object_t *obj)
aout->mute_set = SoftMuteSet; aout->mute_set = SoftMuteSet;
} }
return VLC_SUCCESS; return VLC_SUCCESS;
error:
Close (obj);
return VLC_EGENERIC;
} }
static void Close (vlc_object_t *obj) 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; audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
if (sys->cleanup != NULL)
sys->cleanup (sys->opaque);
free (sys); free (sys);
} }

View File

@ -79,11 +79,10 @@ vlc_module_end ()
* Open: open the audio device * 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; audio_output_t *p_aout = (audio_output_t *)p_this;
struct aout_sys_t *p_sys = malloc(sizeof(aout_sys_t)); aout_sys_t *p_sys = aout->sys;
p_aout->sys = p_sys;
OSStatus status = 0; OSStatus status = 0;
@ -120,13 +119,10 @@ static int Open ( vlc_object_t *p_this )
AudioQueueCallback(NULL, p_sys->audioQueue, buffer); AudioQueueCallback(NULL, p_sys->audioQueue, buffer);
} }
/* Volume is entirely done in software. */ fmt->i_format = VLC_CODEC_S16L;
aout_SoftVolumeInit( p_aout ); fmt->i_physical_channels = AOUT_CHANS_STEREO;
fmt->i_rate = 44100;
p_aout->format.i_format = VLC_CODEC_S16L; aout_PacketInit(p_aout, &p_sys->packet, FRAME_SIZE, fmt);
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);
p_aout->play = aout_PacketPlay; p_aout->play = aout_PacketPlay;
p_aout->pause = aout_PacketPause; p_aout->pause = aout_PacketPause;
p_aout->flush = aout_PacketFlush; p_aout->flush = aout_PacketFlush;
@ -156,9 +152,8 @@ static block_t *aout_FifoPop2( aout_fifo_t * p_fifo )
/***************************************************************************** /*****************************************************************************
* Close: close the audio device * 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; struct aout_sys_t * p_sys = p_aout->sys;
msg_Dbg(p_aout, "Stopping AudioQueue"); 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"); msg_Dbg(p_aout, "Disposing of AudioQueue");
AudioQueueDispose(p_sys->audioQueue, false); AudioQueueDispose(p_sys->audioQueue, false);
aout_PacketDestroy(p_aout); aout_PacketDestroy(p_aout);
free (p_sys);
} }
void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) { void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
@ -195,3 +189,25 @@ void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferR
} }
AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL); 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; 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; struct aout_sys_t *p_sys = aout->sys:
audio_output_t *p_aout = (audio_output_t*)(p_this);
int status, size; int status, size;
int afSampleRate, afFrameCount, afLatency, minBufCount, minFrameCount; int afSampleRate, afFrameCount, afLatency, minBufCount, minFrameCount;
int stream_type, channel, rate, format; 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 */ /* 4000 <= frequency <= 48000 */
rate = p_aout->format.i_rate; rate = fmt->i_rate;
if (rate < 4000) if (rate < 4000)
rate = 4000; rate = 4000;
if (rate > 48000) if (rate > 48000)
@ -204,22 +192,22 @@ static int Open(vlc_object_t *p_this)
stream_type = MUSIC; stream_type = MUSIC;
/* We can only accept U8 and S16L */ /* We can only accept U8 and S16L */
if (p_aout->format.i_format != VLC_CODEC_U8 && p_aout->format.i_format != VLC_CODEC_S16L) if (fmt->i_format != VLC_CODEC_U8 && fmt->i_format != VLC_CODEC_S16L)
p_aout->format.i_format = VLC_CODEC_S16L; fmt->i_format = VLC_CODEC_S16L;
format = (p_aout->format.i_format == VLC_CODEC_S16L) ? PCM_16_BIT : PCM_8_BIT; format = (fmt->i_format == VLC_CODEC_S16L) ? PCM_16_BIT : PCM_8_BIT;
/* TODO: android supports more channels */ /* TODO: android supports more channels */
p_aout->format.i_original_channels = p_aout->format.i_physical_channels; fmt->i_original_channels = fmt->i_physical_channels;
switch(aout_FormatNbChannels(&p_aout->format)) switch(aout_FormatNbChannels(fmt))
{ {
case 1: case 1:
channel = CHANNEL_OUT_MONO; channel = CHANNEL_OUT_MONO;
p_aout->format.i_physical_channels = AOUT_CHAN_CENTER; fmt->i_physical_channels = AOUT_CHAN_CENTER;
break; break;
case 2: case 2:
default: default:
channel = CHANNEL_OUT_STEREO; channel = CHANNEL_OUT_STEREO;
p_aout->format.i_physical_channels = AOUT_CHANS_STEREO; fmt->i_physical_channels = AOUT_CHANS_STEREO;
break; break;
} }
@ -230,8 +218,6 @@ static int Open(vlc_object_t *p_this)
status ^= p_sys->as_getOutputLatency((uint32_t*)(&afLatency), stream_type); status ^= p_sys->as_getOutputLatency((uint32_t*)(&afLatency), stream_type);
if (status != 0) { if (status != 0) {
msg_Err(p_aout, "Could not query the AudioStream parameters"); msg_Err(p_aout, "Could not query the AudioStream parameters");
dlclose(p_sys->libmedia);
free(p_sys);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate); 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); status = p_sys->at_getMinFrameCount(&minFrameCount, stream_type, rate);
if (status != 0) { if (status != 0) {
msg_Err(p_aout, "Could not query the AudioTrack parameters"); msg_Err(p_aout, "Could not query the AudioTrack parameters");
dlclose(p_sys->libmedia);
free(p_sys);
return VLC_EGENERIC; 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 */ /* Sizeof(AudioTrack) == 0x58 (not sure) on 2.2.1, this should be enough */
p_sys->AudioTrack = malloc(SIZE_OF_AUDIOTRACK); p_sys->AudioTrack = malloc(SIZE_OF_AUDIOTRACK);
if (!p_sys->AudioTrack) { if (!p_sys->AudioTrack)
dlclose(p_sys->libmedia);
free(p_sys);
return VLC_ENOMEM; return VLC_ENOMEM;
}
*((uint32_t *) ((uint32_t)p_sys->AudioTrack + SIZE_OF_AUDIOTRACK - 4)) = 0xbaadbaad; *((uint32_t *) ((uint32_t)p_sys->AudioTrack + SIZE_OF_AUDIOTRACK - 4)) = 0xbaadbaad;
// Higher than android 2.2 // Higher than android 2.2
@ -280,9 +261,7 @@ static int Open(vlc_object_t *p_this)
} }
if (status != 0) { if (status != 0) {
msg_Err(p_aout, "Cannot create AudioTrack!"); msg_Err(p_aout, "Cannot create AudioTrack!");
dlclose(p_sys->libmedia);
free(p_sys->AudioTrack); free(p_sys->AudioTrack);
free(p_sys);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
@ -292,7 +271,7 @@ static int Open(vlc_object_t *p_this)
p_sys->at_start(p_sys->AudioTrack); p_sys->at_start(p_sys->AudioTrack);
p_aout->format.i_rate = rate; fmt->i_rate = rate;
return VLC_SUCCESS; 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_flush(p_sys->AudioTrack);
p_sys->at_dtor(p_sys->AudioTrack); p_sys->at_dtor(p_sys->AudioTrack);
free(p_sys->AudioTrack); free(p_sys->AudioTrack);
dlclose(p_sys->libmedia);
free(p_sys);
} }
/* FIXME: lipsync */ /* 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); 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 * 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; OSStatus err = noErr;
UInt32 i_param_size = 0; UInt32 i_param_size = 0;
struct aout_sys_t *p_sys = NULL; struct aout_sys_t *p_sys = NULL;
vlc_value_t val; vlc_value_t val;
audio_output_t *p_aout = (audio_output_t *)p_this;
/* Use int here, to match kAudioDevicePropertyDeviceIsAlive /* Use int here, to match kAudioDevicePropertyDeviceIsAlive
* property size */ * property size */
int b_alive = false; 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 = p_aout->sys;
p_sys->i_default_dev = 0; p_sys->i_default_dev = 0;
p_sys->i_selected_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->pause = aout_PacketPause;
p_aout->flush = aout_PacketFlush; 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 */ /* Persistent device variable */
if (var_Type(p_aout->p_libvlc, "macosx-audio-device") == 0) 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); var_AddCallback(p_aout, "audio-device", AudioDeviceCallback, NULL);
/* Check for Digital mode or Analog output mode */ /* 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)) { if (OpenSPDIF (p_aout)) {
msg_Dbg(p_aout, "digital output successfully opened"); msg_Dbg(p_aout, "digital output successfully opened");
return VLC_SUCCESS; return VLC_SUCCESS;
@ -271,14 +265,13 @@ error:
/* If we reach this, this aout has failed */ /* If we reach this, this aout has failed */
msg_Err(p_aout, "opening the auhal output failed"); msg_Err(p_aout, "opening the auhal output failed");
var_Destroy(p_aout, "audio-device"); var_Destroy(p_aout, "audio-device");
free(p_sys);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/***************************************************************************** /*****************************************************************************
* Open: open and setup a HAL AudioUnit to do analog (multichannel) audio output * 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; struct aout_sys_t *p_sys = p_aout->sys;
OSStatus err = noErr; 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); msg_Dbg(p_aout, "layout of AUHAL has %d channels" , (int)layout->mNumberChannelDescriptions);
/* Initialize the VLC core channel count */ /* Initialize the VLC core channel count */
p_aout->format.i_physical_channels = 0; fmt->i_physical_channels = 0;
i_original = p_aout->format.i_original_channels & AOUT_CHAN_PHYSMASK; i_original = fmt->i_original_channels & AOUT_CHAN_PHYSMASK;
if (i_original == AOUT_CHAN_CENTER || layout->mNumberChannelDescriptions < 2) { if (i_original == AOUT_CHAN_CENTER || layout->mNumberChannelDescriptions < 2) {
/* We only need Mono or cannot output more than 1 channel */ /* 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) { } else if (i_original == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) || layout->mNumberChannelDescriptions < 3) {
/* We only need Stereo or cannot output more than 2 channels */ /* 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 { } else {
/* We want more than stereo and we can do that */ /* We want more than stereo and we can do that */
for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; i++) { 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) { switch(layout->mChannelDescriptions[i].mChannelLabel) {
case kAudioChannelLabel_Left: case kAudioChannelLabel_Left:
p_aout->format.i_physical_channels |= AOUT_CHAN_LEFT; fmt->i_physical_channels |= AOUT_CHAN_LEFT;
continue; continue;
case kAudioChannelLabel_Right: case kAudioChannelLabel_Right:
p_aout->format.i_physical_channels |= AOUT_CHAN_RIGHT; fmt->i_physical_channels |= AOUT_CHAN_RIGHT;
continue; continue;
case kAudioChannelLabel_Center: case kAudioChannelLabel_Center:
p_aout->format.i_physical_channels |= AOUT_CHAN_CENTER; fmt->i_physical_channels |= AOUT_CHAN_CENTER;
continue; continue;
case kAudioChannelLabel_LFEScreen: case kAudioChannelLabel_LFEScreen:
p_aout->format.i_physical_channels |= AOUT_CHAN_LFE; fmt->i_physical_channels |= AOUT_CHAN_LFE;
continue; continue;
case kAudioChannelLabel_LeftSurround: case kAudioChannelLabel_LeftSurround:
p_aout->format.i_physical_channels |= AOUT_CHAN_REARLEFT; fmt->i_physical_channels |= AOUT_CHAN_REARLEFT;
continue; continue;
case kAudioChannelLabel_RightSurround: case kAudioChannelLabel_RightSurround:
p_aout->format.i_physical_channels |= AOUT_CHAN_REARRIGHT; fmt->i_physical_channels |= AOUT_CHAN_REARRIGHT;
continue; continue;
case kAudioChannelLabel_RearSurroundLeft: case kAudioChannelLabel_RearSurroundLeft:
p_aout->format.i_physical_channels |= AOUT_CHAN_MIDDLELEFT; fmt->i_physical_channels |= AOUT_CHAN_MIDDLELEFT;
continue; continue;
case kAudioChannelLabel_RearSurroundRight: case kAudioChannelLabel_RearSurroundRight:
p_aout->format.i_physical_channels |= AOUT_CHAN_MIDDLERIGHT; fmt->i_physical_channels |= AOUT_CHAN_MIDDLERIGHT;
continue; continue;
case kAudioChannelLabel_CenterSurround: case kAudioChannelLabel_CenterSurround:
p_aout->format.i_physical_channels |= AOUT_CHAN_REARCENTER; fmt->i_physical_channels |= AOUT_CHAN_REARCENTER;
continue; continue;
default: default:
msg_Warn(p_aout, "unrecognized channel form provided by driver: %d", (int)layout->mChannelDescriptions[i].mChannelLabel); msg_Warn(p_aout, "unrecognized channel form provided by driver: %d", (int)layout->mChannelDescriptions[i].mChannelLabel);
} }
} }
if (p_aout->format.i_physical_channels == 0) { if (fmt->i_physical_channels == 0) {
p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; 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."); 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", dialog_Fatal(p_aout, _("Audio device is not configured"), "%s",
_("You should configure your speaker layout with " _("You should configure your speaker layout with "
@ -432,14 +425,14 @@ static int OpenAnalog(audio_output_t *p_aout)
free(layout); free(layout);
} else { } else {
msg_Warn(p_aout, "this driver does not support kAudioDevicePropertyPreferredChannelLayout. BAD DRIVER AUTHOR !!!"); 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, "selected %d physical channels for device output", aout_FormatNbChannels(fmt));
msg_Dbg(p_aout, "VLC will output: %s", aout_FormatPrintChannels(&p_aout->format)); msg_Dbg(p_aout, "VLC will output: %s", aout_FormatPrintChannels(fmt));
memset (&new_layout, 0, sizeof(new_layout)); memset (&new_layout, 0, sizeof(new_layout));
switch(aout_FormatNbChannels(&p_aout->format)) { switch(aout_FormatNbChannels(fmt)) {
case 1: case 1:
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
break; break;
@ -447,27 +440,27 @@ static int OpenAnalog(audio_output_t *p_aout)
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
break; break;
case 3: 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 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 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_4; // L R LFE
break; break;
case 4: 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 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 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 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_3; // L R C Cs
break; break;
case 5: 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 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 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_18; // L R Ls Rs LFE
break; break;
case 6: 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 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_20; // L R Ls Rs C LFE
else else
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_6_0; // L R Ls Rs C Cs 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 */ /* Set up the format to be used */
DeviceFormat.mSampleRate = p_aout->format.i_rate; DeviceFormat.mSampleRate = fmt->i_rate;
DeviceFormat.mFormatID = kAudioFormatLinearPCM; DeviceFormat.mFormatID = kAudioFormatLinearPCM;
/* We use float 32. It's the best supported format by both VLC and Coreaudio */ /* 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.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
DeviceFormat.mBitsPerChannel = 32; DeviceFormat.mBitsPerChannel = 32;
DeviceFormat.mChannelsPerFrame = aout_FormatNbChannels(&p_aout->format); DeviceFormat.mChannelsPerFrame = aout_FormatNbChannels(fmt);
/* Calculate framesizes and stuff */ /* Calculate framesizes and stuff */
DeviceFormat.mFramesPerPacket = 1; 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)); msg_Dbg(p_aout, STREAM_FORMAT_MSG("the actual set AU format is " , DeviceFormat));
/* Do the last VLC aout setups */ /* Do the last VLC aout setups */
aout_FormatPrepare(&p_aout->format); aout_FormatPrepare(fmt);
aout_PacketInit(p_aout, &p_sys->packet, FRAMESIZE); aout_PacketInit(p_aout, &p_sys->packet, FRAMESIZE, fmt);
p_aout->volume_set = VolumeSet;
p_aout->mute_set = MuteSet;
/* set the IOproc callback */ /* set the IOproc callback */
input.inputProc = (AURenderCallback) RenderCallbackAnalog; input.inputProc = (AURenderCallback) RenderCallbackAnalog;
@ -562,7 +553,7 @@ static int OpenAnalog(audio_output_t *p_aout)
/***************************************************************************** /*****************************************************************************
* Setup a encoded digital stream (SPDIF) * 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; struct aout_sys_t *p_sys = p_aout->sys;
OSStatus err = noErr; 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 == 'iac3' ||
p_format_list[j].mFormat.mFormatID == kAudioFormat60958AC3 || p_format_list[j].mFormat.mFormatID == kAudioFormat60958AC3 ||
p_format_list[j].mFormat.mFormatID == kAudioFormatAC3) { 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; i_requested_rate_format = j;
break; break;
} else if (p_format_list[j].mFormat.mSampleRate == p_sys->sfmt_revert.mSampleRate) } 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 */ /* Set the format flags */
if (p_sys->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian) if (p_sys->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian)
p_aout->format.i_format = VLC_CODEC_SPDIFB; fmt->i_format = VLC_CODEC_SPDIFB;
else else
p_aout->format.i_format = VLC_CODEC_SPDIFL; fmt->i_format = VLC_CODEC_SPDIFL;
p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE; fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->format.i_frame_length = A52_FRAME_NB; fmt->i_frame_length = A52_FRAME_NB;
p_aout->format.i_rate = (unsigned int)p_sys->stream_format.mSampleRate; fmt->i_rate = (unsigned int)p_sys->stream_format.mSampleRate;
aout_FormatPrepare(&p_aout->format); aout_FormatPrepare(fmt);
aout_PacketInit(p_aout, &p_sys->packet, A52_FRAME_NB); aout_PacketInit(p_aout, &p_sys->packet, A52_FRAME_NB, fmt);
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
/* Add IOProc callback */ /* Add IOProc callback */
err = AudioDeviceCreateIOProcID(p_sys->i_selected_dev, err = AudioDeviceCreateIOProcID(p_sys->i_selected_dev,
@ -775,9 +764,8 @@ static int OpenSPDIF (audio_output_t * p_aout)
/***************************************************************************** /*****************************************************************************
* Close: Close HAL AudioUnit * 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; struct aout_sys_t *p_sys = p_aout->sys;
OSStatus err = noErr; OSStatus err = noErr;
UInt32 i_param_size = 0; 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); var_DelCallback(p_aout, "audio-device", AudioDeviceCallback, NULL);
aout_PacketDestroy(p_aout); 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], &p_sys->p_remainder_buffer[p_sys->i_read_bytes],
i_mData_bytes); i_mData_bytes);
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) * current_date += (mtime_t) ((mtime_t) 1000000 / p_sys->packet.format.i_rate) *
(i_mData_bytes / 4 / aout_FormatNbChannels(&p_aout->format)); // 4 is fl32 specific (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) if (p_sys->i_read_bytes >= p_sys->i_total_bytes)
p_sys->i_read_bytes = p_sys->i_total_bytes = 0; p_sys->i_read_bytes = p_sys->i_total_bytes = 0;
@ -1245,8 +1232,8 @@ static OSStatus RenderCallbackAnalog(vlc_object_t *_p_aout,
break; break;
} else } else
/* update current_date */ /* update current_date */
current_date += (mtime_t) ((mtime_t) 1000000 / p_aout->format.i_rate) * current_date += (mtime_t) ((mtime_t) 1000000 / p_sys->packet.format.i_rate) *
(i_second_mData_bytes / 4 / aout_FormatNbChannels(&p_aout->format)); // 4 is fl32 specific (i_second_mData_bytes / 4 / aout_FormatNbChannels(&p_sys->packet.format)); // 4 is fl32 specific
block_Release(p_buffer); block_Release(p_buffer);
} else { } else {
memset((uint8_t *)ioData->mBuffers[0].mData +i_mData_bytes, 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; 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" #include "windows_audio_common.h"
#define FRAME_SIZE ((int)p_aout->format.i_rate/20) /* Size in samples */
/***************************************************************************** /*****************************************************************************
* notification_thread_t: DirectX event thread * notification_thread_t: DirectX event thread
*****************************************************************************/ *****************************************************************************/
@ -98,14 +96,15 @@ struct aout_sys_t
/***************************************************************************** /*****************************************************************************
* Local prototypes. * Local prototypes.
*****************************************************************************/ *****************************************************************************/
static int OpenAudio ( vlc_object_t * ); static int Open( vlc_object_t * );
static void CloseAudio ( 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 void Play ( audio_output_t *, block_t *, mtime_t * );
static int VolumeSet ( audio_output_t *, float ); static int VolumeSet ( audio_output_t *, float );
static int MuteSet ( audio_output_t *, bool ); static int MuteSet ( audio_output_t *, bool );
/* local functions */ /* 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 InitDirectSound ( audio_output_t * );
static int CreateDSBuffer ( audio_output_t *, int, int, int, int, int, bool ); static int CreateDSBuffer ( audio_output_t *, int, int, int, int, int, bool );
static int CreateDSBufferPCM ( audio_output_t *, vlc_fourcc_t*, 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 ) VOLUME_TEXT, VOLUME_LONGTEXT, true )
change_integer_range( DSBVOLUME_MIN, DSBVOLUME_MAX ) change_integer_range( DSBVOLUME_MIN, DSBVOLUME_MAX )
set_callbacks( OpenAudio, CloseAudio ) set_callbacks( Open, Close )
vlc_module_end () vlc_module_end ()
/***************************************************************************** /*****************************************************************************
@ -162,9 +161,8 @@ vlc_module_end ()
***************************************************************************** *****************************************************************************
* This function opens and setups Direct Sound. * 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; vlc_value_t val;
char * psz_speaker; char * psz_speaker;
int i = 0; int i = 0;
@ -173,11 +171,6 @@ static int OpenAudio( vlc_object_t *p_this )
msg_Dbg( p_aout, "Opening DirectSound Audio Output" ); 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 */ /* Retrieve config values */
var_Create( p_aout, "directx-audio-float32", var_Create( p_aout, "directx-audio-float32",
VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); 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 ) if( var_Type( p_aout, "audio-device" ) == 0 )
{ {
Probe( p_aout ); Probe( p_aout, fmt );
} }
if( var_Get( p_aout, "audio-device", &val ) < 0 ) if( var_Get( p_aout, "audio-device", &val ) < 0 )
@ -222,17 +215,16 @@ static int OpenAudio( vlc_object_t *p_this )
/* Open the device */ /* Open the device */
if( val.i_int == AOUT_VAR_SPDIF ) 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 */ /* Calculate the frame size in bytes */
p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE; fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->format.i_frame_length = A52_FRAME_NB; fmt->i_frame_length = A52_FRAME_NB;
p_aout->sys->i_frame_size = p_aout->format.i_bytes_per_frame; p_aout->sys->i_frame_size = fmt->i_bytes_per_frame;
if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL, if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL,
p_aout->format.i_physical_channels, fmt->i_physical_channels,
aout_FormatNbChannels( &p_aout->format ), aout_FormatNbChannels( fmt ), fmt->i_rate,
p_aout->format.i_rate,
p_aout->sys->i_frame_size, false ) p_aout->sys->i_frame_size, false )
!= VLC_SUCCESS ) != VLC_SUCCESS )
{ {
@ -240,26 +232,27 @@ static int OpenAudio( vlc_object_t *p_this )
goto error; 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 else
{ {
if( val.i_int == AOUT_VAR_5_1 ) 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 ) 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 ) 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 ) 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 ) 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 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, aout_FormatPrepare( fmt );
p_aout->format.i_physical_channels,
p_aout->format.i_rate, false ) if( CreateDSBufferPCM( p_aout, &fmt->i_format,
fmt->i_physical_channels, fmt->i_rate, false )
!= VLC_SUCCESS ) != VLC_SUCCESS )
{ {
msg_Err( p_aout, "cannot open directx audio device" ); 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 */ /* Calculate the frame size in bytes */
aout_FormatPrepare( &p_aout->format ); aout_PacketInit( p_aout, &p_aout->sys->packet, fmt->i_rate / 20, fmt );
aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE );
} }
p_aout->sys->volume.volume = -1; p_aout->sys->volume.volume = -1;
@ -315,14 +307,14 @@ static int OpenAudio( vlc_object_t *p_this )
return VLC_SUCCESS; return VLC_SUCCESS;
error: error:
CloseAudio( VLC_OBJECT(p_aout) ); Stop( p_aout );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/***************************************************************************** /*****************************************************************************
* Probe: probe the audio device for available formats and channels * 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_value_t val, text;
vlc_fourcc_t i_format; 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 ); var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
/* Test for 5.1 support */ /* 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, 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; val.i_int = AOUT_VAR_5_1;
text.psz_string = (char*) "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 */ /* 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, 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; val.i_int = AOUT_VAR_7_1;
text.psz_string = (char*) "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 */ /* 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, 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; val.i_int = AOUT_VAR_3F2R;
text.psz_string = _("3 Front 2 Rear"); 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 */ /* Test for 2 Front 2 Rear support */
if( ( p_aout->format.i_physical_channels & AOUT_CHANS_4_0 ) if( ( fmt->i_physical_channels & AOUT_CHANS_4_0 ) == AOUT_CHANS_4_0 )
== AOUT_CHANS_4_0 )
{ {
if( CreateDSBufferPCM( p_aout, &i_format, 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; val.i_int = AOUT_VAR_2F2R;
text.psz_string = _("2 Front 2 Rear"); text.psz_string = _("2 Front 2 Rear");
@ -406,7 +397,7 @@ static void Probe( audio_output_t * p_aout )
/* Test for stereo support */ /* Test for stereo support */
if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHANS_2_0, 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; val.i_int = AOUT_VAR_STEREO;
text.psz_string = _("Stereo"); text.psz_string = _("Stereo");
@ -422,7 +413,7 @@ static void Probe( audio_output_t * p_aout )
/* Test for mono support */ /* Test for mono support */
if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHAN_CENTER, 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; val.i_int = AOUT_VAR_MONO;
text.psz_string = _("Mono"); text.psz_string = _("Mono");
@ -503,12 +494,11 @@ static void Probe( audio_output_t * p_aout )
var_Set( p_aout, "audio-device", val ); var_Set( p_aout, "audio-device", val );
/* Test for SPDIF support */ /* Test for SPDIF support */
if ( AOUT_FMT_SPDIF( &p_aout->format ) ) if ( AOUT_FMT_SPDIF( fmt ) )
{ {
if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL, if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL,
p_aout->format.i_physical_channels, fmt->i_physical_channels,
aout_FormatNbChannels( &p_aout->format ), aout_FormatNbChannels( fmt ), fmt->i_rate,
p_aout->format.i_rate,
AOUT_SPDIF_SIZE, true ) AOUT_SPDIF_SIZE, true )
== VLC_SUCCESS ) == VLC_SUCCESS )
{ {
@ -603,9 +593,8 @@ static int MuteSet( audio_output_t *p_aout, bool mute )
/***************************************************************************** /*****************************************************************************
* CloseAudio: close the audio device * 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; aout_sys_t *p_sys = p_aout->sys;
msg_Dbg( p_aout, "closing audio device" ); msg_Dbg( p_aout, "closing audio device" );
@ -629,11 +618,7 @@ static void CloseAudio( vlc_object_t *p_this )
/* finally release the DirectSound object */ /* finally release the DirectSound object */
if( p_sys->p_dsobject ) IDirectSound_Release( p_sys->p_dsobject ); 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_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 *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
HRESULT (WINAPI *OurDirectSoundEnumerate)(LPDSENUMCALLBACKW, LPVOID); 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 *) OurDirectSoundCreate = (void *)
GetProcAddress( p_aout->sys->hdsound_dll, GetProcAddress( p_aout->sys->hdsound_dll,
"DirectSoundCreate" ); "DirectSoundCreate" );
@ -742,11 +720,6 @@ static int InitDirectSound( audio_output_t *p_aout )
error: error:
p_aout->sys->p_dsobject = NULL; 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; return VLC_EGENERIC;
} }
@ -903,12 +876,12 @@ static int CreateDSBufferPCM( audio_output_t *p_aout, vlc_fourcc_t *i_format,
i_nb_channels > 2 || i_nb_channels > 2 ||
CreateDSBuffer( p_aout, VLC_CODEC_FL32, CreateDSBuffer( p_aout, VLC_CODEC_FL32,
i_channels, i_nb_channels, i_rate, 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 ) != VLC_SUCCESS )
{ {
if ( CreateDSBuffer( p_aout, VLC_CODEC_S16L, if ( CreateDSBuffer( p_aout, VLC_CODEC_S16L,
i_channels, i_nb_channels, i_rate, 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 ) != VLC_SUCCESS )
{ {
return VLC_EGENERIC; return VLC_EGENERIC;
@ -1079,15 +1052,15 @@ static void* DirectSoundThread( void *data )
/* Detect underruns */ /* Detect underruns */
if( l_queued && mtime - last_time > 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!" ); msg_Dbg( p_aout, "detected underrun!" );
} }
last_time = mtime; last_time = mtime;
/* Try to fill in as many frame buffers as possible */ /* Try to fill in as many frame buffers as possible */
l_read /= (p_aout->format.i_bytes_per_frame / l_read /= (p_aout->sys->packet.format.i_bytes_per_frame /
p_aout->format.i_frame_length); p_aout->sys->packet.format.i_frame_length);
l_queued = p_notif->i_write_slot * i_frame_siz - l_read; l_queued = p_notif->i_write_slot * i_frame_siz - l_read;
if( l_queued < 0 ) l_queued += (i_frame_siz * FRAMES_NUM); if( l_queued < 0 ) l_queued += (i_frame_siz * FRAMES_NUM);
l_free_slots = (FRAMES_NUM * i_frame_siz - l_queued) / i_frame_siz; 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, block_t *p_buffer = aout_PacketNext( p_aout,
mtime + INT64_C(1000000) * (i * i_frame_siz + l_queued) / 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 /* If there is no audio data available and we have some buffered
* already, then just wait for the next time */ * already, then just wait for the next time */
@ -1108,7 +1081,7 @@ static void* DirectSoundThread( void *data )
/* Sleep a reasonable amount of time */ /* Sleep a reasonable amount of time */
l_queued += (i * i_frame_siz); 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 */ /* make sure the buffer isn't playing */
@ -1182,3 +1155,34 @@ error:
return nb_devices; 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. * Local prototypes.
*****************************************************************************/ *****************************************************************************/
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static void Play ( audio_output_t *, block_t *, mtime_t * ); static void Play ( audio_output_t *, block_t *, mtime_t * );
/***************************************************************************** /*****************************************************************************
@ -121,21 +120,17 @@ vlc_module_begin ()
set_capability( "audio output", 0 ) set_capability( "audio output", 0 )
add_shortcut( "file", "audiofile" ) add_shortcut( "file", "audiofile" )
set_callbacks( Open, Close ) set_callbacks( Open, NULL )
vlc_module_end () vlc_module_end ()
/***************************************************************************** static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
* Open: open a dummy audio device
*****************************************************************************/
static int Open( vlc_object_t * p_this )
{ {
audio_output_t * p_aout = (audio_output_t *)p_this;
char * psz_name, * psz_format; char * psz_name, * psz_format;
const char * const * ppsz_compare = format_list; const char * const * ppsz_compare = format_list;
int i_channels, i = 0; int i_channels, i = 0;
psz_name = var_CreateGetString( p_this, "audiofile-file" ); psz_name = var_InheritString( p_aout, "audiofile-file" );
if( !psz_name || !*psz_name ) if( !psz_name )
{ {
msg_Err( p_aout, "you need to specify an output file name" ); msg_Err( p_aout, "you need to specify an output file name" );
free( psz_name ); free( psz_name );
@ -164,7 +159,8 @@ static int Open( vlc_object_t * p_this )
p_aout->flush = NULL; p_aout->flush = NULL;
/* Audio format */ /* 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 ) while ( *ppsz_compare != NULL )
{ {
@ -187,28 +183,22 @@ static int Open( vlc_object_t * p_this )
} }
free( psz_format ); free( psz_format );
p_aout->format.i_format = format_int[i]; fmt->i_format = format_int[i];
if ( AOUT_FMT_SPDIF( &p_aout->format ) ) if ( AOUT_FMT_SPDIF( fmt ) )
{ {
p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE; fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->format.i_frame_length = A52_FRAME_NB; fmt->i_frame_length = A52_FRAME_NB;
} }
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
/* Channels number */ /* 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 ) if( i_channels > 0 && i_channels <= CHANNELS_MAX )
{ {
p_aout->format.i_physical_channels = fmt->i_physical_channels = pi_channels_maps[i_channels];
pi_channels_maps[i_channels];
} }
/* WAV header */ /* WAV header */
p_aout->sys->b_add_wav_header = var_CreateGetBool( p_this, p_aout->sys->b_add_wav_header = var_InheritBool( p_aout, "audiofile-wav" );
"audiofile-wav" );
if( p_aout->sys->b_add_wav_header ) if( p_aout->sys->b_add_wav_header )
{ {
/* Write wave header */ /* Write wave header */
@ -216,7 +206,7 @@ static int Open( vlc_object_t * p_this )
memset( wh, 0, sizeof(*wh) ); memset( wh, 0, sizeof(*wh) );
switch( p_aout->format.i_format ) switch( fmt->i_format )
{ {
case VLC_CODEC_FL32: case VLC_CODEC_FL32:
wh->Format = WAVE_FORMAT_IEEE_FLOAT; 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->SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
wh->SubChunkLength = 16; wh->SubChunkLength = 16;
wh->Modus = aout_FormatNbChannels( &p_aout->format ); wh->Modus = aout_FormatNbChannels( fmt );
wh->SampleFreq = p_aout->format.i_rate; wh->SampleFreq = fmt->i_rate;
wh->BytesPerSample = wh->Modus * ( wh->BitsPerSample / 8 ); wh->BytesPerSample = wh->Modus * ( wh->BitsPerSample / 8 );
wh->BytesPerSec = wh->BytesPerSample * wh->SampleFreq; wh->BytesPerSec = wh->BytesPerSample * wh->SampleFreq;
@ -269,10 +259,8 @@ static int Open( vlc_object_t * p_this )
/***************************************************************************** /*****************************************************************************
* Close: close our file * 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" ); msg_Dbg( p_aout, "closing audio file" );
if( p_aout->sys->b_add_wav_header ) 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 ); block_Release( p_buffer );
(void) drift; (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 ) set_callbacks( Open, Close )
vlc_module_end () vlc_module_end ()
/*****************************************************************************
* Open: create a JACK client static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{ {
char psz_name[32]; char psz_name[32];
audio_output_t *p_aout = (audio_output_t *)p_this; struct aout_sys_t *p_sys = p_aout->sys;
struct aout_sys_t *p_sys = NULL;
int status = VLC_SUCCESS; int status = VLC_SUCCESS;
unsigned int i; unsigned int i;
int i_error; 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; p_sys->latency = 0;
/* Connect to the JACK server */ /* 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_set_graph_order_callback ( p_sys->p_jack_client, GraphChange, p_aout );
/* JACK only supports fl32 format */ /* JACK only supports fl32 format */
p_aout->format.i_format = VLC_CODEC_FL32; fmt->i_format = VLC_CODEC_FL32;
// TODO add buffer size callback // 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->play = aout_PacketPlay;
p_aout->pause = aout_PacketPause; p_aout->pause = aout_PacketPause;
p_aout->flush = aout_PacketFlush; p_aout->flush = aout_PacketFlush;
aout_PacketInit( p_aout, &p_sys->packet, 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 ); 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 * p_sys->p_jack_ports = malloc( p_sys->i_channels *
sizeof(jack_port_t *) ); 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)", 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: error_out:
/* Clean up, if an error occurred */ /* Clean up, if an error occurred */
@ -245,7 +234,6 @@ error_out:
} }
free( p_sys->p_jack_ports ); free( p_sys->p_jack_ports );
free( p_sys->p_jack_buffers ); free( p_sys->p_jack_buffers );
free( p_sys );
} }
return status; return status;
} }
@ -338,10 +326,9 @@ static int GraphChange( void *p_arg )
/***************************************************************************** /*****************************************************************************
* Close: close the JACK client * Close: close the JACK client
*****************************************************************************/ *****************************************************************************/
static void Close( vlc_object_t *p_this ) static void Stop( audio_output_t *p_aout )
{ {
int i_error; int i_error;
audio_output_t *p_aout = (audio_output_t *)p_this;
struct aout_sys_t *p_sys = p_aout->sys; struct aout_sys_t *p_sys = p_aout->sys;
i_error = jack_deactivate( p_sys->p_jack_client ); 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_ports );
free( p_sys->p_jack_buffers ); free( p_sys->p_jack_buffers );
aout_PacketDestroy( p_aout ); 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 * Local prototypes
*****************************************************************************/ *****************************************************************************/
static int Open ( vlc_object_t * ); 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 void Play ( audio_output_t *_p_aout, block_t *block, mtime_t * );
static ULONG APIENTRY KaiCallback ( PVOID, PVOID, ULONG ); static ULONG APIENTRY KaiCallback ( PVOID, PVOID, ULONG );
@ -94,15 +93,14 @@ vlc_module_begin ()
add_bool( "kai-audio-exclusive-mode", false, add_bool( "kai-audio-exclusive-mode", false,
KAI_AUDIO_EXCLUSIVE_MODE_TEXT, KAI_AUDIO_EXCLUSIVE_MODE_LONGTEXT, KAI_AUDIO_EXCLUSIVE_MODE_TEXT, KAI_AUDIO_EXCLUSIVE_MODE_LONGTEXT,
true ) true )
set_callbacks( Open, Close ) set_callbacks( Open, NULL )
vlc_module_end () vlc_module_end ()
/***************************************************************************** /*****************************************************************************
* Open: open the audio device * 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; aout_sys_t *p_sys;
char *psz_mode; char *psz_mode;
ULONG i_kai_mode; ULONG i_kai_mode;
@ -110,7 +108,7 @@ static int Open ( vlc_object_t *p_this )
int i_nb_channels; int i_nb_channels;
int i_bytes_per_frame; int i_bytes_per_frame;
vlc_value_t val, text; vlc_value_t val, text;
audio_format_t format = p_aout->format; audio_format_t format = *format;
/* Allocate structure */ /* Allocate structure */
p_aout->sys = calloc( 1, sizeof( aout_sys_t ) ); 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", msg_Dbg( p_aout, "obtained i_bytes_per_frame = %d",
format.i_bytes_per_frame ); format.i_bytes_per_frame );
p_aout->format = format; *fmt = format;
p_aout->play = Play; p_aout->play = Play;
p_aout->pause = aout_PacketPause; 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 * 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; aout_sys_t *p_sys = p_aout->sys;
kaiClose( p_sys->hkai ); kaiClose( p_sys->hkai );
@ -341,3 +338,13 @@ static ULONG APIENTRY KaiCallback( PVOID p_cb_data,
return i_buf_size; 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. * Local prototypes.
*****************************************************************************/ *****************************************************************************/
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
@ -96,7 +95,7 @@ vlc_module_begin ()
set_capability( "audio output", 170 ) set_capability( "audio output", 170 )
add_shortcut( "opensles", "android" ) add_shortcut( "opensles", "android" )
set_callbacks( Open, Close ) set_callbacks( Open, NULL )
vlc_module_end () vlc_module_end ()
@ -235,9 +234,8 @@ static void PlayedCallback (SLAndroidSimpleBufferQueueItf caller, void *pContext
/***************************************************************************** /*****************************************************************************
* Open * 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; SLresult result;
SLEngineItf engineEngine; SLEngineItf engineEngine;
@ -321,7 +319,7 @@ static int Open( vlc_object_t *p_this )
SLDataFormat_PCM format_pcm; SLDataFormat_PCM format_pcm;
format_pcm.formatType = SL_DATAFORMAT_PCM; format_pcm.formatType = SL_DATAFORMAT_PCM;
format_pcm.numChannels = 2; 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.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16; format_pcm.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 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; p_sys->pp_last = &p_sys->p_chain;
// we want 16bit signed data little endian. // we want 16bit signed data little endian.
p_aout->format.i_format = VLC_CODEC_S16L; fmt->i_format = VLC_CODEC_S16L;
p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; fmt->i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
p_aout->play = Play; p_aout->play = Play;
p_aout->pause = Pause; p_aout->pause = Pause;
p_aout->flush = Flush; p_aout->flush = Flush;
aout_FormatPrepare( &p_aout->format ); aout_FormatPrepare( fmt );
return VLC_SUCCESS; return VLC_SUCCESS;
error: error:
@ -385,9 +383,8 @@ error:
/***************************************************************************** /*****************************************************************************
* Close * 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; aout_sys_t *p_sys = p_aout->sys;
SetPlayState( p_sys->playerPlay, SL_PLAYSTATE_STOPPED ); 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 ); vlc_mutex_destroy( &p_sys->lock );
Clean( p_sys ); 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 int Open (vlc_object_t *);
static void Close (vlc_object_t *);
#define AUDIO_DEV_TEXT N_("Audio output device") #define AUDIO_DEV_TEXT N_("Audio output device")
#define AUDIO_DEV_LONGTEXT N_("OSS device node path.") #define AUDIO_DEV_LONGTEXT N_("OSS device node path.")
@ -72,7 +71,7 @@ vlc_module_begin ()
add_string ("oss-audio-device", "", add_string ("oss-audio-device", "",
AUDIO_DEV_TEXT, AUDIO_DEV_LONGTEXT, false) AUDIO_DEV_TEXT, AUDIO_DEV_LONGTEXT, false)
set_capability( "audio output", 100 ) set_capability( "audio output", 100 )
set_callbacks( Open, Close ) set_callbacks (Open, NULL)
vlc_module_end () vlc_module_end ()
static void Play (audio_output_t *, block_t *, mtime_t *); 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; 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; audio_output_t *aout = (audio_output_t *)obj;
@ -124,10 +123,9 @@ static int Open (vlc_object_t *obj)
/* Select audio format */ /* Select audio format */
int format; int format;
vlc_fourcc_t fourcc = aout->format.i_format;
bool spdif = false; bool spdif = false;
switch (fourcc) switch (fmt->i_format)
{ {
#ifdef AFMT_FLOAT #ifdef AFMT_FLOAT
case VLC_CODEC_F64B: case VLC_CODEC_F64B:
@ -154,7 +152,7 @@ static int Open (vlc_object_t *obj)
format = AFMT_U8; format = AFMT_U8;
break; break;
default: default:
if (AOUT_FMT_SPDIF(&aout->format)) if (AOUT_FMT_SPDIF(fmt))
spdif = var_InheritBool (aout, "spdif"); spdif = var_InheritBool (aout, "spdif");
if (spdif) if (spdif)
format = AFMT_AC3; format = AFMT_AC3;
@ -174,21 +172,21 @@ static int Open (vlc_object_t *obj)
switch (format) switch (format)
{ {
case AFMT_S8: fourcc = VLC_CODEC_S8; break; case AFMT_S8: fmt->i_format = VLC_CODEC_S8; break;
case AFMT_U8: fourcc = VLC_CODEC_U8; break; case AFMT_U8: fmt->i_format = VLC_CODEC_U8; break;
case AFMT_S16_BE: fourcc = VLC_CODEC_S16B; break; case AFMT_S16_BE: fmt->i_format = VLC_CODEC_S16B; break;
case AFMT_S16_LE: fourcc = VLC_CODEC_S16L; break; case AFMT_S16_LE: fmt->i_format = VLC_CODEC_S16L; break;
//case AFMT_S24_BE: //case AFMT_S24_BE:
//case AFMT_S24_LE: //case AFMT_S24_LE:
case AFMT_S32_BE: fourcc = VLC_CODEC_S32B; break; case AFMT_S32_BE: fmt->i_format = VLC_CODEC_S32B; break;
case AFMT_S32_LE: fourcc = VLC_CODEC_S32L; break; case AFMT_S32_LE: fmt->i_format = VLC_CODEC_S32L; break;
#ifdef AFMT_FLOAT #ifdef AFMT_FLOAT
case AFMT_FLOAT: fourcc = VLC_CODEC_FL32; break; case AFMT_FLOAT: fmt->i_format = VLC_CODEC_FL32; break;
#endif #endif
case AFMT_AC3: case AFMT_AC3:
if (spdif) if (spdif)
{ {
fourcc = VLC_CODEC_SPDIFL; fmt->i_format = VLC_CODEC_SPDIFL;
break; break;
} }
default: default:
@ -197,7 +195,7 @@ static int Open (vlc_object_t *obj)
} }
/* Select channels count */ /* 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) if (ioctl (fd, SNDCTL_DSP_CHANNELS, &channels) < 0)
{ {
msg_Err (aout, "cannot set %d channels: %m", channels); msg_Err (aout, "cannot set %d channels: %m", channels);
@ -217,7 +215,7 @@ static int Open (vlc_object_t *obj)
} }
/* Select sample rate */ /* 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) if (ioctl (fd, SNDCTL_DSP_SPEED, &rate) < 0)
{ {
msg_Err (aout, "cannot set %d Hz sample rate: %m", rate); 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 */ /* Setup audio_output_t */
aout->format.i_format = fourcc;
aout->play = Play; aout->play = Play;
aout->pause = Pause; aout->pause = Pause;
aout->flush = Flush; aout->flush = Flush;
@ -234,14 +231,14 @@ static int Open (vlc_object_t *obj)
if (spdif) if (spdif)
{ {
aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE; fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
aout->format.i_frame_length = A52_FRAME_NB; fmt->i_frame_length = A52_FRAME_NB;
} }
else else
{ {
aout->format.i_rate = rate; fmt->i_rate = rate;
aout->format.i_original_channels = fmt->i_original_channels =
aout->format.i_physical_channels = channels; fmt->i_physical_channels = channels;
sys->level = 100; sys->level = 100;
sys->mute = false; sys->mute = false;
@ -303,9 +300,8 @@ error:
/** /**
* Releases the audio output. * 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; aout_sys_t *sys = aout->sys;
int fd = sys->fd; int fd = sys->fd;
@ -445,3 +441,13 @@ static int MuteSet (audio_output_t *aout, bool mute)
aout_MuteReport (aout, mute); aout_MuteReport (aout, mute);
return 0; 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); 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)); assert (p == aout_packet (aout));
vlc_mutex_init (&p->lock); vlc_mutex_init (&p->lock);
aout_FifoInit (&p->partial, aout->format.i_rate); p->format = *fmt;
aout_FifoInit (&p->fifo, aout->format.i_rate); aout_FifoInit (&p->partial, p->format.i_rate);
aout_FifoInit (&p->fifo, p->format.i_rate);
p->pause_date = VLC_TS_INVALID; p->pause_date = VLC_TS_INVALID;
p->time_report = INT64_MIN; p->time_report = INT64_MIN;
p->samples = samples; p->samples = samples;
@ -253,9 +255,9 @@ static block_t *aout_OutputSlice (audio_output_t *p_aout)
available += p_buffer->i_nb_samples; 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 */ /* Build packet with adequate number of samples */
unsigned needed = samples * framesize; unsigned needed = samples * framesize;
@ -285,7 +287,7 @@ static block_t *aout_OutputSlice (audio_output_t *p_aout)
needed /= framesize; needed /= framesize;
p_fifo->p_first->i_nb_samples -= needed; 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_pts += t;
p_fifo->p_first->i_length -= t; p_fifo->p_first->i_length -= t;
break; 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_packet_t *p = aout_packet (p_aout);
aout_fifo_t *p_fifo = &p->fifo; aout_fifo_t *p_fifo = &p->fifo;
block_t *p_buffer; 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 now = mdate ();
const mtime_t threshold = const mtime_t threshold =
(b_can_sleek ? start_date : now) - AOUT_MAX_PTS_DELAY; (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 last_pts; /**< Play time of buffer write offset */
mtime_t paused; /**< Time when (last) paused */ mtime_t paused; /**< Time when (last) paused */
mtime_t desync; /**< Measured desynchronization */ 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 *); 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) static void stream_reset_sync(pa_stream *s, audio_output_t *aout)
{ {
aout_sys_t *sys = aout->sys; 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->first_pts = VLC_TS_INVALID;
sys->last_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)) if (unlikely(op == NULL))
return; return;
pa_operation_unref(op); pa_operation_unref(op);
sys->rate = rate; sys->actual_rate = rate;
} }
static void stream_start_now(pa_stream *s, audio_output_t *aout) 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)", //msg_Dbg(aout, "desync: %+"PRId64" us (variation: %+"PRId64" us)",
// delta, change); // delta, change);
const unsigned inrate = aout->format.i_rate; const unsigned inrate = sys->nominal_rate;
unsigned outrate = sys->rate; unsigned outrate = sys->actual_rate;
bool sync = false; bool sync = false;
if (delta < -AOUT_MAX_PTS_DELAY) if (delta < -AOUT_MAX_PTS_DELAY)
@ -325,7 +326,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
int limit = inrate >> 10; int limit = inrate >> 10;
/* However, to improve stability and try to converge, closing to the /* However, to improve stability and try to converge, closing to the
* nominal rate is favored over drifting from it. */ * nominal rate is favored over drifting from it. */
if ((adj > 0) == (sys->rate > inrate)) if ((adj > 0) == (sys->actual_rate > inrate))
limit *= 2; limit *= 2;
if (adj > +limit) if (adj > +limit)
adj = +limit; adj = +limit;
@ -342,7 +343,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
outrate = inrate - limit; outrate = inrate - limit;
/* Apply adjusted sample rate */ /* Apply adjusted sample rate */
if (outrate == sys->rate) if (outrate == sys->actual_rate)
return; return;
pa_operation *op = pa_stream_update_sample_rate(s, outrate, NULL, NULL); pa_operation *op = pa_stream_update_sample_rate(s, outrate, NULL, NULL);
if (unlikely(op == NULL)) { if (unlikely(op == NULL)) {
@ -351,7 +352,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
} }
pa_operation_unref(op); pa_operation_unref(op);
msg_Dbg(aout, "changed sample rate to %u Hz",outrate); 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; return (op != NULL) ? VLC_SUCCESS : VLC_EGENERIC;
} }
static void Stop(audio_output_t *);
/** /**
* Create a PulseAudio playback stream, a.k.a. a sink input. * 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) aout_sys_t *sys = aout->sys;
if (!vlc_xlib_init(obj))
return VLC_EGENERIC;
#endif
audio_output_t *aout = (audio_output_t *)obj;
pa_operation *op; pa_operation *op;
/* Sample format specification */ /* Sample format specification */
struct pa_sample_spec ss; struct pa_sample_spec ss;
vlc_fourcc_t format = aout->format.i_format;
#if PA_CHECK_VERSION(1,0,0) #if PA_CHECK_VERSION(1,0,0)
pa_encoding_t encoding = PA_ENCODING_INVALID; pa_encoding_t encoding = PA_ENCODING_INVALID;
#endif #endif
switch(format) switch (fmt->i_format)
{ {
case VLC_CODEC_F64B: case VLC_CODEC_F64B:
format = VLC_CODEC_F32B; fmt->i_format = VLC_CODEC_F32B;
case VLC_CODEC_F32B: case VLC_CODEC_F32B:
ss.format = PA_SAMPLE_FLOAT32BE; ss.format = PA_SAMPLE_FLOAT32BE;
break; break;
case VLC_CODEC_F64L: case VLC_CODEC_F64L:
format = VLC_CODEC_F32L; fmt->i_format = VLC_CODEC_F32L;
case VLC_CODEC_F32L: case VLC_CODEC_F32L:
ss.format = PA_SAMPLE_FLOAT32LE; ss.format = PA_SAMPLE_FLOAT32LE;
break; break;
@ -751,28 +747,28 @@ static int Open(vlc_object_t *obj)
ss.format = PA_SAMPLE_S16LE; ss.format = PA_SAMPLE_S16LE;
break; break;
case VLC_CODEC_S8: case VLC_CODEC_S8:
format = VLC_CODEC_U8; fmt->i_format = VLC_CODEC_U8;
case VLC_CODEC_U8: case VLC_CODEC_U8:
ss.format = PA_SAMPLE_U8; ss.format = PA_SAMPLE_U8;
break; break;
#if PA_CHECK_VERSION(1,0,0) #if PA_CHECK_VERSION(1,0,0)
case VLC_CODEC_A52: case VLC_CODEC_A52:
format = VLC_CODEC_SPDIFL; fmt->i_format = VLC_CODEC_SPDIFL;
encoding = PA_ENCODING_AC3_IEC61937; encoding = PA_ENCODING_AC3_IEC61937;
ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE; ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
break; break;
/*case VLC_CODEC_EAC3: /*case VLC_CODEC_EAC3:
format = VLC_CODEC_SPDIFL FIXME; fmt->i_format = VLC_CODEC_SPDIFL FIXME;
encoding = PA_ENCODING_EAC3_IEC61937; encoding = PA_ENCODING_EAC3_IEC61937;
ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE; ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
break; break;
case VLC_CODEC_MPGA: case VLC_CODEC_MPGA:
format = VLC_CODEC_SPDIFL FIXME; fmt->i_format = VLC_CODEC_SPDIFL FIXME;
encoding = PA_ENCODING_MPEG_IEC61937; encoding = PA_ENCODING_MPEG_IEC61937;
ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE; ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
break;*/ break;*/
case VLC_CODEC_DTS: case VLC_CODEC_DTS:
format = VLC_CODEC_SPDIFL; fmt->i_format = VLC_CODEC_SPDIFL;
encoding = PA_ENCODING_DTS_IEC61937; encoding = PA_ENCODING_DTS_IEC61937;
ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE; ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
break; break;
@ -780,19 +776,19 @@ static int Open(vlc_object_t *obj)
default: default:
if (HAVE_FPU) if (HAVE_FPU)
{ {
format = VLC_CODEC_FL32; fmt->i_format = VLC_CODEC_FL32;
ss.format = PA_SAMPLE_FLOAT32NE; ss.format = PA_SAMPLE_FLOAT32NE;
} }
else else
{ {
format = VLC_CODEC_S16N; fmt->i_format = VLC_CODEC_S16N;
ss.format = PA_SAMPLE_S16NE; ss.format = PA_SAMPLE_S16NE;
} }
break; break;
} }
ss.rate = aout->format.i_rate; ss.rate = fmt->i_rate;
ss.channels = aout_FormatNbChannels(&aout->format); ss.channels = aout_FormatNbChannels(fmt);
if (!pa_sample_spec_valid(&ss)) { if (!pa_sample_spec_valid(&ss)) {
msg_Err(aout, "unsupported sample specification"); msg_Err(aout, "unsupported sample specification");
return VLC_EGENERIC; return VLC_EGENERIC;
@ -802,28 +798,28 @@ static int Open(vlc_object_t *obj)
struct pa_channel_map map; struct pa_channel_map map;
map.channels = 0; 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; 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; 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; 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; 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; 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; 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; 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) if (ss.channels == 1)
map.map[map.channels++] = PA_CHANNEL_POSITION_MONO; map.map[map.channels++] = PA_CHANNEL_POSITION_MONO;
else else
map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_CENTER; 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; map.map[map.channels++] = PA_CHANNEL_POSITION_LFE;
for (unsigned i = 0; map.channels < ss.channels; i++) { for (unsigned i = 0; map.channels < ss.channels; i++) {
@ -859,27 +855,14 @@ static int Open(vlc_object_t *obj)
attr.minreq = -1; attr.minreq = -1;
attr.fragsize = 0; /* not used for output */ 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->stream = NULL;
sys->context = ctx;
sys->trigger = NULL; sys->trigger = NULL;
sys->first_pts = VLC_TS_INVALID; sys->first_pts = VLC_TS_INVALID;
sys->last_pts = VLC_TS_INVALID; sys->last_pts = VLC_TS_INVALID;
sys->paused = VLC_TS_INVALID; sys->paused = VLC_TS_INVALID;
sys->desync = 0; sys->desync = 0;
sys->rate = ss.rate; sys->nominal_rate = ss.rate;
sys->actual_rate = ss.rate;
/* Channel volume */ /* Channel volume */
sys->base_volume = PA_VOLUME_NORM; 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_proplist_sets (props, PA_PROP_MEDIA_ROLE, "video");
pa_threaded_mainloop_lock(sys->mainloop); 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)) if (likely(props != NULL))
pa_proplist_free(props); pa_proplist_free(props);
@ -924,11 +908,12 @@ static int Open(vlc_object_t *obj)
pa_format_info_free(formatv[i]); pa_format_info_free(formatv[i]);
#else #else
pa_threaded_mainloop_lock(sys->mainloop); 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 #endif
if (s == NULL) { if (s == NULL) {
vlc_pa_error(obj, "stream creation failure", ctx); pa_threaded_mainloop_unlock(sys->mainloop);
goto fail; vlc_pa_error(aout, "stream creation failure", sys->context);
return VLC_EGENERIC;
} }
sys->stream = s; sys->stream = s;
pa_stream_set_state_callback(s, stream_state_cb, sys->mainloop); 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 if (pa_stream_connect_playback(s, NULL, &attr, flags, NULL, NULL) < 0
|| stream_wait(s, sys->mainloop)) { || stream_wait(s, sys->mainloop)) {
vlc_pa_error(obj, "stream connection failure", ctx); vlc_pa_error(aout, "stream connection failure", sys->context);
goto fail; goto fail;
} }
@ -954,7 +939,7 @@ static int Open(vlc_object_t *obj)
assert (info != NULL); assert (info != NULL);
if (pa_format_info_is_pcm (info)) { if (pa_format_info_is_pcm (info)) {
msg_Dbg(aout, "digital pass-through not available"); 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 { } else {
msg_Dbg(aout, "digital pass-through enabled"); msg_Dbg(aout, "digital pass-through enabled");
pa_stream_set_latency_update_callback(s, NULL, NULL); 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") }, &(vlc_value_t){ .psz_string = (char *)_("Audio device") },
NULL); NULL);
var_AddCallback (aout, "audio-device", StreamMove, s); 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 */ /* We may need to wait for completion... once LibVLC supports this */
if (op != NULL) if (op != NULL)
pa_operation_unref(op); pa_operation_unref(op);
@ -977,61 +962,90 @@ static int Open(vlc_object_t *obj)
/* Context events */ /* Context events */
const pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SINK const pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SINK
| PA_SUBSCRIPTION_MASK_SINK_INPUT; | PA_SUBSCRIPTION_MASK_SINK_INPUT;
pa_context_set_subscribe_callback(ctx, context_cb, aout); pa_context_set_subscribe_callback(sys->context, context_cb, aout);
op = pa_context_subscribe(ctx, mask, NULL, NULL); op = pa_context_subscribe(sys->context, mask, NULL, NULL);
if (likely(op != NULL)) if (likely(op != NULL))
pa_operation_unref(op); pa_operation_unref(op);
pa_threaded_mainloop_unlock(sys->mainloop); 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; return VLC_SUCCESS;
fail: fail:
pa_threaded_mainloop_unlock(sys->mainloop); pa_threaded_mainloop_unlock(sys->mainloop);
Close(obj); Stop(aout);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/** /**
* Removes a PulseAudio playback stream * 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; audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
pa_context *ctx = sys->context; 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); vlc_pa_disconnect(obj, ctx, sys->mainloop);
free(sys); free(sys);

View File

@ -32,7 +32,7 @@
#include <sndio.h> #include <sndio.h>
static int Open (vlc_object_t *); static int Open (vlc_object_t *);
static void Close (vlc_object_t *); static void Close (vlc_objec_t *);
vlc_module_begin () vlc_module_begin ()
set_shortname ("sndio") set_shortname ("sndio")
@ -40,7 +40,7 @@ vlc_module_begin ()
set_category (CAT_AUDIO) set_category (CAT_AUDIO)
set_subcategory (SUBCAT_AUDIO_AOUT) set_subcategory (SUBCAT_AUDIO_AOUT)
set_capability ("audio output", 120) set_capability ("audio output", 120)
set_callbacks (Open, Close ) set_callbacks (Open, Close)
vlc_module_end () vlc_module_end ()
static void Play (audio_output_t *, block_t *, mtime_t *); static void Play (audio_output_t *, block_t *, mtime_t *);
@ -57,12 +57,9 @@ struct aout_sys_t
}; };
/** Initializes an sndio playback stream */ /** 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 = aout->sys;
aout_sys_t *sys = malloc (sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_EGENERIC;
sys->hdl = sio_open (NULL, SIO_PLAY, 0 /* blocking */); sys->hdl = sio_open (NULL, SIO_PLAY, 0 /* blocking */);
if (sys->hdl == NULL) if (sys->hdl == NULL)
@ -79,8 +76,8 @@ static int Open (vlc_object_t *obj)
par.bps = par.bits >> 3; par.bps = par.bits >> 3;
par.sig = 1; par.sig = 1;
par.le = SIO_LE_NATIVE; par.le = SIO_LE_NATIVE;
par.pchan = aout_FormatNbChannels (&aout->format); par.pchan = aout_FormatNbChannels (fmt);
par.rate = aout->format.i_rate; par.rate = fmt->i_rate;
par.xrun = SIO_SYNC; par.xrun = SIO_SYNC;
if (!sio_setpar (sys->hdl, &par) || !sio_getpar (sys->hdl, &par)) if (!sio_setpar (sys->hdl, &par) || !sio_getpar (sys->hdl, &par))
@ -96,23 +93,24 @@ static int Open (vlc_object_t *obj)
goto error; goto error;
} }
audio_format_t f;
switch (par.bits) switch (par.bits)
{ {
case 8: 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; break;
case 16: 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); : (par.le ? VLC_CODEC_U16L : VLC_CODEC_U16B);
break; break;
case 24: 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); : (par.le ? VLC_CODEC_U24L : VLC_CODEC_U24B);
break; break;
case 32: 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); : (par.le ? VLC_CODEC_U32L : VLC_CODEC_U32B);
break; break;
default: default:
@ -121,7 +119,7 @@ static int Open (vlc_object_t *obj)
goto error; goto error;
} }
f.i_rate = par.rate; fmt->i_rate = par.rate;
/* Channel map */ /* Channel map */
unsigned chans; unsigned chans;
@ -147,10 +145,9 @@ static int Open (vlc_object_t *obj)
goto error; goto error;
} }
f.i_original_channels = f.i_physical_channels = chans; fmt->i_original_channels = fmt->i_physical_channels = chans;
aout_FormatPrepare (&f); aout_FormatPrepare (fmt);
aout->format = f;
aout->sys = sys; aout->sys = sys;
aout->play = Play; aout->play = Play;
aout->pause = Pause; aout->pause = Pause;
@ -170,7 +167,7 @@ static int Open (vlc_object_t *obj)
return VLC_SUCCESS; return VLC_SUCCESS;
error: error:
Close (obj); sio_close (sys->hdl);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
@ -180,7 +177,6 @@ static void Close (vlc_object_t *obj)
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
sio_close (sys->hdl); sio_close (sys->hdl);
free (sys);
} }
static void Play (audio_output_t *aout, block_t *block, 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; sys->mute = mute;
return 0; 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; struct IAudioSessionEvents events;
LONG refs; LONG refs;
unsigned rate; /**< Sample rate */
unsigned bytes_per_frame;
UINT32 frames; /**< Total buffer size (frames) */ UINT32 frames; /**< Total buffer size (frames) */
HANDLE ready; /**< Semaphore from MTA thread */ HANDLE ready; /**< Semaphore from MTA thread */
HANDLE done; /**< Semaphore to 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; 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); memcpy(dst, block->p_buffer, copy);
hr = IAudioRenderClient_ReleaseBuffer(sys->render, frames, 0); 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 */ /* Out of buffer space, sleep */
msleep(AOUT_MIN_PREPARE_TIME msleep(AOUT_MIN_PREPARE_TIME
+ block->i_nb_samples * CLOCK_FREQ / aout->format.i_rate); + block->i_nb_samples * CLOCK_FREQ / sys->rate);
} }
Leave(); Leave();
@ -653,20 +655,11 @@ fail:
ReleaseSemaphore(sys->ready, 1, NULL); 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; 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->client = NULL;
sys->render = NULL; sys->render = NULL;
sys->clock = NULL; sys->clock = NULL;
@ -674,17 +667,8 @@ static int Open(vlc_object_t *obj)
sys->refs = 1; sys->refs = 1;
sys->ready = NULL; sys->ready = NULL;
sys->done = 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; IMMDeviceEnumerator *devs;
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
&IID_IMMDeviceEnumerator, (void **)&devs); &IID_IMMDeviceEnumerator, (void **)&devs);
@ -693,6 +677,9 @@ retry:
msg_Dbg(aout, "cannot create device enumerator (error 0x%lx)", hr); msg_Dbg(aout, "cannot create device enumerator (error 0x%lx)", hr);
goto error; 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. // Without configuration item, the variable must be created explicitly.
var_Create (aout, "wasapi-audio-device", VLC_VAR_STRING); var_Create (aout, "wasapi-audio-device", VLC_VAR_STRING);
@ -741,11 +728,10 @@ retry:
} }
/* Configure audio stream */ /* Configure audio stream */
audio_sample_format_t format = aout->format;
WAVEFORMATEXTENSIBLE wf; WAVEFORMATEXTENSIBLE wf;
WAVEFORMATEX *pwf; WAVEFORMATEX *pwf;
vlc_ToWave(&wf, &format); vlc_ToWave(&wf, fmt);
hr = IAudioClient_IsFormatSupported(sys->client, AUDCLNT_SHAREMODE_SHARED, hr = IAudioClient_IsFormatSupported(sys->client, AUDCLNT_SHAREMODE_SHARED,
&wf.Format, &pwf); &wf.Format, &pwf);
if (FAILED(hr)) if (FAILED(hr))
@ -757,7 +743,7 @@ retry:
if (hr == S_FALSE) if (hr == S_FALSE)
{ {
assert(pwf != NULL); assert(pwf != NULL);
if (vlc_FromWave(pwf, &format)) if (vlc_FromWave(pwf, fmt))
{ {
CoTaskMemFree(pwf); CoTaskMemFree(pwf);
msg_Err(aout, "unsupported audio format"); msg_Err(aout, "unsupported audio format");
@ -799,15 +785,11 @@ retry:
Leave(); Leave();
aout->format = format; sys->rate = fmt->i_rate;
sys->bytes_per_frame = fmt->i_bytes_per_frame;
aout->play = Play; aout->play = Play;
aout->pause = Pause; aout->pause = Pause;
aout->flush = Flush; aout->flush = Flush;
/*if (AOUT_FMT_LINEAR(&format) && !exclusive)*/
{
aout->volume_set = SimpleVolumeSet;
aout->mute_set = SimpleMuteSet;
}
if (likely(sys->control != NULL)) if (likely(sys->control != NULL))
IAudioSessionControl_RegisterAudioSessionNotification(sys->control, IAudioSessionControl_RegisterAudioSessionNotification(sys->control,
&sys->events); &sys->events);
@ -828,13 +810,11 @@ error:
goto retry; goto retry;
} }
Leave(); Leave();
free(sys);
return VLC_EGENERIC; 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; aout_sys_t *sys = aout->sys;
Enter(); Enter();
@ -852,5 +832,40 @@ static void Close (vlc_object_t *obj)
CloseHandle(sys->done); CloseHandle(sys->done);
CloseHandle(sys->ready); 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); free(sys);
} }

View File

@ -57,7 +57,7 @@ static void Play ( audio_output_t *, block_t *, mtime_t * );
* notification_thread_t: waveOut event thread * notification_thread_t: waveOut event thread
*****************************************************************************/ *****************************************************************************/
/* local functions */ /* 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, static int OpenWaveOut ( audio_output_t *, uint32_t,
int, int, int, int, bool ); int, int, int, int, bool );
static int OpenWaveOutPCM( audio_output_t *, uint32_t, static int OpenWaveOutPCM( audio_output_t *, uint32_t,
@ -153,21 +153,14 @@ vlc_module_begin ()
vlc_module_end () vlc_module_end ()
/***************************************************************************** /*****************************************************************************
* Open: open the audio device * Opens the audio device
***************************************************************************** *****************************************************************************
* This function opens and setups Win32 waveOut * 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; 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->play = Play;
p_aout->pause = aout_PacketPause; p_aout->pause = aout_PacketPause;
p_aout->flush = aout_PacketFlush; 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 ) if( var_Type( p_aout, "audio-device" ) == 0 )
{ {
Probe( p_aout ); Probe( p_aout, fmt );
} }
if( var_Get( p_aout, "audio-device", &val ) < 0 ) if( var_Get( p_aout, "audio-device", &val ) < 0 )
@ -226,14 +219,11 @@ static int Open( vlc_object_t *p_this )
/* Open the device */ /* Open the device */
if( val.i_int == AOUT_VAR_SPDIF ) 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, if( OpenWaveOut( p_aout, p_aout->sys->i_wave_device_id,
p_aout->sys->i_wave_device_id, VLC_CODEC_SPDIFL, fmt->i_physical_channels,
VLC_CODEC_SPDIFL, aout_FormatNbChannels( fmt ), fmt->i_rate, false )
p_aout->format.i_physical_channels,
aout_FormatNbChannels( &p_aout->format ),
p_aout->format.i_rate, false )
!= VLC_SUCCESS ) != VLC_SUCCESS )
{ {
msg_Err( p_aout, "cannot open waveout audio device" ); 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 */ /* Calculate the frame size in bytes */
p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE; fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
p_aout->format.i_frame_length = A52_FRAME_NB; fmt->i_frame_length = A52_FRAME_NB;
p_aout->sys->i_buffer_size = p_aout->sys->i_buffer_size = fmt->i_bytes_per_frame;
p_aout->format.i_bytes_per_frame;
aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB ); aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB, fmt );
p_aout->volume_set = NULL;
p_aout->mute_set = NULL;
} }
else else
{ {
@ -258,30 +245,26 @@ static int Open( vlc_object_t *p_this )
switch( val.i_int ) switch( val.i_int )
{ {
case AOUT_VAR_5_1: 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_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
| AOUT_CHAN_LFE; | AOUT_CHAN_LFE;
break; break;
case AOUT_VAR_2F2R: case AOUT_VAR_2F2R:
p_aout->format.i_physical_channels fmt->i_physical_channels
= AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
break; break;
case AOUT_VAR_MONO: case AOUT_VAR_MONO:
p_aout->format.i_physical_channels = AOUT_CHAN_CENTER; fmt->i_physical_channels = AOUT_CHAN_CENTER;
break; break;
default: default:
p_aout->format.i_physical_channels fmt->i_physical_channels = AOUT_CHANS_STEREO;
= AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
} }
if( OpenWaveOutPCM( p_aout, if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
p_aout->sys->i_wave_device_id, &fmt->i_format, fmt->i_physical_channels,
&p_aout->format.i_format, aout_FormatNbChannels( fmt ), fmt->i_rate, false )
p_aout->format.i_physical_channels,
aout_FormatNbChannels( &p_aout->format ),
p_aout->format.i_rate, false )
!= VLC_SUCCESS ) != VLC_SUCCESS )
{ {
msg_Err( p_aout, "cannot open waveout audio device" ); 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 */ /* Calculate the frame size in bytes */
aout_FormatPrepare( &p_aout->format ); aout_FormatPrepare( fmt );
p_aout->sys->i_buffer_size = FRAME_SIZE * p_aout->sys->i_buffer_size = FRAME_SIZE * fmt->i_bytes_per_frame;
p_aout->format.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 */ /* Check for hardware volume support */
if( waveOutGetDevCaps( (UINT_PTR)p_aout->sys->h_waveout, if( waveOutGetDevCaps( (UINT_PTR)p_aout->sys->h_waveout,
&wocaps, sizeof(wocaps) ) == MMSYSERR_NOERROR &wocaps, sizeof(wocaps) ) == MMSYSERR_NOERROR
&& (wocaps.dwSupport & WAVECAPS_VOLUME) ) && (wocaps.dwSupport & WAVECAPS_VOLUME) )
{ { /* FIXME: this needs to be moved to Open() */
p_aout->volume_set = VolumeSet; p_aout->volume_set = VolumeSet;
p_aout->mute_set = MuteSet; p_aout->mute_set = MuteSet;
p_aout->sys->volume = 0xffff.fp0; 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 * 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_value_t val, text;
vlc_fourcc_t i_format; 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 | i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; 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, if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
p_aout->sys->i_wave_device_id, &i_format, i_physical_channels, 6,
&i_format, fmt->i_rate, true )
i_physical_channels, 6,
p_aout->format.i_rate, true )
== VLC_SUCCESS ) == VLC_SUCCESS )
{ {
val.i_int = AOUT_VAR_5_1; 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 */ /* Test for 2 Front 2 Rear support */
i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; 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 ) == i_physical_channels )
{ {
if( OpenWaveOutPCM( p_aout, if( OpenWaveOutPCM( p_aout,p_aout->sys->i_wave_device_id,
p_aout->sys->i_wave_device_id, &i_format, i_physical_channels, 4,
&i_format, fmt->i_rate, true )
i_physical_channels, 4,
p_aout->format.i_rate, true )
== VLC_SUCCESS ) == VLC_SUCCESS )
{ {
val.i_int = AOUT_VAR_2F2R; val.i_int = AOUT_VAR_2F2R;
@ -414,11 +392,9 @@ static void Probe( audio_output_t * p_aout )
/* Test for stereo support */ /* Test for stereo support */
i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
if( OpenWaveOutPCM( p_aout, if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
p_aout->sys->i_wave_device_id, &i_format,i_physical_channels, 2,
&i_format, fmt->i_rate, true )
i_physical_channels, 2,
p_aout->format.i_rate, true )
== VLC_SUCCESS ) == VLC_SUCCESS )
{ {
val.i_int = AOUT_VAR_STEREO; val.i_int = AOUT_VAR_STEREO;
@ -429,11 +405,8 @@ static void Probe( audio_output_t * p_aout )
/* Test for mono support */ /* Test for mono support */
i_physical_channels = AOUT_CHAN_CENTER; i_physical_channels = AOUT_CHAN_CENTER;
if( OpenWaveOutPCM( p_aout, if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
p_aout->sys->i_wave_device_id, &i_format, i_physical_channels, 1, fmt->i_rate, true )
&i_format,
i_physical_channels, 1,
p_aout->format.i_rate, true )
== VLC_SUCCESS ) == VLC_SUCCESS )
{ {
val.i_int = AOUT_VAR_MONO; val.i_int = AOUT_VAR_MONO;
@ -443,14 +416,11 @@ static void Probe( audio_output_t * p_aout )
} }
/* Test for SPDIF support */ /* Test for SPDIF support */
if ( AOUT_FMT_SPDIF( &p_aout->format ) ) if ( AOUT_FMT_SPDIF( fmt ) )
{ {
if( OpenWaveOut( p_aout, if( OpenWaveOut( p_aout, p_aout->sys->i_wave_device_id,
p_aout->sys->i_wave_device_id, VLC_CODEC_SPDIFL, fmt->i_physical_channels,
VLC_CODEC_SPDIFL, aout_FormatNbChannels( fmt ), fmt->i_rate, true )
p_aout->format.i_physical_channels,
aout_FormatNbChannels( &p_aout->format ),
p_aout->format.i_rate, true )
== VLC_SUCCESS ) == VLC_SUCCESS )
{ {
msg_Dbg( p_aout, "device supports A/52 over S/PDIF" ); 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 * 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; aout_sys_t *p_sys = p_aout->sys;
/* Before calling waveOutClose we must reset the device */ /* 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 ); free( p_sys->p_silence_buffer );
aout_PacketDestroy( p_aout ); aout_PacketDestroy( p_aout );
free( p_sys );
} }
/***************************************************************************** /*****************************************************************************
@ -886,7 +854,7 @@ static void* WaveOutThread( void *data )
int canc = vlc_savecancel (); int canc = vlc_savecancel ();
/* We don't want any resampling when using S/PDIF */ /* 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()" // wait for first call to "play()"
while( !p_sys->start_date && !vlc_atomic_get(&p_aout->sys->abort) ) 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; 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. * This function is entered with the mixer lock.
*****************************************************************************/ *****************************************************************************/
int aout_OutputNew( audio_output_t *p_aout, int aout_OutputNew (audio_output_t *aout, const audio_sample_format_t *fmtp)
const audio_sample_format_t * p_format )
{ {
aout_owner_t *owner = aout_owner (p_aout); aout_owner_t *owner = aout_owner (aout);
aout_assert_locked( p_aout ); audio_sample_format_t fmt = *fmtp;
p_aout->format = *p_format; aout_FormatPrepare (&fmt);
aout_FormatPrepare( &p_aout->format );
p_aout->event.volume_report = aout_OutputVolumeReport; aout_assert_locked (aout);
p_aout->event.mute_report = aout_OutputMuteReport;
p_aout->event.policy_report = aout_OutputPolicyReport; aout->event.volume_report = aout_OutputVolumeReport;
p_aout->event.gain_request = aout_OutputGainRequest; aout->event.mute_report = aout_OutputMuteReport;
aout->event.policy_report = aout_OutputPolicyReport;
aout->event.gain_request = aout_OutputGainRequest;
/* Find the best output plug-in. */ /* 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) if (owner->module == NULL)
{ {
msg_Err( p_aout, "no suitable audio output module" ); msg_Err (aout, "no suitable audio output module");
return -1; return -1;
} }
if (!var_Type (p_aout, "stereo-mode")) if (aout->start (aout, &fmt))
var_Create (p_aout, "stereo-mode", {
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); VLC_VAR_INTEGER | VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT);
/* The user may have selected a different channels configuration. */ /* The user may have selected a different channels configuration. */
var_AddCallback (p_aout, "stereo-mode", aout_ChannelsRestart, NULL); var_AddCallback (aout, "stereo-mode", aout_ChannelsRestart, NULL);
switch (var_GetInteger (p_aout, "stereo-mode")) switch (var_GetInteger (aout, "stereo-mode"))
{ {
case AOUT_VAR_CHAN_RSTEREO: case AOUT_VAR_CHAN_RSTEREO:
p_aout->format.i_original_channels |= AOUT_CHAN_REVERSESTEREO; fmt.i_original_channels |= AOUT_CHAN_REVERSESTEREO;
break; break;
case AOUT_VAR_CHAN_STEREO: case AOUT_VAR_CHAN_STEREO:
p_aout->format.i_original_channels = AOUT_CHANS_STEREO; fmt.i_original_channels = AOUT_CHANS_STEREO;
break; break;
case AOUT_VAR_CHAN_LEFT: case AOUT_VAR_CHAN_LEFT:
p_aout->format.i_original_channels = AOUT_CHAN_LEFT; fmt.i_original_channels = AOUT_CHAN_LEFT;
break; break;
case AOUT_VAR_CHAN_RIGHT: case AOUT_VAR_CHAN_RIGHT:
p_aout->format.i_original_channels = AOUT_CHAN_RIGHT; fmt.i_original_channels = AOUT_CHAN_RIGHT;
break; break;
case AOUT_VAR_CHAN_DOLBYS: case AOUT_VAR_CHAN_DOLBYS:
p_aout->format.i_original_channels = fmt.i_original_channels = AOUT_CHANS_STEREO|AOUT_CHAN_DOLBYSTEREO;
AOUT_CHANS_STEREO | AOUT_CHAN_DOLBYSTEREO;
break; break;
default: default:
{ {
if ((p_aout->format.i_original_channels & AOUT_CHAN_PHYSMASK) if ((fmt.i_original_channels & AOUT_CHAN_PHYSMASK)
!= AOUT_CHANS_STEREO) != AOUT_CHANS_STEREO)
break; break;
vlc_value_t val, txt; vlc_value_t val, txt;
val.i_int = 0; 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"); txt.psz_string = _("Stereo audio mode");
var_Change (p_aout, "stereo-mode", VLC_VAR_SETTEXT, &txt, NULL); var_Change (aout, "stereo-mode", VLC_VAR_SETTEXT, &txt, NULL);
if (p_aout->format.i_original_channels & AOUT_CHAN_DOLBYSTEREO) if (fmt.i_original_channels & AOUT_CHAN_DOLBYSTEREO)
{ {
val.i_int = AOUT_VAR_CHAN_DOLBYS; val.i_int = AOUT_VAR_CHAN_DOLBYS;
txt.psz_string = _("Dolby Surround"); txt.psz_string = _("Dolby Surround");
@ -143,33 +150,32 @@ int aout_OutputNew( audio_output_t *p_aout,
val.i_int = AOUT_VAR_CHAN_STEREO; val.i_int = AOUT_VAR_CHAN_STEREO;
txt.psz_string = _("Stereo"); txt.psz_string = _("Stereo");
} }
var_Change (p_aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt); var_Change (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_SETVALUE, &val, NULL);
val.i_int = AOUT_VAR_CHAN_LEFT; val.i_int = AOUT_VAR_CHAN_LEFT;
txt.psz_string = _("Left"); txt.psz_string = _("Left");
var_Change (p_aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt); var_Change (aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
if (p_aout->format.i_original_channels & AOUT_CHAN_DUALMONO) if (fmt.i_original_channels & AOUT_CHAN_DUALMONO)
{ /* Go directly to the left channel. */ { /* Go directly to the left channel. */
p_aout->format.i_original_channels = AOUT_CHAN_LEFT; fmt.i_original_channels = AOUT_CHAN_LEFT;
var_Change (p_aout, "stereo-mode", VLC_VAR_SETVALUE, &val, var_Change (aout, "stereo-mode", VLC_VAR_SETVALUE, &val, NULL);
NULL);
} }
val.i_int = AOUT_VAR_CHAN_RIGHT; val.i_int = AOUT_VAR_CHAN_RIGHT;
txt.psz_string = _("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; val.i_int = AOUT_VAR_CHAN_RSTEREO;
txt.psz_string = _("Reverse stereo"); 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_FormatPrepare (&fmt);
aout_FormatPrint( p_aout, "output", &p_aout->format ); aout_FormatPrint (aout, "output", &fmt );
/* Choose the mixer format. */ /* Choose the mixer format. */
owner->mixer_format = p_aout->format; owner->mixer_format = fmt;
if (!AOUT_FMT_LINEAR(&p_aout->format)) if (!AOUT_FMT_LINEAR(&fmt))
owner->mixer_format.i_format = p_format->i_format; owner->mixer_format.i_format = fmtp->i_format;
else else
/* Most audio filters can only deal with single-precision, /* Most audio filters can only deal with single-precision,
* so lets always use that when hardware supports floating point. */ * 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; owner->mixer_format.i_format = VLC_CODEC_S16N;
aout_FormatPrepare (&owner->mixer_format); aout_FormatPrepare (&owner->mixer_format);
aout_FormatPrint (p_aout, "mixer", &owner->mixer_format); aout_FormatPrint (aout, "mixer", &owner->mixer_format);
/* Create filters. */ /* Create filters. */
owner->nb_filters = 0; owner->nb_filters = 0;
if (aout_FiltersCreatePipeline (p_aout, owner->filters, if (aout_FiltersCreatePipeline (aout, owner->filters, &owner->nb_filters,
&owner->nb_filters, &owner->mixer_format, &owner->mixer_format, &fmt) < 0)
&p_aout->format) < 0)
{ {
msg_Err( p_aout, "couldn't create audio output pipeline" ); msg_Err (aout, "couldn't create audio output pipeline");
module_unneed (p_aout, owner->module); module_unneed (aout, owner->module);
owner->module = NULL; owner->module = NULL;
return -1; return -1;
} }
@ -210,6 +215,8 @@ void aout_OutputDelete (audio_output_t *aout)
return; return;
var_DelCallback (aout, "stereo-mode", aout_ChannelsRestart, NULL); var_DelCallback (aout, "stereo-mode", aout_ChannelsRestart, NULL);
if (aout->stop != NULL)
aout->stop (aout);
module_unneed (aout, owner->module); module_unneed (aout, owner->module);
aout->volume_set = NULL; aout->volume_set = NULL;
aout->mute_set = NULL; aout->mute_set = NULL;