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
25354b9d
Commit
25354b9d
authored
Mar 10, 2021
by
Max Kellermann
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'v0.22.x'
parents
ee720064
25b01940
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
168 additions
and
134 deletions
+168
-134
FileDescriptor.cxx
src/io/FileDescriptor.cxx
+9
-1
FileDescriptor.hxx
src/io/FileDescriptor.hxx
+3
-0
WasapiMixerPlugin.cxx
src/mixer/plugins/WasapiMixerPlugin.cxx
+16
-8
AudioClient.hxx
src/output/plugins/wasapi/AudioClient.hxx
+9
-9
Device.hxx
src/output/plugins/wasapi/Device.hxx
+9
-9
ForMixer.hxx
src/output/plugins/wasapi/ForMixer.hxx
+7
-0
WasapiOutputPlugin.cxx
src/output/plugins/wasapi/WasapiOutputPlugin.cxx
+0
-0
Com.hxx
src/win32/Com.hxx
+2
-10
ComPtr.hxx
src/win32/ComPtr.hxx
+1
-1
ComWorker.cxx
src/win32/ComWorker.cxx
+4
-6
ComWorker.hxx
src/win32/ComWorker.hxx
+30
-52
HResult.cxx
src/win32/HResult.cxx
+12
-1
HResult.hxx
src/win32/HResult.hxx
+9
-0
run_convert.cxx
test/run_convert.cxx
+27
-20
run_input.cxx
test/run_input.cxx
+2
-0
run_output.cxx
test/run_output.cxx
+28
-17
No files found.
src/io/FileDescriptor.cxx
View file @
25354b9d
...
@@ -172,7 +172,15 @@ FileDescriptor::CreatePipe(FileDescriptor &r, FileDescriptor &w) noexcept
...
@@ -172,7 +172,15 @@ FileDescriptor::CreatePipe(FileDescriptor &r, FileDescriptor &w) noexcept
#endif
#endif
}
}
#ifndef _WIN32
#ifdef _WIN32
void
FileDescriptor
::
SetBinaryMode
()
noexcept
{
_setmode
(
fd
,
_O_BINARY
);
}
#else // !_WIN32
bool
bool
FileDescriptor
::
CreatePipeNonBlock
(
FileDescriptor
&
r
,
FileDescriptor
::
CreatePipeNonBlock
(
FileDescriptor
&
r
,
...
...
src/io/FileDescriptor.hxx
View file @
25354b9d
...
@@ -147,10 +147,13 @@ public:
...
@@ -147,10 +147,13 @@ public:
#ifdef _WIN32
#ifdef _WIN32
void
EnableCloseOnExec
()
noexcept
{}
void
EnableCloseOnExec
()
noexcept
{}
void
DisableCloseOnExec
()
noexcept
{}
void
DisableCloseOnExec
()
noexcept
{}
void
SetBinaryMode
()
noexcept
;
#else
#else
static
bool
CreatePipeNonBlock
(
FileDescriptor
&
r
,
static
bool
CreatePipeNonBlock
(
FileDescriptor
&
r
,
FileDescriptor
&
w
)
noexcept
;
FileDescriptor
&
w
)
noexcept
;
void
SetBinaryMode
()
noexcept
{}
/**
/**
* Enable non-blocking mode on this file descriptor.
* Enable non-blocking mode on this file descriptor.
*/
*/
...
...
src/mixer/plugins/WasapiMixerPlugin.cxx
View file @
25354b9d
...
@@ -44,7 +44,11 @@ public:
...
@@ -44,7 +44,11 @@ public:
void
Close
()
noexcept
override
{}
void
Close
()
noexcept
override
{}
int
GetVolume
()
override
{
int
GetVolume
()
override
{
auto
future
=
COMWorker
::
Async
([
&
]()
->
int
{
auto
com_worker
=
wasapi_output_get_com_worker
(
output
);
if
(
!
com_worker
)
return
-
1
;
auto
future
=
com_worker
->
Async
([
&
]()
->
int
{
HRESULT
result
;
HRESULT
result
;
float
volume_level
;
float
volume_level
;
...
@@ -55,9 +59,9 @@ public:
...
@@ -55,9 +59,9 @@ public:
result
=
endpoint_volume
->
GetMasterVolumeLevelScalar
(
result
=
endpoint_volume
->
GetMasterVolumeLevelScalar
(
&
volume_level
);
&
volume_level
);
if
(
FAILED
(
result
))
{
if
(
FAILED
(
result
))
{
throw
Format
HResultError
(
result
,
throw
Make
HResultError
(
result
,
"Unable to get master "
"Unable to get master "
"volume level"
);
"volume level"
);
}
}
}
else
{
}
else
{
auto
session_volume
=
auto
session_volume
=
...
@@ -65,7 +69,7 @@ public:
...
@@ -65,7 +69,7 @@ public:
result
=
session_volume
->
GetMasterVolume
(
&
volume_level
);
result
=
session_volume
->
GetMasterVolume
(
&
volume_level
);
if
(
FAILED
(
result
))
{
if
(
FAILED
(
result
))
{
throw
Format
HResultError
(
throw
Make
HResultError
(
result
,
"Unable to get master volume"
);
result
,
"Unable to get master volume"
);
}
}
}
}
...
@@ -76,7 +80,11 @@ public:
...
@@ -76,7 +80,11 @@ public:
}
}
void
SetVolume
(
unsigned
volume
)
override
{
void
SetVolume
(
unsigned
volume
)
override
{
COMWorker
::
Async
([
&
]()
{
auto
com_worker
=
wasapi_output_get_com_worker
(
output
);
if
(
!
com_worker
)
throw
std
::
runtime_error
(
"Cannot set WASAPI volume"
);
com_worker
->
Async
([
&
]()
{
HRESULT
result
;
HRESULT
result
;
const
float
volume_level
=
volume
/
100.0
f
;
const
float
volume_level
=
volume
/
100.0
f
;
...
@@ -87,7 +95,7 @@ public:
...
@@ -87,7 +95,7 @@ public:
result
=
endpoint_volume
->
SetMasterVolumeLevelScalar
(
result
=
endpoint_volume
->
SetMasterVolumeLevelScalar
(
volume_level
,
nullptr
);
volume_level
,
nullptr
);
if
(
FAILED
(
result
))
{
if
(
FAILED
(
result
))
{
throw
Format
HResultError
(
throw
Make
HResultError
(
result
,
result
,
"Unable to set master volume level"
);
"Unable to set master volume level"
);
}
}
...
@@ -98,7 +106,7 @@ public:
...
@@ -98,7 +106,7 @@ public:
result
=
session_volume
->
SetMasterVolume
(
volume_level
,
result
=
session_volume
->
SetMasterVolume
(
volume_level
,
nullptr
);
nullptr
);
if
(
FAILED
(
result
))
{
if
(
FAILED
(
result
))
{
throw
Format
HResultError
(
throw
Make
HResultError
(
result
,
"Unable to set master volume"
);
result
,
"Unable to set master volume"
);
}
}
}
}
...
...
src/output/plugins/wasapi/AudioClient.hxx
View file @
25354b9d
...
@@ -33,8 +33,8 @@ GetBufferSizeInFrames(IAudioClient &client)
...
@@ -33,8 +33,8 @@ GetBufferSizeInFrames(IAudioClient &client)
HRESULT
result
=
client
.
GetBufferSize
(
&
buffer_size_in_frames
);
HRESULT
result
=
client
.
GetBufferSize
(
&
buffer_size_in_frames
);
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
throw
Make
HResultError
(
result
,
"Unable to get audio client buffer size"
);
"Unable to get audio client buffer size"
);
return
buffer_size_in_frames
;
return
buffer_size_in_frames
;
}
}
...
@@ -46,8 +46,8 @@ GetCurrentPaddingFrames(IAudioClient &client)
...
@@ -46,8 +46,8 @@ GetCurrentPaddingFrames(IAudioClient &client)
HRESULT
result
=
client
.
GetCurrentPadding
(
&
padding_frames
);
HRESULT
result
=
client
.
GetCurrentPadding
(
&
padding_frames
);
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
throw
Make
HResultError
(
result
,
"Failed to get current padding"
);
"Failed to get current padding"
);
return
padding_frames
;
return
padding_frames
;
}
}
...
@@ -59,7 +59,7 @@ GetMixFormat(IAudioClient &client)
...
@@ -59,7 +59,7 @@ GetMixFormat(IAudioClient &client)
HRESULT
result
=
client
.
GetMixFormat
(
&
f
);
HRESULT
result
=
client
.
GetMixFormat
(
&
f
);
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
"GetMixFormat failed"
);
throw
Make
HResultError
(
result
,
"GetMixFormat failed"
);
return
ComHeapPtr
{
f
};
return
ComHeapPtr
{
f
};
}
}
...
@@ -69,7 +69,7 @@ Start(IAudioClient &client)
...
@@ -69,7 +69,7 @@ Start(IAudioClient &client)
{
{
HRESULT
result
=
client
.
Start
();
HRESULT
result
=
client
.
Start
();
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
"Failed to start client"
);
throw
Make
HResultError
(
result
,
"Failed to start client"
);
}
}
inline
void
inline
void
...
@@ -77,7 +77,7 @@ Stop(IAudioClient &client)
...
@@ -77,7 +77,7 @@ Stop(IAudioClient &client)
{
{
HRESULT
result
=
client
.
Stop
();
HRESULT
result
=
client
.
Stop
();
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
"Failed to stop client"
);
throw
Make
HResultError
(
result
,
"Failed to stop client"
);
}
}
inline
void
inline
void
...
@@ -85,7 +85,7 @@ SetEventHandle(IAudioClient &client, HANDLE h)
...
@@ -85,7 +85,7 @@ SetEventHandle(IAudioClient &client, HANDLE h)
{
{
HRESULT
result
=
client
.
SetEventHandle
(
h
);
HRESULT
result
=
client
.
SetEventHandle
(
h
);
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
"Unable to set event handle"
);
throw
Make
HResultError
(
result
,
"Unable to set event handle"
);
}
}
template
<
typename
T
>
template
<
typename
T
>
...
@@ -95,7 +95,7 @@ GetService(IAudioClient &client)
...
@@ -95,7 +95,7 @@ GetService(IAudioClient &client)
T
*
p
=
nullptr
;
T
*
p
=
nullptr
;
HRESULT
result
=
client
.
GetService
(
IID_PPV_ARGS
(
&
p
));
HRESULT
result
=
client
.
GetService
(
IID_PPV_ARGS
(
&
p
));
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
"Unable to get service"
);
throw
Make
HResultError
(
result
,
"Unable to get service"
);
return
ComPtr
{
p
};
return
ComPtr
{
p
};
}
}
...
...
src/output/plugins/wasapi/Device.hxx
View file @
25354b9d
...
@@ -33,8 +33,8 @@ GetDefaultAudioEndpoint(IMMDeviceEnumerator &e)
...
@@ -33,8 +33,8 @@ GetDefaultAudioEndpoint(IMMDeviceEnumerator &e)
HRESULT
result
=
e
.
GetDefaultAudioEndpoint
(
eRender
,
eMultimedia
,
HRESULT
result
=
e
.
GetDefaultAudioEndpoint
(
eRender
,
eMultimedia
,
&
device
);
&
device
);
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
throw
Make
HResultError
(
result
,
"Unable to get default device for multimedia"
);
"Unable to get default device for multimedia"
);
return
ComPtr
{
device
};
return
ComPtr
{
device
};
}
}
...
@@ -47,7 +47,7 @@ EnumAudioEndpoints(IMMDeviceEnumerator &e)
...
@@ -47,7 +47,7 @@ EnumAudioEndpoints(IMMDeviceEnumerator &e)
HRESULT
result
=
e
.
EnumAudioEndpoints
(
eRender
,
DEVICE_STATE_ACTIVE
,
HRESULT
result
=
e
.
EnumAudioEndpoints
(
eRender
,
DEVICE_STATE_ACTIVE
,
&
dc
);
&
dc
);
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
"Unable to enumerate devices"
);
throw
Make
HResultError
(
result
,
"Unable to enumerate devices"
);
return
ComPtr
{
dc
};
return
ComPtr
{
dc
};
}
}
...
@@ -59,7 +59,7 @@ GetCount(IMMDeviceCollection &dc)
...
@@ -59,7 +59,7 @@ GetCount(IMMDeviceCollection &dc)
HRESULT
result
=
dc
.
GetCount
(
&
count
);
HRESULT
result
=
dc
.
GetCount
(
&
count
);
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
"Collection->GetCount failed"
);
throw
Make
HResultError
(
result
,
"Collection->GetCount failed"
);
return
count
;
return
count
;
}
}
...
@@ -71,7 +71,7 @@ Item(IMMDeviceCollection &dc, UINT i)
...
@@ -71,7 +71,7 @@ Item(IMMDeviceCollection &dc, UINT i)
auto
result
=
dc
.
Item
(
i
,
&
device
);
auto
result
=
dc
.
Item
(
i
,
&
device
);
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
"Collection->Item failed"
);
throw
Make
HResultError
(
result
,
"Collection->Item failed"
);
return
ComPtr
{
device
};
return
ComPtr
{
device
};
}
}
...
@@ -83,7 +83,7 @@ GetState(IMMDevice &device)
...
@@ -83,7 +83,7 @@ GetState(IMMDevice &device)
HRESULT
result
=
device
.
GetState
(
&
state
);;
HRESULT
result
=
device
.
GetState
(
&
state
);;
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
"Unable to get device status"
);
throw
Make
HResultError
(
result
,
"Unable to get device status"
);
return
state
;
return
state
;
}
}
...
@@ -96,7 +96,7 @@ Activate(IMMDevice &device)
...
@@ -96,7 +96,7 @@ Activate(IMMDevice &device)
HRESULT
result
=
device
.
Activate
(
__uuidof
(
T
),
CLSCTX_ALL
,
HRESULT
result
=
device
.
Activate
(
__uuidof
(
T
),
CLSCTX_ALL
,
nullptr
,
(
void
**
)
&
p
);
nullptr
,
(
void
**
)
&
p
);
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
"Unable to activate device"
);
throw
Make
HResultError
(
result
,
"Unable to activate device"
);
return
ComPtr
{
p
};
return
ComPtr
{
p
};
}
}
...
@@ -108,8 +108,8 @@ OpenPropertyStore(IMMDevice &device)
...
@@ -108,8 +108,8 @@ OpenPropertyStore(IMMDevice &device)
HRESULT
result
=
device
.
OpenPropertyStore
(
STGM_READ
,
&
property_store
);
HRESULT
result
=
device
.
OpenPropertyStore
(
STGM_READ
,
&
property_store
);
if
(
FAILED
(
result
))
if
(
FAILED
(
result
))
throw
Format
HResultError
(
result
,
throw
Make
HResultError
(
result
,
"Device->OpenPropertyStore failed"
);
"Device->OpenPropertyStore failed"
);
return
ComPtr
{
property_store
};
return
ComPtr
{
property_store
};
}
}
...
...
src/output/plugins/wasapi/ForMixer.hxx
View file @
25354b9d
...
@@ -20,10 +20,13 @@
...
@@ -20,10 +20,13 @@
#ifndef MPD_WASAPI_OUTPUT_FOR_MIXER_HXX
#ifndef MPD_WASAPI_OUTPUT_FOR_MIXER_HXX
#define MPD_WASAPI_OUTPUT_FOR_MIXER_HXX
#define MPD_WASAPI_OUTPUT_FOR_MIXER_HXX
#include <memory>
struct
IMMDevice
;
struct
IMMDevice
;
struct
IAudioClient
;
struct
IAudioClient
;
class
AudioOutput
;
class
AudioOutput
;
class
WasapiOutput
;
class
WasapiOutput
;
class
COMWorker
;
[[
gnu
::
pure
]]
[[
gnu
::
pure
]]
WasapiOutput
&
WasapiOutput
&
...
@@ -34,6 +37,10 @@ bool
...
@@ -34,6 +37,10 @@ bool
wasapi_is_exclusive
(
WasapiOutput
&
output
)
noexcept
;
wasapi_is_exclusive
(
WasapiOutput
&
output
)
noexcept
;
[[
gnu
::
pure
]]
[[
gnu
::
pure
]]
std
::
shared_ptr
<
COMWorker
>
wasapi_output_get_com_worker
(
WasapiOutput
&
output
)
noexcept
;
[[
gnu
::
pure
]]
IMMDevice
*
IMMDevice
*
wasapi_output_get_device
(
WasapiOutput
&
output
)
noexcept
;
wasapi_output_get_device
(
WasapiOutput
&
output
)
noexcept
;
...
...
src/output/plugins/wasapi/WasapiOutputPlugin.cxx
View file @
25354b9d
This diff is collapsed.
Click to expand it.
src/win32/Com.hxx
View file @
25354b9d
...
@@ -29,17 +29,9 @@
...
@@ -29,17 +29,9 @@
class
COM
{
class
COM
{
public
:
public
:
COM
()
{
COM
()
{
if
(
HRESULT
result
=
CoInitializeEx
(
nullptr
,
COINIT_
MULTITHREADED
);
if
(
HRESULT
result
=
CoInitializeEx
(
nullptr
,
COINIT_
APARTMENTTHREADED
|
COINIT_DISABLE_OLE1DDE
);
FAILED
(
result
))
{
FAILED
(
result
))
{
throw
FormatHResultError
(
throw
MakeHResultError
(
result
,
"Unable to initialize COM with COINIT_MULTITHREADED"
);
}
}
COM
(
bool
)
{
if
(
HRESULT
result
=
CoInitializeEx
(
nullptr
,
COINIT_APARTMENTTHREADED
);
FAILED
(
result
))
{
throw
FormatHResultError
(
result
,
result
,
"Unable to initialize COM with COINIT_APARTMENTTHREADED"
);
"Unable to initialize COM with COINIT_APARTMENTTHREADED"
);
}
}
...
...
src/win32/ComPtr.hxx
View file @
25354b9d
...
@@ -85,7 +85,7 @@ public:
...
@@ -85,7 +85,7 @@ public:
::
CoCreateInstance
(
class_id
,
unknown_outer
,
class_context
,
::
CoCreateInstance
(
class_id
,
unknown_outer
,
class_context
,
__uuidof
(
T
),
reinterpret_cast
<
void
**>
(
&
ptr
));
__uuidof
(
T
),
reinterpret_cast
<
void
**>
(
&
ptr
));
if
(
FAILED
(
result
))
{
if
(
FAILED
(
result
))
{
throw
Format
HResultError
(
result
,
"Unable to create instance"
);
throw
Make
HResultError
(
result
,
"Unable to create instance"
);
}
}
}
}
...
...
src/win32/ComWorker.cxx
View file @
25354b9d
...
@@ -21,13 +21,11 @@
...
@@ -21,13 +21,11 @@
#include "Com.hxx"
#include "Com.hxx"
#include "thread/Name.hxx"
#include "thread/Name.hxx"
Mutex
COMWorker
::
mutex
;
void
unsigned
int
COMWorker
::
reference_count
=
0
;
COMWorker
::
Work
()
noexcept
std
::
optional
<
COMWorker
::
COMWorkerThread
>
COMWorker
::
thread
;
{
void
COMWorker
::
COMWorkerThread
::
Work
()
noexcept
{
SetThreadName
(
"COM Worker"
);
SetThreadName
(
"COM Worker"
);
COM
com
{
true
}
;
COM
com
;
while
(
true
)
{
while
(
true
)
{
if
(
!
running_flag
.
test_and_set
())
{
if
(
!
running_flag
.
test_and_set
())
{
return
;
return
;
...
...
src/win32/ComWorker.hxx
View file @
25354b9d
...
@@ -22,76 +22,46 @@
...
@@ -22,76 +22,46 @@
#include "WinEvent.hxx"
#include "WinEvent.hxx"
#include "thread/Future.hxx"
#include "thread/Future.hxx"
#include "thread/Mutex.hxx"
#include "thread/Thread.hxx"
#include "thread/Thread.hxx"
#include <boost/lockfree/spsc_queue.hpp>
#include <boost/lockfree/spsc_queue.hpp>
#include <mutex>
#include <optional>
#include <windows.h>
#include <windows.h>
// Worker thread for all COM operation
// Worker thread for all COM operation
class
COMWorker
{
class
COMWorker
{
private
:
Thread
thread
{
BIND_THIS_METHOD
(
Work
)};
class
COMWorkerThread
:
public
Thread
{
public
:
COMWorkerThread
()
:
Thread
{
BIND_THIS_METHOD
(
Work
)}
{}
private
:
friend
class
COMWorker
;
void
Work
()
noexcept
;
void
Finish
()
noexcept
{
running_flag
.
clear
();
event
.
Set
();
}
void
Push
(
const
std
::
function
<
void
()
>
&
function
)
{
spsc_buffer
.
push
(
function
);
event
.
Set
();
}
boost
::
lockfree
::
spsc_queue
<
std
::
function
<
void
()
>>
spsc_buffer
{
32
};
boost
::
lockfree
::
spsc_queue
<
std
::
function
<
void
()
>>
spsc_buffer
{
32
};
std
::
atomic_flag
running_flag
=
true
;
std
::
atomic_flag
running_flag
=
true
;
WinEvent
event
{};
WinEvent
event
{};
};
public
:
public
:
static
void
Aquire
()
{
COMWorker
()
{
std
::
unique_lock
locker
(
mutex
);
thread
.
Start
();
if
(
reference_count
==
0
)
{
thread
.
emplace
();
thread
->
Start
();
}
++
reference_count
;
}
}
static
void
Release
()
noexcept
{
std
::
unique_lock
locker
(
mutex
);
~
COMWorker
()
noexcept
{
--
reference_count
;
Finish
();
if
(
reference_count
==
0
)
{
thread
.
Join
();
thread
->
Finish
();
thread
->
Join
();
thread
.
reset
();
}
}
}
template
<
typename
Function
,
typename
...
Args
>
COMWorker
(
const
COMWorker
&
)
=
delete
;
static
auto
Async
(
Function
&&
function
,
Args
&&
...
args
)
{
COMWorker
&
operator
=
(
const
COMWorker
&
)
=
delete
;
using
R
=
std
::
invoke_result_t
<
std
::
decay_t
<
Function
>
,
std
::
decay_t
<
Args
>
...
>
;
template
<
typename
Function
>
auto
Async
(
Function
&&
function
)
{
using
R
=
std
::
invoke_result_t
<
std
::
decay_t
<
Function
>>
;
auto
promise
=
std
::
make_shared
<
Promise
<
R
>>
();
auto
promise
=
std
::
make_shared
<
Promise
<
R
>>
();
auto
future
=
promise
->
get_future
();
auto
future
=
promise
->
get_future
();
thread
->
Push
([
function
=
std
::
forward
<
Function
>
(
function
),
Push
([
function
=
std
::
forward
<
Function
>
(
function
),
args
=
std
::
make_tuple
(
std
::
forward
<
Args
>
(
args
)...),
promise
=
std
::
move
(
promise
)]()
mutable
{
promise
=
std
::
move
(
promise
)]()
mutable
{
try
{
try
{
if
constexpr
(
std
::
is_void_v
<
R
>
)
{
if
constexpr
(
std
::
is_void_v
<
R
>
)
{
std
::
apply
(
std
::
forward
<
Function
>
(
function
),
std
::
invoke
(
std
::
forward
<
Function
>
(
function
));
std
::
move
(
args
));
promise
->
set_value
();
promise
->
set_value
();
}
else
{
}
else
{
promise
->
set_value
(
std
::
apply
(
promise
->
set_value
(
std
::
invoke
(
std
::
forward
<
Function
>
(
function
)));
std
::
forward
<
Function
>
(
function
),
std
::
move
(
args
)));
}
}
}
catch
(...)
{
}
catch
(...)
{
promise
->
set_exception
(
std
::
current_exception
());
promise
->
set_exception
(
std
::
current_exception
());
...
@@ -101,9 +71,17 @@ public:
...
@@ -101,9 +71,17 @@ public:
}
}
private
:
private
:
static
Mutex
mutex
;
void
Finish
()
noexcept
{
static
unsigned
int
reference_count
;
running_flag
.
clear
();
static
std
::
optional
<
COMWorkerThread
>
thread
;
event
.
Set
();
}
void
Push
(
const
std
::
function
<
void
()
>
&
function
)
{
spsc_buffer
.
push
(
function
);
event
.
Set
();
}
void
Work
()
noexcept
;
};
};
#endif
#endif
src/win32/HResult.cxx
View file @
25354b9d
...
@@ -18,6 +18,7 @@
...
@@ -18,6 +18,7 @@
*/
*/
#include "HResult.hxx"
#include "HResult.hxx"
#include "system/Error.hxx"
#include <cassert>
#include <cassert>
#include <cstdarg>
#include <cstdarg>
...
@@ -27,11 +28,21 @@
...
@@ -27,11 +28,21 @@
std
::
string
std
::
string
HResultCategory
::
message
(
int
Errcode
)
const
HResultCategory
::
message
(
int
Errcode
)
const
{
{
char
buffer
[
256
];
/* FormatMessage() supports some HRESULT values (depending on
the Windows version) */
if
(
FormatMessageA
(
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
nullptr
,
Errcode
,
0
,
buffer
,
sizeof
(
buffer
),
nullptr
))
return
buffer
;
const
auto
msg
=
HRESULTToString
(
Errcode
);
const
auto
msg
=
HRESULTToString
(
Errcode
);
if
(
!
msg
.
empty
())
if
(
!
msg
.
empty
())
return
std
::
string
(
msg
);
return
std
::
string
(
msg
);
char
buffer
[
11
];
// "0x12345678\0"
int
size
=
snprintf
(
buffer
,
sizeof
(
buffer
),
"0x%1x"
,
Errcode
);
int
size
=
snprintf
(
buffer
,
sizeof
(
buffer
),
"0x%1x"
,
Errcode
);
assert
(
2
<=
size
&&
size
<=
10
);
assert
(
2
<=
size
&&
size
<=
10
);
return
std
::
string
(
buffer
,
size
);
return
std
::
string
(
buffer
,
size
);
...
...
src/win32/HResult.hxx
View file @
25354b9d
...
@@ -50,6 +50,8 @@ case x:
...
@@ -50,6 +50,8 @@ case x:
C
(
AUDCLNT_E_SERVICE_NOT_RUNNING
);
C
(
AUDCLNT_E_SERVICE_NOT_RUNNING
);
C
(
AUDCLNT_E_UNSUPPORTED_FORMAT
);
C
(
AUDCLNT_E_UNSUPPORTED_FORMAT
);
C
(
AUDCLNT_E_WRONG_ENDPOINT_TYPE
);
C
(
AUDCLNT_E_WRONG_ENDPOINT_TYPE
);
C
(
AUDCLNT_E_NOT_INITIALIZED
);
C
(
AUDCLNT_E_NOT_STOPPED
);
C
(
CO_E_NOTINITIALIZED
);
C
(
CO_E_NOTINITIALIZED
);
C
(
E_INVALIDARG
);
C
(
E_INVALIDARG
);
C
(
E_OUTOFMEMORY
);
C
(
E_OUTOFMEMORY
);
...
@@ -74,6 +76,13 @@ static inline const std::error_category &hresult_category() noexcept {
...
@@ -74,6 +76,13 @@ static inline const std::error_category &hresult_category() noexcept {
return
hresult_category_instance
;
return
hresult_category_instance
;
}
}
inline
std
::
system_error
MakeHResultError
(
HRESULT
result
,
const
char
*
msg
)
noexcept
{
return
std
::
system_error
(
std
::
error_code
(
result
,
hresult_category
()),
msg
);
}
gcc_printf
(
2
,
3
)
std
::
system_error
gcc_printf
(
2
,
3
)
std
::
system_error
FormatHResultError
(
HRESULT
result
,
const
char
*
fmt
,
...)
noexcept
;
FormatHResultError
(
HRESULT
result
,
const
char
*
fmt
,
...)
noexcept
;
...
...
test/run_convert.cxx
View file @
25354b9d
...
@@ -29,6 +29,7 @@
...
@@ -29,6 +29,7 @@
#include "pcm/Convert.hxx"
#include "pcm/Convert.hxx"
#include "fs/Path.hxx"
#include "fs/Path.hxx"
#include "fs/NarrowPath.hxx"
#include "fs/NarrowPath.hxx"
#include "io/FileDescriptor.hxx"
#include "util/ConstBuffer.hxx"
#include "util/ConstBuffer.hxx"
#include "util/StaticFifoBuffer.hxx"
#include "util/StaticFifoBuffer.hxx"
#include "util/OptionDef.hxx"
#include "util/OptionDef.hxx"
...
@@ -101,26 +102,21 @@ public:
...
@@ -101,26 +102,21 @@ public:
}
}
};
};
int
static
void
main
(
int
argc
,
char
**
argv
)
RunConvert
(
PcmConvert
&
convert
,
size_t
in_frame_size
,
try
{
FileDescriptor
in_fd
,
FileDescriptor
out_fd
)
const
auto
c
=
ParseCommandLine
(
argc
,
argv
);
{
in_fd
.
SetBinaryMode
();
SetLogThreshold
(
c
.
verbose
?
LogLevel
::
DEBUG
:
LogLevel
::
INFO
);
out_fd
.
SetBinaryMode
();
const
GlobalInit
init
(
c
.
config_path
);
const
size_t
in_frame_size
=
c
.
in_audio_format
.
GetFrameSize
();
PcmConvert
state
(
c
.
in_audio_format
,
c
.
out_audio_format
);
StaticFifoBuffer
<
uint8_t
,
4096
>
buffer
;
StaticFifoBuffer
<
std
::
byte
,
4096
>
buffer
;
while
(
true
)
{
while
(
true
)
{
{
{
const
auto
dest
=
buffer
.
Write
();
const
auto
dest
=
buffer
.
Write
();
assert
(
!
dest
.
empty
());
assert
(
!
dest
.
empty
());
ssize_t
nbytes
=
read
(
0
,
dest
.
data
,
dest
.
size
);
ssize_t
nbytes
=
in_fd
.
Read
(
dest
.
data
,
dest
.
size
);
if
(
nbytes
<=
0
)
if
(
nbytes
<=
0
)
break
;
break
;
...
@@ -136,20 +132,31 @@ try {
...
@@ -136,20 +132,31 @@ try {
buffer
.
Consume
(
src
.
size
);
buffer
.
Consume
(
src
.
size
);
auto
output
=
state
.
Convert
({
src
.
data
,
src
.
size
});
auto
output
=
convert
.
Convert
({
src
.
data
,
src
.
size
});
out_fd
.
FullWrite
(
output
.
data
,
output
.
size
);
[[
maybe_unused
]]
ssize_t
ignored
=
write
(
1
,
output
.
data
,
output
.
size
);
}
}
while
(
true
)
{
while
(
true
)
{
auto
output
=
state
.
Flush
();
auto
output
=
convert
.
Flush
();
if
(
output
.
IsNull
())
if
(
output
.
IsNull
())
break
;
break
;
[[
maybe_unused
]]
ssize_t
ignored
=
write
(
1
,
output
.
data
,
out_fd
.
FullWrite
(
output
.
data
,
output
.
size
);
output
.
size
);
}
}
}
int
main
(
int
argc
,
char
**
argv
)
try
{
const
auto
c
=
ParseCommandLine
(
argc
,
argv
);
SetLogThreshold
(
c
.
verbose
?
LogLevel
::
DEBUG
:
LogLevel
::
INFO
);
const
GlobalInit
init
(
c
.
config_path
);
PcmConvert
state
(
c
.
in_audio_format
,
c
.
out_audio_format
);
RunConvert
(
state
,
c
.
in_audio_format
.
GetFrameSize
(),
FileDescriptor
(
STDIN_FILENO
),
FileDescriptor
(
STDOUT_FILENO
));
return
EXIT_SUCCESS
;
return
EXIT_SUCCESS
;
}
catch
(...)
{
}
catch
(...)
{
...
...
test/run_input.cxx
View file @
25354b9d
...
@@ -164,6 +164,8 @@ static int
...
@@ -164,6 +164,8 @@ static int
dump_input_stream
(
InputStream
&
is
,
FileDescriptor
out
,
dump_input_stream
(
InputStream
&
is
,
FileDescriptor
out
,
offset_type
seek
,
size_t
chunk_size
)
offset_type
seek
,
size_t
chunk_size
)
{
{
out
.
SetBinaryMode
();
std
::
unique_lock
<
Mutex
>
lock
(
is
.
mutex
);
std
::
unique_lock
<
Mutex
>
lock
(
is
.
mutex
);
if
(
seek
>
0
)
if
(
seek
>
0
)
...
...
test/run_output.cxx
View file @
25354b9d
...
@@ -31,6 +31,7 @@
...
@@ -31,6 +31,7 @@
#include "util/StringBuffer.hxx"
#include "util/StringBuffer.hxx"
#include "util/RuntimeError.hxx"
#include "util/RuntimeError.hxx"
#include "util/ScopeExit.hxx"
#include "util/ScopeExit.hxx"
#include "util/StaticFifoBuffer.hxx"
#include "util/PrintException.hxx"
#include "util/PrintException.hxx"
#include "LogBackend.hxx"
#include "LogBackend.hxx"
...
@@ -113,8 +114,11 @@ LoadAudioOutput(const ConfigData &config, EventLoop &event_loop,
...
@@ -113,8 +114,11 @@ LoadAudioOutput(const ConfigData &config, EventLoop &event_loop,
}
}
static
void
static
void
run_output
(
AudioOutput
&
ao
,
AudioFormat
audio_format
)
RunOutput
(
AudioOutput
&
ao
,
AudioFormat
audio_format
,
FileDescriptor
in_fd
)
{
{
in_fd
.
SetBinaryMode
();
/* open the audio output */
/* open the audio output */
ao
.
Enable
();
ao
.
Enable
();
...
@@ -126,33 +130,40 @@ run_output(AudioOutput &ao, AudioFormat audio_format)
...
@@ -126,33 +130,40 @@ run_output(AudioOutput &ao, AudioFormat audio_format)
fprintf
(
stderr
,
"audio_format=%s
\n
"
,
fprintf
(
stderr
,
"audio_format=%s
\n
"
,
ToString
(
audio_format
).
c_str
());
ToString
(
audio_format
).
c_str
());
size_t
frame_size
=
audio_format
.
GetFrameSize
();
const
size_t
in_
frame_size
=
audio_format
.
GetFrameSize
();
/* play */
/* play */
size_t
length
=
0
;
StaticFifoBuffer
<
std
::
byte
,
4096
>
buffer
;
char
buffer
[
4096
];
while
(
true
)
{
while
(
true
)
{
if
(
length
<
sizeof
(
buffer
))
{
{
ssize_t
nbytes
=
read
(
0
,
buffer
+
length
,
const
auto
dest
=
buffer
.
Write
();
sizeof
(
buffer
)
-
length
);
assert
(
!
dest
.
empty
());
ssize_t
nbytes
=
in_fd
.
Read
(
dest
.
data
,
dest
.
size
);
if
(
nbytes
<=
0
)
if
(
nbytes
<=
0
)
break
;
break
;
length
+=
(
size_t
)
nbytes
;
buffer
.
Append
(
nbytes
)
;
}
}
size_t
play_length
=
(
length
/
frame_size
)
*
frame_size
;
auto
src
=
buffer
.
Read
();
if
(
play_length
>
0
)
{
assert
(
!
src
.
empty
());
size_t
consumed
=
ao
.
Play
(
buffer
,
play_length
);
assert
(
consumed
<=
length
);
src
.
size
-=
src
.
size
%
in_frame_size
;
assert
(
consumed
%
frame_size
==
0
);
if
(
src
.
empty
())
continue
;
length
-=
consumed
;
size_t
consumed
=
ao
.
Play
(
src
.
data
,
src
.
size
);
memmove
(
buffer
,
buffer
+
consumed
,
length
);
}
assert
(
consumed
<=
src
.
size
);
assert
(
consumed
%
in_frame_size
==
0
);
buffer
.
Consume
(
consumed
);
}
}
ao
.
Drain
();
}
}
int
main
(
int
argc
,
char
**
argv
)
int
main
(
int
argc
,
char
**
argv
)
...
@@ -174,7 +185,7 @@ try {
...
@@ -174,7 +185,7 @@ try {
/* do it */
/* do it */
run_output
(
*
ao
,
c
.
audio_format
);
RunOutput
(
*
ao
,
c
.
audio_format
,
FileDescriptor
(
STDIN_FILENO
)
);
/* cleanup and exit */
/* cleanup and exit */
...
...
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