/*****************************************************************************
* auhal.c: AUHAL and Coreaudio output plugin
*****************************************************************************
- * Copyright (C) 2005, 2012 the VideoLAN team
+ * Copyright (C) 2005 - 2012 VLC authors and VideoLAN
* $Id$
*
* Authors: Derk-Jan Hartman <hartman at videolan dot org>
* Felix Paul Kühne <fkuehne at videolan dot org>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
+ * You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#import <vlc_plugin.h>
#import <vlc_dialog.h> // dialog_Fatal
#import <vlc_aout.h> // aout_*
-#import <vlc_aout_intf.h>
#import <AudioUnit/AudioUnit.h> // AudioUnit
#import <CoreAudio/CoreAudio.h> // AudioDeviceID
#define BUFSIZE (FRAMESIZE * 8) * 8
#define AOUT_VAR_SPDIF_FLAG 0xf00000
-/*
- * TODO:
- * - clean up the debug info
- * - be better at changing stream setup or devices setup changes while playing.
- * - fix 6.1 and 7.1
- */
+#define AOUT_VOLUME_DEFAULT 256
+#define AOUT_VOLUME_MAX 512
+
/*****************************************************************************
* aout_sys_t: private audio output method descriptor
bool b_digital; /* Are we running in digital mode? */
mtime_t clock_diff; /* Difference between VLC clock and Device clock */
+ uint8_t chans_to_reorder; /* do we need channel reordering */
+ uint8_t chan_table[AOUT_CHAN_MAX];
+
/* AUHAL specific */
Component au_component; /* The Audiocomponent we use */
AudioUnit au_unit; /* The AudioUnit we use */
* Local prototypes.
*****************************************************************************/
static int Open (vlc_object_t *);
-static int OpenAnalog (audio_output_t *);
-static int OpenSPDIF (audio_output_t *);
+static int OpenAnalog (audio_output_t *, audio_sample_format_t *);
+static int OpenSPDIF (audio_output_t *, audio_sample_format_t *);
static void Close (vlc_object_t *);
static void Probe (audio_output_t *);
"audio device, as listed in your 'Audio Device' menu. This device will " \
"then be used by default for audio playback.")
+#define VOLUME_TEXT N_("Audio volume")
+#define VOLUME_LONGTEXT VOLUME_TEXT
+
vlc_module_begin ()
set_shortname("auhal")
set_description(N_("HAL AudioUnit output"))
set_subcategory(SUBCAT_AUDIO_AOUT)
set_callbacks(Open, Close)
add_integer("macosx-audio-device", 0, ADEV_TEXT, ADEV_LONGTEXT, false)
+ add_integer( "auhal-volume", AOUT_VOLUME_DEFAULT,
+ VOLUME_TEXT, VOLUME_LONGTEXT, true )
+ change_integer_range( 0, AOUT_VOLUME_MAX )
vlc_module_end ()
/*****************************************************************************
* Open: open macosx audio output
*****************************************************************************/
-static int Open(vlc_object_t * p_this)
+static int Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
{
OSStatus err = noErr;
UInt32 i_param_size = 0;
struct aout_sys_t *p_sys = NULL;
vlc_value_t val;
- audio_output_t *p_aout = (audio_output_t *)p_this;
/* Use int here, to match kAudioDevicePropertyDeviceIsAlive
* property size */
int b_alive = false;
- /* Allocate structure */
- p_aout->sys = malloc(sizeof(aout_sys_t));
- if (p_aout->sys == NULL)
- return VLC_ENOMEM;
-
p_sys = p_aout->sys;
p_sys->i_default_dev = 0;
p_sys->i_selected_dev = 0;
p_sys->b_changed_mixing = false;
memset(p_sys->p_remainder_buffer, 0, sizeof(uint8_t) * BUFSIZE);
- p_aout->pf_play = aout_PacketPlay;
- p_aout->pf_pause = aout_PacketPause;
- p_aout->pf_flush = aout_PacketFlush;
+ p_aout->time_get = aout_PacketTimeGet;
+ p_aout->play = aout_PacketPlay;
+ p_aout->pause = NULL;
+ p_aout->flush = aout_PacketFlush;
- aout_FormatPrint(p_aout, "VLC is looking for:", &p_aout->format);
+ aout_FormatPrint(p_aout, "VLC is looking for:", fmt);
/* Persistent device variable */
if (var_Type(p_aout->p_libvlc, "macosx-audio-device") == 0)
var_AddCallback(p_aout, "audio-device", AudioDeviceCallback, NULL);
/* Check for Digital mode or Analog output mode */
- if (AOUT_FMT_SPDIF (&p_aout->format) && b_supports_digital) {
- if (OpenSPDIF (p_aout)) {
+ if (AOUT_FMT_SPDIF (fmt) && b_supports_digital) {
+ if (OpenSPDIF (p_aout, fmt)) {
msg_Dbg(p_aout, "digital output successfully opened");
return VLC_SUCCESS;
}
} else {
- if (OpenAnalog(p_aout)) {
+ if (OpenAnalog(p_aout, fmt)) {
msg_Dbg(p_aout, "analog output successfully opened");
return VLC_SUCCESS;
}
/* If we reach this, this aout has failed */
msg_Err(p_aout, "opening the auhal output failed");
var_Destroy(p_aout, "audio-device");
- free(p_sys);
return VLC_EGENERIC;
}
/*****************************************************************************
* Open: open and setup a HAL AudioUnit to do analog (multichannel) audio output
*****************************************************************************/
-static int OpenAnalog(audio_output_t *p_aout)
+static int OpenAnalog(audio_output_t *p_aout, audio_sample_format_t *fmt)
{
struct aout_sys_t *p_sys = p_aout->sys;
OSStatus err = noErr;
msg_Dbg(p_aout, "layout of AUHAL has %d channels" , (int)layout->mNumberChannelDescriptions);
/* Initialize the VLC core channel count */
- p_aout->format.i_physical_channels = 0;
- i_original = p_aout->format.i_original_channels & AOUT_CHAN_PHYSMASK;
+ fmt->i_physical_channels = 0;
+ i_original = fmt->i_original_channels & AOUT_CHAN_PHYSMASK;
if (i_original == AOUT_CHAN_CENTER || layout->mNumberChannelDescriptions < 2) {
/* We only need Mono or cannot output more than 1 channel */
- p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
+ fmt->i_physical_channels = AOUT_CHAN_CENTER;
} else if (i_original == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) || layout->mNumberChannelDescriptions < 3) {
/* We only need Stereo or cannot output more than 2 channels */
- p_aout->format.i_physical_channels = AOUT_CHAN_RIGHT | AOUT_CHAN_LEFT;
+ fmt->i_physical_channels = AOUT_CHANS_STEREO;
} else {
/* We want more than stereo and we can do that */
for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; i++) {
+#ifndef NDEBUG
msg_Dbg(p_aout, "this is channel: %d", (int)layout->mChannelDescriptions[i].mChannelLabel);
+#endif
switch(layout->mChannelDescriptions[i].mChannelLabel) {
case kAudioChannelLabel_Left:
- p_aout->format.i_physical_channels |= AOUT_CHAN_LEFT;
+ fmt->i_physical_channels |= AOUT_CHAN_LEFT;
continue;
case kAudioChannelLabel_Right:
- p_aout->format.i_physical_channels |= AOUT_CHAN_RIGHT;
+ fmt->i_physical_channels |= AOUT_CHAN_RIGHT;
continue;
case kAudioChannelLabel_Center:
- p_aout->format.i_physical_channels |= AOUT_CHAN_CENTER;
+ fmt->i_physical_channels |= AOUT_CHAN_CENTER;
continue;
case kAudioChannelLabel_LFEScreen:
- p_aout->format.i_physical_channels |= AOUT_CHAN_LFE;
+ fmt->i_physical_channels |= AOUT_CHAN_LFE;
continue;
case kAudioChannelLabel_LeftSurround:
- p_aout->format.i_physical_channels |= AOUT_CHAN_REARLEFT;
+ fmt->i_physical_channels |= AOUT_CHAN_REARLEFT;
continue;
case kAudioChannelLabel_RightSurround:
- p_aout->format.i_physical_channels |= AOUT_CHAN_REARRIGHT;
+ fmt->i_physical_channels |= AOUT_CHAN_REARRIGHT;
continue;
case kAudioChannelLabel_RearSurroundLeft:
- p_aout->format.i_physical_channels |= AOUT_CHAN_MIDDLELEFT;
+ fmt->i_physical_channels |= AOUT_CHAN_MIDDLELEFT;
continue;
case kAudioChannelLabel_RearSurroundRight:
- p_aout->format.i_physical_channels |= AOUT_CHAN_MIDDLERIGHT;
+ fmt->i_physical_channels |= AOUT_CHAN_MIDDLERIGHT;
continue;
case kAudioChannelLabel_CenterSurround:
- p_aout->format.i_physical_channels |= AOUT_CHAN_REARCENTER;
+ fmt->i_physical_channels |= AOUT_CHAN_REARCENTER;
continue;
default:
msg_Warn(p_aout, "unrecognized channel form provided by driver: %d", (int)layout->mChannelDescriptions[i].mChannelLabel);
}
}
- if (p_aout->format.i_physical_channels == 0) {
- p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+ if (fmt->i_physical_channels == 0) {
+ fmt->i_physical_channels = AOUT_CHANS_STEREO;
msg_Err(p_aout, "You should configure your speaker layout with Audio Midi Setup Utility in /Applications/Utilities. Now using Stereo mode.");
dialog_Fatal(p_aout, _("Audio device is not configured"), "%s",
_("You should configure your speaker layout with "
free(layout);
} else {
msg_Warn(p_aout, "this driver does not support kAudioDevicePropertyPreferredChannelLayout. BAD DRIVER AUTHOR !!!");
- p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+ fmt->i_physical_channels = AOUT_CHANS_STEREO;
}
- msg_Dbg(p_aout, "selected %d physical channels for device output", aout_FormatNbChannels(&p_aout->format));
- msg_Dbg(p_aout, "VLC will output: %s", aout_FormatPrintChannels(&p_aout->format));
+ msg_Dbg(p_aout, "selected %d physical channels for device output", aout_FormatNbChannels(fmt));
+ msg_Dbg(p_aout, "VLC will output: %s", aout_FormatPrintChannels(fmt));
memset (&new_layout, 0, sizeof(new_layout));
- switch(aout_FormatNbChannels(&p_aout->format)) {
+ uint32_t chans_out[AOUT_CHAN_MAX];
+
+ switch(aout_FormatNbChannels(fmt)) {
case 1:
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
break;
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
break;
case 3:
- if (p_aout->format.i_physical_channels & AOUT_CHAN_CENTER)
+ if (fmt->i_physical_channels & AOUT_CHAN_CENTER)
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_7; // L R C
- else if (p_aout->format.i_physical_channels & AOUT_CHAN_LFE)
+ else if (fmt->i_physical_channels & AOUT_CHAN_LFE)
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_4; // L R LFE
break;
case 4:
- if (p_aout->format.i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_LFE))
+ if (fmt->i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_LFE))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_10; // L R C LFE
- else if (p_aout->format.i_physical_channels & (AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT))
+ else if (fmt->i_physical_channels & (AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_3; // L R Ls Rs
- else if (p_aout->format.i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER))
+ else if (fmt->i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_3; // L R C Cs
break;
case 5:
- if (p_aout->format.i_physical_channels & (AOUT_CHAN_CENTER))
+ if (fmt->i_physical_channels & (AOUT_CHAN_CENTER))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_19; // L R Ls Rs C
- else if (p_aout->format.i_physical_channels & (AOUT_CHAN_LFE))
+ else if (fmt->i_physical_channels & (AOUT_CHAN_LFE))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_18; // L R Ls Rs LFE
break;
case 6:
- if (p_aout->format.i_physical_channels & (AOUT_CHAN_LFE))
+ if (fmt->i_physical_channels & (AOUT_CHAN_LFE))
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_20; // L R Ls Rs C LFE
else
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_6_0; // L R Ls Rs C Cs
break;
case 7:
- /* FIXME: This is incorrect. VLC uses the internal ordering: L R Lm Rm Lr Rr C LFE but this is wrong */
- new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_6_1_A; // L R C LFE Ls Rs Cs
+ new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_6_1_A;
+
+ chans_out[0] = AOUT_CHAN_LEFT;
+ chans_out[1] = AOUT_CHAN_RIGHT;
+ chans_out[2] = AOUT_CHAN_CENTER;
+ chans_out[3] = AOUT_CHAN_LFE;
+ chans_out[4] = AOUT_CHAN_REARLEFT;
+ chans_out[5] = AOUT_CHAN_REARRIGHT;
+ chans_out[6] = AOUT_CHAN_REARCENTER;
+
+ p_aout->sys->chans_to_reorder = aout_CheckChannelReorder( NULL, chans_out, fmt->i_physical_channels, p_aout->sys->chan_table );
+ if (p_aout->sys->chans_to_reorder)
+ msg_Dbg( p_aout, "channel reordering needed" );
+
break;
case 8:
- /* FIXME: This is incorrect. VLC uses the internal ordering: L R Lm Rm Lr Rr C LFE but this is wrong */
- new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_7_1_A; // L R C LFE Ls Rs Lc Rc
+ new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_MPEG_7_1_A;
+
+ chans_out[0] = AOUT_CHAN_LEFT;
+ chans_out[1] = AOUT_CHAN_RIGHT;
+ chans_out[2] = AOUT_CHAN_CENTER;
+ chans_out[3] = AOUT_CHAN_LFE;
+ chans_out[4] = AOUT_CHAN_MIDDLELEFT;
+ chans_out[5] = AOUT_CHAN_MIDDLERIGHT;
+ chans_out[6] = AOUT_CHAN_REARLEFT;
+ chans_out[7] = AOUT_CHAN_REARRIGHT;
+
+ p_aout->sys->chans_to_reorder = aout_CheckChannelReorder( NULL, chans_out, fmt->i_physical_channels, p_aout->sys->chan_table );
+ if (p_aout->sys->chans_to_reorder)
+ msg_Dbg( p_aout, "channel reordering needed" );
+
break;
}
/* Set up the format to be used */
- DeviceFormat.mSampleRate = p_aout->format.i_rate;
+ DeviceFormat.mSampleRate = fmt->i_rate;
DeviceFormat.mFormatID = kAudioFormatLinearPCM;
/* We use float 32. It's the best supported format by both VLC and Coreaudio */
- p_aout->format.i_format = VLC_CODEC_FL32;
+ fmt->i_format = VLC_CODEC_FL32;
DeviceFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
DeviceFormat.mBitsPerChannel = 32;
- DeviceFormat.mChannelsPerFrame = aout_FormatNbChannels(&p_aout->format);
+ DeviceFormat.mChannelsPerFrame = aout_FormatNbChannels(fmt);
/* Calculate framesizes and stuff */
DeviceFormat.mFramesPerPacket = 1;
msg_Dbg(p_aout, STREAM_FORMAT_MSG("the actual set AU format is " , DeviceFormat));
/* Do the last VLC aout setups */
- aout_FormatPrepare(&p_aout->format);
- aout_PacketInit(p_aout, &p_sys->packet, FRAMESIZE);
- p_aout->volume_set = VolumeSet;
- p_aout->mute_set = MuteSet;
+ aout_FormatPrepare(fmt);
+ aout_PacketInit(p_aout, &p_sys->packet, FRAMESIZE, fmt);
/* set the IOproc callback */
input.inputProc = (AURenderCallback) RenderCallbackAnalog;
kAudioUnitScope_Input,
0, &input, sizeof(input)));
- input.inputProc = (AURenderCallback) RenderCallbackAnalog;
- input.inputProcRefCon = p_aout;
-
/* Set the new_layout as the layout VLC will use to feed the AU unit */
verify_noerr(AudioUnitSetProperty(p_sys->au_unit,
kAudioUnitProperty_AudioChannelLayout,
- kAudioUnitScope_Input,
+ kAudioUnitScope_Output,
0, &new_layout, sizeof(new_layout)));
if (new_layout.mNumberChannelDescriptions > 0)
/* Start the AU */
verify_noerr(AudioOutputUnitStart(p_sys->au_unit));
+ /* Set volume for output unit */
+ float volume = var_InheritInteger(p_aout, "auhal-volume") / (float)AOUT_VOLUME_DEFAULT;
+ verify_noerr(AudioUnitSetParameter(p_sys->au_unit,
+ kHALOutputParam_Volume,
+ kAudioUnitScope_Global,
+ 0,
+ volume * volume * volume,
+ 0));
+
return true;
}
/*****************************************************************************
* Setup a encoded digital stream (SPDIF)
*****************************************************************************/
-static int OpenSPDIF (audio_output_t * p_aout)
+static int OpenSPDIF (audio_output_t * p_aout, audio_sample_format_t *fmt)
{
struct aout_sys_t *p_sys = p_aout->sys;
OSStatus err = noErr;
p_format_list[j].mFormat.mFormatID == 'iac3' ||
p_format_list[j].mFormat.mFormatID == kAudioFormat60958AC3 ||
p_format_list[j].mFormat.mFormatID == kAudioFormatAC3) {
- if (p_format_list[j].mFormat.mSampleRate == p_aout->format.i_rate) {
+ if (p_format_list[j].mFormat.mSampleRate == fmt->i_rate) {
i_requested_rate_format = j;
break;
} else if (p_format_list[j].mFormat.mSampleRate == p_sys->sfmt_revert.mSampleRate)
/* Set the format flags */
if (p_sys->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian)
- p_aout->format.i_format = VLC_CODEC_SPDIFB;
+ fmt->i_format = VLC_CODEC_SPDIFB;
else
- p_aout->format.i_format = VLC_CODEC_SPDIFL;
- p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
- p_aout->format.i_frame_length = A52_FRAME_NB;
- p_aout->format.i_rate = (unsigned int)p_sys->stream_format.mSampleRate;
- aout_FormatPrepare(&p_aout->format);
- aout_PacketInit(p_aout, &p_sys->packet, A52_FRAME_NB);
- p_aout->volume_set = NULL;
- p_aout->mute_set = NULL;
+ fmt->i_format = VLC_CODEC_SPDIFL;
+ fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
+ fmt->i_frame_length = A52_FRAME_NB;
+ fmt->i_rate = (unsigned int)p_sys->stream_format.mSampleRate;
+ aout_FormatPrepare(fmt);
+ aout_PacketInit(p_aout, &p_sys->packet, A52_FRAME_NB, fmt);
/* Add IOProc callback */
err = AudioDeviceCreateIOProcID(p_sys->i_selected_dev,
/*****************************************************************************
* Close: Close HAL AudioUnit
*****************************************************************************/
-static void Close(vlc_object_t * p_this)
+static void Stop(audio_output_t *p_aout)
{
- audio_output_t *p_aout = (audio_output_t *)p_this;
struct aout_sys_t *p_sys = p_aout->sys;
OSStatus err = noErr;
UInt32 i_param_size = 0;
var_DelCallback(p_aout, "audio-device", AudioDeviceCallback, NULL);
aout_PacketDestroy(p_aout);
- free(p_sys);
}
/*****************************************************************************
}
for (int i = 0; i < i_formats; i++) {
+#ifndef NDEBUG
msg_Dbg(p_aout, STREAM_FORMAT_MSG("supported format: ", p_format_list[i].mFormat));
+#endif
if (p_format_list[i].mFormat.mFormatID == 'IAC3' ||
p_format_list[i].mFormat.mFormatID == 'iac3' ||
if (ioData->mNumberBuffers > 1)
msg_Err(p_aout, "well this is weird. seems like there is more than one buffer...");
-
if (p_sys->i_total_bytes > 0) {
i_mData_bytes = __MIN(p_sys->i_total_bytes - p_sys->i_read_bytes, ioData->mBuffers[0].mDataByteSize);
memcpy(ioData->mBuffers[0].mData,
&p_sys->p_remainder_buffer[p_sys->i_read_bytes],
i_mData_bytes);
p_sys->i_read_bytes += i_mData_bytes;
- current_date += (mtime_t) ((mtime_t) 1000000 / p_aout->format.i_rate) *
- (i_mData_bytes / 4 / aout_FormatNbChannels(&p_aout->format)); // 4 is fl32 specific
+ current_date += (mtime_t) ((mtime_t) 1000000 / p_sys->packet.format.i_rate) *
+ (i_mData_bytes / 4 / aout_FormatNbChannels(&p_sys->packet.format)); // 4 is fl32 specific
if (p_sys->i_read_bytes >= p_sys->i_total_bytes)
p_sys->i_read_bytes = p_sys->i_total_bytes = 0;
if (p_buffer != NULL)
{
+ /* Do the channel reordering */
+ if (p_buffer && p_sys->chans_to_reorder)
+ {
+ aout_ChannelReorder(p_buffer->p_buffer,
+ p_buffer->i_buffer,
+ p_sys->chans_to_reorder,
+ p_sys->chan_table,
+ 32);
+ }
+
uint32_t i_second_mData_bytes = __MIN(p_buffer->i_buffer, ioData->mBuffers[0].mDataByteSize - i_mData_bytes);
memcpy((uint8_t *)ioData->mBuffers[0].mData + i_mData_bytes,
break;
} else
/* update current_date */
- current_date += (mtime_t) ((mtime_t) 1000000 / p_aout->format.i_rate) *
- (i_second_mData_bytes / 4 / aout_FormatNbChannels(&p_aout->format)); // 4 is fl32 specific
+ current_date += (mtime_t) ((mtime_t) 1000000 / p_sys->packet.format.i_rate) *
+ (i_second_mData_bytes / 4 / aout_FormatNbChannels(&p_sys->packet.format)); // 4 is fl32 specific
block_Release(p_buffer);
} else {
memset((uint8_t *)ioData->mBuffers[0].mData +i_mData_bytes,
/*****************************************************************************
- * VolumeSet: Implements pf_volume_set(). Update the CoreAudio AU volume immediately.
+ * VolumeSet: Implements volume_set(). Update the CoreAudio AU volume immediately.
*****************************************************************************/
static int VolumeSet(audio_output_t * p_aout, float volume)
{
- struct aout_sys_t *p_sys = p_aout->sys;
+ struct aout_sys_t *p_sys = p_aout->sys;
OSStatus ostatus;
aout_VolumeReport(p_aout, volume);
- volume = volume * volume * volume; // cubic mapping from output.c
-
/* Set volume for output unit */
ostatus = AudioUnitSetParameter(p_sys->au_unit,
- kHALOutputParam_Volume,
- kAudioUnitScope_Global,
- 0,
- volume,
- 0);
+ kHALOutputParam_Volume,
+ kAudioUnitScope_Global,
+ 0,
+ volume * volume * volume,
+ 0);
+
+ if (var_InheritBool(p_aout, "volume-save"))
+ config_PutInt(p_aout, "auhal-volume", lroundf(volume * AOUT_VOLUME_DEFAULT));
return ostatus;
}
static int MuteSet(audio_output_t * p_aout, bool mute)
{
+ struct aout_sys_t *p_sys = p_aout->sys;
+ OSStatus ostatus;
+
aout_MuteReport(p_aout, mute);
- return 0;
+ float volume = .0;
+
+ if (!mute)
+ volume = var_InheritInteger(p_aout, "auhal-volume") / (float)AOUT_VOLUME_DEFAULT;
+
+ ostatus = AudioUnitSetParameter(p_sys->au_unit,
+ kHALOutputParam_Volume,
+ kAudioUnitScope_Global,
+ 0,
+ volume * volume * volume,
+ 0);
+
+ return ostatus;
+}
+
+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;
+
+ /* remember the volume */
+ aout_VolumeReport(aout, var_InheritInteger(aout, "auhal-volume") / (float)AOUT_VOLUME_DEFAULT);
+ MuteSet(aout, var_InheritBool(aout, "mute"));
+
+ 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);
}