Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
44d273e0
Commit
44d273e0
authored
Feb 17, 2013
by
Felix Paul Kühne
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
auhal: re-arrange code to suit a sane structure and use #pragma mark to illustrate segments
parent
6d85209c
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
282 additions
and
277 deletions
+282
-277
modules/audio_output/auhal.c
modules/audio_output/auhal.c
+282
-277
No files found.
modules/audio_output/auhal.c
View file @
44d273e0
...
...
@@ -22,9 +22,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#pragma mark includes
#ifdef HAVE_CONFIG_H
# import "config.h"
...
...
@@ -42,6 +40,9 @@
#import "TPCircularBuffer.h"
#pragma mark -
#pragma mark private declarations
#ifndef verify_noerr
# define verify_noerr(a) assert((a) == noErr)
#endif
...
...
@@ -60,6 +61,8 @@
#define AOUT_VOLUME_DEFAULT 256
#define AOUT_VOLUME_MAX 512
#define VOLUME_TEXT N_("Audio volume")
#define VOLUME_LONGTEXT VOLUME_TEXT
/*****************************************************************************
* aout_sys_t: private audio output method descriptor
...
...
@@ -112,44 +115,41 @@ struct audio_device_t
char
*
name
;
};
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
#pragma mark -
#pragma mark local prototypes & module descriptor
static
int
Open
(
vlc_object_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
Play
(
audio_output_t
*
,
block_t
*
);
static
void
Flush
(
audio_output_t
*
,
bool
);
static
void
Pause
(
audio_output_t
*
,
bool
,
mtime_t
);
static
int
TimeGet
(
audio_output_t
*
,
mtime_t
*
);
static
int
Start
(
audio_output_t
*
,
audio_sample_format_t
*
);
static
int
StartAnalog
(
audio_output_t
*
,
audio_sample_format_t
*
);
static
int
StartSPDIF
(
audio_output_t
*
,
audio_sample_format_t
*
);
static
void
Stop
(
audio_output_t
*
);
static
int
DeviceList
(
audio_output_t
*
p_aout
,
char
***
namesp
,
char
***
descsp
);
static
void
RebuildDeviceList
(
audio_output_t
*
);
static
int
SwitchAudioDevice
(
audio_output_t
*
p_aout
,
const
char
*
name
);
static
int
VolumeSet
(
audio_output_t
*
,
float
);
static
int
MuteSet
(
audio_output_t
*
,
bool
);
static
int
AudioDeviceHasOutput
(
AudioDeviceID
);
static
int
AudioDeviceSupportsDigital
(
audio_output_t
*
,
AudioDeviceID
);
static
int
AudioStreamSupportsDigital
(
audio_output_t
*
,
AudioStreamID
);
static
int
AudioStreamChangeFormat
(
audio_output_t
*
,
AudioStreamID
,
AudioStreamBasicDescription
);
static
OSStatus
RenderCallbackAnalog
(
vlc_object_t
*
,
AudioUnitRenderActionFlags
*
,
const
AudioTimeStamp
*
,
UInt32
,
UInt32
,
AudioBufferList
*
);
static
void
Play
(
audio_output_t
*
,
block_t
*
);
static
void
Pause
(
audio_output_t
*
,
bool
,
mtime_t
);
static
void
Flush
(
audio_output_t
*
,
bool
);
static
int
TimeGet
(
audio_output_t
*
,
mtime_t
*
);
static
OSStatus
RenderCallbackAnalog
(
vlc_object_t
*
,
AudioUnitRenderActionFlags
*
,
const
AudioTimeStamp
*
,
UInt32
,
UInt32
,
AudioBufferList
*
);
static
OSStatus
RenderCallbackSPDIF
(
AudioDeviceID
,
const
AudioTimeStamp
*
,
const
void
*
,
const
AudioTimeStamp
*
,
AudioBufferList
*
,
const
AudioTimeStamp
*
,
void
*
);
static
OSStatus
HardwareListener
(
AudioObjectID
,
UInt32
,
const
AudioObjectPropertyAddress
*
,
void
*
);
static
OSStatus
StreamListener
(
AudioObjectID
,
UInt32
,
const
AudioObjectPropertyAddress
*
,
void
*
);
static
int
VolumeSet
(
audio_output_t
*
,
float
);
static
int
MuteSet
(
audio_output_t
*
,
bool
);
static
int
AudioDeviceHasOutput
(
AudioDeviceID
);
static
int
AudioDeviceSupportsDigital
(
audio_output_t
*
,
AudioDeviceID
);
static
int
AudioStreamSupportsDigital
(
audio_output_t
*
,
AudioStreamID
);
static
int
AudioStreamChangeFormat
(
audio_output_t
*
,
AudioStreamID
,
AudioStreamBasicDescription
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#define VOLUME_TEXT N_("Audio volume")
#define VOLUME_LONGTEXT VOLUME_TEXT
vlc_module_begin
()
set_shortname
(
"auhal"
)
...
...
@@ -164,9 +164,53 @@ vlc_module_begin ()
add_obsolete_integer
(
"macosx-audio-device"
)
/* since 2.1.0 */
vlc_module_end
()
/*****************************************************************************
* Open: open macosx audio output
*****************************************************************************/
#pragma mark -
#pragma mark initialization
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
;
vlc_mutex_init
(
&
sys
->
lock
);
aout
->
sys
=
sys
;
aout
->
start
=
Start
;
aout
->
stop
=
Stop
;
aout
->
volume_set
=
VolumeSet
;
aout
->
mute_set
=
MuteSet
;
aout
->
device_enum
=
DeviceList
;
aout
->
sys
->
devices
=
NULL
;
aout
->
device_select
=
SwitchAudioDevice
;
RebuildDeviceList
(
aout
);
/* 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
;
for
(
struct
audio_device_t
*
device
=
sys
->
devices
,
*
next
;
device
!=
NULL
;
device
=
next
)
{
next
=
device
->
next
;
free
(
device
->
name
);
free
(
device
);
}
vlc_mutex_destroy
(
&
sys
->
lock
);
free
(
sys
);
}
static
int
Start
(
audio_output_t
*
p_aout
,
audio_sample_format_t
*
restrict
fmt
)
{
OSStatus
err
=
noErr
;
...
...
@@ -246,12 +290,12 @@ static int Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
/* Check for Digital mode or Analog output mode */
if
(
AOUT_FMT_SPDIF
(
fmt
)
&&
p_sys
->
b_selected_dev_is_digital
)
{
if
(
Open
SPDIF
(
p_aout
,
fmt
))
{
if
(
Start
SPDIF
(
p_aout
,
fmt
))
{
msg_Dbg
(
p_aout
,
"digital output successfully opened"
);
b_success
=
true
;
}
}
else
{
if
(
Open
Analog
(
p_aout
,
fmt
))
{
if
(
Start
Analog
(
p_aout
,
fmt
))
{
msg_Dbg
(
p_aout
,
"analog output successfully opened"
);
b_success
=
true
;
}
...
...
@@ -267,14 +311,14 @@ static int Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
error:
/* If we reach this, this aout has failed */
msg_Err
(
p_aout
,
"opening
the
auhal output failed"
);
msg_Err
(
p_aout
,
"opening auhal output failed"
);
return
VLC_EGENERIC
;
}
/*
****************************************************************************
*
Open: open and setup a HAL AudioUnit to do analog (multichannel)
audio output
*
****************************************************************************
/
static
int
Open
Analog
(
audio_output_t
*
p_aout
,
audio_sample_format_t
*
fmt
)
/*
*
StartAnalog: open and setup a HAL AudioUnit to do PCM
audio output
*/
static
int
Start
Analog
(
audio_output_t
*
p_aout
,
audio_sample_format_t
*
fmt
)
{
struct
aout_sys_t
*
p_sys
=
p_aout
->
sys
;
OSStatus
err
=
noErr
;
...
...
@@ -600,10 +644,10 @@ static int OpenAnalog(audio_output_t *p_aout, audio_sample_format_t *fmt)
return
true
;
}
/*
****************************************************************************
* S
etup a encoded digital stream (SPDIF)
*
****************************************************************************
/
static
int
Open
SPDIF
(
audio_output_t
*
p_aout
,
audio_sample_format_t
*
fmt
)
/*
* S
tartSPDIF: Setup an encoded digital stream (SPDIF) output
*/
static
int
Start
SPDIF
(
audio_output_t
*
p_aout
,
audio_sample_format_t
*
fmt
)
{
struct
aout_sys_t
*
p_sys
=
p_aout
->
sys
;
OSStatus
err
=
noErr
;
...
...
@@ -678,7 +722,7 @@ static int OpenSPDIF (audio_output_t * p_aout, audio_sample_format_t *fmt)
/* Retrieve all the stream formats supported by each output stream */
err
=
AudioObjectGetPropertyDataSize
(
p_streams
[
i
],
&
physicalFormatsAddress
,
0
,
NULL
,
&
i_param_size
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"
OpenSPDIF:
could not get number of streamformats: [%s] (%i)"
,
(
char
*
)
&
err
,
(
int32_t
)
err
);
msg_Err
(
p_aout
,
"could not get number of streamformats: [%s] (%i)"
,
(
char
*
)
&
err
,
(
int32_t
)
err
);
continue
;
}
...
...
@@ -808,10 +852,6 @@ static int OpenSPDIF (audio_output_t * p_aout, audio_sample_format_t *fmt)
return
true
;
}
/*****************************************************************************
* Close: Close HAL AudioUnit
*****************************************************************************/
static
void
Stop
(
audio_output_t
*
p_aout
)
{
struct
aout_sys_t
*
p_sys
=
p_aout
->
sys
;
...
...
@@ -895,6 +935,9 @@ static void Stop(audio_output_t *p_aout)
TPCircularBufferCleanup
(
&
p_sys
->
circular_buffer
);
}
#pragma mark -
#pragma mark core interaction
static
int
DeviceList
(
audio_output_t
*
p_aout
,
char
***
namesp
,
char
***
descsp
)
{
struct
aout_sys_t
*
p_sys
=
p_aout
->
sys
;
...
...
@@ -1072,184 +1115,51 @@ static int SwitchAudioDevice(audio_output_t *p_aout, const char *name)
return
0
;
}
/*****************************************************************************
* AudioDeviceHasOutput: Checks if the Device actually provides any outputs at all
*****************************************************************************/
static
int
AudioDeviceHasOutput
(
AudioDeviceID
i_dev_id
)
{
UInt32
dataSize
=
0
;
OSStatus
status
;
AudioObjectPropertyAddress
streamsAddress
=
{
kAudioDevicePropertyStreams
,
kAudioDevicePropertyScopeOutput
,
kAudioObjectPropertyElementMaster
};
status
=
AudioObjectGetPropertyDataSize
(
i_dev_id
,
&
streamsAddress
,
0
,
NULL
,
&
dataSize
);
if
(
dataSize
==
0
||
status
!=
noErr
)
return
FALSE
;
return
TRUE
;
}
/*****************************************************************************
* AudioDeviceSupportsDigital: Check i_dev_id for digital stream support.
*****************************************************************************/
static
int
AudioDeviceSupportsDigital
(
audio_output_t
*
p_aout
,
AudioDeviceID
i_dev_id
)
static
int
VolumeSet
(
audio_output_t
*
p_aout
,
float
volume
)
{
OSStatus
err
=
noErr
;
UInt32
i_param_size
=
0
;
AudioStreamID
*
p_streams
=
NULL
;
int
i_streams
=
0
;
bool
b_return
=
false
;
/* Retrieve all the output streams */
AudioObjectPropertyAddress
streamsAddress
=
{
kAudioDevicePropertyStreams
,
kAudioDevicePropertyScopeOutput
,
kAudioObjectPropertyElementMaster
};
err
=
AudioObjectGetPropertyDataSize
(
i_dev_id
,
&
streamsAddress
,
0
,
NULL
,
&
i_param_size
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"could not get number of streams: [%s] (%i)"
,
(
char
*
)
&
err
,
(
int32_t
)
err
);
return
false
;
}
struct
aout_sys_t
*
p_sys
=
p_aout
->
sys
;
OSStatus
ostatus
;
i_streams
=
i_param_size
/
sizeof
(
AudioStreamID
);
p_streams
=
(
AudioStreamID
*
)
malloc
(
i_param_size
);
if
(
p_streams
==
NULL
)
return
VLC_ENOMEM
;
aout_VolumeReport
(
p_aout
,
volume
);
err
=
AudioObjectGetPropertyData
(
i_dev_id
,
&
streamsAddress
,
0
,
NULL
,
&
i_param_size
,
p_streams
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"could not get list of streams: [%s]"
,
(
char
*
)
&
err
);
return
false
;
}
/* Set volume for output unit */
ostatus
=
AudioUnitSetParameter
(
p_sys
->
au_unit
,
kHALOutputParam_Volume
,
kAudioUnitScope_Global
,
0
,
volume
*
volume
*
volume
,
0
);
for
(
int
i
=
0
;
i
<
i_streams
;
i
++
)
{
if
(
AudioStreamSupportsDigital
(
p_aout
,
p_streams
[
i
]))
b_return
=
true
;
}
if
(
var_InheritBool
(
p_aout
,
"volume-save"
))
config_PutInt
(
p_aout
,
"auhal-volume"
,
lroundf
(
volume
*
AOUT_VOLUME_DEFAULT
));
free
(
p_streams
);
return
b_return
;
return
ostatus
;
}
/*****************************************************************************
* AudioStreamSupportsDigital: Check i_stream_id for digital stream support.
*****************************************************************************/
static
int
AudioStreamSupportsDigital
(
audio_output_t
*
p_aout
,
AudioStreamID
i_stream_id
)
static
int
MuteSet
(
audio_output_t
*
p_aout
,
bool
mute
)
{
OSStatus
err
=
noErr
;
UInt32
i_param_size
=
0
;
AudioStreamRangedDescription
*
p_format_list
=
NULL
;
int
i_formats
=
0
;
bool
b_return
=
false
;
/* Retrieve all the stream formats supported by each output stream */
AudioObjectPropertyAddress
physicalFormatsAddress
=
{
kAudioStreamPropertyAvailablePhysicalFormats
,
kAudioObjectPropertyScopeGlobal
,
0
};
err
=
AudioObjectGetPropertyDataSize
(
i_stream_id
,
&
physicalFormatsAddress
,
0
,
NULL
,
&
i_param_size
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"could not get number of streamformats: [%s] (%i)"
,
(
char
*
)
&
err
,
(
int32_t
)
err
);
return
false
;
}
i_formats
=
i_param_size
/
sizeof
(
AudioStreamRangedDescription
);
msg_Dbg
(
p_aout
,
"found %i stream formats"
,
i_formats
);
struct
aout_sys_t
*
p_sys
=
p_aout
->
sys
;
OSStatus
ostatus
;
p_format_list
=
(
AudioStreamRangedDescription
*
)
malloc
(
i_param_size
);
if
(
p_format_list
==
NULL
)
return
false
;
aout_MuteReport
(
p_aout
,
mute
);
err
=
AudioObjectGetPropertyData
(
i_stream_id
,
&
physicalFormatsAddress
,
0
,
NULL
,
&
i_param_size
,
p_format_list
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"could not get the list of streamformats: [%4.4s]"
,
(
char
*
)
&
err
);
free
(
p_format_list
);
p_format_list
=
NULL
;
return
false
;
}
float
volume
=
.
0
;
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
(
!
mute
)
volume
=
var_InheritInteger
(
p_aout
,
"auhal-volume"
)
/
(
float
)
AOUT_VOLUME_DEFAULT
;
if
(
p_format_list
[
i
].
mFormat
.
mFormatID
==
'
IAC3
'
||
p_format_list
[
i
].
mFormat
.
mFormatID
==
'
iac3
'
||
p_format_list
[
i
].
mFormat
.
mFormatID
==
kAudioFormat60958AC3
||
p_format_list
[
i
].
mFormat
.
mFormatID
==
kAudioFormatAC3
)
b_return
=
true
;
}
ostatus
=
AudioUnitSetParameter
(
p_sys
->
au_unit
,
kHALOutputParam_Volume
,
kAudioUnitScope_Global
,
0
,
volume
*
volume
*
volume
,
0
);
free
(
p_format_list
);
return
b_return
;
return
ostatus
;
}
/*****************************************************************************
* AudioStreamChangeFormat: Change i_stream_id to change_format
*****************************************************************************/
static
int
AudioStreamChangeFormat
(
audio_output_t
*
p_aout
,
AudioStreamID
i_stream_id
,
AudioStreamBasicDescription
change_format
)
{
OSStatus
err
=
noErr
;
UInt32
i_param_size
=
0
;
AudioObjectPropertyAddress
physicalFormatAddress
=
{
kAudioStreamPropertyPhysicalFormat
,
kAudioObjectPropertyScopeGlobal
,
kAudioObjectPropertyElementMaster
};
struct
{
vlc_mutex_t
lock
;
vlc_cond_t
cond
;
}
w
;
msg_Dbg
(
p_aout
,
STREAM_FORMAT_MSG
(
"setting stream format: "
,
change_format
));
/* Condition because SetProperty is asynchronious */
vlc_cond_init
(
&
w
.
cond
);
vlc_mutex_init
(
&
w
.
lock
);
vlc_mutex_lock
(
&
w
.
lock
);
/* Install the callback */
err
=
AudioObjectAddPropertyListener
(
i_stream_id
,
&
physicalFormatAddress
,
StreamListener
,
(
void
*
)
&
w
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"AudioObjectAddPropertyListener for kAudioStreamPropertyPhysicalFormat failed: [%4.4s]"
,
(
char
*
)
&
err
);
return
false
;
}
/* change the format */
err
=
AudioObjectSetPropertyData
(
i_stream_id
,
&
physicalFormatAddress
,
0
,
NULL
,
sizeof
(
AudioStreamBasicDescription
),
&
change_format
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"could not set the stream format: [%4.4s]"
,
(
char
*
)
&
err
);
return
false
;
}
/* The AudioStreamSetProperty is not only asynchronious (requiring the locks)
* it is also not atomic in its behaviour.
* Therefore we check 5 times before we really give up.
* FIXME: failing isn't actually implemented yet. */
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
AudioStreamBasicDescription
actual_format
;
mtime_t
timeout
=
mdate
()
+
500000
;
if
(
vlc_cond_timedwait
(
&
w
.
cond
,
&
w
.
lock
,
timeout
))
msg_Dbg
(
p_aout
,
"reached timeout"
);
i_param_size
=
sizeof
(
AudioStreamBasicDescription
);
err
=
AudioObjectGetPropertyData
(
i_stream_id
,
&
physicalFormatAddress
,
0
,
NULL
,
&
i_param_size
,
&
actual_format
);
msg_Dbg
(
p_aout
,
STREAM_FORMAT_MSG
(
"actual format in use: "
,
actual_format
));
if
(
actual_format
.
mSampleRate
==
change_format
.
mSampleRate
&&
actual_format
.
mFormatID
==
change_format
.
mFormatID
&&
actual_format
.
mFramesPerPacket
==
change_format
.
mFramesPerPacket
)
{
/* The right format is now active */
break
;
}
/* We need to check again */
}
/* Removing the property listener */
err
=
AudioObjectRemovePropertyListener
(
i_stream_id
,
&
physicalFormatAddress
,
StreamListener
,
(
void
*
)
&
w
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"AudioStreamRemovePropertyListener failed: [%4.4s]"
,
(
char
*
)
&
err
);
return
false
;
}
/* Destroy the lock and condition */
vlc_mutex_unlock
(
&
w
.
lock
);
vlc_mutex_destroy
(
&
w
.
lock
);
vlc_cond_destroy
(
&
w
.
cond
);
return
true
;
}
#pragma mark -
#pragma mark actual playback
static
void
Play
(
audio_output_t
*
p_aout
,
block_t
*
p_block
)
{
...
...
@@ -1382,9 +1292,9 @@ static OSStatus RenderCallbackAnalog(vlc_object_t *p_obj,
return
noErr
;
}
/*
****************************************************************************
/*
* RenderCallbackSPDIF: callback for SPDIF audio output
*
****************************************************************************
/
*/
static
OSStatus
RenderCallbackSPDIF
(
AudioDeviceID
inDevice
,
const
AudioTimeStamp
*
inNow
,
const
void
*
inInputData
,
...
...
@@ -1423,9 +1333,12 @@ static OSStatus RenderCallbackSPDIF (AudioDeviceID inDevice,
return
noErr
;
}
/*****************************************************************************
#pragma mark -
#pragma mark Stream / Hardware Listeners
/*
* HardwareListener: Warns us of changes in the list of registered devices
*
****************************************************************************
/
*/
static
OSStatus
HardwareListener
(
AudioObjectID
inObjectID
,
UInt32
inNumberAddresses
,
const
AudioObjectPropertyAddress
inAddresses
[],
void
*
inClientData
)
{
OSStatus
err
=
noErr
;
...
...
@@ -1464,9 +1377,9 @@ static OSStatus HardwareListener(AudioObjectID inObjectID, UInt32 inNumberAddre
return
err
;
}
/*
****************************************************************************
* StreamListener
*
****************************************************************************
/
/*
* StreamListener
: check whether the device's physical format changes on-the-fly (unlikely)
*/
static
OSStatus
StreamListener
(
AudioObjectID
inObjectID
,
UInt32
inNumberAddresses
,
const
AudioObjectPropertyAddress
inAddresses
[],
void
*
inClientData
)
{
OSStatus
err
=
noErr
;
...
...
@@ -1485,92 +1398,184 @@ static OSStatus StreamListener(AudioObjectID inObjectID, UInt32 inNumberAddress
return
err
;
}
/*****************************************************************************
* 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
;
OSStatus
ostatus
;
#pragma mark -
#pragma mark helpers
aout_VolumeReport
(
p_aout
,
volume
);
/*
* AudioDeviceHasOutput: Checks if the device is actually an output device
*/
static
int
AudioDeviceHasOutput
(
AudioDeviceID
i_dev_id
)
{
UInt32
dataSize
=
0
;
OSStatus
status
;
/* Set volume for output unit */
ostatus
=
AudioUnitSetParameter
(
p_sys
->
au_unit
,
kHALOutputParam_Volume
,
kAudioUnitScope_Global
,
0
,
volume
*
volume
*
volume
,
0
);
AudioObjectPropertyAddress
streamsAddress
=
{
kAudioDevicePropertyStreams
,
kAudioDevicePropertyScopeOutput
,
kAudioObjectPropertyElementMaster
};
status
=
AudioObjectGetPropertyDataSize
(
i_dev_id
,
&
streamsAddress
,
0
,
NULL
,
&
dataSize
);
if
(
var_InheritBool
(
p_aout
,
"volume-save"
)
)
config_PutInt
(
p_aout
,
"auhal-volume"
,
lroundf
(
volume
*
AOUT_VOLUME_DEFAULT
))
;
if
(
dataSize
==
0
||
status
!=
noErr
)
return
FALSE
;
return
ostatus
;
return
TRUE
;
}
static
int
MuteSet
(
audio_output_t
*
p_aout
,
bool
mute
)
/*
* AudioDeviceSupportsDigital: Checks if device supports raw bitstreams
*/
static
int
AudioDeviceSupportsDigital
(
audio_output_t
*
p_aout
,
AudioDeviceID
i_dev_id
)
{
struct
aout_sys_t
*
p_sys
=
p_aout
->
sys
;
OSStatus
ostatus
;
OSStatus
err
=
noErr
;
UInt32
i_param_size
=
0
;
AudioStreamID
*
p_streams
=
NULL
;
int
i_streams
=
0
;
bool
b_return
=
false
;
aout_MuteReport
(
p_aout
,
mute
);
/* Retrieve all the output streams */
AudioObjectPropertyAddress
streamsAddress
=
{
kAudioDevicePropertyStreams
,
kAudioDevicePropertyScopeOutput
,
kAudioObjectPropertyElementMaster
};
err
=
AudioObjectGetPropertyDataSize
(
i_dev_id
,
&
streamsAddress
,
0
,
NULL
,
&
i_param_size
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"could not get number of streams: [%s] (%i)"
,
(
char
*
)
&
err
,
(
int32_t
)
err
);
return
false
;
}
float
volume
=
.
0
;
i_streams
=
i_param_size
/
sizeof
(
AudioStreamID
);
p_streams
=
(
AudioStreamID
*
)
malloc
(
i_param_size
);
if
(
p_streams
==
NULL
)
return
VLC_ENOMEM
;
if
(
!
mute
)
volume
=
var_InheritInteger
(
p_aout
,
"auhal-volume"
)
/
(
float
)
AOUT_VOLUME_DEFAULT
;
err
=
AudioObjectGetPropertyData
(
i_dev_id
,
&
streamsAddress
,
0
,
NULL
,
&
i_param_size
,
p_streams
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"could not get list of streams: [%s]"
,
(
char
*
)
&
err
);
return
false
;
}
ostatus
=
AudioUnitSetParameter
(
p_sys
->
au_unit
,
kHALOutputParam_Volume
,
kAudioUnitScope_Global
,
0
,
volume
*
volume
*
volume
,
0
);
for
(
int
i
=
0
;
i
<
i_streams
;
i
++
)
{
if
(
AudioStreamSupportsDigital
(
p_aout
,
p_streams
[
i
]))
b_return
=
true
;
}
return
ostatus
;
free
(
p_streams
);
return
b_return
;
}
static
int
Open
(
vlc_object_t
*
obj
)
/*
* AudioStreamSupportsDigital: Checks if audio stream is compatible with raw bitstreams
*/
static
int
AudioStreamSupportsDigital
(
audio_output_t
*
p_aout
,
AudioStreamID
i_stream_id
)
{
audio_output_t
*
aout
=
(
audio_output_t
*
)
obj
;
aout_sys_t
*
sys
=
malloc
(
sizeof
(
*
sys
));
OSStatus
err
=
noErr
;
UInt32
i_param_size
=
0
;
AudioStreamRangedDescription
*
p_format_list
=
NULL
;
int
i_formats
=
0
;
bool
b_return
=
false
;
if
(
unlikely
(
sys
==
NULL
))
return
VLC_ENOMEM
;
/* Retrieve all the stream formats supported by each output stream */
AudioObjectPropertyAddress
physicalFormatsAddress
=
{
kAudioStreamPropertyAvailablePhysicalFormats
,
kAudioObjectPropertyScopeGlobal
,
0
};
err
=
AudioObjectGetPropertyDataSize
(
i_stream_id
,
&
physicalFormatsAddress
,
0
,
NULL
,
&
i_param_size
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"could not get number of streamformats: [%s] (%i)"
,
(
char
*
)
&
err
,
(
int32_t
)
err
);
return
false
;
}
vlc_mutex_init
(
&
sys
->
lock
);
i_formats
=
i_param_size
/
sizeof
(
AudioStreamRangedDescription
);
msg_Dbg
(
p_aout
,
"found %i stream formats"
,
i_formats
);
aout
->
sys
=
sys
;
aout
->
start
=
Start
;
aout
->
stop
=
Stop
;
aout
->
volume_set
=
VolumeSet
;
aout
->
mute_set
=
MuteSet
;
aout
->
device_enum
=
DeviceList
;
aout
->
sys
->
devices
=
NULL
;
aout
->
device_select
=
SwitchAudioDevice
;
p_format_list
=
(
AudioStreamRangedDescription
*
)
malloc
(
i_param_size
);
if
(
p_format_list
==
NULL
)
return
false
;
RebuildDeviceList
(
aout
);
err
=
AudioObjectGetPropertyData
(
i_stream_id
,
&
physicalFormatsAddress
,
0
,
NULL
,
&
i_param_size
,
p_format_list
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"could not get the list of streamformats: [%4.4s]"
,
(
char
*
)
&
err
);
free
(
p_format_list
);
p_format_list
=
NULL
;
return
false
;
}
/* remember the volume */
aout_VolumeReport
(
aout
,
var_InheritInteger
(
aout
,
"auhal-volume"
)
/
(
float
)
AOUT_VOLUME_DEFAULT
);
MuteSet
(
aout
,
var_InheritBool
(
aout
,
"mute"
));
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
return
VLC_SUCCESS
;
if
(
p_format_list
[
i
].
mFormat
.
mFormatID
==
'
IAC3
'
||
p_format_list
[
i
].
mFormat
.
mFormatID
==
'
iac3
'
||
p_format_list
[
i
].
mFormat
.
mFormatID
==
kAudioFormat60958AC3
||
p_format_list
[
i
].
mFormat
.
mFormatID
==
kAudioFormatAC3
)
b_return
=
true
;
}
free
(
p_format_list
);
return
b_return
;
}
static
void
Close
(
vlc_object_t
*
obj
)
/*
* AudioStreamChangeFormat: switch stream format based on the provided description
*/
static
int
AudioStreamChangeFormat
(
audio_output_t
*
p_aout
,
AudioStreamID
i_stream_id
,
AudioStreamBasicDescription
change_format
)
{
audio_output_t
*
aout
=
(
audio_output_t
*
)
obj
;
aout_sys_t
*
sys
=
aout
->
sys
;
OSStatus
err
=
noErr
;
UInt32
i_param_size
=
0
;
for
(
struct
audio_device_t
*
device
=
sys
->
devices
,
*
next
;
device
!=
NULL
;
device
=
next
)
{
next
=
device
->
next
;
free
(
device
->
name
);
free
(
device
);
AudioObjectPropertyAddress
physicalFormatAddress
=
{
kAudioStreamPropertyPhysicalFormat
,
kAudioObjectPropertyScopeGlobal
,
kAudioObjectPropertyElementMaster
};
struct
{
vlc_mutex_t
lock
;
vlc_cond_t
cond
;
}
w
;
msg_Dbg
(
p_aout
,
STREAM_FORMAT_MSG
(
"setting stream format: "
,
change_format
));
/* Condition because SetProperty is asynchronious */
vlc_cond_init
(
&
w
.
cond
);
vlc_mutex_init
(
&
w
.
lock
);
vlc_mutex_lock
(
&
w
.
lock
);
/* Install the callback */
err
=
AudioObjectAddPropertyListener
(
i_stream_id
,
&
physicalFormatAddress
,
StreamListener
,
(
void
*
)
&
w
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"AudioObjectAddPropertyListener for kAudioStreamPropertyPhysicalFormat failed: [%4.4s]"
,
(
char
*
)
&
err
);
return
false
;
}
vlc_mutex_destroy
(
&
sys
->
lock
);
/* change the format */
err
=
AudioObjectSetPropertyData
(
i_stream_id
,
&
physicalFormatAddress
,
0
,
NULL
,
sizeof
(
AudioStreamBasicDescription
),
&
change_format
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"could not set the stream format: [%4.4s]"
,
(
char
*
)
&
err
);
return
false
;
}
free
(
sys
);
/* The AudioStreamSetProperty is not only asynchronious (requiring the locks)
* it is also not atomic in its behaviour.
* Therefore we check 5 times before we really give up.
* FIXME: failing isn't actually implemented yet. */
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
AudioStreamBasicDescription
actual_format
;
mtime_t
timeout
=
mdate
()
+
500000
;
if
(
vlc_cond_timedwait
(
&
w
.
cond
,
&
w
.
lock
,
timeout
))
msg_Dbg
(
p_aout
,
"reached timeout"
);
i_param_size
=
sizeof
(
AudioStreamBasicDescription
);
err
=
AudioObjectGetPropertyData
(
i_stream_id
,
&
physicalFormatAddress
,
0
,
NULL
,
&
i_param_size
,
&
actual_format
);
msg_Dbg
(
p_aout
,
STREAM_FORMAT_MSG
(
"actual format in use: "
,
actual_format
));
if
(
actual_format
.
mSampleRate
==
change_format
.
mSampleRate
&&
actual_format
.
mFormatID
==
change_format
.
mFormatID
&&
actual_format
.
mFramesPerPacket
==
change_format
.
mFramesPerPacket
)
{
/* The right format is now active */
break
;
}
/* We need to check again */
}
/* Removing the property listener */
err
=
AudioObjectRemovePropertyListener
(
i_stream_id
,
&
physicalFormatAddress
,
StreamListener
,
(
void
*
)
&
w
);
if
(
err
!=
noErr
)
{
msg_Err
(
p_aout
,
"AudioStreamRemovePropertyListener failed: [%4.4s]"
,
(
char
*
)
&
err
);
return
false
;
}
/* Destroy the lock and condition */
vlc_mutex_unlock
(
&
w
.
lock
);
vlc_mutex_destroy
(
&
w
.
lock
);
vlc_cond_destroy
(
&
w
.
cond
);
return
true
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment