Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
2b7328b4
Commit
2b7328b4
authored
Jul 03, 2019
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
output/osx: fix coding style
parent
ca705e1e
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
82 additions
and
53 deletions
+82
-53
OSXOutputPlugin.cxx
src/output/plugins/OSXOutputPlugin.cxx
+82
-53
No files found.
src/output/plugins/OSXOutputPlugin.cxx
View file @
2b7328b4
...
...
@@ -45,7 +45,8 @@
static
constexpr
unsigned
MPD_OSX_BUFFER_TIME_MS
=
100
;
static
StringBuffer
<
64
>
StreamDescriptionToString
(
const
AudioStreamBasicDescription
desc
)
{
StreamDescriptionToString
(
const
AudioStreamBasicDescription
desc
)
{
// Only convert the lpcm formats (nothing else supported / used by MPD)
assert
(
desc
.
mFormatID
==
kAudioFormatLinearPCM
);
...
...
@@ -107,7 +108,8 @@ private:
static
constexpr
Domain
osx_output_domain
(
"osx_output"
);
static
void
osx_os_status_to_cstring
(
OSStatus
status
,
char
*
str
,
size_t
size
)
{
osx_os_status_to_cstring
(
OSStatus
status
,
char
*
str
,
size_t
size
)
{
CFErrorRef
cferr
=
CFErrorCreate
(
nullptr
,
kCFErrorDomainOSStatus
,
status
,
nullptr
);
CFStringRef
cfstr
=
CFErrorCopyDescription
(
cferr
);
if
(
!
CFStringGetCString
(
cfstr
,
str
,
size
,
kCFStringEncodingUTF8
))
{
...
...
@@ -121,7 +123,7 @@ osx_os_status_to_cstring(OSStatus status, char *str, size_t size) {
}
static
bool
osx_output_test_default_device
(
void
)
osx_output_test_default_device
()
{
/* on a Mac, this is always the default plugin, if nothing
else is configured */
...
...
@@ -170,7 +172,8 @@ OSXOutput::Create(EventLoop &, const ConfigBlock &block)
kAudioObjectPropertyElementMaster
};
else
// fallback to default device initially (can still be changed by osx_output_set_device)
/* fallback to default device initially (can still be
changed by osx_output_set_device) */
aopa
=
{
kAudioHardwarePropertyDefaultOutputDevice
,
kAudioObjectPropertyScopeOutput
,
...
...
@@ -216,7 +219,8 @@ OSXOutput::GetVolume()
}
void
OSXOutput
::
SetVolume
(
unsigned
new_volume
)
{
OSXOutput
::
SetVolume
(
unsigned
new_volume
)
{
Float32
vol
=
new_volume
/
100.0
;
AudioObjectPropertyAddress
aopa
=
{
.
mSelector
=
kAudioHardwareServiceDeviceProperty_VirtualMasterVolume
,
...
...
@@ -240,8 +244,7 @@ OSXOutput::SetVolume(unsigned new_volume) {
}
static
void
osx_output_parse_channel_map
(
const
char
*
device_name
,
osx_output_parse_channel_map
(
const
char
*
device_name
,
const
char
*
channel_map_str
,
SInt32
channel_map
[],
UInt32
num_channels
)
...
...
@@ -331,7 +334,8 @@ osx_output_set_channel_map(OSXOutput *oo)
static
float
osx_output_score_sample_rate
(
Float64
destination_rate
,
unsigned
int
source_rate
)
{
osx_output_score_sample_rate
(
Float64
destination_rate
,
unsigned
source_rate
)
{
float
score
=
0
;
double
int_portion
;
double
frac_portion
=
modf
(
source_rate
/
destination_rate
,
&
int_portion
);
...
...
@@ -341,7 +345,7 @@ osx_output_score_sample_rate(Float64 destination_rate, unsigned int source_rate)
score
+=
(
int_portion
==
1.0
)
?
500
:
0
;
if
(
source_rate
==
destination_rate
)
score
+=
1000
;
else
if
(
source_rate
>
destination_rate
)
else
if
(
source_rate
>
destination_rate
)
score
+=
(
int_portion
>
1
&&
int_portion
<
100
)
?
(
100
-
int_portion
)
/
100
*
100
:
0
;
else
score
+=
(
int_portion
>
1
&&
int_portion
<
100
)
?
(
100
+
int_portion
)
/
100
*
100
:
0
;
...
...
@@ -350,11 +354,14 @@ osx_output_score_sample_rate(Float64 destination_rate, unsigned int source_rate)
}
static
float
osx_output_score_format
(
const
AudioStreamBasicDescription
&
format_desc
,
const
AudioStreamBasicDescription
&
target_format
)
{
osx_output_score_format
(
const
AudioStreamBasicDescription
&
format_desc
,
const
AudioStreamBasicDescription
&
target_format
)
{
float
score
=
0
;
// Score only linear PCM formats (everything else MPD cannot use)
if
(
format_desc
.
mFormatID
==
kAudioFormatLinearPCM
)
{
score
+=
osx_output_score_sample_rate
(
format_desc
.
mSampleRate
,
target_format
.
mSampleRate
);
score
+=
osx_output_score_sample_rate
(
format_desc
.
mSampleRate
,
target_format
.
mSampleRate
);
// Just choose the stream / format with the highest number of output channels
score
+=
format_desc
.
mChannelsPerFrame
*
5
;
...
...
@@ -371,11 +378,13 @@ osx_output_score_format(const AudioStreamBasicDescription &format_desc, const Au
}
}
return
score
;
}
static
Float64
osx_output_set_device_format
(
AudioDeviceID
dev_id
,
const
AudioStreamBasicDescription
&
target_format
)
osx_output_set_device_format
(
AudioDeviceID
dev_id
,
const
AudioStreamBasicDescription
&
target_format
)
{
AudioObjectPropertyAddress
aopa
=
{
kAudioDevicePropertyStreams
,
...
...
@@ -385,16 +394,14 @@ osx_output_set_device_format(AudioDeviceID dev_id, const AudioStreamBasicDescrip
UInt32
property_size
;
OSStatus
err
=
AudioObjectGetPropertyDataSize
(
dev_id
,
&
aopa
,
0
,
NULL
,
&
property_size
);
if
(
err
!=
noErr
)
{
if
(
err
!=
noErr
)
throw
FormatRuntimeError
(
"Cannot get number of streams: %d
\n
"
,
err
);
}
int
n_streams
=
property_size
/
sizeof
(
AudioStreamID
);
AudioStreamID
streams
[
n_streams
];
err
=
AudioObjectGetPropertyData
(
dev_id
,
&
aopa
,
0
,
NULL
,
&
property_size
,
streams
);
if
(
err
!=
noErr
)
{
if
(
err
!=
noErr
)
throw
FormatRuntimeError
(
"Cannot get streams: %d
\n
"
,
err
);
}
bool
format_found
=
false
;
int
output_stream
;
...
...
@@ -411,26 +418,29 @@ osx_output_set_device_format(AudioDeviceID dev_id, const AudioStreamBasicDescrip
NULL
,
&
property_size
,
&
direction
);
if
(
err
!=
noErr
)
{
throw
FormatRuntimeError
(
"Cannot get streams direction: %d
\n
"
,
err
);
}
if
(
direction
!=
0
)
{
if
(
err
!=
noErr
)
throw
FormatRuntimeError
(
"Cannot get streams direction: %d
\n
"
,
err
);
if
(
direction
!=
0
)
continue
;
}
aopa
.
mSelector
=
kAudioStreamPropertyAvailablePhysicalFormats
;
err
=
AudioObjectGetPropertyDataSize
(
stream
,
&
aopa
,
0
,
NULL
,
&
property_size
);
err
=
AudioObjectGetPropertyDataSize
(
stream
,
&
aopa
,
0
,
NULL
,
&
property_size
);
if
(
err
!=
noErr
)
throw
FormatRuntimeError
(
"Unable to get format size s for stream %d. Error = %s"
,
streams
[
i
],
err
);
throw
FormatRuntimeError
(
"Unable to get format size s for stream %d. Error = %s"
,
streams
[
i
],
err
);
in
t
format_count
=
property_size
/
sizeof
(
AudioStreamRangedDescription
);
const
size_
t
format_count
=
property_size
/
sizeof
(
AudioStreamRangedDescription
);
AudioStreamRangedDescription
format_list
[
format_count
];
err
=
AudioObjectGetPropertyData
(
stream
,
&
aopa
,
0
,
NULL
,
&
property_size
,
format_list
);
if
(
err
!=
noErr
)
throw
FormatRuntimeError
(
"Unable to get available formats for stream %d. Error = %s"
,
streams
[
i
],
err
);
throw
FormatRuntimeError
(
"Unable to get available formats for stream %d. Error = %s"
,
streams
[
i
],
err
);
float
output_score
=
0
;
for
(
in
t
j
=
0
;
j
<
format_count
;
j
++
)
{
for
(
size_
t
j
=
0
;
j
<
format_count
;
j
++
)
{
AudioStreamBasicDescription
format_desc
=
format_list
[
j
].
mFormat
;
std
::
string
format_string
;
...
...
@@ -441,8 +451,10 @@ osx_output_set_device_format(AudioDeviceID dev_id, const AudioStreamBasicDescrip
float
score
=
osx_output_score_format
(
format_desc
,
target_format
);
// print all (linear pcm) formats and their rating
if
(
score
>
0.0
)
FormatDebug
(
osx_output_domain
,
"Format: %s rated %f"
,
StreamDescriptionToString
(
format_desc
).
c_str
(),
score
);
if
(
score
>
0.0
)
FormatDebug
(
osx_output_domain
,
"Format: %s rated %f"
,
StreamDescriptionToString
(
format_desc
).
c_str
(),
score
);
if
(
score
>
output_score
)
{
output_score
=
score
;
...
...
@@ -461,16 +473,17 @@ osx_output_set_device_format(AudioDeviceID dev_id, const AudioStreamBasicDescrip
NULL
,
sizeof
(
output_format
),
&
output_format
);
if
(
err
!=
noErr
)
{
throw
FormatRuntimeError
(
"Failed to change the stream format: %d
\n
"
,
err
);
}
if
(
err
!=
noErr
)
throw
FormatRuntimeError
(
"Failed to change the stream format: %d
\n
"
,
err
);
}
return
output_format
.
mSampleRate
;
}
static
OSStatus
osx_output_set_buffer_size
(
AudioUnit
au
,
AudioStreamBasicDescription
desc
,
UInt32
*
frame_size
)
osx_output_set_buffer_size
(
AudioUnit
au
,
AudioStreamBasicDescription
desc
,
UInt32
*
frame_size
)
{
AudioValueRange
value_range
=
{
0
,
0
};
UInt32
property_size
=
sizeof
(
AudioValueRange
);
...
...
@@ -542,6 +555,7 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog)
err
);
return
;
}
if
(
hog
)
{
if
(
hog_pid
!=
-
1
)
{
FormatDebug
(
osx_output_domain
,
...
...
@@ -555,6 +569,7 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog)
return
;
}
}
hog_pid
=
hog
?
getpid
()
:
-
1
;
size
=
sizeof
(
hog_pid
);
err
=
AudioObjectSetPropertyData
(
dev_id
,
...
...
@@ -568,8 +583,9 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog)
"Cannot hog the device: %d"
,
err
);
}
else
{
FormatDebug
(
osx_output_domain
,
hog_pid
==
-
1
?
"Device is unhogged"
LogDebug
(
osx_output_domain
,
hog_pid
==
-
1
?
"Device is unhogged"
:
"Device is hogged"
);
}
}
...
...
@@ -595,8 +611,11 @@ osx_output_set_device(OSXOutput *oo)
return
;
/* how many audio devices are there? */
propaddr
=
{
kAudioHardwarePropertyDevices
,
kAudioObjectPropertyScopeGlobal
,
kAudioObjectPropertyElementMaster
};
status
=
AudioObjectGetPropertyDataSize
(
kAudioObjectSystemObject
,
&
propaddr
,
0
,
nullptr
,
&
size
);
propaddr
=
{
kAudioHardwarePropertyDevices
,
kAudioObjectPropertyScopeGlobal
,
kAudioObjectPropertyElementMaster
};
status
=
AudioObjectGetPropertyDataSize
(
kAudioObjectSystemObject
,
&
propaddr
,
0
,
nullptr
,
&
size
);
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
throw
FormatRuntimeError
(
"Unable to determine number of OS X audio devices: %s"
,
...
...
@@ -606,7 +625,9 @@ osx_output_set_device(OSXOutput *oo)
/* what are the available audio device IDs? */
numdevices
=
size
/
sizeof
(
AudioDeviceID
);
std
::
unique_ptr
<
AudioDeviceID
[]
>
deviceids
(
new
AudioDeviceID
[
numdevices
]);
status
=
AudioObjectGetPropertyData
(
kAudioObjectSystemObject
,
&
propaddr
,
0
,
nullptr
,
&
size
,
deviceids
.
get
());
status
=
AudioObjectGetPropertyData
(
kAudioObjectSystemObject
,
&
propaddr
,
0
,
nullptr
,
&
size
,
deviceids
.
get
());
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
throw
FormatRuntimeError
(
"Unable to determine OS X audio device IDs: %s"
,
...
...
@@ -614,10 +635,14 @@ osx_output_set_device(OSXOutput *oo)
}
/* which audio device matches oo->device_name? */
propaddr
=
{
kAudioObjectPropertyName
,
kAudioObjectPropertyScopeGlobal
,
kAudioObjectPropertyElementMaster
};
propaddr
=
{
kAudioObjectPropertyName
,
kAudioObjectPropertyScopeGlobal
,
kAudioObjectPropertyElementMaster
};
size
=
sizeof
(
CFStringRef
);
for
(
i
=
0
;
i
<
numdevices
;
i
++
)
{
status
=
AudioObjectGetPropertyData
(
deviceids
[
i
],
&
propaddr
,
0
,
nullptr
,
&
size
,
&
cfname
);
status
=
AudioObjectGetPropertyData
(
deviceids
[
i
],
&
propaddr
,
0
,
nullptr
,
&
size
,
&
cfname
);
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
throw
FormatRuntimeError
(
"Unable to determine OS X device name "
...
...
@@ -626,7 +651,8 @@ osx_output_set_device(OSXOutput *oo)
errormsg
);
}
if
(
!
CFStringGetCString
(
cfname
,
name
,
sizeof
(
name
),
kCFStringEncodingUTF8
))
if
(
!
CFStringGetCString
(
cfname
,
name
,
sizeof
(
name
),
kCFStringEncodingUTF8
))
throw
std
::
runtime_error
(
"Unable to convert device name from CFStringRef to char*"
);
if
(
strcmp
(
oo
->
device_name
,
name
)
==
0
)
{
...
...
@@ -636,10 +662,10 @@ osx_output_set_device(OSXOutput *oo)
break
;
}
}
if
(
i
==
numdevices
)
{
if
(
i
==
numdevices
)
throw
FormatRuntimeError
(
"Found no audio device with name '%s' "
,
oo
->
device_name
);
}
status
=
AudioUnitSetProperty
(
oo
->
au
,
kAudioOutputUnitProperty_CurrentDevice
,
...
...
@@ -663,13 +689,13 @@ osx_output_set_device(OSXOutput *oo)
}
/*
This function (the 'render callback' osx_render) is called by the
OS X audio subsystem (CoreAudio) to request audio data that will be
played by the audio hardware. This function has hard time constraints
so it cannot do IO (debug statements) or memory allocations.
*/
/*
*
*
This function (the 'render callback' osx_render) is called by the
*
OS X audio subsystem (CoreAudio) to request audio data that will be
* played by the audio hardware. This function has hard time
* constraints so it cannot do IO (debug statements) or memory
* allocations.
*/
static
OSStatus
osx_render
(
void
*
vdata
,
gcc_unused
AudioUnitRenderActionFlags
*
io_action_flags
,
...
...
@@ -794,7 +820,9 @@ OSXOutput::Open(AudioFormat &audio_format)
Float64
sample_rate
=
osx_output_set_device_format
(
dev_id
,
asbd
);
#ifdef ENABLE_DSD
if
(
audio_format
.
format
==
SampleFormat
::
DSD
&&
sample_rate
!=
asbd
.
mSampleRate
)
{
// fall back to PCM in case sample_rate cannot be synchronized
if
(
audio_format
.
format
==
SampleFormat
::
DSD
&&
sample_rate
!=
asbd
.
mSampleRate
)
{
// fall back to PCM in case sample_rate cannot be synchronized
params
.
dop
=
false
;
audio_format
.
format
=
SampleFormat
::
S32
;
asbd
.
mBitsPerChannel
=
32
;
...
...
@@ -868,7 +896,7 @@ size_t
OSXOutput
::
Play
(
const
void
*
chunk
,
size_t
size
)
{
assert
(
size
>
0
);
if
(
pause
)
{
if
(
pause
)
{
pause
=
false
;
OSStatus
status
=
AudioOutputUnitStart
(
au
);
if
(
status
!=
0
)
{
...
...
@@ -903,8 +931,9 @@ OSXOutput::Delay() const noexcept
:
std
::
chrono
::
milliseconds
(
MPD_OSX_BUFFER_TIME_MS
/
4
);
}
bool
OSXOutput
::
Pause
()
{
if
(
!
pause
)
{
bool
OSXOutput
::
Pause
()
{
if
(
!
pause
)
{
pause
=
true
;
AudioOutputUnitStop
(
au
);
}
...
...
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