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