Christian Costa : dmusic: Implement instrument regions loading.

Alexandre Julliard julliard at winehq.org
Fri Dec 21 11:05:21 CST 2012


Module: wine
Branch: master
Commit: bf0605c08abd990ebb584cdc18e32bccdf9b94ee
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=bf0605c08abd990ebb584cdc18e32bccdf9b94ee

Author: Christian Costa <titan.costa at gmail.com>
Date:   Fri Dec 21 10:27:38 2012 +0100

dmusic: Implement instrument regions loading.

---

 dlls/dmusic/dmusic_private.h |   29 +++++---
 dlls/dmusic/instrument.c     |  157 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 173 insertions(+), 13 deletions(-)

diff --git a/dlls/dmusic/dmusic_private.h b/dlls/dmusic/dmusic_private.h
index 3c05ceb..a37a1c3 100644
--- a/dlls/dmusic/dmusic_private.h
+++ b/dlls/dmusic/dmusic_private.h
@@ -77,6 +77,13 @@ typedef struct port_info {
     ULONG device;
 } port_info;
 
+typedef struct instrument_region {
+    RGNHEADER header;
+    WAVELINK wave_link;
+    WSMPL wave_sample;
+    WLOOP wave_loop;
+    BOOL loop_present;
+} instrument_region;
 
 /*****************************************************************************
  * ClassFactory
@@ -224,17 +231,19 @@ struct IDirectMusicCollectionImpl {
  * IDirectMusicInstrumentImpl implementation structure
  */
 struct IDirectMusicInstrumentImpl {
-  /* IUnknown fields */
-  IDirectMusicInstrument IDirectMusicInstrument_iface;
-  LONG           ref;
+    /* IUnknown fields */
+    IDirectMusicInstrument IDirectMusicInstrument_iface;
+    LONG ref;
 
-  /* IDirectMusicInstrumentImpl fields */
-  LARGE_INTEGER liInstrumentPosition; /* offset in a stream where instrument chunk can be found */
-  ULONG length; /* Length of the instrument in the stream */
-  LPGUID pInstrumentID;
-  LPINSTHEADER pHeader;
-  WCHAR wszName[DMUS_MAX_NAME];
-  /* instrument data */
+    /* IDirectMusicInstrumentImpl fields */
+    LARGE_INTEGER liInstrumentPosition; /* offset in a stream where instrument chunk can be found */
+    ULONG length; /* Length of the instrument in the stream */
+    LPGUID pInstrumentID;
+    LPINSTHEADER pHeader;
+    WCHAR wszName[DMUS_MAX_NAME];
+    /* instrument data */
+    BOOL loaded;
+    instrument_region *regions;
 };
 
 static inline IDirectMusicInstrumentImpl *impl_from_IDirectMusicInstrument(IDirectMusicInstrument *iface)
diff --git a/dlls/dmusic/instrument.c b/dlls/dmusic/instrument.c
index cc57313..13d0c2f 100644
--- a/dlls/dmusic/instrument.c
+++ b/dlls/dmusic/instrument.c
@@ -75,7 +75,10 @@ static ULONG WINAPI IDirectMusicInstrumentImpl_Release(LPDIRECTMUSICINSTRUMENT i
     TRACE("(%p)->(): new ref = %u\n", iface, ref);
 
     if (!ref)
+    {
+        HeapFree(GetProcessHeap(), 0, This->regions);
         HeapFree(GetProcessHeap(), 0, This);
+    }
 
     DMUSIC_UnlockModule();
 
@@ -170,16 +173,90 @@ static inline HRESULT advance_stream(IStream *stream, ULONG bytes)
     return ret;
 }
 
