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
db7caa2d
Commit
db7caa2d
authored
Dec 02, 2020
by
Shen-Ta Hsieh
Committed by
Max Kellermann
Mar 04, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
src/output: Move event and spsc_queue into thread object
parent
29747377
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
33 additions
and
39 deletions
+33
-39
WasapiOutputPlugin.cxx
src/output/plugins/WasapiOutputPlugin.cxx
+33
-39
No files found.
src/output/plugins/WasapiOutputPlugin.cxx
View file @
db7caa2d
...
...
@@ -118,15 +118,14 @@ inline constexpr const unsigned int kErrorId = -1;
class
WasapiOutputThread
:
public
Thread
{
public
:
enum
class
Status
:
uint32_t
{
FINISH
,
PLAY
,
PAUSE
};
WasapiOutputThread
(
std
::
shared_ptr
<
WinEvent
>
_event
,
ComPtr
<
IAudioClient
>
_client
,
WasapiOutputThread
(
IAudioClient
*
_client
,
ComPtr
<
IAudioRenderClient
>
&&
_render_client
,
const
UINT32
_frame_size
,
const
UINT32
_buffer_size_in_frames
,
bool
_is_exclusive
,
boost
::
lockfree
::
spsc_queue
<
BYTE
>
&
_spsc_buffer
)
:
Thread
(
BIND_THIS_METHOD
(
Work
)),
event
(
std
::
move
(
_event
)),
client
(
std
::
move
(
_client
)),
render_client
(
std
::
move
(
_render_client
)),
frame_size
(
_frame_size
),
buffer_size_in_frames
(
_buffer_size_in_frames
),
is_exclusive
(
_is_exclusive
),
spsc_buffer
(
_spsc_buffer
)
{}
bool
_is_exclusive
)
:
Thread
(
BIND_THIS_METHOD
(
Work
)),
client
(
_client
),
render_client
(
std
::
move
(
_render_client
)),
frame_size
(
_frame_size
),
buffer_size_in_frames
(
_buffer_size_in_frames
),
is_exclusive
(
_is_exclusive
),
spsc_buffer
(
_buffer_size_in_frames
*
4
*
_frame_size
)
{}
void
Finish
()
noexcept
{
return
SetStatus
(
Status
::
FINISH
);
}
void
Play
()
noexcept
{
return
SetStatus
(
Status
::
PLAY
);
}
void
Pause
()
noexcept
{
return
SetStatus
(
Status
::
PAUSE
);
}
...
...
@@ -144,13 +143,13 @@ public:
}
private
:
std
::
shared_ptr
<
WinEvent
>
event
;
ComPtr
<
IAudioClient
>
client
;
friend
class
WasapiOutput
;
WinEvent
event
;
IAudioClient
*
client
;
ComPtr
<
IAudioRenderClient
>
render_client
;
const
UINT32
frame_size
;
const
UINT32
buffer_size_in_frames
;
bool
is_exclusive
;
boost
::
lockfree
::
spsc_queue
<
BYTE
>
&
spsc_buffer
;
alignas
(
BOOST_LOCKFREE_CACHELINE_BYTES
)
std
::
atomic
<
Status
>
status
=
Status
::
PAUSE
;
alignas
(
BOOST_LOCKFREE_CACHELINE_BYTES
)
struct
{
...
...
@@ -162,10 +161,11 @@ private:
Cond
cond
;
std
::
exception_ptr
error_ptr
=
nullptr
;
}
error
{};
boost
::
lockfree
::
spsc_queue
<
BYTE
>
spsc_buffer
;
void
SetStatus
(
Status
s
)
noexcept
{
status
.
store
(
s
);
event
->
Set
();
event
.
Set
();
}
void
Work
()
noexcept
;
};
...
...
@@ -203,13 +203,11 @@ private:
bool
enumerate_devices
;
std
::
string
device_config
;
std
::
vector
<
std
::
pair
<
unsigned
int
,
AllocatedString
>>
device_desc
;
std
::
shared_ptr
<
WinEvent
>
event
;
ComPtr
<
IMMDeviceEnumerator
>
enumerator
;
ComPtr
<
IMMDevice
>
device
;
ComPtr
<
IAudioClient
>
client
;
WAVEFORMATEXTENSIBLE
device_format
;
std
::
unique_ptr
<
WasapiOutputThread
>
thread
;
std
::
unique_ptr
<
boost
::
lockfree
::
spsc_queue
<
BYTE
>>
spsc_buffer
;
std
::
optional
<
WasapiOutputThread
>
thread
;
std
::
size_t
watermark
;
friend
bool
wasapi_is_exclusive
(
WasapiOutput
&
output
)
noexcept
;
...
...
@@ -248,7 +246,7 @@ void WasapiOutputThread::Work() noexcept {
COM
com
{
true
};
while
(
true
)
{
try
{
event
->
Wait
(
INFINITE
);
event
.
Wait
(
INFINITE
);
Status
current_state
=
status
.
load
();
if
(
current_state
==
Status
::
FINISH
)
{
...
...
@@ -330,13 +328,10 @@ void WasapiOutput::DoDisable() noexcept {
err
.
what
());
}
thread
.
reset
();
spsc_buffer
.
reset
();
client
.
reset
();
}
device
.
reset
();
enumerator
.
reset
();
com
.
reset
();
event
.
reset
();
}
/// run inside COMWorkerThread
...
...
@@ -442,11 +437,6 @@ void WasapiOutput::DoOpen(AudioFormat &audio_format) {
throw
FormatHResultError
(
result
,
"Unable to get new render client"
);
}
result
=
client
->
SetEventHandle
(
event
->
handle
());
if
(
FAILED
(
result
))
{
throw
FormatHResultError
(
result
,
"Unable to set event handler"
);
}
UINT32
buffer_size_in_frames
;
result
=
client
->
GetBufferSize
(
&
buffer_size_in_frames
);
if
(
FAILED
(
result
))
{
...
...
@@ -455,11 +445,14 @@ void WasapiOutput::DoOpen(AudioFormat &audio_format) {
}
watermark
=
buffer_size_in_frames
*
3
*
FrameSize
();
spsc_buffer
=
std
::
make_unique
<
boost
::
lockfree
::
spsc_queue
<
BYTE
>>
(
buffer_size_in_frames
*
4
*
FrameSize
());
thread
=
std
::
make_unique
<
WasapiOutputThread
>
(
event
,
client
,
std
::
move
(
render_client
),
FrameSize
(),
buffer_size_in_frames
,
is_exclusive
,
*
spsc_buffer
);
thread
.
emplace
(
client
.
get
(),
std
::
move
(
render_client
),
FrameSize
(),
buffer_size_in_frames
,
is_exclusive
);
result
=
client
->
SetEventHandle
(
thread
->
event
.
handle
());
if
(
FAILED
(
result
))
{
throw
FormatHResultError
(
result
,
"Unable to set event handler"
);
}
thread
->
Start
();
}
...
...
@@ -472,7 +465,6 @@ void WasapiOutput::Close() noexcept {
thread
.
reset
();
client
.
reset
();
}).
get
();
spsc_buffer
.
reset
();
}
std
::
chrono
::
steady_clock
::
duration
WasapiOutput
::
Delay
()
const
noexcept
{
...
...
@@ -480,7 +472,9 @@ std::chrono::steady_clock::duration WasapiOutput::Delay() const noexcept {
return
std
::
chrono
::
steady_clock
::
duration
::
zero
();
}
const
size_t
data_size
=
spsc_buffer
->
read_available
();
assert
(
thread
);
const
size_t
data_size
=
thread
->
spsc_buffer
.
read_available
();
const
size_t
delay_size
=
std
::
max
(
data_size
,
watermark
)
-
watermark
;
using
s
=
std
::
chrono
::
seconds
;
...
...
@@ -490,13 +484,11 @@ std::chrono::steady_clock::duration WasapiOutput::Delay() const noexcept {
}
size_t
WasapiOutput
::
Play
(
const
void
*
chunk
,
size_t
size
)
{
if
(
!
client
||
!
thread
)
{
return
0
;
}
assert
(
thread
);
do
{
const
size_t
consumed_size
=
spsc_buffer
->
push
(
static_cast
<
const
BYTE
*>
(
chunk
),
size
);
thread
->
spsc_buffer
.
push
(
static_cast
<
const
BYTE
*>
(
chunk
),
size
);
if
(
consumed_size
==
0
)
{
assert
(
is_started
);
thread
->
WaitWrite
();
...
...
@@ -523,11 +515,6 @@ size_t WasapiOutput::Play(const void *chunk, size_t size) {
}
while
(
true
);
}
void
WasapiOutput
::
Drain
()
{
spsc_buffer
->
consume_all
([](
auto
&&
)
{});
thread
->
CheckException
();
}
bool
WasapiOutput
::
Pause
()
{
if
(
!
client
||
!
thread
)
{
return
false
;
...
...
@@ -549,6 +536,13 @@ bool WasapiOutput::Pause() {
return
true
;
}
void
WasapiOutput
::
Drain
()
{
assert
(
thread
);
thread
->
spsc_buffer
.
consume_all
([](
auto
&&
)
{});
thread
->
CheckException
();
}
/// run inside COMWorkerThread
void
WasapiOutput
::
OpenDevice
()
{
enumerator
.
CoCreateInstance
(
__uuidof
(
MMDeviceEnumerator
),
nullptr
,
...
...
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