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
7b2cdd61
Commit
7b2cdd61
authored
Nov 07, 2016
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
output/winmm: use AudioOutputWrapper
parent
30bb3f1f
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
93 additions
and
90 deletions
+93
-90
WinmmOutputPlugin.cxx
src/output/plugins/WinmmOutputPlugin.cxx
+93
-90
No files found.
src/output/plugins/WinmmOutputPlugin.cxx
View file @
7b2cdd61
...
@@ -20,6 +20,7 @@
...
@@ -20,6 +20,7 @@
#include "config.h"
#include "config.h"
#include "WinmmOutputPlugin.hxx"
#include "WinmmOutputPlugin.hxx"
#include "../OutputAPI.hxx"
#include "../OutputAPI.hxx"
#include "../Wrapper.hxx"
#include "pcm/PcmBuffer.hxx"
#include "pcm/PcmBuffer.hxx"
#include "mixer/MixerList.hxx"
#include "mixer/MixerList.hxx"
#include "fs/AllocatedPath.hxx"
#include "fs/AllocatedPath.hxx"
...
@@ -36,7 +37,9 @@ struct WinmmBuffer {
...
@@ -36,7 +37,9 @@ struct WinmmBuffer {
WAVEHDR
hdr
;
WAVEHDR
hdr
;
};
};
struct
WinmmOutput
{
class
WinmmOutput
{
friend
struct
AudioOutputWrapper
<
WinmmOutput
>
;
AudioOutput
base
;
AudioOutput
base
;
const
UINT
device_id
;
const
UINT
device_id
;
...
@@ -51,7 +54,34 @@ struct WinmmOutput {
...
@@ -51,7 +54,34 @@ struct WinmmOutput {
WinmmBuffer
buffers
[
8
];
WinmmBuffer
buffers
[
8
];
unsigned
next_buffer
;
unsigned
next_buffer
;
public
:
WinmmOutput
(
const
ConfigBlock
&
block
);
WinmmOutput
(
const
ConfigBlock
&
block
);
HWAVEOUT
GetHandle
()
{
return
handle
;
}
static
WinmmOutput
*
Create
(
const
ConfigBlock
&
block
,
Error
&
)
{
return
new
WinmmOutput
(
block
);
}
bool
Open
(
AudioFormat
&
audio_format
,
Error
&
);
void
Close
();
size_t
Play
(
const
void
*
chunk
,
size_t
size
,
Error
&
);
void
Drain
();
void
Cancel
();
private
:
/**
* Wait until the buffer is finished.
*/
void
DrainBuffer
(
WinmmBuffer
&
buffer
);
void
DrainAllBuffers
();
void
Stop
();
};
};
static
std
::
runtime_error
static
std
::
runtime_error
...
@@ -68,7 +98,7 @@ MakeWaveOutError(MMRESULT result, const char *prefix)
...
@@ -68,7 +98,7 @@ MakeWaveOutError(MMRESULT result, const char *prefix)
HWAVEOUT
HWAVEOUT
winmm_output_get_handle
(
WinmmOutput
&
output
)
winmm_output_get_handle
(
WinmmOutput
&
output
)
{
{
return
output
.
handle
;
return
output
.
GetHandle
()
;
}
}
static
bool
static
bool
...
@@ -121,27 +151,11 @@ WinmmOutput::WinmmOutput(const ConfigBlock &block)
...
@@ -121,27 +151,11 @@ WinmmOutput::WinmmOutput(const ConfigBlock &block)
{
{
}
}
static
AudioOutput
*
bool
winmm_output_init
(
const
ConfigBlock
&
block
,
Error
&
)
WinmmOutput
::
Open
(
AudioFormat
&
audio_format
,
Error
&
)
{
{
return
&
(
new
WinmmOutput
(
block
))
->
base
;
event
=
CreateEvent
(
nullptr
,
false
,
false
,
nullptr
);
}
if
(
event
==
nullptr
)
static
void
winmm_output_finish
(
AudioOutput
*
ao
)
{
WinmmOutput
*
wo
=
(
WinmmOutput
*
)
ao
;
delete
wo
;
}
static
bool
winmm_output_open
(
AudioOutput
*
ao
,
AudioFormat
&
audio_format
,
Error
&
)
{
WinmmOutput
*
wo
=
(
WinmmOutput
*
)
ao
;
wo
->
event
=
CreateEvent
(
nullptr
,
false
,
false
,
nullptr
);
if
(
wo
->
event
==
nullptr
)
throw
std
::
runtime_error
(
"CreateEvent() failed"
);
throw
std
::
runtime_error
(
"CreateEvent() failed"
);
switch
(
audio_format
.
format
)
{
switch
(
audio_format
.
format
)
{
...
@@ -172,40 +186,37 @@ winmm_output_open(AudioOutput *ao, AudioFormat &audio_format, Error &)
...
@@ -172,40 +186,37 @@ winmm_output_open(AudioOutput *ao, AudioFormat &audio_format, Error &)
format
.
wBitsPerSample
=
audio_format
.
GetSampleSize
()
*
8
;
format
.
wBitsPerSample
=
audio_format
.
GetSampleSize
()
*
8
;
format
.
cbSize
=
0
;
format
.
cbSize
=
0
;
MMRESULT
result
=
waveOutOpen
(
&
wo
->
handle
,
wo
->
device_id
,
&
format
,
MMRESULT
result
=
waveOutOpen
(
&
handle
,
device_id
,
&
format
,
(
DWORD_PTR
)
wo
->
event
,
0
,
CALLBACK_EVENT
);
(
DWORD_PTR
)
event
,
0
,
CALLBACK_EVENT
);
if
(
result
!=
MMSYSERR_NOERROR
)
{
if
(
result
!=
MMSYSERR_NOERROR
)
{
CloseHandle
(
wo
->
event
);
CloseHandle
(
event
);
throw
MakeWaveOutError
(
result
,
"waveOutOpen() failed"
);
throw
MakeWaveOutError
(
result
,
"waveOutOpen() failed"
);
}
}
for
(
unsigned
i
=
0
;
i
<
ARRAY_SIZE
(
wo
->
buffers
);
++
i
)
{
for
(
unsigned
i
=
0
;
i
<
ARRAY_SIZE
(
buffers
);
++
i
)
memset
(
&
wo
->
buffers
[
i
].
hdr
,
0
,
sizeof
(
wo
->
buffers
[
i
].
hdr
));
memset
(
&
buffers
[
i
].
hdr
,
0
,
sizeof
(
buffers
[
i
].
hdr
));
}
wo
->
next_buffer
=
0
;
next_buffer
=
0
;
return
true
;
return
true
;
}
}
static
void
void
winmm_output_close
(
AudioOutput
*
ao
)
WinmmOutput
::
Close
(
)
{
{
WinmmOutput
*
wo
=
(
WinmmOutput
*
)
ao
;
for
(
unsigned
i
=
0
;
i
<
ARRAY_SIZE
(
buffers
);
++
i
)
buffers
[
i
].
buffer
.
Clear
();
for
(
unsigned
i
=
0
;
i
<
ARRAY_SIZE
(
wo
->
buffers
);
++
i
)
wo
->
buffers
[
i
].
buffer
.
Clear
();
waveOutClose
(
wo
->
handle
);
waveOutClose
(
handle
);
CloseHandle
(
wo
->
event
);
CloseHandle
(
event
);
}
}
/**
/**
* Copy data into a buffer, and prepare the wave header.
* Copy data into a buffer, and prepare the wave header.
*/
*/
static
void
static
void
winmm_set_buffer
(
WinmmOutput
*
wo
,
WinmmBuffer
*
buffer
,
winmm_set_buffer
(
HWAVEOUT
handle
,
WinmmBuffer
*
buffer
,
const
void
*
data
,
size_t
size
)
const
void
*
data
,
size_t
size
)
{
{
void
*
dest
=
buffer
->
buffer
.
Get
(
size
);
void
*
dest
=
buffer
->
buffer
.
Get
(
size
);
...
@@ -217,27 +228,24 @@ winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
...
@@ -217,27 +228,24 @@ winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
buffer
->
hdr
.
lpData
=
(
LPSTR
)
dest
;
buffer
->
hdr
.
lpData
=
(
LPSTR
)
dest
;
buffer
->
hdr
.
dwBufferLength
=
size
;
buffer
->
hdr
.
dwBufferLength
=
size
;
MMRESULT
result
=
waveOutPrepareHeader
(
wo
->
handle
,
&
buffer
->
hdr
,
MMRESULT
result
=
waveOutPrepareHeader
(
handle
,
&
buffer
->
hdr
,
sizeof
(
buffer
->
hdr
));
sizeof
(
buffer
->
hdr
));
if
(
result
!=
MMSYSERR_NOERROR
)
if
(
result
!=
MMSYSERR_NOERROR
)
throw
MakeWaveOutError
(
result
,
throw
MakeWaveOutError
(
result
,
"waveOutPrepareHeader() failed"
);
"waveOutPrepareHeader() failed"
);
}
}
/**
void
* Wait until the buffer is finished.
WinmmOutput
::
DrainBuffer
(
WinmmBuffer
&
buffer
)
*/
static
void
winmm_drain_buffer
(
WinmmOutput
*
wo
,
WinmmBuffer
*
buffer
)
{
{
if
((
buffer
->
hdr
.
dwFlags
&
WHDR_DONE
)
==
WHDR_DONE
)
if
((
buffer
.
hdr
.
dwFlags
&
WHDR_DONE
)
==
WHDR_DONE
)
/* already finished */
/* already finished */
return
;
return
;
while
(
true
)
{
while
(
true
)
{
MMRESULT
result
=
waveOutUnprepareHeader
(
wo
->
handle
,
MMRESULT
result
=
waveOutUnprepareHeader
(
handle
,
&
buffer
->
hdr
,
&
buffer
.
hdr
,
sizeof
(
buffer
->
hdr
));
sizeof
(
buffer
.
hdr
));
if
(
result
==
MMSYSERR_NOERROR
)
if
(
result
==
MMSYSERR_NOERROR
)
return
;
return
;
else
if
(
result
!=
WAVERR_STILLPLAYING
)
else
if
(
result
!=
WAVERR_STILLPLAYING
)
...
@@ -245,93 +253,88 @@ winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer)
...
@@ -245,93 +253,88 @@ winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer)
"waveOutUnprepareHeader() failed"
);
"waveOutUnprepareHeader() failed"
);
/* wait some more */
/* wait some more */
WaitForSingleObject
(
wo
->
event
,
INFINITE
);
WaitForSingleObject
(
event
,
INFINITE
);
}
}
}
}
s
tatic
s
ize_t
size_t
winmm_output_play
(
AudioOutput
*
ao
,
const
void
*
chunk
,
size_t
size
,
Error
&
)
WinmmOutput
::
Play
(
const
void
*
chunk
,
size_t
size
,
Error
&
)
{
{
WinmmOutput
*
wo
=
(
WinmmOutput
*
)
ao
;
/* get the next buffer from the ring and prepare it */
/* get the next buffer from the ring and prepare it */
WinmmBuffer
*
buffer
=
&
wo
->
buffers
[
wo
->
next_buffer
];
WinmmBuffer
*
buffer
=
&
buffers
[
next_buffer
];
winmm_drain_buffer
(
wo
,
buffer
);
DrainBuffer
(
*
buffer
);
winmm_set_buffer
(
wo
,
buffer
,
chunk
,
size
);
winmm_set_buffer
(
handle
,
buffer
,
chunk
,
size
);
/* enqueue the buffer */
/* enqueue the buffer */
MMRESULT
result
=
waveOutWrite
(
wo
->
handle
,
&
buffer
->
hdr
,
MMRESULT
result
=
waveOutWrite
(
handle
,
&
buffer
->
hdr
,
sizeof
(
buffer
->
hdr
));
sizeof
(
buffer
->
hdr
));
if
(
result
!=
MMSYSERR_NOERROR
)
{
if
(
result
!=
MMSYSERR_NOERROR
)
{
waveOutUnprepareHeader
(
wo
->
handle
,
&
buffer
->
hdr
,
waveOutUnprepareHeader
(
handle
,
&
buffer
->
hdr
,
sizeof
(
buffer
->
hdr
));
sizeof
(
buffer
->
hdr
));
throw
MakeWaveOutError
(
result
,
"waveOutWrite() failed"
);
throw
MakeWaveOutError
(
result
,
"waveOutWrite() failed"
);
}
}
/* mark our buffer as "used" */
/* mark our buffer as "used" */
wo
->
next_buffer
=
(
wo
->
next_buffer
+
1
)
%
next_buffer
=
(
next_buffer
+
1
)
%
ARRAY_SIZE
(
buffers
);
ARRAY_SIZE
(
wo
->
buffers
);
return
size
;
return
size
;
}
}
static
void
void
winmm_drain_all_buffers
(
WinmmOutput
*
wo
)
WinmmOutput
::
DrainAllBuffers
(
)
{
{
for
(
unsigned
i
=
wo
->
next_buffer
;
i
<
ARRAY_SIZE
(
wo
->
buffers
);
++
i
)
for
(
unsigned
i
=
next_buffer
;
i
<
ARRAY_SIZE
(
buffers
);
++
i
)
winmm_drain_buffer
(
wo
,
&
wo
->
buffers
[
i
]);
DrainBuffer
(
buffers
[
i
]);
for
(
unsigned
i
=
0
;
i
<
wo
->
next_buffer
;
++
i
)
for
(
unsigned
i
=
0
;
i
<
next_buffer
;
++
i
)
winmm_drain_buffer
(
wo
,
&
wo
->
buffers
[
i
]);
DrainBuffer
(
buffers
[
i
]);
}
}
static
void
void
winmm_stop
(
WinmmOutput
*
wo
)
WinmmOutput
::
Stop
(
)
{
{
waveOutReset
(
wo
->
handle
);
waveOutReset
(
handle
);
for
(
unsigned
i
=
0
;
i
<
ARRAY_SIZE
(
wo
->
buffers
);
++
i
)
{
for
(
unsigned
i
=
0
;
i
<
ARRAY_SIZE
(
buffers
);
++
i
)
{
WinmmBuffer
*
buffer
=
&
wo
->
buffers
[
i
];
WinmmBuffer
*
buffer
=
&
buffers
[
i
];
waveOutUnprepareHeader
(
wo
->
handle
,
&
buffer
->
hdr
,
waveOutUnprepareHeader
(
handle
,
&
buffer
->
hdr
,
sizeof
(
buffer
->
hdr
));
sizeof
(
buffer
->
hdr
));
}
}
}
}
static
void
void
winmm_output_drain
(
AudioOutput
*
ao
)
WinmmOutput
::
Drain
(
)
{
{
WinmmOutput
*
wo
=
(
WinmmOutput
*
)
ao
;
try
{
try
{
winmm_drain_all_buffers
(
wo
);
DrainAllBuffers
(
);
}
catch
(...)
{
}
catch
(...)
{
winmm_stop
(
wo
);
Stop
(
);
throw
;
throw
;
}
}
}
}
static
void
void
winmm_output_cancel
(
AudioOutput
*
ao
)
WinmmOutput
::
Cancel
(
)
{
{
WinmmOutput
*
wo
=
(
WinmmOutput
*
)
ao
;
Stop
();
winmm_stop
(
wo
);
}
}
typedef
AudioOutputWrapper
<
WinmmOutput
>
Wrapper
;
const
struct
AudioOutputPlugin
winmm_output_plugin
=
{
const
struct
AudioOutputPlugin
winmm_output_plugin
=
{
"winmm"
,
"winmm"
,
winmm_output_test_default_device
,
winmm_output_test_default_device
,
winmm_output_i
nit
,
&
Wrapper
::
I
nit
,
winmm_output_f
inish
,
&
Wrapper
::
F
inish
,
nullptr
,
nullptr
,
nullptr
,
nullptr
,
winmm_output_o
pen
,
&
Wrapper
::
O
pen
,
winmm_output_c
lose
,
&
Wrapper
::
C
lose
,
nullptr
,
nullptr
,
nullptr
,
nullptr
,
winmm_output_p
lay
,
&
Wrapper
::
P
lay
,
winmm_output_d
rain
,
&
Wrapper
::
D
rain
,
winmm_output_c
ancel
,
&
Wrapper
::
C
ancel
,
nullptr
,
nullptr
,
&
winmm_mixer_plugin
,
&
winmm_mixer_plugin
,
};
};
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