/*****************************************************************************
* 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 */
"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 ()
/*****************************************************************************
p_sys->b_changed_mixing = false;
memset(p_sys->p_remainder_buffer, 0, sizeof(uint8_t) * BUFSIZE);
+ p_aout->time_get = aout_PacketTimeGet;
p_aout->play = aout_PacketPlay;
- p_aout->pause = aout_PacketPause;
+ p_aout->pause = NULL;
p_aout->flush = aout_PacketFlush;
aout_FormatPrint(p_aout, "VLC is looking for:", fmt);
} 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:
msg_Dbg(p_aout, "VLC will output: %s", aout_FormatPrintChannels(fmt));
memset (&new_layout, 0, sizeof(new_layout));
+ uint32_t chans_out[AOUT_CHAN_MAX];
+
switch(aout_FormatNbChannels(fmt)) {
case 1:
new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
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;
}
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;
}
}
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,
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,
*****************************************************************************/
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)
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;
}