https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a16afc25c96cc1681fb4bf...
commit a16afc25c96cc1681fb4bfced5f26e585e701064 Author: Amine Khaldi amine.khaldi@reactos.org AuthorDate: Mon Oct 1 00:22:26 2018 +0100 Commit: Amine Khaldi amine.khaldi@reactos.org CommitDate: Mon Oct 1 00:22:26 2018 +0100
[DMUSIC] Sync with Wine Staging 3.17. CORE-15127 --- dll/directx/wine/dmusic/collection.c | 208 ++---------------------- dll/directx/wine/dmusic/dmobject.c | 214 ++++++++++++++++++++++++ dll/directx/wine/dmusic/dmobject.h | 53 ++++++ dll/directx/wine/dmusic/port.c | 307 ++++++++++++++++++++++++++++++++++- media/doc/README.WINE | 2 +- 5 files changed, 585 insertions(+), 199 deletions(-)
diff --git a/dll/directx/wine/dmusic/collection.c b/dll/directx/wine/dmusic/collection.c index ec9914faa1..28202228bc 100644 --- a/dll/directx/wine/dmusic/collection.c +++ b/dll/directx/wine/dmusic/collection.c @@ -176,210 +176,34 @@ static const IDirectMusicCollectionVtbl DirectMusicCollection_Collection_Vtbl = };
/* IDirectMusicCollectionImpl IDirectMusicObject part: */ -static HRESULT read_from_stream(IStream *stream, void *data, ULONG size) -{ - ULONG read; - HRESULT hr; - - hr = IStream_Read(stream, data, size, &read); - if (FAILED(hr)) { - TRACE("IStream_Read failed: %08x\n", hr); - return hr; - } - if (read < size) { - TRACE("Didn't read full chunk: %u < %u\n", read, size); - return E_FAIL; - } - - return S_OK; -} - -static HRESULT WINAPI IDirectMusicObjectImpl_ParseDescriptor(IDirectMusicObject *iface, +static HRESULT WINAPI col_IDirectMusicObject_ParseDescriptor(IDirectMusicObject *iface, IStream *stream, DMUS_OBJECTDESC *desc) { - struct dmobject *This = impl_from_IDirectMusicObject(iface); - DMUS_PRIVATE_CHUNK chunk; - DWORD StreamSize, StreamCount, ListSize[1], ListCount[1]; - LARGE_INTEGER liMove; /* used when skipping chunks */ + struct chunk_entry riff = {0}; HRESULT hr;
- TRACE("(%p)->(%p, %p)\n", This, stream, desc); + TRACE("(%p, %p, %p)\n", iface, stream, desc);
- /* FIXME: should this be determined from stream? */ - desc->dwValidData |= DMUS_OBJ_CLASS; - desc->guidClass = This->desc.guidClass; + if (!stream || !desc) + return E_POINTER;
- hr = read_from_stream(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD)); - if (FAILED(hr)) + if ((hr = stream_get_chunk(stream, &riff)) != S_OK) return hr; - TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize); - - if (chunk.fccID != FOURCC_RIFF) { - TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); - liMove.QuadPart = chunk.dwSize; - IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ - return DMUS_E_INVALIDFILE; + if (riff.id != FOURCC_RIFF || riff.type != FOURCC_DLS) { + TRACE("loading failed: unexpected %s\n", debugstr_chunk(&riff)); + stream_skip_chunk(stream, &riff); + return DMUS_E_NOTADLSCOL; }
- hr = read_from_stream(stream, &chunk.fccID, sizeof(FOURCC)); + hr = dmobj_parsedescriptor(stream, &riff, desc, DMUS_OBJ_NAME_INFO|DMUS_OBJ_VERSION); if (FAILED(hr)) return hr; - TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(chunk.fccID)); - StreamSize = chunk.dwSize - sizeof(FOURCC); - - if (chunk.fccID != FOURCC_DLS) { - TRACE_(dmfile)(": unexpected chunk; loading failed)\n"); - liMove.QuadPart = StreamSize; - IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */ - return E_FAIL; - } - - StreamCount = 0; - TRACE_(dmfile)(": collection form\n"); - - do { - hr = read_from_stream(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD)); - if (FAILED(hr)) - return hr; - StreamCount += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize; - TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize); - switch (chunk.fccID) { - case FOURCC_DLID: - TRACE_(dmfile)(": GUID chunk\n"); - desc->dwValidData |= DMUS_OBJ_OBJECT; - hr = read_from_stream(stream, &desc->guidObject, chunk.dwSize); - if (FAILED(hr)) - return hr; - break; - - case DMUS_FOURCC_VERSION_CHUNK: - TRACE_(dmfile)(": version chunk\n"); - desc->dwValidData |= DMUS_OBJ_VERSION; - hr = read_from_stream(stream, &desc->vVersion, chunk.dwSize); - if (FAILED(hr)) - return hr; - break; - - case DMUS_FOURCC_CATEGORY_CHUNK: - TRACE_(dmfile)(": category chunk\n"); - desc->dwValidData |= DMUS_OBJ_CATEGORY; - hr = read_from_stream(stream, desc->wszCategory, chunk.dwSize); - if (FAILED(hr)) - return hr; - break; - - case FOURCC_LIST: - hr = read_from_stream(stream, &chunk.fccID, sizeof(FOURCC)); - if (FAILED(hr)) - return hr; - TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunk.fccID)); - ListSize[0] = chunk.dwSize - sizeof(FOURCC); - ListCount[0] = 0; - switch (chunk.fccID) { - /* pure INFO list, such can be found in dls collections */ - case DMUS_FOURCC_INFO_LIST: - TRACE_(dmfile)(": INFO list\n"); - do { - hr = read_from_stream(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD)); - if (FAILED(hr)) - return hr; - ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize; - TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize); - switch (chunk.fccID) { - case mmioFOURCC('I','N','A','M'): { - CHAR szName[DMUS_MAX_NAME]; - TRACE_(dmfile)(": name chunk\n"); - desc->dwValidData |= DMUS_OBJ_NAME; - hr = read_from_stream(stream, szName, chunk.dwSize); - if (FAILED(hr)) - return hr; - MultiByteToWideChar (CP_ACP, 0, szName, -1, desc->wszName, DMUS_MAX_NAME); - if (even_or_odd(chunk.dwSize)) { - ListCount[0]++; - liMove.QuadPart = 1; - IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); - } - break; - } - - case mmioFOURCC('I','A','R','T'): - TRACE_(dmfile)(": artist chunk (ignored)\n"); - if (even_or_odd(chunk.dwSize)) { - ListCount[0]++; - chunk.dwSize++; - } - liMove.QuadPart = chunk.dwSize; - IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); - break; - - case mmioFOURCC('I','C','O','P'): - TRACE_(dmfile)(": copyright chunk (ignored)\n"); - if (even_or_odd(chunk.dwSize)) { - ListCount[0]++; - chunk.dwSize++; - } - liMove.QuadPart = chunk.dwSize; - IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); - break; - - case mmioFOURCC('I','S','B','J'): - TRACE_(dmfile)(": subject chunk (ignored)\n"); - if (even_or_odd(chunk.dwSize)) { - ListCount[0]++; - chunk.dwSize++; - } - liMove.QuadPart = chunk.dwSize; - IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); - break;
- case mmioFOURCC('I','C','M','T'): - TRACE_(dmfile)(": comment chunk (ignored)\n"); - if (even_or_odd(chunk.dwSize)) { - ListCount[0]++; - chunk.dwSize++; - liMove.QuadPart = chunk.dwSize; - IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); - break; - } - - default: - TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); - if (even_or_odd(chunk.dwSize)) { - ListCount[0] ++; - chunk.dwSize++; - } - liMove.QuadPart = chunk.dwSize; - IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); - break; - } - TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]); - } while (ListCount[0] < ListSize[0]); - break; - - default: - TRACE_(dmfile)(": unknown (skipping)\n"); - liMove.QuadPart = chunk.dwSize - sizeof(FOURCC); - IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); - break; - } - break; - - default: - TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n"); - liMove.QuadPart = chunk.dwSize; - IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); - break; - } - TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize); - } while (StreamCount < StreamSize); - - TRACE_(dmfile)(": reading finished\n"); - - if (TRACE_ON(dmusic)) { - TRACE("Returning descriptor:\n"); - dump_DMUS_OBJECTDESC(desc); - } + desc->guidClass = CLSID_DirectMusicCollection; + desc->dwValidData |= DMUS_OBJ_CLASS;
+ TRACE("returning descriptor:\n"); + dump_DMUS_OBJECTDESC(desc); return S_OK; }
@@ -389,7 +213,7 @@ static const IDirectMusicObjectVtbl dmobject_vtbl = { dmobj_IDirectMusicObject_Release, dmobj_IDirectMusicObject_GetDescriptor, dmobj_IDirectMusicObject_SetDescriptor, - IDirectMusicObjectImpl_ParseDescriptor + col_IDirectMusicObject_ParseDescriptor };
/* IDirectMusicCollectionImpl IPersistStream part: */ diff --git a/dll/directx/wine/dmusic/dmobject.c b/dll/directx/wine/dmusic/dmobject.c index cabb6f74db..0a00fbc7e3 100644 --- a/dll/directx/wine/dmusic/dmobject.c +++ b/dll/directx/wine/dmusic/dmobject.c @@ -21,12 +21,154 @@ */
#define COBJMACROS +#include <assert.h> #include "objbase.h" #include "dmusici.h" +#include "dmusicf.h" #include "dmobject.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmobj); +WINE_DECLARE_DEBUG_CHANNEL(dmfile); + +/* RIFF format parsing */ +#define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD)) + +#ifndef __REACTOS__ +static inline const char *debugstr_fourcc(DWORD fourcc) +{ + if (!fourcc) return "''"; + return wine_dbg_sprintf("'%c%c%c%c'", (char)(fourcc), (char)(fourcc >> 8), + (char)(fourcc >> 16), (char)(fourcc >> 24)); +} +#endif + +const char *debugstr_chunk(const struct chunk_entry *chunk) +{ + const char *type = ""; + + if (!chunk) + return "(null)"; + if (chunk->id == FOURCC_RIFF || chunk->id == FOURCC_LIST) + type = wine_dbg_sprintf("type %s, ", debugstr_fourcc(chunk->type)); + return wine_dbg_sprintf("%s chunk, %ssize %u", debugstr_fourcc(chunk->id), type, chunk->size); +} + +static HRESULT stream_read(IStream *stream, void *data, ULONG size) +{ + ULONG read; + HRESULT hr; + + hr = IStream_Read(stream, data, size, &read); + if (FAILED(hr)) + TRACE_(dmfile)("IStream_Read failed: %08x\n", hr); + else if (!read && read < size) { + /* All or nothing: Handle a partial read due to end of stream as an error */ + TRACE_(dmfile)("Short read: %u < %u\n", read, size); + return E_FAIL; + } + + return hr; +} + +HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) +{ + static const LARGE_INTEGER zero; + ULONGLONG ck_end = 0, p_end = 0; + HRESULT hr; + + hr = IStream_Seek(stream, zero, STREAM_SEEK_CUR, &chunk->offset); + if (FAILED(hr)) + return hr; + assert(!(chunk->offset.QuadPart & 1)); + if (chunk->parent) { + p_end = chunk->parent->offset.QuadPart + CHUNK_HDR_SIZE + ((chunk->parent->size + 1) & ~1); + if (chunk->offset.QuadPart == p_end) + return S_FALSE; + ck_end = chunk->offset.QuadPart + CHUNK_HDR_SIZE; + if (ck_end > p_end) { + WARN_(dmfile)("No space for sub-chunk header in parent chunk: ends at offset %s > %s\n", + wine_dbgstr_longlong(ck_end), wine_dbgstr_longlong(p_end)); + return E_FAIL; + } + } + + hr = stream_read(stream, chunk, CHUNK_HDR_SIZE); + if (hr != S_OK) + return hr; + if (chunk->parent) { + ck_end += (chunk->size + 1) & ~1; + if (ck_end > p_end) { + WARN_(dmfile)("No space for sub-chunk data in parent chunk: ends at offset %s > %s\n", + wine_dbgstr_longlong(ck_end), wine_dbgstr_longlong(p_end)); + return E_FAIL; + } + } + + if (chunk->id == FOURCC_LIST || chunk->id == FOURCC_RIFF) { + hr = stream_read(stream, &chunk->type, sizeof(FOURCC)); + if (hr != S_OK) + return hr != S_FALSE ? hr : E_FAIL; + } + + TRACE_(dmfile)("Returning %s\n", debugstr_chunk(chunk)); + + return S_OK; +} + +HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) +{ + LARGE_INTEGER end; + + end.QuadPart = (chunk->offset.QuadPart + CHUNK_HDR_SIZE + chunk->size + 1) & ~(ULONGLONG)1; + + return IStream_Seek(stream, end, STREAM_SEEK_SET, NULL); +} + +HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) +{ + HRESULT hr; + + if (chunk->id) { + hr = stream_skip_chunk(stream, chunk); + if (FAILED(hr)) + return hr; + } + + return stream_get_chunk(stream, chunk); +} + +HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data, + ULONG size) +{ + if (chunk->size != size) { + WARN_(dmfile)("Chunk %s (size %u, offset %s) doesn't contains the expected data size %u\n", + debugstr_fourcc(chunk->id), chunk->size, + wine_dbgstr_longlong(chunk->offset.QuadPart), size); + return E_FAIL; + } + return stream_read(stream, data, size); +} + +HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str, + ULONG size) +{ + ULONG len; + HRESULT hr; + + hr = IStream_Read(stream, str, min(chunk->size, size), &len); + if (FAILED(hr)) + return hr; + + /* Don't assume the string is properly zero terminated */ + str[min(len, size - 1)] = 0; + + if (len < chunk->size) + return S_FALSE; + return S_OK; +} + +
/* Generic IDirectMusicObject methods */ static inline struct dmobject *impl_from_IDirectMusicObject(IDirectMusicObject *iface) @@ -110,6 +252,78 @@ HRESULT WINAPI dmobj_IDirectMusicObject_SetDescriptor(IDirectMusicObject *iface, return ret; }
+/* Helper for IDirectMusicObject::ParseDescriptor */ +static inline void info_get_name(IStream *stream, const struct chunk_entry *info, + DMUS_OBJECTDESC *desc) +{ + struct chunk_entry chunk = {.parent = info}; + char name[DMUS_MAX_NAME]; + ULONG len; + HRESULT hr = E_FAIL; + + while (stream_next_chunk(stream, &chunk) == S_OK) + if (chunk.id == mmioFOURCC('I','N','A','M')) + hr = IStream_Read(stream, name, min(chunk.size, sizeof(name)), &len); + + if (SUCCEEDED(hr)) { + len = MultiByteToWideChar(CP_ACP, 0, name, len, desc->wszName, sizeof(desc->wszName)); + desc->wszName[min(len, sizeof(desc->wszName) - 1)] = 0; + desc->dwValidData |= DMUS_OBJ_NAME; + } +} + +static inline void unfo_get_name(IStream *stream, const struct chunk_entry *unfo, + DMUS_OBJECTDESC *desc, BOOL inam) +{ + struct chunk_entry chunk = {.parent = unfo}; + + while (stream_next_chunk(stream, &chunk) == S_OK) + if (chunk.id == DMUS_FOURCC_UNAM_CHUNK || (inam && chunk.id == mmioFOURCC('I','N','A','M'))) + if (stream_chunk_get_wstr(stream, &chunk, desc->wszName, sizeof(desc->wszName)) == S_OK) + desc->dwValidData |= DMUS_OBJ_NAME; +} + +HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff, + DMUS_OBJECTDESC *desc, DWORD supported) +{ + struct chunk_entry chunk = {.parent = riff}; + HRESULT hr; + + TRACE("Looking for %#x in %p: %s\n", supported, stream, debugstr_chunk(riff)); + + desc->dwValidData = 0; + desc->dwSize = sizeof(*desc); + + while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) { + switch (chunk.id) { + case DMUS_FOURCC_GUID_CHUNK: + if ((supported & DMUS_OBJ_OBJECT) && stream_chunk_get_data(stream, &chunk, + &desc->guidObject, sizeof(desc->guidObject)) == S_OK) + desc->dwValidData |= DMUS_OBJ_OBJECT; + break; + case DMUS_FOURCC_CATEGORY_CHUNK: + if ((supported & DMUS_OBJ_CATEGORY) && stream_chunk_get_wstr(stream, &chunk, + desc->wszCategory, sizeof(desc->wszCategory)) == S_OK) + desc->dwValidData |= DMUS_OBJ_CATEGORY; + break; + case DMUS_FOURCC_VERSION_CHUNK: + if ((supported & DMUS_OBJ_VERSION) && stream_chunk_get_data(stream, &chunk, + &desc->vVersion, sizeof(desc->vVersion)) == S_OK) + desc->dwValidData |= DMUS_OBJ_VERSION; + break; + case FOURCC_LIST: + if (chunk.type == DMUS_FOURCC_UNFO_LIST && (supported & DMUS_OBJ_NAME)) + unfo_get_name(stream, &chunk, desc, supported & DMUS_OBJ_NAME_INAM); + else if (chunk.type == DMUS_FOURCC_INFO_LIST && (supported & DMUS_OBJ_NAME_INFO)) + info_get_name(stream, &chunk, desc); + break; + } + } + TRACE("Found %#x\n", desc->dwValidData); + + return hr; +} + /* Generic IPersistStream methods */ static inline struct dmobject *impl_from_IPersistStream(IPersistStream *iface) { diff --git a/dll/directx/wine/dmusic/dmobject.h b/dll/directx/wine/dmusic/dmobject.h index 5fc9918015..e7b95b7fde 100644 --- a/dll/directx/wine/dmusic/dmobject.h +++ b/dll/directx/wine/dmusic/dmobject.h @@ -21,6 +21,51 @@
#pragma once
+#include "wine/debug.h" + +/* RIFF stream parsing */ +struct chunk_entry; +struct chunk_entry { + FOURCC id; + DWORD size; + FOURCC type; /* valid only for LIST and RIFF chunks */ + ULARGE_INTEGER offset; /* chunk offset from start of stream */ + const struct chunk_entry *parent; /* enclosing RIFF or LIST chunk */ +}; + +HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN; +HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN; +HRESULT stream_skip_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN; + +HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data, + ULONG size) DECLSPEC_HIDDEN; +HRESULT stream_chunk_get_wstr(IStream *stream, const struct chunk_entry *chunk, WCHAR *str, + ULONG size) DECLSPEC_HIDDEN; + +static inline HRESULT stream_reset_chunk_data(IStream *stream, const struct chunk_entry *chunk) +{ + LARGE_INTEGER offset; + + offset.QuadPart = chunk->offset.QuadPart + sizeof(FOURCC) + sizeof(DWORD); + if (chunk->id == FOURCC_RIFF || chunk->id == FOURCC_LIST) + offset.QuadPart += sizeof(FOURCC); + + return IStream_Seek(stream, offset, STREAM_SEEK_SET, NULL); +} + +static inline HRESULT stream_reset_chunk_start(IStream *stream, const struct chunk_entry *chunk) +{ + LARGE_INTEGER offset; + + offset.QuadPart = chunk->offset.QuadPart; + + return IStream_Seek(stream, offset, STREAM_SEEK_SET, NULL); +} + +const char *debugstr_chunk(const struct chunk_entry *chunk) DECLSPEC_HIDDEN; + + +/* IDirectMusicObject base object */ struct dmobject { IDirectMusicObject IDirectMusicObject_iface; IPersistStream IPersistStream_iface; @@ -40,6 +85,14 @@ HRESULT WINAPI dmobj_IDirectMusicObject_GetDescriptor(IDirectMusicObject *iface, HRESULT WINAPI dmobj_IDirectMusicObject_SetDescriptor(IDirectMusicObject *iface, DMUS_OBJECTDESC *desc) DECLSPEC_HIDDEN;
+/* Helper for IDirectMusicObject::ParseDescriptor */ +HRESULT dmobj_parsedescriptor(IStream *stream, const struct chunk_entry *riff, + DMUS_OBJECTDESC *desc, DWORD supported) DECLSPEC_HIDDEN; +/* Additional supported flags for dmobj_parsedescriptor. + DMUS_OBJ_NAME is 'UNAM' chunk in UNFO list */ +#define DMUS_OBJ_NAME_INAM 0x1000 /* 'INAM' chunk in UNFO list */ +#define DMUS_OBJ_NAME_INFO 0x2000 /* 'INAM' chunk in INFO list */ + /* Generic IPersistStream methods */ HRESULT WINAPI dmobj_IPersistStream_QueryInterface(IPersistStream *iface, REFIID riid, void **ret_iface) DECLSPEC_HIDDEN; diff --git a/dll/directx/wine/dmusic/port.c b/dll/directx/wine/dmusic/port.c index 713175650b..91913a716f 100644 --- a/dll/directx/wine/dmusic/port.c +++ b/dll/directx/wine/dmusic/port.c @@ -21,6 +21,7 @@
#include <assert.h> #include "dmusic_private.h" +#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
@@ -903,18 +904,312 @@ HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_param return hr; }
-HRESULT midi_out_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params, - DMUS_PORTCAPS *port_caps, IDirectMusicPort **port) +struct midi_port { + IDirectMusicPort IDirectMusicPort_iface; + IDirectMusicThru IDirectMusicThru_iface; + LONG ref; + IReferenceClock *clock; +}; + +static inline struct midi_port *impl_from_IDirectMusicPort(IDirectMusicPort *iface) +{ + return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicPort_iface); +} + +static HRESULT WINAPI midi_IDirectMusicPort_QueryInterface(IDirectMusicPort *iface, REFIID riid, + void **ret_iface) +{ + struct midi_port *This = impl_from_IDirectMusicPort(iface); + + TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface); + + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicPort)) + *ret_iface = iface; + else if (IsEqualIID(riid, &IID_IDirectMusicThru)) + *ret_iface = &This->IDirectMusicThru_iface; + else { + WARN("no interface for %s\n", debugstr_dmguid(riid)); + *ret_iface = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*ret_iface); + + return S_OK; +} + +static ULONG WINAPI midi_IDirectMusicPort_AddRef(IDirectMusicPort *iface) +{ + struct midi_port *This = impl_from_IDirectMusicPort(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref = %u\n", iface, ref); + + return ref; +} + +static ULONG WINAPI midi_IDirectMusicPort_Release(IDirectMusicPort *iface) +{ + struct midi_port *This = impl_from_IDirectMusicPort(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref = %u\n", iface, ref); + + if (!ref) { + if (This->clock) + IReferenceClock_Release(This->clock); + heap_free(This); + } + + return ref; +} + +static HRESULT WINAPI midi_IDirectMusicPort_PlayBuffer(IDirectMusicPort *iface, + IDirectMusicBuffer *buffer) { - FIXME("(%p, %p, %p): stub\n", port_params, port_caps, port); + FIXME("(%p, %p) stub!\n", iface, buffer);
return E_NOTIMPL; }
-HRESULT midi_in_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params, - DMUS_PORTCAPS *port_caps, IDirectMusicPort **port) +static HRESULT WINAPI midi_IDirectMusicPort_SetReadNotificationHandle(IDirectMusicPort *iface, + HANDLE event) +{ + FIXME("(%p, %p) stub!\n", iface, event); + + return S_OK; +} + +static HRESULT WINAPI midi_IDirectMusicPort_Read(IDirectMusicPort *iface, + IDirectMusicBuffer *buffer) +{ + FIXME("(%p, %p) stub!\n", iface, buffer); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_IDirectMusicPort_DownloadInstrument(IDirectMusicPort *iface, + IDirectMusicInstrument *instrument, IDirectMusicDownloadedInstrument **downloaded, + DMUS_NOTERANGE *ranges, DWORD num_ranges) +{ + FIXME("(%p, %p, %p, %p, %u) stub!\n", iface, instrument, downloaded, ranges, num_ranges); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_IDirectMusicPort_UnloadInstrument(IDirectMusicPort *iface, + IDirectMusicDownloadedInstrument *downloaded) +{ + FIXME("(%p, %p) stub!\n", iface, downloaded); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_IDirectMusicPort_GetLatencyClock(IDirectMusicPort *iface, + IReferenceClock **clock) +{ + struct midi_port *This = impl_from_IDirectMusicPort(iface); + + TRACE("(%p, %p)\n", iface, clock); + + if (!clock) + return E_POINTER; + + *clock = This->clock; + IReferenceClock_AddRef(*clock); + + return S_OK; +} + +static HRESULT WINAPI midi_IDirectMusicPort_GetRunningStats(IDirectMusicPort *iface, + DMUS_SYNTHSTATS *stats) +{ + FIXME("(%p, %p) stub!\n", iface, stats); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_IDirectMusicPort_Compact(IDirectMusicPort *iface) +{ + FIXME("(%p) stub!\n", iface); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_IDirectMusicPort_GetCaps(IDirectMusicPort *iface, DMUS_PORTCAPS *caps) +{ + FIXME("(%p, %p) stub!\n", iface, caps); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_IDirectMusicPort_DeviceIoControl(IDirectMusicPort *iface, + DWORD io_control_code, void *in, DWORD size_in, void *out, DWORD size_out, DWORD *ret_len, + OVERLAPPED *overlapped) { - FIXME("(%p, %p, %p): stub\n", port_params, port_caps, port); + FIXME("(%p, %u, %p, %u, %p, %u, %p, %p) stub!\n", iface, io_control_code, in, size_in, out + , size_out, ret_len, overlapped);
return E_NOTIMPL; } + +static HRESULT WINAPI midi_IDirectMusicPort_SetNumChannelGroups(IDirectMusicPort *iface, + DWORD cgroups) +{ + FIXME("(%p, %u) stub!\n", iface, cgroups); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_IDirectMusicPort_GetNumChannelGroups(IDirectMusicPort *iface, + DWORD *cgroups) +{ + FIXME("(%p, %p) stub!\n", iface, cgroups); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_IDirectMusicPort_Activate(IDirectMusicPort *iface, BOOL active) +{ + FIXME("(%p, %u) stub!\n", iface, active); + + return S_OK; +} + +static HRESULT WINAPI midi_IDirectMusicPort_SetChannelPriority(IDirectMusicPort *iface, + DWORD channel_group, DWORD channel, DWORD priority) +{ + FIXME("(%p, %u, %u, %u) stub!\n", iface, channel_group, channel, priority); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_IDirectMusicPort_GetChannelPriority(IDirectMusicPort *iface, + DWORD channel_group, DWORD channel, DWORD *priority) +{ + FIXME("(%p, %u, %u, %p) stub!\n", iface, channel_group, channel, priority); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_IDirectMusicPort_SetDirectSound(IDirectMusicPort *iface, + IDirectSound *dsound, IDirectSoundBuffer *dsbuffer) +{ + FIXME("(%p, %p, %p) stub!\n", iface, dsound, dsbuffer); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_IDirectMusicPort_GetFormat(IDirectMusicPort *iface, WAVEFORMATEX *format, + DWORD *format_size, DWORD *buffer_size) +{ + FIXME("(%p, %p, %p, %p) stub!\n", iface, format, format_size, buffer_size); + + return E_NOTIMPL; +} + +static const IDirectMusicPortVtbl midi_port_vtbl = { + midi_IDirectMusicPort_QueryInterface, + midi_IDirectMusicPort_AddRef, + midi_IDirectMusicPort_Release, + midi_IDirectMusicPort_PlayBuffer, + midi_IDirectMusicPort_SetReadNotificationHandle, + midi_IDirectMusicPort_Read, + midi_IDirectMusicPort_DownloadInstrument, + midi_IDirectMusicPort_UnloadInstrument, + midi_IDirectMusicPort_GetLatencyClock, + midi_IDirectMusicPort_GetRunningStats, + midi_IDirectMusicPort_Compact, + midi_IDirectMusicPort_GetCaps, + midi_IDirectMusicPort_DeviceIoControl, + midi_IDirectMusicPort_SetNumChannelGroups, + midi_IDirectMusicPort_GetNumChannelGroups, + midi_IDirectMusicPort_Activate, + midi_IDirectMusicPort_SetChannelPriority, + midi_IDirectMusicPort_GetChannelPriority, + midi_IDirectMusicPort_SetDirectSound, + midi_IDirectMusicPort_GetFormat, +}; + +static inline struct midi_port *impl_from_IDirectMusicThru(IDirectMusicThru *iface) +{ + return CONTAINING_RECORD(iface, struct midi_port, IDirectMusicThru_iface); +} + +static HRESULT WINAPI midi_IDirectMusicThru_QueryInterface(IDirectMusicThru *iface, REFIID riid, + void **ret_iface) +{ + struct midi_port *This = impl_from_IDirectMusicThru(iface); + + return IDirectMusicPort_QueryInterface(&This->IDirectMusicPort_iface, riid, ret_iface); +} + +static ULONG WINAPI midi_IDirectMusicThru_AddRef(IDirectMusicThru *iface) +{ + struct midi_port *This = impl_from_IDirectMusicThru(iface); + + return IDirectMusicPort_AddRef(&This->IDirectMusicPort_iface); +} + +static ULONG WINAPI midi_IDirectMusicThru_Release(IDirectMusicThru *iface) +{ + struct midi_port *This = impl_from_IDirectMusicThru(iface); + + return IDirectMusicPort_Release(&This->IDirectMusicPort_iface); +} + +static HRESULT WINAPI midi_IDirectMusicThru_ThruChannel(IDirectMusicThru *iface, DWORD src_group, + DWORD src_channel, DWORD dest_group, DWORD dest_channel, IDirectMusicPort *dest_port) +{ + FIXME("(%p, %u, %u, %u, %u, %p) stub!\n", iface, src_group, src_channel, dest_group, + dest_channel, dest_port); + + return S_OK; +} + +static const IDirectMusicThruVtbl midi_thru_vtbl = { + midi_IDirectMusicThru_QueryInterface, + midi_IDirectMusicThru_AddRef, + midi_IDirectMusicThru_Release, + midi_IDirectMusicThru_ThruChannel, +}; + +static HRESULT midi_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params, + DMUS_PORTCAPS *caps, IDirectMusicPort **port) +{ + struct midi_port *obj; + HRESULT hr; + + if (!(obj = heap_alloc_zero(sizeof(*obj)))) + return E_OUTOFMEMORY; + + obj->IDirectMusicPort_iface.lpVtbl = &midi_port_vtbl; + obj->IDirectMusicThru_iface.lpVtbl = &midi_thru_vtbl; + obj->ref = 1; + + hr = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (void **)&obj->clock, NULL); + if (hr != S_OK) { + HeapFree(GetProcessHeap(), 0, obj); + return hr; + } + + *port = &obj->IDirectMusicPort_iface; + + return S_OK; +} + +HRESULT midi_out_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params, + DMUS_PORTCAPS *caps, IDirectMusicPort **port) +{ + TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port); + + return midi_port_create(parent, params, caps, port); +} + +HRESULT midi_in_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *params, + DMUS_PORTCAPS *caps, IDirectMusicPort **port) +{ + TRACE("(%p, %p, %p, %p)\n", parent, params, caps, port); + + return midi_port_create(parent, params, caps, port); +} diff --git a/media/doc/README.WINE b/media/doc/README.WINE index df4d66c340..a0bda6e3b5 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -32,7 +32,7 @@ reactos/dll/directx/wine/ddraw # Synced to WineStaging-3.9 reactos/dll/directx/wine/devenum # Synced to WineStaging-3.9 reactos/dll/directx/wine/dinput # Synced to WineStaging-3.17 reactos/dll/directx/wine/dinput8 # Synced to WineStaging-3.3 -reactos/dll/directx/wine/dmusic # Synced to WineStaging-3.9 +reactos/dll/directx/wine/dmusic # Synced to WineStaging-3.17 reactos/dll/directx/wine/dplay # Synced to WineStaging-3.3 reactos/dll/directx/wine/dplayx # Synced to WineStaging-3.3 reactos/dll/directx/wine/dsound # Synced to Wine-1.3.29