Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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
wine
wine-winehq
Commits
d7eb9090
Commit
d7eb9090
authored
Oct 29, 2015
by
Maarten Lankhorst
Committed by
Alexandre Julliard
Nov 03, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winepulse: Add IAudioRenderClient and IAudioCaptureClient.
Signed-off-by:
Andrew Eikum
<
aeikum@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
6f632aff
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
301 additions
and
0 deletions
+301
-0
mmdevdrv.c
dlls/winepulse.drv/mmdevdrv.c
+301
-0
No files found.
dlls/winepulse.drv/mmdevdrv.c
View file @
d7eb9090
...
@@ -126,6 +126,8 @@ typedef struct _ACPacket {
...
@@ -126,6 +126,8 @@ typedef struct _ACPacket {
struct
ACImpl
{
struct
ACImpl
{
IAudioClient
IAudioClient_iface
;
IAudioClient
IAudioClient_iface
;
IAudioRenderClient
IAudioRenderClient_iface
;
IAudioCaptureClient
IAudioCaptureClient_iface
;
IMMDevice
*
parent
;
IMMDevice
*
parent
;
struct
list
entry
;
struct
list
entry
;
float
vol
[
PA_CHANNELS_MAX
];
float
vol
[
PA_CHANNELS_MAX
];
...
@@ -152,12 +154,24 @@ struct ACImpl {
...
@@ -152,12 +154,24 @@ struct ACImpl {
static
const
WCHAR
defaultW
[]
=
{
'P'
,
'u'
,
'l'
,
's'
,
'e'
,
'a'
,
'u'
,
'd'
,
'i'
,
'o'
,
0
};
static
const
WCHAR
defaultW
[]
=
{
'P'
,
'u'
,
'l'
,
's'
,
'e'
,
'a'
,
'u'
,
'd'
,
'i'
,
'o'
,
0
};
static
const
IAudioClientVtbl
AudioClient_Vtbl
;
static
const
IAudioClientVtbl
AudioClient_Vtbl
;
static
const
IAudioRenderClientVtbl
AudioRenderClient_Vtbl
;
static
const
IAudioCaptureClientVtbl
AudioCaptureClient_Vtbl
;
static
inline
ACImpl
*
impl_from_IAudioClient
(
IAudioClient
*
iface
)
static
inline
ACImpl
*
impl_from_IAudioClient
(
IAudioClient
*
iface
)
{
{
return
CONTAINING_RECORD
(
iface
,
ACImpl
,
IAudioClient_iface
);
return
CONTAINING_RECORD
(
iface
,
ACImpl
,
IAudioClient_iface
);
}
}
static
inline
ACImpl
*
impl_from_IAudioRenderClient
(
IAudioRenderClient
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
ACImpl
,
IAudioRenderClient_iface
);
}
static
inline
ACImpl
*
impl_from_IAudioCaptureClient
(
IAudioCaptureClient
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
ACImpl
,
IAudioCaptureClient_iface
);
}
/* Following pulseaudio design here, mainloop has the lock taken whenever
/* Following pulseaudio design here, mainloop has the lock taken whenever
* it is handling something for pulse, and the lock is required whenever
* it is handling something for pulse, and the lock is required whenever
* doing any pa_* call that can affect the state in any way
* doing any pa_* call that can affect the state in any way
...
@@ -767,6 +781,8 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
...
@@ -767,6 +781,8 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient
return
E_OUTOFMEMORY
;
return
E_OUTOFMEMORY
;
This
->
IAudioClient_iface
.
lpVtbl
=
&
AudioClient_Vtbl
;
This
->
IAudioClient_iface
.
lpVtbl
=
&
AudioClient_Vtbl
;
This
->
IAudioRenderClient_iface
.
lpVtbl
=
&
AudioRenderClient_Vtbl
;
This
->
IAudioCaptureClient_iface
.
lpVtbl
=
&
AudioCaptureClient_Vtbl
;
This
->
dataflow
=
dataflow
;
This
->
dataflow
=
dataflow
;
This
->
parent
=
dev
;
This
->
parent
=
dev
;
for
(
i
=
0
;
i
<
PA_CHANNELS_MAX
;
++
i
)
for
(
i
=
0
;
i
<
PA_CHANNELS_MAX
;
++
i
)
...
@@ -1557,6 +1573,16 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid,
...
@@ -1557,6 +1573,16 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid,
if
(
FAILED
(
hr
))
if
(
FAILED
(
hr
))
return
hr
;
return
hr
;
if
(
IsEqualIID
(
riid
,
&
IID_IAudioRenderClient
))
{
if
(
This
->
dataflow
!=
eRender
)
return
AUDCLNT_E_WRONG_ENDPOINT_TYPE
;
*
ppv
=
&
This
->
IAudioRenderClient_iface
;
}
else
if
(
IsEqualIID
(
riid
,
&
IID_IAudioCaptureClient
))
{
if
(
This
->
dataflow
!=
eCapture
)
return
AUDCLNT_E_WRONG_ENDPOINT_TYPE
;
*
ppv
=
&
This
->
IAudioCaptureClient_iface
;
}
if
(
*
ppv
)
{
if
(
*
ppv
)
{
IUnknown_AddRef
((
IUnknown
*
)
*
ppv
);
IUnknown_AddRef
((
IUnknown
*
)
*
ppv
);
return
S_OK
;
return
S_OK
;
...
@@ -1585,6 +1611,281 @@ static const IAudioClientVtbl AudioClient_Vtbl =
...
@@ -1585,6 +1611,281 @@ static const IAudioClientVtbl AudioClient_Vtbl =
AudioClient_GetService
AudioClient_GetService
};
};
static
HRESULT
WINAPI
AudioRenderClient_QueryInterface
(
IAudioRenderClient
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
TRACE
(
"(%p)->(%s, %p)
\n
"
,
iface
,
debugstr_guid
(
riid
),
ppv
);
if
(
!
ppv
)
return
E_POINTER
;
*
ppv
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
)
||
IsEqualIID
(
riid
,
&
IID_IAudioRenderClient
))
*
ppv
=
iface
;
if
(
*
ppv
)
{
IUnknown_AddRef
((
IUnknown
*
)
*
ppv
);
return
S_OK
;
}
WARN
(
"Unknown interface %s
\n
"
,
debugstr_guid
(
riid
));
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
AudioRenderClient_AddRef
(
IAudioRenderClient
*
iface
)
{
ACImpl
*
This
=
impl_from_IAudioRenderClient
(
iface
);
return
AudioClient_AddRef
(
&
This
->
IAudioClient_iface
);
}
static
ULONG
WINAPI
AudioRenderClient_Release
(
IAudioRenderClient
*
iface
)
{
ACImpl
*
This
=
impl_from_IAudioRenderClient
(
iface
);
return
AudioClient_Release
(
&
This
->
IAudioClient_iface
);
}
static
HRESULT
WINAPI
AudioRenderClient_GetBuffer
(
IAudioRenderClient
*
iface
,
UINT32
frames
,
BYTE
**
data
)
{
ACImpl
*
This
=
impl_from_IAudioRenderClient
(
iface
);
size_t
avail
,
req
,
bytes
=
frames
*
pa_frame_size
(
&
This
->
ss
);
UINT32
pad
;
HRESULT
hr
=
S_OK
;
int
ret
=
-
1
;
TRACE
(
"(%p)->(%u, %p)
\n
"
,
This
,
frames
,
data
);
if
(
!
data
)
return
E_POINTER
;
*
data
=
NULL
;
pthread_mutex_lock
(
&
pulse_lock
);
hr
=
pulse_stream_valid
(
This
);
if
(
FAILED
(
hr
)
||
This
->
locked
)
{
pthread_mutex_unlock
(
&
pulse_lock
);
return
FAILED
(
hr
)
?
hr
:
AUDCLNT_E_OUT_OF_ORDER
;
}
if
(
!
frames
)
{
pthread_mutex_unlock
(
&
pulse_lock
);
return
S_OK
;
}
ACImpl_GetRenderPad
(
This
,
&
pad
);
avail
=
This
->
bufsize_frames
-
pad
;
if
(
avail
<
frames
||
bytes
>
This
->
bufsize_bytes
)
{
pthread_mutex_unlock
(
&
pulse_lock
);
WARN
(
"Wanted to write %u, but only %zu available
\n
"
,
frames
,
avail
);
return
AUDCLNT_E_BUFFER_TOO_LARGE
;
}
This
->
locked
=
frames
;
req
=
bytes
;
ret
=
pa_stream_begin_write
(
This
->
stream
,
&
This
->
locked_ptr
,
&
req
);
if
(
ret
<
0
||
req
<
bytes
)
{
FIXME
(
"%p Not using pulse locked data: %i %zu/%u %u/%u
\n
"
,
This
,
ret
,
req
/
pa_frame_size
(
&
This
->
ss
),
frames
,
pad
,
This
->
bufsize_frames
);
if
(
ret
>=
0
)
pa_stream_cancel_write
(
This
->
stream
);
*
data
=
This
->
tmp_buffer
;
This
->
locked_ptr
=
NULL
;
}
else
*
data
=
This
->
locked_ptr
;
pthread_mutex_unlock
(
&
pulse_lock
);
return
hr
;
}
static
void
pulse_free_noop
(
void
*
buf
)
{
}
static
HRESULT
WINAPI
AudioRenderClient_ReleaseBuffer
(
IAudioRenderClient
*
iface
,
UINT32
written_frames
,
DWORD
flags
)
{
ACImpl
*
This
=
impl_from_IAudioRenderClient
(
iface
);
UINT32
written_bytes
=
written_frames
*
pa_frame_size
(
&
This
->
ss
);
TRACE
(
"(%p)->(%u, %x)
\n
"
,
This
,
written_frames
,
flags
);
pthread_mutex_lock
(
&
pulse_lock
);
if
(
!
This
->
locked
||
!
written_frames
)
{
if
(
This
->
locked_ptr
)
pa_stream_cancel_write
(
This
->
stream
);
This
->
locked
=
0
;
This
->
locked_ptr
=
NULL
;
pthread_mutex_unlock
(
&
pulse_lock
);
return
written_frames
?
AUDCLNT_E_OUT_OF_ORDER
:
S_OK
;
}
if
(
This
->
locked
<
written_frames
)
{
pthread_mutex_unlock
(
&
pulse_lock
);
return
AUDCLNT_E_INVALID_SIZE
;
}
if
(
flags
&
AUDCLNT_BUFFERFLAGS_SILENT
)
{
if
(
This
->
ss
.
format
==
PA_SAMPLE_U8
)
memset
(
This
->
tmp_buffer
,
128
,
written_bytes
);
else
memset
(
This
->
tmp_buffer
,
0
,
written_bytes
);
}
This
->
locked
=
0
;
if
(
This
->
locked_ptr
)
pa_stream_write
(
This
->
stream
,
This
->
locked_ptr
,
written_bytes
,
NULL
,
0
,
PA_SEEK_RELATIVE
);
else
pa_stream_write
(
This
->
stream
,
This
->
tmp_buffer
,
written_bytes
,
pulse_free_noop
,
0
,
PA_SEEK_RELATIVE
);
This
->
pad
+=
written_bytes
;
This
->
locked_ptr
=
NULL
;
TRACE
(
"Released %u, pad %zu
\n
"
,
written_frames
,
This
->
pad
/
pa_frame_size
(
&
This
->
ss
));
assert
(
This
->
pad
<=
This
->
bufsize_bytes
);
pthread_mutex_unlock
(
&
pulse_lock
);
return
S_OK
;
}
static
const
IAudioRenderClientVtbl
AudioRenderClient_Vtbl
=
{
AudioRenderClient_QueryInterface
,
AudioRenderClient_AddRef
,
AudioRenderClient_Release
,
AudioRenderClient_GetBuffer
,
AudioRenderClient_ReleaseBuffer
};
static
HRESULT
WINAPI
AudioCaptureClient_QueryInterface
(
IAudioCaptureClient
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
TRACE
(
"(%p)->(%s, %p)
\n
"
,
iface
,
debugstr_guid
(
riid
),
ppv
);
if
(
!
ppv
)
return
E_POINTER
;
*
ppv
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
)
||
IsEqualIID
(
riid
,
&
IID_IAudioCaptureClient
))
*
ppv
=
iface
;
if
(
*
ppv
)
{
IUnknown_AddRef
((
IUnknown
*
)
*
ppv
);
return
S_OK
;
}
WARN
(
"Unknown interface %s
\n
"
,
debugstr_guid
(
riid
));
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
AudioCaptureClient_AddRef
(
IAudioCaptureClient
*
iface
)
{
ACImpl
*
This
=
impl_from_IAudioCaptureClient
(
iface
);
return
IAudioClient_AddRef
(
&
This
->
IAudioClient_iface
);
}
static
ULONG
WINAPI
AudioCaptureClient_Release
(
IAudioCaptureClient
*
iface
)
{
ACImpl
*
This
=
impl_from_IAudioCaptureClient
(
iface
);
return
IAudioClient_Release
(
&
This
->
IAudioClient_iface
);
}
static
HRESULT
WINAPI
AudioCaptureClient_GetBuffer
(
IAudioCaptureClient
*
iface
,
BYTE
**
data
,
UINT32
*
frames
,
DWORD
*
flags
,
UINT64
*
devpos
,
UINT64
*
qpcpos
)
{
ACImpl
*
This
=
impl_from_IAudioCaptureClient
(
iface
);
HRESULT
hr
;
ACPacket
*
packet
;
TRACE
(
"(%p)->(%p, %p, %p, %p, %p)
\n
"
,
This
,
data
,
frames
,
flags
,
devpos
,
qpcpos
);
if
(
!
data
||
!
frames
||
!
flags
)
return
E_POINTER
;
pthread_mutex_lock
(
&
pulse_lock
);
hr
=
pulse_stream_valid
(
This
);
if
(
FAILED
(
hr
)
||
This
->
locked
)
{
pthread_mutex_unlock
(
&
pulse_lock
);
return
FAILED
(
hr
)
?
hr
:
AUDCLNT_E_OUT_OF_ORDER
;
}
ACImpl_GetCapturePad
(
This
,
NULL
);
if
((
packet
=
This
->
locked_ptr
))
{
*
frames
=
This
->
capture_period
/
pa_frame_size
(
&
This
->
ss
);
*
flags
=
0
;
if
(
packet
->
discont
)
*
flags
|=
AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY
;
if
(
devpos
)
{
if
(
packet
->
discont
)
*
devpos
=
(
This
->
clock_written
+
This
->
capture_period
)
/
pa_frame_size
(
&
This
->
ss
);
else
*
devpos
=
This
->
clock_written
/
pa_frame_size
(
&
This
->
ss
);
}
if
(
qpcpos
)
*
qpcpos
=
packet
->
qpcpos
;
*
data
=
packet
->
data
;
}
else
*
frames
=
0
;
This
->
locked
=
*
frames
;
pthread_mutex_unlock
(
&
pulse_lock
);
return
*
frames
?
S_OK
:
AUDCLNT_S_BUFFER_EMPTY
;
}
static
HRESULT
WINAPI
AudioCaptureClient_ReleaseBuffer
(
IAudioCaptureClient
*
iface
,
UINT32
done
)
{
ACImpl
*
This
=
impl_from_IAudioCaptureClient
(
iface
);
TRACE
(
"(%p)->(%u)
\n
"
,
This
,
done
);
pthread_mutex_lock
(
&
pulse_lock
);
if
(
!
This
->
locked
&&
done
)
{
pthread_mutex_unlock
(
&
pulse_lock
);
return
AUDCLNT_E_OUT_OF_ORDER
;
}
if
(
done
&&
This
->
locked
!=
done
)
{
pthread_mutex_unlock
(
&
pulse_lock
);
return
AUDCLNT_E_INVALID_SIZE
;
}
if
(
done
)
{
ACPacket
*
packet
=
This
->
locked_ptr
;
This
->
locked_ptr
=
NULL
;
This
->
pad
-=
This
->
capture_period
;
if
(
packet
->
discont
)
This
->
clock_written
+=
2
*
This
->
capture_period
;
else
This
->
clock_written
+=
This
->
capture_period
;
list_add_tail
(
&
This
->
packet_free_head
,
&
packet
->
entry
);
}
This
->
locked
=
0
;
pthread_mutex_unlock
(
&
pulse_lock
);
return
S_OK
;
}
static
HRESULT
WINAPI
AudioCaptureClient_GetNextPacketSize
(
IAudioCaptureClient
*
iface
,
UINT32
*
frames
)
{
ACImpl
*
This
=
impl_from_IAudioCaptureClient
(
iface
);
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
frames
);
if
(
!
frames
)
return
E_POINTER
;
pthread_mutex_lock
(
&
pulse_lock
);
ACImpl_GetCapturePad
(
This
,
NULL
);
if
(
This
->
locked_ptr
)
*
frames
=
This
->
capture_period
/
pa_frame_size
(
&
This
->
ss
);
else
*
frames
=
0
;
pthread_mutex_unlock
(
&
pulse_lock
);
return
S_OK
;
}
static
const
IAudioCaptureClientVtbl
AudioCaptureClient_Vtbl
=
{
AudioCaptureClient_QueryInterface
,
AudioCaptureClient_AddRef
,
AudioCaptureClient_Release
,
AudioCaptureClient_GetBuffer
,
AudioCaptureClient_ReleaseBuffer
,
AudioCaptureClient_GetNextPacketSize
};
HRESULT
WINAPI
AUDDRV_GetAudioSessionManager
(
IMMDevice
*
device
,
HRESULT
WINAPI
AUDDRV_GetAudioSessionManager
(
IMMDevice
*
device
,
IAudioSessionManager2
**
out
)
IAudioSessionManager2
**
out
)
{
{
...
...
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