Michael Stefaniuc : dmime: Simplify loading/storing of the Tempo Track data.
Alexandre Julliard
julliard at winehq.org
Wed Aug 5 16:04:59 CDT 2020
Module: wine
Branch: master
Commit: c64b31c71db4e7216f72e15c9d252e8f2635abe6
URL: https://source.winehq.org/git/wine.git/?a=commit;h=c64b31c71db4e7216f72e15c9d252e8f2635abe6
Author: Michael Stefaniuc <mstefani at winehq.org>
Date: Wed Aug 5 00:14:32 2020 +0200
dmime: Simplify loading/storing of the Tempo Track data.
Fixes loading more than one tempo items.
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/dmime/dmobject.c | 45 +++++++++++++++++++++
dlls/dmime/dmobject.h | 2 +
dlls/dmime/tempotrack.c | 102 ++++++++++++++++++------------------------------
3 files changed, 85 insertions(+), 64 deletions(-)
diff --git a/dlls/dmime/dmobject.c b/dlls/dmime/dmobject.c
index 0ef007530f..e6a1ce906a 100644
--- a/dlls/dmime/dmobject.c
+++ b/dlls/dmime/dmobject.c
@@ -28,6 +28,7 @@
#include "dmusics.h"
#include "dmobject.h"
#include "wine/debug.h"
+#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmobj);
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
@@ -371,6 +372,50 @@ HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk)
return stream_get_chunk(stream, chunk);
}
+/* Reads chunk data of the form:
+ DWORD - size of array element
+ element[] - Array of elements
+ The caller needs to heap_free() the array.
+*/
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size)
+{
+ DWORD size;
+ HRESULT hr;
+
+ *array = NULL;
+ *count = 0;
+
+ if (chunk->size < sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Too short to read element size\n", debugstr_chunk(chunk));
+ return E_FAIL;
+ }
+ if (FAILED(hr = stream_read(stream, &size, sizeof(DWORD))))
+ return hr;
+ if (size != elem_size) {
+ WARN_(dmfile)("%s: Array element size mismatch: got %u, expected %u\n",
+ debugstr_chunk(chunk), size, elem_size);
+ return DMUS_E_UNSUPPORTED_STREAM;
+ }
+
+ *count = (chunk->size - sizeof(DWORD)) / elem_size;
+ size = *count * elem_size;
+ if (!(*array = heap_alloc(size)))
+ return E_OUTOFMEMORY;
+ if (FAILED(hr = stream_read(stream, *array, size))) {
+ heap_free(*array);
+ *array = NULL;
+ return hr;
+ }
+
+ if (chunk->size > size + sizeof(DWORD)) {
+ WARN_(dmfile)("%s: Extraneous data at end of array\n", debugstr_chunk(chunk));
+ stream_skip_chunk(stream, chunk);
+ return S_FALSE;
+ }
+ return S_OK;
+}
+
HRESULT stream_chunk_get_data(IStream *stream, const struct chunk_entry *chunk, void *data,
ULONG size)
{
diff --git a/dlls/dmime/dmobject.h b/dlls/dmime/dmobject.h
index a1729c8323..afe721dc82 100644
--- a/dlls/dmime/dmobject.h
+++ b/dlls/dmime/dmobject.h
@@ -35,6 +35,8 @@ HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HI
HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk) DECLSPEC_HIDDEN;
HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk) DECLSPEC_HIDDEN;
+HRESULT stream_chunk_get_array(IStream *stream, const struct chunk_entry *chunk, void **array,
+ unsigned int *count, DWORD elem_size) 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,
diff --git a/dlls/dmime/tempotrack.c b/dlls/dmime/tempotrack.c
index 94e4430b7f..9d25ccc298 100644
--- a/dlls/dmime/tempotrack.c
+++ b/dlls/dmime/tempotrack.c
@@ -29,11 +29,13 @@ WINE_DECLARE_DEBUG_CHANNEL(dmfile);
/*****************************************************************************
* IDirectMusicTempoTrack implementation
*/
+
typedef struct IDirectMusicTempoTrack {
IDirectMusicTrack8 IDirectMusicTrack8_iface;
struct dmobject dmobj; /* IPersistStream only */
LONG ref;
- struct list Items;
+ DMUS_IO_TEMPO_ITEM *items;
+ unsigned int count;
} IDirectMusicTempoTrack;
/* IDirectMusicTempoTrack IDirectMusicTrack8 part: */
@@ -83,16 +85,7 @@ static ULONG WINAPI tempo_track_Release(IDirectMusicTrack8 *iface)
TRACE("(%p) ref=%d\n", This, ref);
if (!ref) {
- struct list *cursor, *cursor2;
- DMUS_PRIVATE_TEMPO_ITEM *item;
-
- LIST_FOR_EACH_SAFE(cursor, cursor2, &This->Items) {
- item = LIST_ENTRY(cursor, DMUS_PRIVATE_TEMPO_ITEM, entry);
- list_remove(cursor);
-
- heap_free(item);
- }
-
+ heap_free(This->items);
heap_free(This);
DMIME_UnlockModule();
}
@@ -157,8 +150,8 @@ static HRESULT WINAPI tempo_track_GetParam(IDirectMusicTrack8 *iface, REFGUID ty
MUSIC_TIME *next, void *param)
{
IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
- DMUS_PRIVATE_TEMPO_ITEM *item = NULL;
DMUS_TEMPO_PARAM *prm = param;
+ unsigned int i;
TRACE("(%p, %s, %d, %p, %p)\n", This, debugstr_dmguid(type), time, next, param);
@@ -174,15 +167,15 @@ static HRESULT WINAPI tempo_track_GetParam(IDirectMusicTrack8 *iface, REFGUID ty
prm->mtTime = 0;
prm->dblTempo = 0.123456;
- LIST_FOR_EACH_ENTRY(item, &This->Items, DMUS_PRIVATE_TEMPO_ITEM, entry) {
- if (item->item.lTime <= time) {
- MUSIC_TIME ofs = item->item.lTime - time;
+ for (i = 0; i < This->count; i++) {
+ if (This->items[i].lTime <= time) {
+ MUSIC_TIME ofs = This->items[i].lTime - time;
if (ofs > prm->mtTime) {
prm->mtTime = ofs;
- prm->dblTempo = item->item.dblTempo;
+ prm->dblTempo = This->items[i].dblTempo;
}
- if (next && item->item.lTime > time && item->item.lTime < *next)
- *next = item->item.lTime;
+ if (next && This->items[i].lTime > time && This->items[i].lTime < *next)
+ *next = This->items[i].lTime;
}
}
@@ -334,53 +327,35 @@ static inline IDirectMusicTempoTrack *impl_from_IPersistStream(IPersistStream *i
return CONTAINING_RECORD(iface, IDirectMusicTempoTrack, dmobj.IPersistStream_iface);
}
-static HRESULT WINAPI tempo_IPersistStream_Load(IPersistStream *iface, IStream *pStm)
+static HRESULT WINAPI tempo_IPersistStream_Load(IPersistStream *iface, IStream *stream)
{
- IDirectMusicTempoTrack *This = impl_from_IPersistStream(iface);
- DMUS_PRIVATE_CHUNK Chunk;
- DWORD StreamSize, StreamCount;
- LARGE_INTEGER liMove;
- DMUS_IO_TEMPO_ITEM item;
- LPDMUS_PRIVATE_TEMPO_ITEM pNewItem = NULL;
- DWORD nItem = 0;
- FIXME("(%p, %p): Loading not fully implemented yet\n", This, pStm);
-
- IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
- TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
- switch (Chunk.fccID) {
- case DMUS_FOURCC_TEMPO_TRACK: {
- TRACE_(dmfile)(": Tempo track\n");
- IStream_Read (pStm, &StreamSize, sizeof(DWORD), NULL);
- StreamSize -= sizeof(DWORD);
- StreamCount = 0;
- TRACE_(dmfile)(" - sizeof(DMUS_IO_TEMPO_ITEM): %u (chunkSize = %u)\n", StreamSize, Chunk.dwSize);
- do {
- IStream_Read (pStm, &item, sizeof(item), NULL);
- ++nItem;
- TRACE_(dmfile)("DMUS_IO_TEMPO_ITEM #%d\n", nItem);
- TRACE_(dmfile)(" - lTime = %u\n", item.lTime);
- TRACE_(dmfile)(" - dblTempo = %g\n", item.dblTempo);
- pNewItem = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_TEMPO_ITEM));
- if (NULL == pNewItem)
- return E_OUTOFMEMORY;
-
- pNewItem->item = item;
- list_add_tail (&This->Items, &pNewItem->entry);
- pNewItem = NULL;
- StreamCount += sizeof(item);
- TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
- } while (StreamCount < StreamSize);
- break;
- }
- default: {
- TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
- liMove.QuadPart = Chunk.dwSize;
- IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
- return E_FAIL;
- }
- }
+ IDirectMusicTempoTrack *This = impl_from_IPersistStream(iface);
+ struct chunk_entry chunk = {0};
+ unsigned int i;
+ HRESULT hr;
- return S_OK;
+ TRACE("%p, %p\n", This, stream);
+
+ if (!stream)
+ return E_POINTER;
+
+ if ((hr = stream_get_chunk(stream, &chunk) != S_OK))
+ return hr;
+ if (chunk.id != DMUS_FOURCC_TEMPO_TRACK)
+ return DMUS_E_UNSUPPORTED_STREAM;
+
+ hr = stream_chunk_get_array(stream, &chunk, (void **)&This->items, &This->count,
+ sizeof(DMUS_IO_TEMPO_ITEM));
+ if (FAILED(hr))
+ return hr;
+
+ for (i = 0; i < This->count; i++) {
+ TRACE_(dmfile)("DMUS_IO_TEMPO_ITEM #%u\n", i);
+ TRACE_(dmfile)(" - lTime = %u\n", This->items[i].lTime);
+ TRACE_(dmfile)(" - dblTempo = %g\n", This->items[i].dblTempo);
+ }
+
+ return S_OK;
}
static const IPersistStreamVtbl persiststream_vtbl = {
@@ -410,7 +385,6 @@ HRESULT WINAPI create_dmtempotrack(REFIID lpcGUID, void **ppobj)
dmobject_init(&track->dmobj, &CLSID_DirectMusicTempoTrack,
(IUnknown *)&track->IDirectMusicTrack8_iface);
track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
- list_init(&track->Items);
DMIME_LockModule();
hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj);
More information about the wine-cvs
mailing list