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
289dfacf
Commit
289dfacf
authored
Jan 17, 2024
by
Yuxuan Shui
Committed by
Alexandre Julliard
Jan 22, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dmime: Parse AudioPathConfig.
parent
a300815c
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
277 additions
and
4 deletions
+277
-4
audiopath.c
dlls/dmime/audiopath.c
+277
-4
No files found.
dlls/dmime/audiopath.c
View file @
289dfacf
...
...
@@ -32,11 +32,31 @@ struct IDirectMusicAudioPathImpl {
BOOL
fActive
;
};
struct
audio_path_pchannel_to_buffer
{
struct
list
entry
;
DMUS_IO_PCHANNELTOBUFFER_HEADER
header
;
GUID
guids
[];
};
C_ASSERT
(
sizeof
(
struct
audio_path_pchannel_to_buffer
)
==
offsetof
(
struct
audio_path_pchannel_to_buffer
,
guids
[
0
]));
struct
audio_path_port_config
{
struct
list
entry
;
DMUS_IO_PORTCONFIG_HEADER
header
;
DMUS_PORTPARAMS8
params
;
struct
list
pchannel_to_buffer_entries
;
};
struct
audio_path_config
{
IUnknown
IUnknown_iface
;
struct
dmobject
dmobj
;
LONG
ref
;
struct
list
port_config_entries
;
};
static
inline
struct
IDirectMusicAudioPathImpl
*
impl_from_IDirectMusicAudioPath
(
IDirectMusicAudioPath
*
iface
)
...
...
@@ -299,15 +319,252 @@ static const IDirectMusicObjectVtbl dmobject_vtbl = {
path_config_IDirectMusicObject_ParseDescriptor
};
static
HRESULT
parse_pchannel_to_buffers_list
(
struct
audio_path_port_config
*
This
,
IStream
*
stream
,
const
struct
chunk_entry
*
pchl
)
{
struct
chunk_entry
chunk
=
{
.
parent
=
pchl
};
struct
audio_path_pchannel_to_buffer
*
pchannel_to_buffer
=
NULL
;
DMUS_IO_PCHANNELTOBUFFER_HEADER
header
;
SIZE_T
bytes
;
ULONG
i
;
HRESULT
hr
;
while
((
hr
=
stream_next_chunk
(
stream
,
&
chunk
))
==
S_OK
)
{
switch
(
chunk
.
id
)
{
case
DMUS_FOURCC_PCHANNELS_ITEM
:
hr
=
stream_read
(
stream
,
&
header
,
sizeof
(
header
));
if
(
FAILED
(
hr
))
break
;
TRACE
(
"Got PChannelToBuffer header:
\n
"
);
TRACE
(
"
\t
dwPChannelCount: %lu
\n
"
,
header
.
dwPChannelCount
);
TRACE
(
"
\t
dwPChannelBase: %lu
\n
"
,
header
.
dwPChannelBase
);
TRACE
(
"
\t
dwBufferCount: %lu
\n
"
,
header
.
dwBufferCount
);
TRACE
(
"
\t
dwFlags: %lx
\n
"
,
header
.
dwFlags
);
bytes
=
chunk
.
size
-
sizeof
(
header
);
if
(
bytes
!=
sizeof
(
GUID
)
*
header
.
dwBufferCount
)
{
WARN
(
"Invalid size of GUIDs array
\n
"
);
hr
=
E_FAIL
;
break
;
}
pchannel_to_buffer
=
calloc
(
1
,
sizeof
(
*
pchannel_to_buffer
)
+
bytes
);
if
(
!
pchannel_to_buffer
)
{
hr
=
E_OUTOFMEMORY
;
break
;
}
pchannel_to_buffer
->
header
=
header
;
TRACE
(
"number of GUIDs: %lu
\n
"
,
pchannel_to_buffer
->
header
.
dwBufferCount
);
hr
=
stream_read
(
stream
,
pchannel_to_buffer
->
guids
,
bytes
);
if
(
FAILED
(
hr
))
break
;
for
(
i
=
0
;
i
<
pchannel_to_buffer
->
header
.
dwBufferCount
;
i
++
)
TRACE
(
"
\t
guids[%lu]: %s
\n
"
,
i
,
debugstr_dmguid
(
&
pchannel_to_buffer
->
guids
[
i
]));
list_add_tail
(
&
This
->
pchannel_to_buffer_entries
,
&
pchannel_to_buffer
->
entry
);
pchannel_to_buffer
=
NULL
;
break
;
case
FOURCC_LIST
:
if
(
chunk
.
type
==
DMUS_FOURCC_UNFO_LIST
)
TRACE
(
"Unfo list in PChannelToBuffer is ignored
\n
"
);
else
WARN
(
"Unknown %s
\n
"
,
debugstr_chunk
(
&
chunk
));
break
;
case
MAKEFOURCC
(
'p'
,
'b'
,
'g'
,
'd'
):
FIXME
(
"Undocumented %s
\n
"
,
debugstr_chunk
(
&
chunk
));
break
;
default:
WARN
(
"Unknown %s
\n
"
,
debugstr_chunk
(
&
chunk
));
break
;
}
if
(
FAILED
(
hr
))
break
;
}
if
(
FAILED
(
hr
)
&&
pchannel_to_buffer
)
free
(
pchannel_to_buffer
);
return
hr
;
}
static
void
port_config_destroy
(
struct
audio_path_port_config
*
port_config
)
{
struct
audio_path_pchannel_to_buffer
*
pchannel_to_buffer
,
*
next_pchannel_to_buffer
;
LIST_FOR_EACH_ENTRY_SAFE
(
pchannel_to_buffer
,
next_pchannel_to_buffer
,
&
port_config
->
pchannel_to_buffer_entries
,
struct
audio_path_pchannel_to_buffer
,
entry
)
{
list_remove
(
&
pchannel_to_buffer
->
entry
);
free
(
pchannel_to_buffer
);
}
free
(
port_config
);
}
static
HRESULT
parse_port_config_list
(
struct
audio_path_config
*
This
,
IStream
*
stream
,
const
struct
chunk_entry
*
pcfl
)
{
struct
chunk_entry
chunk
=
{
.
parent
=
pcfl
};
struct
audio_path_port_config
*
port_config
=
calloc
(
1
,
sizeof
(
*
port_config
));
HRESULT
hr
;
if
(
!
port_config
)
return
E_OUTOFMEMORY
;
list_init
(
&
port_config
->
pchannel_to_buffer_entries
);
while
((
hr
=
stream_next_chunk
(
stream
,
&
chunk
))
==
S_OK
)
{
switch
(
chunk
.
id
)
{
case
DMUS_FOURCC_PORTCONFIG_ITEM
:
hr
=
stream_chunk_get_data
(
stream
,
&
chunk
,
&
port_config
->
header
,
sizeof
(
port_config
->
header
));
if
(
FAILED
(
hr
))
break
;
TRACE
(
"Got PortConfig header:
\n
"
);
TRACE
(
"
\t
dwPChannelBase: %lu
\n
"
,
port_config
->
header
.
dwPChannelBase
);
TRACE
(
"
\t
dwPChannelCount: %lu
\n
"
,
port_config
->
header
.
dwPChannelCount
);
TRACE
(
"
\t
dwFlags: %lx
\n
"
,
port_config
->
header
.
dwFlags
);
TRACE
(
"
\t
guidPort: %s
\n
"
,
debugstr_dmguid
(
&
port_config
->
header
.
guidPort
));
break
;
case
DMUS_FOURCC_PORTPARAMS_ITEM
:
hr
=
stream_chunk_get_data
(
stream
,
&
chunk
,
&
port_config
->
params
,
sizeof
(
port_config
->
params
));
if
(
FAILED
(
hr
))
break
;
TRACE
(
"Got PortConfig params:
\n
"
);
TRACE
(
"
\t
dwSize: %lu
\n
"
,
port_config
->
params
.
dwSize
);
TRACE
(
"
\t
dwValidParams: %lx
\n
"
,
port_config
->
params
.
dwValidParams
);
if
(
port_config
->
params
.
dwValidParams
&
DMUS_PORTPARAMS_VOICES
)
TRACE
(
"
\t
voices: %lu
\n
"
,
port_config
->
params
.
dwVoices
);
if
(
port_config
->
params
.
dwValidParams
&
DMUS_PORTPARAMS_CHANNELGROUPS
)
TRACE
(
"
\t
channel groups: %lu
\n
"
,
port_config
->
params
.
dwChannelGroups
);
if
(
port_config
->
params
.
dwValidParams
&
DMUS_PORTPARAMS_AUDIOCHANNELS
)
TRACE
(
"
\t
audio channels: %lu
\n
"
,
port_config
->
params
.
dwAudioChannels
);
if
(
port_config
->
params
.
dwValidParams
&
DMUS_PORTPARAMS_SAMPLERATE
)
TRACE
(
"
\t
sample rate: %lu
\n
"
,
port_config
->
params
.
dwSampleRate
);
if
(
port_config
->
params
.
dwValidParams
&
DMUS_PORTPARAMS_EFFECTS
)
TRACE
(
"
\t
effects: %lx
\n
"
,
port_config
->
params
.
dwEffectFlags
);
if
(
port_config
->
params
.
dwValidParams
&
DMUS_PORTPARAMS_SHARE
)
TRACE
(
"
\t
share: %d
\n
"
,
port_config
->
params
.
fShare
);
if
(
port_config
->
params
.
dwValidParams
&
DMUS_PORTPARAMS_FEATURES
)
TRACE
(
"
\t
features: %lx
\n
"
,
port_config
->
params
.
dwFeatures
);
break
;
case
FOURCC_LIST
:
if
(
chunk
.
type
==
DMUS_FOURCC_DSBUFFER_LIST
)
FIXME
(
"DirectSound buffer descriptors is not supported
\n
"
);
else
if
(
chunk
.
type
==
DMUS_FOURCC_PCHANNELS_LIST
)
hr
=
parse_pchannel_to_buffers_list
(
port_config
,
stream
,
&
chunk
);
else
if
(
chunk
.
type
==
DMUS_FOURCC_UNFO_LIST
)
TRACE
(
"Unfo list in PortConfig is ignored
\n
"
);
else
WARN
(
"Unknown %s
\n
"
,
debugstr_chunk
(
&
chunk
));
break
;
default:
WARN
(
"Unknown %s
\n
"
,
debugstr_chunk
(
&
chunk
));
}
if
(
FAILED
(
hr
))
break
;
}
if
(
FAILED
(
hr
))
port_config_destroy
(
port_config
);
else
list_add_tail
(
&
This
->
port_config_entries
,
&
port_config
->
entry
);
return
hr
;
}
static
HRESULT
parse_port_configs_list
(
struct
audio_path_config
*
This
,
IStream
*
stream
,
const
struct
chunk_entry
*
pcsl
)
{
struct
chunk_entry
chunk
=
{
.
parent
=
pcsl
};
HRESULT
hr
;
while
((
hr
=
stream_next_chunk
(
stream
,
&
chunk
))
==
S_OK
)
{
switch
(
MAKE_IDTYPE
(
chunk
.
id
,
chunk
.
type
))
{
case
MAKE_IDTYPE
(
FOURCC_LIST
,
DMUS_FOURCC_PORTCONFIG_LIST
):
hr
=
parse_port_config_list
(
This
,
stream
,
&
chunk
);
if
(
FAILED
(
hr
))
return
hr
;
break
;
default:
WARN
(
"Unknown %s
\n
"
,
debugstr_chunk
(
&
chunk
));
break
;
}
}
return
SUCCEEDED
(
hr
)
?
S_OK
:
hr
;
}
/* IPersistStream */
static
HRESULT
WINAPI
path_config_IPersistStream_Load
(
IPersistStream
*
iface
,
IStream
*
stream
)
{
struct
audio_path_config
*
This
=
impl_from_IPersistStream
(
iface
);
struct
chunk_entry
riff
=
{
0
},
chunk
=
{
0
};
HRESULT
hr
=
S_OK
;
FIXME
(
"(%p, %p): Loading
\n
"
,
This
,
stream
);
if
(
!
stream
)
return
E_POINTER
;
hr
=
stream_get_chunk
(
stream
,
&
riff
);
if
(
FAILED
(
hr
))
{
WARN
(
"Failed to get chunk %#lx.
\n
"
,
hr
);
return
hr
;
}
if
(
MAKE_IDTYPE
(
riff
.
id
,
riff
.
type
)
!=
MAKE_IDTYPE
(
FOURCC_RIFF
,
DMUS_FOURCC_AUDIOPATH_FORM
))
{
WARN
(
"loading failed: unexpected %s
\n
"
,
debugstr_chunk
(
&
riff
));
return
E_UNEXPECTED
;
}
FIXME
(
"(%p, %p): Loading not implemented yet
\n
"
,
This
,
stream
);
if
(
FAILED
(
hr
=
dmobj_parsedescriptor
(
stream
,
&
riff
,
&
This
->
dmobj
.
desc
,
DMUS_OBJ_OBJECT
|
DMUS_OBJ_VERSION
|
DMUS_OBJ_NAME
|
DMUS_OBJ_CATEGORY
))
||
FAILED
(
hr
=
stream_reset_chunk_data
(
stream
,
&
riff
)))
{
WARN
(
"Failed to parse descriptor %#lx.
\n
"
,
hr
);
return
hr
;
}
This
->
dmobj
.
desc
.
guidClass
=
CLSID_DirectMusicAudioPathConfig
;
This
->
dmobj
.
desc
.
dwValidData
|=
DMUS_OBJ_CLASS
;
return
IDirectMusicObject_ParseDescriptor
(
&
This
->
dmobj
.
IDirectMusicObject_iface
,
stream
,
&
This
->
dmobj
.
desc
);
chunk
.
parent
=
&
riff
;
while
((
hr
=
stream_next_chunk
(
stream
,
&
chunk
))
==
S_OK
)
{
switch
(
MAKE_IDTYPE
(
chunk
.
id
,
chunk
.
type
))
{
case
MAKE_IDTYPE
(
FOURCC_LIST
,
DMUS_FOURCC_PORTCONFIGS_LIST
):
hr
=
parse_port_configs_list
(
This
,
stream
,
&
chunk
);
if
(
FAILED
(
hr
))
return
hr
;
case
MAKE_IDTYPE
(
FOURCC_LIST
,
DMUS_FOURCC_DSBUFFER_LIST
):
FIXME
(
"buffer attributes are not supported
\n
"
);
break
;
case
MAKE_IDTYPE
(
FOURCC_LIST
,
MAKEFOURCC
(
'p'
,
'a'
,
'p'
,
'd'
)):
FIXME
(
"Undocumented %s
\n
"
,
debugstr_chunk
(
&
chunk
));
break
;
case
MAKE_IDTYPE
(
FOURCC_LIST
,
DMUS_FOURCC_UNFO_LIST
):
WARN
(
"Unknown %s
\n
"
,
debugstr_chunk
(
&
chunk
));
break
;
case
DMUS_FOURCC_GUID_CHUNK
:
case
DMUS_FOURCC_VERSION_CHUNK
:
/* Already parsed in dmobj_parsedescriptor. */
break
;
default:
WARN
(
"Unknown %s
\n
"
,
debugstr_chunk
(
&
chunk
));
break
;
}
}
TRACE
(
"Finished parsing %#lx
\n
"
,
hr
);
return
SUCCEEDED
(
hr
)
?
S_OK
:
hr
;
}
static
const
IPersistStreamVtbl
persiststream_vtbl
=
{
...
...
@@ -354,7 +611,11 @@ static HRESULT WINAPI path_config_IUnknown_QueryInterface(IUnknown *iface, REFII
static
ULONG
WINAPI
path_config_IUnknown_AddRef
(
IUnknown
*
unk
)
{
struct
audio_path_config
*
This
=
impl_from_IUnknown
(
unk
);
return
InterlockedIncrement
(
&
This
->
ref
);
ULONG
ref
=
InterlockedIncrement
(
&
This
->
ref
);
TRACE
(
"(%p): ref=%ld
\n
"
,
This
,
ref
);
return
ref
;
}
static
ULONG
WINAPI
path_config_IUnknown_Release
(
IUnknown
*
unk
)
...
...
@@ -362,8 +623,18 @@ static ULONG WINAPI path_config_IUnknown_Release(IUnknown *unk)
struct
audio_path_config
*
This
=
impl_from_IUnknown
(
unk
);
ULONG
ref
=
InterlockedDecrement
(
&
This
->
ref
);
TRACE
(
"(%p): ref=%ld
\n
"
,
This
,
ref
);
if
(
!
ref
)
{
struct
audio_path_port_config
*
config
,
*
next_config
;
LIST_FOR_EACH_ENTRY_SAFE
(
config
,
next_config
,
&
This
->
port_config_entries
,
struct
audio_path_port_config
,
entry
)
{
list_remove
(
&
config
->
entry
);
port_config_destroy
(
config
);
}
free
(
This
);
}
return
ref
;
}
...
...
@@ -403,6 +674,8 @@ HRESULT create_dmaudiopath_config(REFIID riid, void **ppobj)
obj
->
dmobj
.
IPersistStream_iface
.
lpVtbl
=
&
persiststream_vtbl
;
obj
->
ref
=
1
;
list_init
(
&
obj
->
port_config_entries
);
hr
=
IUnknown_QueryInterface
(
&
obj
->
IUnknown_iface
,
riid
,
ppobj
);
IUnknown_Release
(
&
obj
->
IUnknown_iface
);
return
hr
;
...
...
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