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
df4616ae
Commit
df4616ae
authored
8 years ago
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
output/osx: migrate from class Error to C++ exceptions
Beware, this commit was not tested. I don't have OS X, but I want to prepare an API change.
parent
10f62db9
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
74 additions
and
131 deletions
+74
-131
OSXOutputPlugin.cxx
src/output/plugins/OSXOutputPlugin.cxx
+74
-131
No files found.
src/output/plugins/OSXOutputPlugin.cxx
View file @
df4616ae
...
...
@@ -21,7 +21,7 @@
#include "OSXOutputPlugin.hxx"
#include "../OutputAPI.hxx"
#include "util/ScopeExit.hxx"
#include "util/Error.hxx"
#include "util/
Runtime
Error.hxx"
#include "util/Domain.hxx"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
...
...
@@ -52,8 +52,7 @@ struct OSXOutput {
boost
::
lockfree
::
spsc_queue
<
uint8_t
>
*
ring_buffer
;
OSXOutput
()
:
base
(
osx_output_plugin
)
{}
OSXOutput
(
const
ConfigBlock
&
block
);
};
static
constexpr
Domain
osx_output_domain
(
"osx_output"
);
...
...
@@ -80,40 +79,34 @@ osx_output_test_default_device(void)
return
true
;
}
static
void
osx_output_configure
(
OSXOutput
*
oo
,
const
ConfigBlock
&
block
)
OSXOutput
::
OSXOutput
(
const
ConfigBlock
&
block
)
:
base
(
osx_output_plugin
,
block
)
{
const
char
*
device
=
block
.
GetBlockValue
(
"device"
);
if
(
device
==
nullptr
||
0
==
strcmp
(
device
,
"default"
))
{
oo
->
component_subtype
=
kAudioUnitSubType_DefaultOutput
;
oo
->
device_name
=
nullptr
;
component_subtype
=
kAudioUnitSubType_DefaultOutput
;
device_name
=
nullptr
;
}
else
if
(
0
==
strcmp
(
device
,
"system"
))
{
oo
->
component_subtype
=
kAudioUnitSubType_SystemOutput
;
oo
->
device_name
=
nullptr
;
component_subtype
=
kAudioUnitSubType_SystemOutput
;
device_name
=
nullptr
;
}
else
{
oo
->
component_subtype
=
kAudioUnitSubType_HALOutput
;
component_subtype
=
kAudioUnitSubType_HALOutput
;
/* XXX am I supposed to strdup() this? */
oo
->
device_name
=
device
;
device_name
=
device
;
}
oo
->
channel_map
=
block
.
GetBlockValue
(
"channel_map"
);
oo
->
hog_device
=
block
.
GetBlockValue
(
"hog_device"
,
false
);
oo
->
sync_sample_rate
=
block
.
GetBlockValue
(
"sync_sample_rate"
,
false
);
channel_map
=
block
.
GetBlockValue
(
"channel_map"
);
hog_device
=
block
.
GetBlockValue
(
"hog_device"
,
false
);
sync_sample_rate
=
block
.
GetBlockValue
(
"sync_sample_rate"
,
false
);
}
static
AudioOutput
*
osx_output_init
(
const
ConfigBlock
&
block
,
Error
&
error
)
osx_output_init
(
const
ConfigBlock
&
block
,
Error
&
)
{
OSXOutput
*
oo
=
new
OSXOutput
();
if
(
!
oo
->
base
.
Configure
(
block
,
error
))
{
delete
oo
;
return
nullptr
;
}
osx_output_configure
(
oo
,
block
);
OSXOutput
*
oo
=
new
OSXOutput
(
block
);
AudioObjectPropertyAddress
aopa
=
{
kAudioHardwarePropertyDefaultOutputDevice
,
...
...
@@ -142,25 +135,21 @@ osx_output_finish(AudioOutput *ao)
delete
oo
;
}
static
bool
static
void
osx_output_parse_channel_map
(
const
char
*
device_name
,
const
char
*
channel_map_str
,
SInt32
channel_map
[],
UInt32
num_channels
,
Error
&
error
)
UInt32
num_channels
)
{
char
*
endptr
;
unsigned
int
inserted_channels
=
0
;
bool
want_number
=
true
;
while
(
*
channel_map_str
)
{
if
(
inserted_channels
>=
num_channels
)
{
error
.
Format
(
osx_output_domain
,
"%s: channel map contains more than %u entries or trailing garbage"
,
device_name
,
num_channels
);
return
false
;
}
if
(
inserted_channels
>=
num_channels
)
throw
FormatRuntimeError
(
"%s: channel map contains more than %u entries or trailing garbage"
,
device_name
,
num_channels
);
if
(
!
want_number
&&
*
channel_map_str
==
','
)
{
++
channel_map_str
;
...
...
@@ -172,12 +161,9 @@ osx_output_parse_channel_map(
(
isdigit
(
*
channel_map_str
)
||
*
channel_map_str
==
'-'
)
)
{
channel_map
[
inserted_channels
]
=
strtol
(
channel_map_str
,
&
endptr
,
10
);
if
(
channel_map
[
inserted_channels
]
<
-
1
)
{
error
.
Format
(
osx_output_domain
,
"%s: channel map value %d not allowed (must be -1 or greater)"
,
device_name
,
channel_map
[
inserted_channels
]);
return
false
;
}
if
(
channel_map
[
inserted_channels
]
<
-
1
)
throw
FormatRuntimeError
(
"%s: channel map value %d not allowed (must be -1 or greater)"
,
channel_map_str
=
endptr
;
want_number
=
false
;
FormatDebug
(
osx_output_domain
,
...
...
@@ -187,24 +173,17 @@ osx_output_parse_channel_map(
continue
;
}
error
.
Format
(
osx_output_domain
,
"%s: invalid character '%c' in channel map"
,
device_name
,
*
channel_map_str
);
return
false
;
}
if
(
inserted_channels
<
num_channels
)
{
error
.
Format
(
osx_output_domain
,
"%s: channel map contains less than %u entries"
,
device_name
,
num_channels
);
return
false
;
throw
FormatRuntimeError
(
"%s: invalid character '%c' in channel map"
,
device_name
,
*
channel_map_str
);
}
return
true
;
if
(
inserted_channels
<
num_channels
)
throw
FormatRuntimeError
(
"%s: channel map contains less than %u entries"
,
device_name
,
num_channels
);
}
static
bool
osx_output_set_channel_map
(
OSXOutput
*
oo
,
Error
&
error
)
static
void
osx_output_set_channel_map
(
OSXOutput
*
oo
)
{
AudioStreamBasicDescription
desc
;
OSStatus
status
;
...
...
@@ -221,22 +200,16 @@ osx_output_set_channel_map(OSXOutput *oo, Error &error)
&
size
);
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
error
.
Format
(
osx_output_domain
,
status
,
"%s: unable to get number of output device channels: %s"
,
oo
->
device_name
,
errormsg
);
return
false
;
throw
FormatRuntimeError
(
"%s: unable to get number of output device channels: %s"
,
oo
->
device_name
,
errormsg
);
}
num_channels
=
desc
.
mChannelsPerFrame
;
std
::
unique_ptr
<
SInt32
[]
>
channel_map
(
new
SInt32
[
num_channels
]);
if
(
!
osx_output_parse_channel_map
(
oo
->
device_name
,
oo
->
channel_map
,
channel_map
.
get
(),
num_channels
,
error
)
)
{
return
false
;
}
osx_output_parse_channel_map
(
oo
->
device_name
,
oo
->
channel_map
,
channel_map
.
get
(),
num_channels
));
size
=
num_channels
*
sizeof
(
SInt32
);
status
=
AudioUnitSetProperty
(
oo
->
au
,
...
...
@@ -247,12 +220,8 @@ osx_output_set_channel_map(OSXOutput *oo, Error &error)
size
);
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
error
.
Format
(
osx_output_domain
,
status
,
"%s: unable to set channel map: %s"
,
oo
->
device_name
,
errormsg
);
return
false
;
throw
FormatRuntimeError
(
"%s: unable to set channel map: %s"
,
oo
->
device_name
,
errormsg
);
}
return
true
;
}
static
void
...
...
@@ -428,8 +397,8 @@ osx_output_hog_device(AudioDeviceID dev_id, bool hog)
}
static
bool
osx_output_set_device
(
OSXOutput
*
oo
,
Error
&
error
)
static
void
osx_output_set_device
(
OSXOutput
*
oo
)
{
OSStatus
status
;
UInt32
size
,
numdevices
;
...
...
@@ -445,17 +414,15 @@ osx_output_set_device(OSXOutput *oo, Error &error)
};
if
(
oo
->
component_subtype
!=
kAudioUnitSubType_HALOutput
)
return
true
;
return
;
/* how many audio devices are there? */
propaddr
=
{
kAudioHardwarePropertyDevices
,
kAudioObjectPropertyScopeGlobal
,
kAudioObjectPropertyElementMaster
};
status
=
AudioObjectGetPropertyDataSize
(
kAudioObjectSystemObject
,
&
propaddr
,
0
,
nullptr
,
&
size
);
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
error
.
Format
(
osx_output_domain
,
status
,
"Unable to determine number of OS X audio devices: %s"
,
errormsg
);
return
false
;
throw
FormatRuntimeError
(
"Unable to determine number of OS X audio devices: %s"
,
errormsg
);
}
/* what are the available audio device IDs? */
...
...
@@ -464,10 +431,8 @@ osx_output_set_device(OSXOutput *oo, Error &error)
status
=
AudioObjectGetPropertyData
(
kAudioObjectSystemObject
,
&
propaddr
,
0
,
nullptr
,
&
size
,
deviceids
.
get
());
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
error
.
Format
(
osx_output_domain
,
status
,
"Unable to determine OS X audio device IDs: %s"
,
errormsg
);
return
false
;
throw
FormatRuntimeError
(
"Unable to determine OS X audio device IDs: %s"
,
errormsg
);
}
/* which audio device matches oo->device_name? */
...
...
@@ -477,18 +442,14 @@ osx_output_set_device(OSXOutput *oo, Error &error)
status
=
AudioObjectGetPropertyData
(
deviceids
[
i
],
&
propaddr
,
0
,
nullptr
,
&
size
,
&
cfname
);
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
error
.
Format
(
osx_output_domain
,
status
,
"Unable to determine OS X device name "
"(device %u): %s"
,
(
unsigned
int
)
deviceids
[
i
],
errormsg
);
return
false
;
throw
FormatRuntimeError
(
"Unable to determine OS X device name "
"(device %u): %s"
,
(
unsigned
int
)
deviceids
[
i
],
errormsg
);
}
if
(
!
CFStringGetCString
(
cfname
,
name
,
sizeof
(
name
),
kCFStringEncodingUTF8
))
{
error
.
Set
(
osx_output_domain
,
"Unable to convert device name from CFStringRef to char*"
);
return
false
;
}
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
)
{
FormatDebug
(
osx_output_domain
,
...
...
@@ -502,7 +463,7 @@ osx_output_set_device(OSXOutput *oo, Error &error)
"Found no audio device with name '%s' "
"(will use default audio device)"
,
oo
->
device_name
);
return
true
;
return
;
}
status
=
AudioUnitSetProperty
(
oo
->
au
,
...
...
@@ -513,10 +474,8 @@ osx_output_set_device(OSXOutput *oo, Error &error)
sizeof
(
AudioDeviceID
));
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
error
.
Format
(
osx_output_domain
,
status
,
"Unable to set OS X audio output device: %s"
,
errormsg
);
return
false
;
throw
FormatRuntimeError
(
"Unable to set OS X audio output device: %s"
,
errormsg
);
}
oo
->
dev_id
=
deviceids
[
i
];
...
...
@@ -524,10 +483,8 @@ osx_output_set_device(OSXOutput *oo, Error &error)
"set OS X audio output device ID=%u, name=%s"
,
(
unsigned
)
deviceids
[
i
],
name
);
if
(
oo
->
channel_map
&&
!
osx_output_set_channel_map
(
oo
,
error
))
return
false
;
return
true
;
if
(
oo
->
channel_map
)
osx_output_set_channel_map
(
oo
);
}
...
...
@@ -556,7 +513,7 @@ osx_render(void *vdata,
}
static
bool
osx_output_enable
(
AudioOutput
*
ao
,
Error
&
error
)
osx_output_enable
(
AudioOutput
*
ao
,
Error
&
)
{
char
errormsg
[
1024
];
OSXOutput
*
oo
=
(
OSXOutput
*
)
ao
;
...
...
@@ -569,24 +526,21 @@ osx_output_enable(AudioOutput *ao, Error &error)
desc
.
componentFlagsMask
=
0
;
AudioComponent
comp
=
AudioComponentFindNext
(
nullptr
,
&
desc
);
if
(
comp
==
0
)
{
error
.
Set
(
osx_output_domain
,
"Error finding OS X component"
);
return
false
;
}
if
(
comp
==
0
)
throw
std
::
runtime_error
(
"Error finding OS X component"
);
OSStatus
status
=
AudioComponentInstanceNew
(
comp
,
&
oo
->
au
);
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
error
.
Format
(
osx_output_domain
,
status
,
"Unable to open OS X component: %s"
,
errormsg
);
return
false
;
throw
FormatRuntimeError
(
"Unable to open OS X component: %s"
,
errormsg
);
}
if
(
!
osx_output_set_device
(
oo
,
error
))
{
try
{
osx_output_set_device
(
oo
);
}
catch
(...)
{
AudioComponentInstanceDispose
(
oo
->
au
);
return
false
;
throw
;
}
if
(
oo
->
hog_device
)
{
...
...
@@ -621,7 +575,7 @@ osx_output_close(AudioOutput *ao)
static
bool
osx_output_open
(
AudioOutput
*
ao
,
AudioFormat
&
audio_format
,
Error
&
error
)
Error
&
)
{
char
errormsg
[
1024
];
OSXOutput
*
od
=
(
OSXOutput
*
)
ao
;
...
...
@@ -667,11 +621,8 @@ osx_output_open(AudioOutput *ao, AudioFormat &audio_format,
kAudioUnitScope_Input
,
0
,
&
od
->
asbd
,
sizeof
(
od
->
asbd
));
if
(
status
!=
noErr
)
{
error
.
Set
(
osx_output_domain
,
status
,
"Unable to set format on OS X device"
);
return
false
;
}
if
(
status
!=
noErr
)
throw
std
::
runtime_error
(
"Unable to set format on OS X device"
);
AURenderCallbackStruct
callback
;
callback
.
inputProc
=
osx_render
;
...
...
@@ -684,28 +635,22 @@ osx_output_open(AudioOutput *ao, AudioFormat &audio_format,
&
callback
,
sizeof
(
callback
));
if
(
status
!=
noErr
)
{
AudioComponentInstanceDispose
(
od
->
au
);
error
.
Set
(
osx_output_domain
,
status
,
"unable to set callback for OS X audio unit"
);
return
false
;
throw
std
::
runtime_error
(
"unable to set callback for OS X audio unit"
);
}
status
=
AudioUnitInitialize
(
od
->
au
);
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
error
.
Format
(
osx_output_domain
,
status
,
"Unable to initialize OS X audio unit: %s"
,
errormsg
);
return
false
;
throw
FormatRuntimeError
(
"Unable to initialize OS X audio unit: %s"
,
errormsg
);
}
UInt32
buffer_frame_size
=
1
;
status
=
osx_output_set_buffer_size
(
od
->
au
,
od
->
asbd
,
&
buffer_frame_size
);
if
(
status
!=
noErr
)
{
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
error
.
Format
(
osx_output_domain
,
status
,
"Unable to set frame size: %s"
,
errormsg
);
return
false
;
throw
FormatRuntimeError
(
"Unable to set frame size: %s"
,
errormsg
);
}
od
->
ring_buffer
=
new
boost
::
lockfree
::
spsc_queue
<
uint8_t
>
(
buffer_frame_size
);
...
...
@@ -714,10 +659,8 @@ osx_output_open(AudioOutput *ao, AudioFormat &audio_format,
if
(
status
!=
0
)
{
AudioUnitUninitialize
(
od
->
au
);
osx_os_status_to_cstring
(
status
,
errormsg
,
sizeof
(
errormsg
));
error
.
Format
(
osx_output_domain
,
status
,
"unable to start audio output: %s"
,
errormsg
);
return
false
;
throw
FormatRuntimeError
(
"unable to start audio output: %s"
,
errormsg
);
}
return
true
;
...
...
This diff is collapsed.
Click to expand it.
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