+static HRESULT load_region(IDirectMusicInstrumentImpl *This, IStream *stream, instrument_region *region, ULONG length)
+{
+    HRESULT ret;
+    DMUS_PRIVATE_CHUNK chunk;
+
+    TRACE("(%p, %p, %p, %u)\n", This, stream, region, length);
+
+    while (length)
+    {
+        ret = read_from_stream(stream, &chunk, sizeof(chunk));
+        if (FAILED(ret))
+            return ret;
+
+        length = subtract_bytes(length, sizeof(chunk));
+
+        switch (chunk.fccID)
+        {
+            case FOURCC_RGNH:
+                TRACE("RGNH chunk (region header): %u bytes\n", chunk.dwSize);
+
+                ret = read_from_stream(stream, &region->header, sizeof(region->header));
+                if (FAILED(ret))
+                    return ret;
+
+                length = subtract_bytes(length, sizeof(region->header));
+                break;
+
+            case FOURCC_WSMP:
+                TRACE("WSMP chunk (wave sample): %u bytes\n", chunk.dwSize);
+
+                ret = read_from_stream(stream, &region->wave_sample, sizeof(region->wave_sample));
+                if (FAILED(ret))
+                    return ret;
+                length = subtract_bytes(length, sizeof(region->wave_sample));
+
+                if (!(region->loop_present = (chunk.dwSize != sizeof(region->wave_sample))))
+                    break;
+
+                ret = read_from_stream(stream, &region->wave_loop, sizeof(region->wave_loop));
+                if (FAILED(ret))
+                    return ret;
+
+                length = subtract_bytes(length, sizeof(region->wave_loop));
+                break;
+
+            case FOURCC_WLNK:
+                TRACE("WLNK chunk (wave link): %u bytes\n", chunk.dwSize);
+
+                ret = read_from_stream(stream, &region->wave_link, sizeof(region->wave_link));
+                if (FAILED(ret))
+                    return ret;
+
+                length = subtract_bytes(length, sizeof(region->wave_link));
+                break;
+
+            default:
+                TRACE("Unknown chunk %s (skipping): %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
+
+                ret = advance_stream(stream, chunk.dwSize);
+                if (FAILED(ret))
+                    return ret;
+
+                length = subtract_bytes(length, chunk.dwSize);
+                break;
+        }
+    }
+
+    return S_OK;
+}
+
 /* Function that loads all instrument data and which is called from IDirectMusicCollection_GetInstrument as in native */
 HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, IStream *stream)
 {
     IDirectMusicInstrumentImpl *This = impl_from_IDirectMusicInstrument(iface);
     HRESULT hr;
     DMUS_PRIVATE_CHUNK chunk;
+    ULONG i = 0;
     ULONG length = This->length;
 
     TRACE("(%p, %p): offset = 0x%s, length = %u)\n", This, stream, wine_dbgstr_longlong(This->liInstrumentPosition.QuadPart), This->length);
 
+    if (This->loaded)
+        return S_OK;
+
     hr = IStream_Seek(stream, This->liInstrumentPosition, STREAM_SEEK_SET, NULL);
     if (FAILED(hr))
     {
@@ -187,11 +264,15 @@ HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, ISt
         return DMUS_E_UNSUPPORTED_STREAM;
     }
 
+    This->regions = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->regions) * This->pHeader->cRegions);
+    if (!This->regions)
+        return E_OUTOFMEMORY;
+
     while (length)
     {
         hr = read_from_stream(stream, &chunk, sizeof(chunk));
         if (FAILED(hr))
-            return DMUS_E_UNSUPPORTED_STREAM;
+            goto error;
 
         length = subtract_bytes(length, sizeof(chunk) + chunk.dwSize);
 
@@ -204,20 +285,90 @@ HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, ISt
                 /* Instrument header and id are already set so just skip */
                 hr = advance_stream(stream, chunk.dwSize);
                 if (FAILED(hr))
-                    return DMUS_E_UNSUPPORTED_STREAM;
+                    goto error;
+
+                break;
 
+            case FOURCC_LIST: {
+                DWORD size = chunk.dwSize;
+
+                TRACE("LIST chunk: %u bytes\n", chunk.dwSize);
+
+                hr = read_from_stream(stream, &chunk.fccID, sizeof(chunk.fccID));
+                if (FAILED(hr))
+                    goto error;
+
+                size = subtract_bytes(size, sizeof(chunk.fccID));
+
+                switch (chunk.fccID)
+                {
+                    case FOURCC_LRGN:
+                        TRACE("LRGN chunk (regions list): %u bytes\n", size);
+
+                        while (size)
+                        {
+                            hr = read_from_stream(stream, &chunk, sizeof(chunk));
+                            if (FAILED(hr))
+                                goto error;
+
+                            if (chunk.fccID != FOURCC_LIST)
+                            {
+                                TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
+                                goto error;
+                            }
+
+                            hr = read_from_stream(stream, &chunk.fccID, sizeof(chunk.fccID));
+                            if (FAILED(hr))
+                                goto error;
+
+                            if (chunk.fccID == FOURCC_RGN)
+                            {
+                                TRACE("RGN chunk (region list): %u bytes\n", chunk.dwSize);
+                                hr = load_region(This, stream, &This->regions[i++], chunk.dwSize - sizeof(chunk.fccID));
+                            }
+                            else
+                            {
+                                TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
+                                hr = advance_stream(stream, chunk.dwSize - sizeof(chunk.fccID));
+                            }
+                            if (FAILED(hr))
+                                goto error;
+
+                            size = subtract_bytes(size, chunk.dwSize + sizeof(chunk));
+                        }
+                        break;
+
+                    default:
+                        TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
+
+                        hr = advance_stream(stream, chunk.dwSize - sizeof(chunk.fccID));
+                        if (FAILED(hr))
+                            goto error;
+
+                        size = subtract_bytes(size, chunk.dwSize - sizeof(chunk.fccID));
+                        break;
+                }
                 break;
+            }
 
             default:
                 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
 
                 hr = advance_stream(stream, chunk.dwSize);
                 if (FAILED(hr))
-                    return DMUS_E_UNSUPPORTED_STREAM;
+                    goto error;
 
                 break;
         }
     }
 
+    This->loaded = TRUE;
+
     return S_OK;
+
+error:
+    HeapFree(GetProcessHeap(), 0, This->regions);
+    This->regions = NULL;
+
+    return DMUS_E_UNSUPPORTED_STREAM;
 }




More information about the wine-cvs mailing list