From 12acfb22857adad2ea4e65de09903f828d4feef3 Mon Sep 17 00:00:00 2001 From: Rok Mandeljc Date: Mon, 30 Jun 2003 18:28:52 +0000 Subject: [PATCH] File loading improvements. --- dlls/dmusic/dmusic_loader.c | 9 + dlls/dmusic/dmusic_performance.c | 5 +- dlls/dmusic/dmusic_private.h | 70 ++- dlls/dmusic/helper.c | 969 +++++++++++++++++++++++++++++-- 4 files changed, 997 insertions(+), 56 deletions(-) diff --git a/dlls/dmusic/dmusic_loader.c b/dlls/dmusic/dmusic_loader.c index adcf38f9ef2..c2e6cf05215 100644 --- a/dlls/dmusic/dmusic_loader.c +++ b/dlls/dmusic/dmusic_loader.c @@ -202,6 +202,7 @@ HRESULT WINAPI IDirectMusicLoader8Impl_LoadObjectFromFile (LPDIRECTMUSICLOADER8 DMUSIC_FillBandFromFileHandle (NULL, fd); } else if (IsEqualGUID(rguidClassID, &CLSID_DirectMusicContainer)) { FIXME("wanted 'con'\n"); + DMUSIC_FillContainerFromFileHandle (NULL, fd); } else if (IsEqualGUID(rguidClassID, &CLSID_DirectMusicCollection)) { FIXME("wanted 'dls'\n"); } else if (IsEqualGUID(rguidClassID, &CLSID_DirectMusicChordMap)) { @@ -211,6 +212,7 @@ HRESULT WINAPI IDirectMusicLoader8Impl_LoadObjectFromFile (LPDIRECTMUSICLOADER8 DMUSIC_FillSegmentFromFileHandle (NULL, fd); } else if (IsEqualGUID(rguidClassID, &CLSID_DirectMusicScript)) { FIXME("wanted 'spt'\n"); + DMUSIC_FillScriptFromFileHandle (NULL, fd); } else if (IsEqualGUID(rguidClassID, &CLSID_DirectMusicSong)) { FIXME("wanted 'sng'\n"); } else if (IsEqualGUID(rguidClassID, &CLSID_DirectMusicStyle)) { @@ -240,6 +242,13 @@ HRESULT WINAPI IDirectMusicLoader8Impl_LoadObjectFromFile (LPDIRECTMUSICLOADER8 container->ref = 1; *ppObject = container; return S_OK; + } else if (IsEqualGUID(iidInterfaceID, &IID_IDirectMusicScript)) { + IDirectMusicScriptImpl* script; + script = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectMusicScriptImpl)); + script->lpVtbl = &DirectMusicScript_Vtbl; + script->ref = 1; + *ppObject = script; + return S_OK; } else { FIXME("bad iid\n"); } diff --git a/dlls/dmusic/dmusic_performance.c b/dlls/dmusic/dmusic_performance.c index 75742d04591..c668e990c60 100644 --- a/dlls/dmusic/dmusic_performance.c +++ b/dlls/dmusic/dmusic_performance.c @@ -76,8 +76,7 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_Init (LPDIRECTMUSICPERFORMANCE8 ifac { ICOM_THIS(IDirectMusicPerformance8Impl,iface); - FIXME("(iface = %p, dmusic = %p, dsound = %p, hwnd = %p): forward to IDirectMusicPerformanceImpl::Init\n", This, ppDirectMusic, pDirectSound, hWnd); - + FIXME("(iface = %p, dmusic = %p, dsound = %p, hwnd = %p)\n", This, ppDirectMusic, pDirectSound, hWnd); if (This->dmusic || This->dsound) return DMUS_E_ALREADY_INITED; @@ -317,7 +316,7 @@ HRESULT WINAPI IDirectMusicPerformance8Impl_RemovePort (LPDIRECTMUSICPERFORMANCE HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannelBlock (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwBlockNum, IDirectMusicPort* pPort, DWORD dwGroup) { - int i, j, range /* min value in range */; + int i, j, range /* min value in range */; ICOM_THIS(IDirectMusicPerformance8Impl,iface); FIXME("(%p, %ld, %p, %ld): semi-stub\n", This, dwBlockNum, pPort, dwGroup-1); diff --git a/dlls/dmusic/dmusic_private.h b/dlls/dmusic/dmusic_private.h index 775aae25971..eb714cd4821 100644 --- a/dlls/dmusic/dmusic_private.h +++ b/dlls/dmusic/dmusic_private.h @@ -185,6 +185,65 @@ typedef struct _BandTrack } BandTrack; +typedef struct _Part +{ + DMUS_IO_STYLEPART header; + UNFO_List UNFO; + DWORD nrofnotes; + DMUS_IO_STYLENOTE* notes; + DWORD nrofcurves; + DMUS_IO_STYLECURVE* curves; + DWORD nrofmarkers; + DMUS_IO_STYLEMARKER* markers; + DWORD nrofresolutions; + DMUS_IO_STYLERESOLUTION* resolutions; + DWORD nrofanticipations; + DMUS_IO_STYLE_ANTICIPATION* anticipations; +} Part; + +typedef struct _Pattern +{ + DMUS_IO_PATTERN header; + DWORD nrofrhytms; + DWORD* rhytms; + UNFO_List UNFO; + DMUS_IO_MOTIFSETTINGS motsettings; + /* IDirectMusicBandImpl band */ + DWORD nrofpartrefs; + /* FIXME: only in singular form for now */ + UNFO_List partrefUNFO; + DMUS_IO_PARTREF partref; +} Pattern; + +typedef struct _WaveTrack +{ + DMUS_IO_WAVE_TRACK_HEADER header; + /* FIXME: only in singular form now */ + DMUS_IO_WAVE_PART_HEADER partHeader; + DMUS_IO_WAVE_ITEM_HEADER itemHeader; + Reference reference; +} WaveTrack; + +typedef struct _SegTriggerTrack +{ + DMUS_IO_SEGMENT_TRACK_HEADER header; + /* FIXME: only in singular form now */ + DMUS_IO_SEGMENT_ITEM_HEADER itemHeader; + Reference reference; + WCHAR* motifName; +} SegTriggerTrack; + +typedef struct _TimeSigTrack { + DWORD nrofitems; + DMUS_IO_TIMESIGNATURE_ITEM* items; +} TimeSigTrack; + +typedef struct _ScriptEvent { + DMUS_IO_SCRIPTTRACK_EVENTHEADER header; + Reference reference; + WCHAR* name; +} ScriptEvent; + /***************************************************************************** * ClassFactory * @@ -1099,10 +1158,13 @@ extern HRESULT WINAPI IDirectMusicSongImpl_EnumSegment (LPDIRECTMUSICSONG iface, */ void register_waveport (LPGUID lpGUID, LPCSTR lpszDesc, LPCSTR lpszDrvName, LPVOID lpContext); /* Loader Helper Functions */ -HRESULT WINAPI DMUSIC_FillSegmentFromFileHandle (IDirectMusicSegment8Impl *segment, HANDLE fd); -HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, HANDLE fd); -HRESULT WINAPI DMUSIC_FillReferenceFromFileHandle (Reference reference, HANDLE fd); -HRESULT WINAPI DMUSIC_FillUNFOFromFileHandle (UNFO_List UNFO, HANDLE fd); HRESULT WINAPI DMUSIC_FillBandFromFileHandle (IDirectMusicBandImpl *band, HANDLE fd); +HRESULT WINAPI DMUSIC_FillContainerFromFileHandle (IDirectMusicContainerImpl *container, HANDLE fd); +HRESULT WINAPI DMUSIC_FillReferenceFromFileHandle (Reference reference, HANDLE fd); +HRESULT WINAPI DMUSIC_FillScriptFromFileHandle (IDirectMusicScriptImpl *script, HANDLE fd); +HRESULT WINAPI DMUSIC_FillSegmentFromFileHandle (IDirectMusicSegment8Impl *segment, HANDLE fd); +HRESULT WINAPI DMUSIC_FillStyleFromFileHandle (IDirectMusicStyle8Impl *style, HANDLE fd); +HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, HANDLE fd); +HRESULT WINAPI DMUSIC_FillUNFOFromFileHandle (UNFO_List UNFO, HANDLE fd); #endif /* __WINE_DMUSIC_PRIVATE_H */ diff --git a/dlls/dmusic/helper.c b/dlls/dmusic/helper.c index 245b2d3d8ab..57367a9abb4 100644 --- a/dlls/dmusic/helper.c +++ b/dlls/dmusic/helper.c @@ -56,31 +56,31 @@ HRESULT WINAPI DMUSIC_FillUNFOFromFileHandle (UNFO_List UNFO, HANDLE fd) { case DMUS_FOURCC_UNAM_CHUNK: { TRACE("'UNAM': name\n"); - UNFO.name = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, sizeof(WCHAR) * chunk.size); /* allocate space */ + UNFO.name = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); /* allocate space */ ReadFile (fd, UNFO.name, chunk.size, &BytesRead, NULL); TRACE_(dmfiledat)("=> name = %s\n", debugstr_w(UNFO.name)); break; } case DMUS_FOURCC_UART_CHUNK: { TRACE("'UART': artist\n"); - UNFO.artist = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, sizeof(WCHAR) * chunk.size); /* allocate space */ + UNFO.artist = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); /* allocate space */ ReadFile (fd, UNFO.artist, chunk.size, &BytesRead, NULL); TRACE_(dmfiledat)("artist = %s\n", debugstr_w(UNFO.artist)); break; } case DMUS_FOURCC_UCOP_CHUNK: { TRACE("'UCOP': copyright\n"); - UNFO.copyright = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, sizeof(WCHAR) * chunk.size); /* allocate space */ + UNFO.copyright = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); /* allocate space */ ReadFile (fd, UNFO.copyright, chunk.size, &BytesRead, NULL); TRACE_(dmfiledat)("=> copyright = %s\n", debugstr_w(UNFO.copyright)); break; } case DMUS_FOURCC_USBJ_CHUNK:{ TRACE("'USBJ': subject\n"); - UNFO.subject = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, sizeof(WCHAR) * chunk.size); /* allocate space */ + UNFO.subject = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); /* allocate space */ ReadFile (fd, UNFO.subject, chunk.size, &BytesRead, NULL); TRACE_(dmfiledat)("=> subject = %s\n", debugstr_w(UNFO.subject)); break; } case DMUS_FOURCC_UCMT_CHUNK: { TRACE("'UCMT': comment\n"); - UNFO.comment = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, sizeof(WCHAR) * chunk.size); /* allocate space */ + UNFO.comment = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); /* allocate space */ ReadFile (fd, UNFO.comment, chunk.size, &BytesRead, NULL); TRACE_(dmfiledat)("=> comment = %s\n", debugstr_w(UNFO.comment)); break; @@ -138,19 +138,19 @@ HRESULT WINAPI DMUSIC_FillReferenceFromFileHandle (Reference reference, HANDLE f break; } case DMUS_FOURCC_NAME_CHUNK: { TRACE("'name': name\n"); - reference.name = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, sizeof(WCHAR) * chunk.size); + reference.name = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); ReadFile (fd, reference.name, chunk.size, &BytesRead, NULL); TRACE_(dmfiledat)("=> name = %s\n", debugstr_w (reference.name)); break; } case DMUS_FOURCC_FILE_CHUNK: { TRACE("'file': file name\n"); - reference.file = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, sizeof(WCHAR) * chunk.size); + reference.file = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); ReadFile (fd, reference.file, chunk.size, &BytesRead, NULL); TRACE_(dmfiledat)("=> file name = %s\n", debugstr_w (reference.file)); break; } case DMUS_FOURCC_CATEGORY_CHUNK: { TRACE("'catg': category\n"); - reference.category = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, sizeof(WCHAR) * chunk.size); + reference.category = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); ReadFile (fd, reference.category, chunk.size, &BytesRead, NULL); TRACE_(dmfiledat)("=> category = %s\n", debugstr_w (reference.category)); break; @@ -267,7 +267,6 @@ HRESULT WINAPI DMUSIC_FillBandFromFileHandle (IDirectMusicBandImpl *band, HANDLE } TRACE("ListCount2 (%ld) < ListSize2 (%ld)\n", ListCount2, ListSize2); } while (ListCount2 < ListSize2); - } else WARN("invalid chunk (only 'lbin' chunk allowed)\n"); TRACE("ListCount (%ld) < ListSize (%ld)\n", ListCount, ListSize); } while (ListCount < ListSize); @@ -295,7 +294,7 @@ HRESULT WINAPI DMUSIC_FillBandFromFileHandle (IDirectMusicBandImpl *band, HANDLE /****************************************************************************** * DMUSIC_FillTrackFromFileHandle: - * - fills a IDirectMusicTrackImpl struct with data from file handle. + * - fills a IDirectMusicTrack8Impl struct with data from file handle. * - IMPORTANT: it expects a RIFF chunk at beginning, so if you are calling it * from another DMUSIC_Fill* function, make sure pointer is at * correct place! @@ -306,7 +305,9 @@ HRESULT WINAPI DMUSIC_FillBandFromFileHandle (IDirectMusicBandImpl *band, HANDLE HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, HANDLE fd) { rawChunk chunk; - DWORD BytesRead, ListCount = 0, ListCount2 = 0, ListSize, ListSize2, FileCount = 0, FileSize, FileCount2 = 0, FileSize2 /* *2s are for various subchunks */; + DWORD BytesRead, ListCount = 0, ListCount2 = 0, ListCount3 = 0, ListCount4 = 0, \ + ListSize, ListSize2, ListSize3, ListSize4, FileCount = 0, FileSize, FileCount2 = 0, FileSize2 /* *2s, *3s and *4s are for various subchunks */; + int i; /* general track info */ DMUS_IO_TRACK_HEADER header; @@ -326,7 +327,15 @@ HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, Reference reference; /* band track stuff */ BandTrack bandTrack; - + /* wave track stuff (only singular) */ + WaveTrack waveTrack; + /* segment trigger track stuff */ + SegTriggerTrack segTriggerTrack; + /* time signature track stuff */ + TimeSigTrack timeSigTrack; + /* script track list stuff */ + ScriptEvent event; + TRACE("reading 'RIFF' chunk...\n"); ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); if (chunk.id == FOURCC_RIFF) { @@ -391,7 +400,6 @@ HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, TRACE_(dmfiledat)("=> chord root = %i; scale = %i\n", (chordHeader && 0xFF000000) >> 24, chordHeader && 0x00FFFFFF); break; } case DMUS_FOURCC_CHORDTRACKBODY_CHUNK: { - int i; TRACE("'crdb': chord body\n"); ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); /* read sizeof (DMUS_IO_CHORD) */ ReadFile (fd, &chordData.chord, chunk.size, &BytesRead, NULL); /* read DMUS_IO_CHORD */ @@ -425,6 +433,7 @@ HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, ListCount += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; if (chunk.id == FOURCC_LIST && ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL) && chunk.id == DMUS_FOURCC_STYLE_REF_LIST) { ListSize2 = chunk.size - sizeof(FOURCC); + ListCount2 = 0; TRACE("'strf': style reference list (size = %ld)\n", ListSize2); do { @@ -462,7 +471,304 @@ HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, TRACE("ListCount (%ld) < ListSize (%ld)\n", ListCount, ListSize); } while (ListCount < ListSize); break; - } + } case DMUS_FOURCC_PERS_TRACK_LIST: { + FIXME("'pftr': chordmap track list: not supported yet\n"); + break; + } case DMUS_FOURCC_LYRICSTRACK_LIST: { + FIXME("'lyrt': lyrics track list: not supported yet\n"); + break; + } case DMUS_FOURCC_MARKERTRACK_LIST: { + FIXME("'MARK': marker track list: not supported yet\n"); + break; + } case DMUS_FOURCC_MELODYFORM_TRACK_LIST: { + FIXME("'mfrm': melody formulation track list: not supported yet\n"); + break; + } case DMUS_FOURCC_PARAMCONTROLTRACK_TRACK_LIST: { + FIXME("'prmt': parameter control track list: not supported yet\n"); + break; + } case DMUS_FOURCC_SCRIPTTRACK_LIST: { + TRACE("'scrt': script track list\n"); + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + if (chunk.id == FOURCC_LIST && ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL) && chunk.id == DMUS_FOURCC_SCRIPTTRACKEVENTS_LIST) { + TRACE("'scrl': script events list\n"); + ListSize2 = chunk.size - sizeof(FOURCC); /* list content size = size of 'LIST' chunk - FOURCC ID of the list */ + ListCount2 = 0; + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount2 += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + if (chunk.id == FOURCC_LIST && ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL) && chunk.id == DMUS_FOURCC_SCRIPTTRACKEVENT_LIST) { + TRACE("'scre': script event list\n"); + ListSize3 = chunk.size - sizeof(FOURCC); /* list content size = size of 'LIST' chunk - FOURCC ID of the list */ + ListCount3 = 0; + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount3 += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + switch (chunk.id) + { + case DMUS_FOURCC_SCRIPTTRACKEVENTHEADER_CHUNK: { + TRACE("'scrh': event header\n"); + ReadFile (fd, &event.header, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> dwFlags = %ld; lTimeLogical = %li; lTimePhysical = %li\n", \ + event.header.dwFlags, event.header.lTimeLogical, event.header.lTimePhysical); + break; + } case FOURCC_LIST: { + TRACE("'LIST': list\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_REF_LIST){ + TRACE("'DMRF': reference list (forward to DMUSIC_FillReferenceFromFileHandle(...)\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before 'LIST' chunk */ + DMUSIC_FillReferenceFromFileHandle (event.reference, fd); + } else { + WARN("invalid chunk (only 'DMRF' chunk allwed)\n"); + } + break; + } case DMUS_FOURCC_SCRIPTTRACKEVENTNAME_CHUNK: { + TRACE("'scrn': routine name\n"); + event.name = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); + ReadFile (fd, event.name, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> routine name = %s\n", debugstr_w (event.name)); + break; + } default: { + WARN("invalid chunk (only 'scrh', 'scrn' and 'LIST' chunk allowed)\n"); + break; + } + } + TRACE("ListCount3 (%ld) < ListSize3 (%ld)\n", ListCount3, ListSize3); + } while (ListCount3 < ListSize3); + } else { + WARN("invalid chunk (only 'scre' chunk allowed)\n"); + } + TRACE("ListCount2 (%ld) < ListSize2 (%ld)\n", ListCount2, ListSize2); + } while (ListCount2 < ListSize2); + } else { + WARN("invalid chunk (only 'scrl' chunk allowed)\n"); + } + TRACE("ListCount (%ld) < ListSize (%ld)\n", ListCount, ListSize); + } while (ListCount < ListSize); + break; + } case DMUS_FOURCC_SEGTRACK_LIST: { + TRACE("'segt': segment trigger track list\n"); + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + switch (chunk.id) + { + case DMUS_FOURCC_SEGTRACK_CHUNK: { + TRACE("'sgth': segment track header\n"); + ReadFile (fd, &segTriggerTrack.header, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> dwFlags = %ld\n", segTriggerTrack.header.dwFlags); + break; + } case FOURCC_LIST: { + TRACE("'LIST': list\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_SEGMENTS_LIST) { + TRACE("'lsgl': segment lists list\n"); + ListSize2 = chunk.size - sizeof(FOURCC); /* list content size = size of 'LIST' chunk - FOURCC ID of the list */ + ListCount2 = 0; + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount2 += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + if (chunk.id == FOURCC_LIST && ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL) && chunk.id == DMUS_FOURCC_SEGMENT_LIST) { + ListSize3 = chunk.size - sizeof(FOURCC); + ListCount3 = 0; + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount3 += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + switch (chunk.id) + { + case DMUS_FOURCC_SEGMENTITEM_CHUNK: { + TRACE("'sgih': segment item header\n"); + ReadFile (fd, &segTriggerTrack.itemHeader, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> lTimeLogical = %li; lTimePhysical = %li; dwPlayFlags = %ld; dwFlags = %ld\n", \ + segTriggerTrack.itemHeader.lTimeLogical, segTriggerTrack.itemHeader.lTimePhysical, \ + segTriggerTrack.itemHeader.dwPlayFlags, segTriggerTrack.itemHeader.dwFlags); + break; + } case DMUS_FOURCC_SEGMENTITEMNAME_CHUNK: { + TRACE("'snam': motif name\n"); + segTriggerTrack.motifName = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); + ReadFile (fd, segTriggerTrack.motifName, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> motif name = %s\n", debugstr_w (segTriggerTrack.motifName)); + break; + } case FOURCC_LIST: { + TRACE("'LIST': list\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_REF_LIST) { + TRACE("'DMRF': reference list (forward to DMUSIC_FillReferenceFromFileHandle(...)\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before 'LIST' chunk */ + DMUSIC_FillReferenceFromFileHandle (segTriggerTrack.reference, fd); + } else { + WARN("invalid chunk (only 'DMRF' chunk allowed)\n"); + } + break; + } default: { + WARN("invalid chunk (only 'sgih', 'snam' and 'LIST' chunks allowed)\n"); + break; + } + } + TRACE("ListCount3 (%ld) < ListSize3 (%ld)\n", ListCount3, ListSize3); + } while (ListCount3 < ListSize3); + } else { + WARN("invalid chunk (only 'lseg' chunk allowed)\n"); + } + TRACE("ListCount2 (%ld) < ListSize2 (%ld)\n", ListCount2, ListSize2); + } while (ListCount2 < ListSize2); + } else { + WARN("invalid chunk (only 'lsgl' chunk allowed\n"); + } + break; + } default: { + WARN("invalid chunk (only 'sgth' and 'LIST' chunks allowed)\n"); + break; + } + } + TRACE("ListCount (%ld) < ListSize (%ld)\n", ListCount, ListSize); + } while (ListCount < ListSize); + break; + } case DMUS_FOURCC_TIMESIGTRACK_LIST: { + TRACE("'TIMS': time signature track list\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_TIMESIGNATURE_TRACK) { + TRACE("'tims': time signatures\n"); + timeSigTrack.nrofitems = chunk.size - sizeof(DWORD); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + if (chunk.size != sizeof(DMUS_IO_TIMESIGNATURE_ITEM)) + WARN("there seem to be a problem: file claims that size of DMUSIC_IO_TEMPO_ITEM is %ld, while real sizeof returns %i\n", chunk.size, sizeof(DMUS_IO_TIMESIGNATURE_ITEM)); + timeSigTrack.nrofitems /= chunk.size; + TRACE_(dmfiledat)("=> number of items = %ld\n", timeSigTrack.nrofitems); + timeSigTrack.items = (DMUS_IO_TIMESIGNATURE_ITEM*) HeapAlloc (GetProcessHeap (), 0, chunk.size * timeSigTrack.nrofitems); + ReadFile(fd, timeSigTrack.items, chunk.size * timeSigTrack.nrofitems, &BytesRead, NULL); + for (i = 0; i < timeSigTrack.nrofitems; i++) + { + TRACE_(dmfiledat)("=> time signature[%i]: lTime = %li; bBeatsPerMeasure = %i; bBeat = %i; wGridsPerBeat = %d\n", \ + i, timeSigTrack.items[i].lTime, timeSigTrack.items[i].bBeatsPerMeasure, timeSigTrack.items[i].bBeat, timeSigTrack.items[i].wGridsPerBeat); + } + } else { + WARN("invalid chunk (only 'tims' chunk allowed)\n"); + } + break; + } case DMUS_FOURCC_WAVETRACK_LIST: { + TRACE("'wavt': wave track list\n"); + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + switch (chunk.id) + { + case DMUS_FOURCC_WAVETRACK_CHUNK: { + TRACE("'wath': wave track header\n"); + ReadFile (fd, &waveTrack.header, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> lVolume = %li; dwFlags = %ld\n", waveTrack.header.lVolume, waveTrack.header.dwFlags); + break; + } case FOURCC_LIST: { + TRACE("'LIST': list\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_WAVEPART_LIST) { + TRACE("'wavp': wave parts list\n"); + ListSize2 = chunk.size - sizeof(FOURCC); + ListCount2 = 0; + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount2 += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + switch (chunk.id) + { + case DMUS_FOURCC_WAVEPART_CHUNK: { + TRACE("'waph': wave part header\n"); + ReadFile (fd, &waveTrack.partHeader, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> lVolume = %li; dwVariations = %ld; dwPChannel = %ld; dwLockToPart = %ld; dwFlags = %ld; dwIndex = %ld\n", \ + waveTrack.partHeader.lVolume, waveTrack.partHeader.dwVariations, waveTrack.partHeader.dwPChannel, \ + waveTrack.partHeader.dwLockToPart, waveTrack.partHeader.dwFlags, waveTrack.partHeader.dwIndex); + break; + } case FOURCC_LIST: { + TRACE("'LIST': list\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_WAVEITEM_LIST) { + TRACE("'wavi': wave items list\n"); + ListSize3 = chunk.size - sizeof(FOURCC); + ListCount3 = 0; + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount3 += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + if (chunk.id == FOURCC_LIST && ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL) && chunk.id == DMUS_FOURCC_WAVE_LIST) { + TRACE("'wave': wave item list\n"); + ListSize4 = chunk.size - sizeof(FOURCC); /* list content size = size of 'LIST' chunk - FOURCC ID of the list */ + ListCount4 = 0; /* reset */ + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount4 += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + switch (chunk.id) + { + case DMUS_FOURCC_WAVEITEM_CHUNK: { + TRACE("'waih': wave item header\n"); + ReadFile (fd, &waveTrack.itemHeader, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> lVolume = %li; lPitch = %li; dwVariations = %ld; rtTime = FIXME; rtStartOffset = FIXME; rtReserved = FIXME; rtDuration = FIXME; mtLogicalTime = %li; dwLoopStart = %ld; dwLoopEnd = %ld; dwFlags = %ld\n", \ + waveTrack.itemHeader.lVolume, waveTrack.itemHeader.lPitch, waveTrack.itemHeader.dwVariations, /*waveTrack.itemHeader.rtTime, \ + waveTrack.itemHeader.rtStartOffset, waveTrack.itemHeader.rtReserved, waveTrack.itemHeader.rtDuration, */waveTrack.itemHeader.mtLogicalTime, \ + waveTrack.itemHeader.dwLoopStart, waveTrack.itemHeader.dwLoopEnd, waveTrack.itemHeader.dwFlags); + break; + } case mmioFOURCC('w','v','c','u'): { + FIXME("'wvcu': undocumented and unknown chunk type (skipping)\n"); + SetFilePointer (fd, chunk.size, NULL, FILE_CURRENT); /* skip */ + break; + } case FOURCC_LIST: { + TRACE("'LIST': list\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_REF_LIST) { + TRACE("'DMRF': reference list (forward to DMUSIC_FillReferenceFromFileHandle(...)\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before 'LIST' chunk */ + DMUSIC_FillReferenceFromFileHandle (waveTrack.reference, fd); + } else { + WARN ("invalid chunk (only 'DMRF' chunk allowed\n"); + } + break; + } default: { + WARN("invalid chunk (only 'waih' and 'LIST' (and undocumented 'wvcu') chunks allowed)\n"); + } + } + TRACE("ListCount4 (%ld) < ListSize4 (%ld)\n", ListCount4, ListSize4); + } while (ListCount4 < ListSize4); + } else { + WARN("invalid chunk (only 'wave' chunk allowed)\n"); + } + TRACE("ListCount3 (%ld) < ListSize3 (%ld)\n", ListCount3, ListSize3); + } while (ListCount3 < ListSize3); + } else { + WARN("invalid chunk (only 'wavi' chunk allowed)\n"); + } + break; + } default: { + WARN("invalid chunk (only 'waph' and 'LIST' chunks allowed)\n"); + break; + } + } + TRACE("ListCount2 (%ld) < ListSize2 (%ld)\n", ListCount2, ListSize2); + } while (ListCount2 < ListSize2); + } else { + WARN("invalid chunk (only 'wavp' chunk allwed)\n"); + } + break; + } default: { + WARN("invalid chunk (only 'wath' and 'LIST' chunks allowed)\n"); + break; + } + } + TRACE("ListCount (%ld) < ListSize (%ld)\n", ListCount, ListSize); + } while (ListCount < ListSize); + break; + } default: { + WARN ("invalid chunk (only 'UNFO', 'cord', 'sttr', 'pftr', 'lyrt', 'MARK' and 'mfrm' chunks allowed)\n"); + break; + } } break; } case FOURCC_RIFF: { @@ -538,7 +844,7 @@ HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, TRACE("'DMBD': embedded band form (forward to DMUSIC_FillBandFromFileHandle)\n"); SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before 'RIFF' chunk */ DMUSIC_FillBandFromFileHandle (NULL, fd); - } else WARN("invalid chunk (only 'RIFF' chunk allowed)\n"); + } else WARN("invalid chunk (only 'DMBD' chunk allowed)\n"); break; } default: { WARN("invalid chunk (only 'bdih', 'bd2h' and 'RIFF' chunks allowed)\n"); @@ -567,9 +873,6 @@ HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, WARN("invalid chunk (only 'DMBT' chunk allowed\n"); } break; - } case DMUS_FOURCC_PERS_TRACK_LIST: { - FIXME("'pftr': chordmap track list: not supported yet\n"); - break; } case DMUS_FOURCC_COMMANDTRACK_CHUNK: { TRACE("'cmnd': command track\n"); ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); /* read sizeof(DMUS_IO_COMMAND) */ @@ -577,30 +880,12 @@ HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, TRACE_(dmfiledat)("wMeasure = %d; bBeat = %i; bCommand = %i; bGrooveLevel = %i; bGrooveRange = %i; bRepeatMode = %i\n", \ command.wMeasure, command.bBeat, command.bCommand, command.bGrooveLevel, command.bGrooveRange, command.bRepeatMode); break; - } case DMUS_FOURCC_LYRICSTRACK_LIST: { - FIXME("'lyrt': lyrics track list: not supported yet\n"); - break; - } case DMUS_FOURCC_MARKERTRACK_LIST: { - FIXME("'MARK': marker track list: not supported yet\n"); - break; - } case DMUS_FOURCC_MELODYFORM_TRACK_LIST: { - FIXME("'mfrm': melody formulation track list: not supported yet\n"); - break; } case DMUS_FOURCC_MUTE_CHUNK: { FIXME("'mute': mute track chunk: not supported yet\n"); break; - } case DMUS_FOURCC_PARAMCONTROLTRACK_TRACK_LIST: { - FIXME("'prmt': parameter control track list: not supported yet\n"); - break; } case DMUS_FOURCC_PATTERN_FORM: { FIXME("'DMPT': pattern track form: not supported yet\n"); break; - } case DMUS_FOURCC_SCRIPTTRACK_LIST: { - FIXME("'scrt': script track list: not supported yet\n"); - break; - } case DMUS_FOURCC_SEGTRACK_LIST: { - FIXME("'segt': segment trigger track list: not supported yet\n"); - break; } case DMUS_FOURCC_SEQ_TRACK: { FIXME("'seqt': sequence track chunk: not supported yet\n"); break; @@ -614,16 +899,10 @@ HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, TRACE("'tetr': tempo track chunk\n"); ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); if (chunk.size != sizeof(DMUS_IO_TEMPO_ITEM)) - WARN("there seem so te ba problem: file claims that size of DMUSIC_IO_TEMPO_ITEM is %ld, while real sizeof returns %i", \ + WARN("there seem to be a problem: file claims that size of DMUSIC_IO_TEMPO_ITEM is %ld, while real sizeof returns %i\n", \ chunk.size, sizeof(DMUS_IO_TEMPO_ITEM)); ReadFile (fd, &tempo, chunk.size, &BytesRead, NULL); - TRACE_(dmfiledat)("lTime = %ld; dblTempo = %f\n", tempo.lTime, tempo.dblTempo); - break; - } case DMUS_FOURCC_TIMESIGNATURE_TRACK: { - FIXME("'tims': time signature track list: not supported yet\n"); - break; - } case DMUS_FOURCC_WAVETRACK_LIST: { - FIXME("'wavt': wave track list not supported yet\n"); + TRACE_(dmfiledat)("=> lTime = %ld; dblTempo = %f\n", tempo.lTime, tempo.dblTempo); break; } default: { WARN("invalid chunk (too many too list)\n"); @@ -642,6 +921,15 @@ HRESULT WINAPI DMUSIC_FillTrackFromFileHandle (IDirectMusicTrack8Impl *segment, return S_OK; } +/****************************************************************************** + * DMUSIC_FillSegmentFromFileHandle: + * - fills a IDirectMusicSegment8Impl struct with data from file handle. + * - IMPORTANT: it expects a RIFF chunk at beginning, so if you are calling it + * from another DMUSIC_Fill* function, make sure pointer is at + * correct place! + * - TODO: replace data in function with data in IDirectMusicSegmentImpl + * implement loading for missing (empty) clauses + */ HRESULT WINAPI DMUSIC_FillSegmentFromFileHandle (IDirectMusicSegment8Impl *segment, HANDLE fd) { rawChunk chunk; @@ -671,7 +959,7 @@ HRESULT WINAPI DMUSIC_FillSegmentFromFileHandle (IDirectMusicSegment8Impl *segme case DMUS_FOURCC_SEGMENT_CHUNK: { TRACE("segh: segment header\n"); ReadFile (fd, &header, chunk.size, &BytesRead, NULL); - TRACE_(dmfiledat)("dwRepeats = %ld; mtLength = %li; mtPlayStart = %li; mtLoopStart = %li; mtLoopEnd = %li; dwResolution = %ld; rtLenght = FIXME; dwFlags = %ld; dwReserved = %ld\n", \ + TRACE_(dmfiledat)("=> dwRepeats = %ld; mtLength = %li; mtPlayStart = %li; mtLoopStart = %li; mtLoopEnd = %li; dwResolution = %ld; rtLenght = FIXME; dwFlags = %ld; dwReserved = %ld\n", \ header.dwRepeats, header.mtLength, header.mtPlayStart, header.mtLoopStart, header.mtLoopEnd, header.dwResolution/*, header.rtLenght*/, header.dwFlags, header.dwReserved); break; } case DMUS_FOURCC_GUID_CHUNK: { @@ -710,9 +998,15 @@ HRESULT WINAPI DMUSIC_FillSegmentFromFileHandle (IDirectMusicSegment8Impl *segme } } break; - } case DMUS_FOURCC_CONTAINER_FORM: { - FIXME("'DMCN': container form chunk: not supported yet\n"); - break; + } case FOURCC_RIFF: { + TRACE("'RIFF': embedded RIFF (size = %ld; could be embedded container form)\n", chunk.size); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_CONTAINER_FORM) { + TRACE("'DMCN': embedded container form (forward to DMUSIC_FillContainerFromFileHandle(...))\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before 'RIFF' chunk */ + DMUSIC_FillContainerFromFileHandle (NULL, fd); + } else WARN("invalid chunk (only 'DMCN' chunk allowed)\n"); + break; } case DMUS_FOURCC_TOOLGRAPH_FORM: { FIXME("'DMTG': toolgraph chunk: not supported yet\n"); break; @@ -720,12 +1014,14 @@ HRESULT WINAPI DMUSIC_FillSegmentFromFileHandle (IDirectMusicSegment8Impl *segme FIXME("'DMAP': audiopath chunk: not supported yet\n"); break; } default: { - FIXME("invalid chunk (only 'segh', 'guid', 'vers', 'LIST', 'DMCN', 'DMTG' and 'DMAP' chunks allowed)\n"); + WARN("invalid chunk (only 'segh', 'guid', 'vers', 'LIST', 'RIFF', 'DMTG' and 'DMAP' chunks allowed)\n"); break; } } TRACE("FileCount (%ld) < FileSize (%ld)\n", FileCount, FileSize); } while (FileCount < FileSize); + } else { + WARN("invalid chunk (only 'DMSG' chunk allowed)\n"); } } else { WARN("'RIFF' not found: not a RIFF file\n"); @@ -733,3 +1029,578 @@ HRESULT WINAPI DMUSIC_FillSegmentFromFileHandle (IDirectMusicSegment8Impl *segme return S_OK; } + + /****************************************************************************** + * DMUSIC_FillScriptFromFileHandle: + * - fills a IDirectMusicScriptImpl struct with data from file handle. + * - IMPORTANT: it expects a RIFF chunk at beginning, so if you are calling it + * from another DMUSIC_Fill* function, make sure pointer is at + * correct place! + * - TODO: replace data in function with data in IDirectMusicScriptImpl + */ + +HRESULT WINAPI DMUSIC_FillScriptFromFileHandle (IDirectMusicScriptImpl *script, HANDLE fd) +{ + rawChunk chunk; + DWORD BytesRead/*, ListCount = 0*/, ListSize, FileCount = 0, FileSize; + /* FIXME: Replace stuff located below with the stuff in script */ + UNFO_List UNFO; + DMUS_IO_SCRIPT_HEADER header; + DMUS_IO_VERSION version, scriptversion; + GUID guid; + WCHAR* scriptlang; + WCHAR* scriptsrc; + Reference scriptsrcref; + + TRACE("reading 'RIFF' chunk...\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == FOURCC_RIFF) { + TRACE("'RIFF': RIFF file\n"); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); /* read size of 'RIFF' chunk */ + FileSize = chunk.size - sizeof(FOURCC); /* file content size = size of 'RIFF' chunk - FOURCC ID of following form */ + TRACE("reading chunks ...\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); /* read ID of following form */ + if (chunk.id == DMUS_FOURCC_SCRIPT_FORM) { + TRACE("'DMSC': script form\n"); + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + FileCount += chunk.size + sizeof(DWORD) + sizeof(FOURCC); + switch (chunk.id) + { + case DMUS_FOURCC_SCRIPT_CHUNK: { + TRACE("'schd': script header\n"); + ReadFile (fd, &header, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> dwFlags = %ld\n", header.dwFlags); + break; + } case DMUS_FOURCC_GUID_CHUNK: { + TRACE("'guid': GUID\n"); + ReadFile (fd, &guid, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> GUID = %s\n", debugstr_guid(&guid)); + break; + } case DMUS_FOURCC_VERSION_CHUNK: { + TRACE("'vers': version\n"); + ReadFile (fd, &version, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> version = %ld%ld\n", version.dwVersionMS, version.dwVersionLS); + break; + } case FOURCC_LIST:{ + TRACE("'LIST': list (size) = %ld\n", chunk.size); + ListSize = chunk.size - sizeof(FOURCC); /* list content size = size of 'LIST' chunk - FOURCC ID of the list */ + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + switch (chunk.id) + { + case DMUS_FOURCC_UNFO_LIST: { + TRACE("'UNFO': UNFO list (forward to DMUSIC_FillUNFOFromFileHandle(...))\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before the 'LIST' chunk */ + DMUSIC_FillUNFOFromFileHandle (UNFO, fd); + break; + } case DMUS_FOURCC_REF_LIST: { + TRACE("'DMRF': reference list (forward to DMUSIC_FillReferenceFromFileHandle(...)\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before 'LIST' chunk */ + DMUSIC_FillReferenceFromFileHandle (scriptsrcref, fd); + } default: { + WARN("invalid chunk (only 'UNFO' and 'DMRF' chunks allowed)\n"); + } + } + break; + } case DMUS_FOURCC_SCRIPTVERSION_CHUNK: { + TRACE("'scve': DirectMusic version\n"); + ReadFile (fd, &scriptversion, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> script version = %ld%ld\n", scriptversion.dwVersionMS, scriptversion.dwVersionLS); + break; + } case FOURCC_RIFF: { + TRACE("'RIFF': embedded RIFF (size = %ld; could be embedded container form)\n", chunk.size); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_CONTAINER_FORM) { + TRACE("'DMCN': embedded container form (forward to DMUSIC_FillContainerFromFileHandle(...))\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before 'RIFF' chunk */ + DMUSIC_FillContainerFromFileHandle (NULL, fd); + } else WARN("invalid chunk (only 'DMCN' chunk allowed)\n"); + break; + } case DMUS_FOURCC_SCRIPTLANGUAGE_CHUNK: { + TRACE("'scla': scripting language\n"); + scriptlang = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); /* allocate space */ + ReadFile (fd, scriptlang, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("script language = %s\n", debugstr_w(scriptlang)); + break; + } case DMUS_FOURCC_SCRIPTSOURCE_CHUNK: { + TRACE("'scsr': script source\n"); + scriptsrc = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); /* allocate space */ + ReadFile (fd, scriptsrc, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("script source = %s\n", debugstr_w(scriptsrc)); + break; + } default: { + WARN("invalid chunk (only 'schd', 'guid', 'vers', 'LIST', 'scve', 'RIFF' and 'scla' chunks allowed)\n"); + break; + } + } + TRACE("FileCount (%ld) < FileSize (%ld)\n", FileCount, FileSize); + } while (FileCount < FileSize); + } else { + WARN("invalid chunk (only 'DMSC' chunk allowed)\n"); + } + } else { + WARN("'RIFF' not found: not a RIFF file\n"); + } + + return S_OK; +} + +/****************************************************************************** + * DMUSIC_FillContainerFromFileHandle: + * - fills a IDirectMusicContainerImpl struct with data from file handle. + * - IMPORTANT: it expects a RIFF chunk at beginning, so if you are calling it + * from another DMUSIC_Fill* function, make sure pointer is at + * correct place! + * - TODO: replace data in function with data in IDirectMusicContainerImpl + */ +HRESULT WINAPI DMUSIC_FillContainerFromFileHandle (IDirectMusicContainerImpl *container, HANDLE fd) +{ + rawChunk chunk; + DWORD BytesRead, ListCount = 0, ListSize, ListCount2 = 0, ListSize2, FileCount = 0, FileSize; + /* FIXME: Replace stuff located below with the stuff in container */ + UNFO_List UNFO; + DMUS_IO_CONTAINER_HEADER header; + DMUS_IO_VERSION version; + GUID guid; + WCHAR* alias; + DMUS_IO_CONTAINED_OBJECT_HEADER objheader; + Reference dataref; + + TRACE("reading 'RIFF' chunk...\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == FOURCC_RIFF) { + TRACE("'RIFF': RIFF file\n"); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); /* read size of 'RIFF' chunk */ + FileSize = chunk.size - sizeof(FOURCC); /* file content size = size of 'RIFF' chunk - FOURCC ID of following form */ + TRACE("reading chunks ...\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); /* read ID of following form */ + if (chunk.id == DMUS_FOURCC_CONTAINER_FORM) { + TRACE("'DMCN': container form\n"); + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + FileCount += chunk.size + sizeof(DWORD) + sizeof(FOURCC); + switch (chunk.id) + { + case DMUS_FOURCC_CONTAINER_CHUNK: { + TRACE("'conh': container header\n"); + ReadFile (fd, &header, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> dwFlags = %ld\n", header.dwFlags); + break; + } case DMUS_FOURCC_GUID_CHUNK: { + TRACE("'guid': GUID\n"); + ReadFile (fd, &guid, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> GUID = %s\n", debugstr_guid(&guid)); + break; + } case DMUS_FOURCC_VERSION_CHUNK: { + TRACE("'vers': version\n"); + ReadFile (fd, &version, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> version = %ld%ld\n", version.dwVersionMS, version.dwVersionLS); + break; + } case FOURCC_LIST:{ + TRACE("'LIST': list (size) = %ld\n", chunk.size); + ListSize = chunk.size - sizeof(FOURCC); /* list content size = size of 'LIST' chunk - FOURCC ID of the list */ + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + switch (chunk.id) + { + case DMUS_FOURCC_UNFO_LIST: { + TRACE("'UNFO': UNFO list (forward to DMUSIC_FillUNFOFromFileHandle(...))\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before the 'LIST' chunk */ + DMUSIC_FillUNFOFromFileHandle (UNFO, fd); + break; + } case DMUS_FOURCC_CONTAINED_OBJECTS_LIST: { + TRACE("'cosl': objects list (content size = %ld)\n", ListSize); + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + if (chunk.id == FOURCC_LIST && ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL) && chunk.id == DMUS_FOURCC_CONTAINED_OBJECT_LIST) { + ListSize2 = chunk.size - sizeof(FOURCC); /* list content size = size of 'LIST' chunk - FOURCC ID of the list */ + ListCount2 = 0; /* reset */ + TRACE("'cobl': object (content size = %ld)\n", ListSize2); + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount2 += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + switch (chunk.id) + { + case DMUS_FOURCC_CONTAINED_ALIAS_CHUNK: { + TRACE("'coba': alias (size = %ld)\n", chunk.size); + alias = (WCHAR*) HeapAlloc (GetProcessHeap (), 0, chunk.size); /* allocate space */ + ReadFile (fd, alias, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> alias = %s\n", debugstr_w(alias)); + break; + } case DMUS_FOURCC_CONTAINED_OBJECT_CHUNK: { + TRACE("'cobh': object header (size = %ld)\n", chunk.size); + ReadFile (fd, &objheader, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> guidClassID = %s; dwFlags = %ld; ckid = %ld; fccType = %ld\n", \ + debugstr_guid(&objheader.guidClassID), objheader.dwFlags, objheader.ckid, objheader.fccType); + break; + } case FOURCC_LIST: { + TRACE("'LIST': list chunk (size = %ld)\n", chunk.size); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_REF_LIST) { + TRACE("'DMRF': reference list (instead of 'data' chunk: size = %ld)\n", chunk.size - 4); /* set pointer at beginning of list */ + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); + DMUSIC_FillReferenceFromFileHandle (dataref, fd); /* forward to DMUSIC_FillReferenceFromFileHandle */ + } else WARN("invalid chunk (only 'DMRF' chunk allowed\n"); + break; + } case FOURCC_RIFF: { + TRACE("'RIFF': encapsulated data (can be 'DMSG' or 'DMSG')\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before 'RIFF' chunk */ + switch (chunk.id) + { + case DMUS_FOURCC_SEGMENT_FORM: { + TRACE("'DMSG': embedded segment form (forward to DMUSIC_FillSegmentFromFileHandle(...))\n"); + DMUSIC_FillSegmentFromFileHandle (NULL, fd); + break; + } case DMUS_FOURCC_STYLE_FORM: { + TRACE("'DMST': embedded style form (forward to DMUSIC_FillStyleFromFileHandle(...))\n"); + DMUSIC_FillStyleFromFileHandle (NULL, fd); + break; + } case mmioFOURCC('W','A','V','E'): { + FIXME("'WAVE': not yet supported (skipping)\n"); + SetFilePointer (fd, sizeof(FOURCC) + sizeof(DWORD) + chunk.size, NULL, FILE_CURRENT); /* skip */ + break; + } default: { + WARN("invalid chunk (only 'DMSG' and 'DMST' chunks allowed)\n"); + break; + } + } + break; + } default: { + WARN("invalid chunk (only 'coba', 'cobh', 'data' and 'LIST' chunks allowed\n"); + break; + } + } + TRACE("ListCount2 (%ld) < ListSize2 (%ld)\n", ListCount2, ListSize2); + } while (ListCount2 < ListSize2); + } else WARN("invalid chunk (only 'cobl' chunk allowed)\n"); + TRACE("ListCount (%ld) < ListSize (%ld)\n", ListCount, ListSize); + } while (ListCount < ListSize); + break; + } default: { + WARN("invalid chunk (only 'UNFO' and 'cosl' chunks allowed)\n"); + } + } + break; + } default: { + WARN("invalid chunk (only 'schd', 'guid', 'vers', 'LIST', 'scve', 'RIFF' and 'scla' chunks allowed)\n"); + break; + } + } + TRACE("FileCount (%ld) < FileSize (%ld)\n", FileCount, FileSize); + } while (FileCount < FileSize); + } else { + WARN("invalid chunk (only 'DMSC' chunk allowed)\n"); + } + } else { + WARN("'RIFF' not found: not a RIFF file\n"); + } + + return S_OK; +} + +/****************************************************************************** + * DMUSIC_FillStyleFromFileHandle: + * - fills a IDirectMusicStyle8Impl struct with data from file handle. + * - IMPORTANT: it expects a RIFF chunk at beginning, so if you are calling it + * from another DMUSIC_Fill* function, make sure pointer is at + * correct place! + * - TODO: replace data in function with data in IDirectMusicStyleImpl + */ +HRESULT WINAPI DMUSIC_FillStyleFromFileHandle (IDirectMusicStyle8Impl *style, HANDLE fd) +{ + rawChunk chunk; + DWORD BytesRead, ListCount = 0, ListSize, ListCount2 = 0, ListSize2, FileCount = 0, FileSize; + int i; + /* FIXME: Replace stuff located below with the stuff in container */ + UNFO_List UNFO; + DMUS_IO_STYLE header; + DMUS_IO_VERSION version; + GUID guid; + Part part; + Pattern pattern; + + TRACE("reading 'RIFF' chunk...\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == FOURCC_RIFF) { + TRACE("'RIFF': RIFF file\n"); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); /* read size of 'RIFF' chunk */ + FileSize = chunk.size - sizeof(FOURCC); /* file content size = size of 'RIFF' chunk - FOURCC ID of following form */ + TRACE("reading chunks ...\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); /* read ID of following form */ + if (chunk.id == DMUS_FOURCC_STYLE_FORM) { + TRACE("'DMST': style form\n"); + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + FileCount += chunk.size + sizeof(DWORD) + sizeof(FOURCC); + + switch (chunk.id) + { + case DMUS_FOURCC_STYLE_CHUNK: { + TRACE("'styh': style header\n"); + ReadFile (fd, &header, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> timeSig.bBeatsPerMeasure = %i; timeSig.bBeat = %i; timeSig.wGridsPerBeat = %d; dblTempo = %lf\n", \ + header.timeSig.bBeatsPerMeasure, header.timeSig.bBeat, header.timeSig.wGridsPerBeat, header.dblTempo); + break; + } case DMUS_FOURCC_GUID_CHUNK: { + TRACE("'guid': GUID\n"); + ReadFile (fd, &guid, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> GUID = %s\n", debugstr_guid(&guid)); + break; + } case DMUS_FOURCC_VERSION_CHUNK: { + TRACE("'vers': version\n"); + ReadFile (fd, &version, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> version = %ld%ld\n", version.dwVersionMS, version.dwVersionLS); + break; + } case FOURCC_RIFF: { + TRACE("'RIFF': embedded RIFF (size = %ld; could be embedded band form)\n", chunk.size); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_BAND_FORM) { + TRACE("'DMBD': embedded band form (forward to DMUSIC_FillBandFromFileHandle)\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before 'RIFF' chunk */ + DMUSIC_FillBandFromFileHandle (NULL, fd); + } else WARN("invalid chunk (only 'DMBD' chunk allowed)\n"); + break; + } case FOURCC_LIST:{ + TRACE("'LIST': list (size) = %ld\n", chunk.size); + ListSize = chunk.size - sizeof(FOURCC); /* list content size = size of 'LIST' chunk - FOURCC ID of the list */ + ListCount = 0; + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + switch (chunk.id) + { + case DMUS_FOURCC_UNFO_LIST: { + TRACE("'UNFO': UNFO list (forward to DMUSIC_FillUNFOFromFileHandle(...))\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before the 'LIST' chunk */ + DMUSIC_FillUNFOFromFileHandle (UNFO, fd); + break; + } case DMUS_FOURCC_PART_LIST: { + TRACE("'part': parts list (content size = %ld)\n", ListSize); + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + switch (chunk.id) + { + case DMUS_FOURCC_PART_CHUNK: { + TRACE("'prth': part header\n"); + ReadFile (fd, &part.header, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> timeSig.bBeatsPerMeasure = %i; timeSig.bBeat = %i; timeSig.wGridsPerBeat = %d; dwVariationChoices = %p; guidPartID = %s; wNbrMeasures = %d; bPlayModeFlags = %i; bInvertUpper = %i; bInvertLower = %i; bPad = %p; dwFlags = %ld\n", \ + part.header.timeSig.bBeatsPerMeasure, part.header.timeSig.bBeat, part.header.timeSig.wGridsPerBeat, part.header.dwVariationChoices, \ + debugstr_guid (&part.header.guidPartID), part.header.wNbrMeasures, part.header.bPlayModeFlags, part.header.bInvertUpper, part.header.bInvertLower, \ + part.header.bPad, part.header.dwFlags); + break; + } case DMUS_FOURCC_NOTE_CHUNK: { + TRACE("'note': notes (size = %ld)\n", chunk.size); + part.nrofnotes = chunk.size - sizeof(DWORD); /* pure contents of 'note' (without first DWORD) */ + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); /* read sizeof (DMUS_IO_STYLENOTE) */ + part.nrofnotes /= chunk.size; /* nrofnotes = pure contents / sizeof (DMUS_IO_STYLENOTE) */ + part.notes = (DMUS_IO_STYLENOTE*) HeapAlloc (GetProcessHeap (), 0, chunk.size * part.nrofnotes); + ReadFile (fd, part.notes, chunk.size * part.nrofnotes, &BytesRead, NULL); + TRACE_(dmfiledat)("=> number of notes = %ld\n", part.nrofnotes); + for (i = 0; i < part.nrofnotes; i++) + { + TRACE_(dmfiledat)("=> note[%i]: mtGridStart = %li; dwVariation = %ld; mtDuration = %li; nTimeOffset = %i; wMusicValue = %d; bVelocity = %i; bTimeRange = %i; bDurRange = %i; bVelRange = %i; bInversionID = %i; bPlayModeFlags = %i; bNoteFlags= %i;\n", \ + i, part.notes[i].mtGridStart, part.notes[i].dwVariation, part.notes[i].mtDuration, part.notes[i].nTimeOffset, part.notes[i].wMusicValue, part.notes[i].bVelocity, part.notes[i].bTimeRange, \ + part.notes[i].bDurRange, part.notes[i].bVelRange, part.notes[i].bInversionID, part.notes[i].bPlayModeFlags, part.notes[i].bNoteFlags); + } + break; + } case DMUS_FOURCC_CURVE_CHUNK: { + TRACE("'crve': curves (size = %ld)\n", chunk.size); + part.nrofcurves = chunk.size - sizeof(DWORD); /* pure contents of 'crve' (without first DWORD) */ + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); /* read sizeof (DMUS_IO_STYLECURVE) */ + part.nrofcurves /= chunk.size; /* nrofnotes = pure contents / sizeof (DMUS_IO_STYLECURVE) */ + part.curves = (DMUS_IO_STYLECURVE*) HeapAlloc (GetProcessHeap (), 0, chunk.size * part.nrofcurves); + ReadFile (fd, part.curves, chunk.size * part.nrofcurves, &BytesRead, NULL); + TRACE_(dmfiledat)("=> number of curves = %ld\n", part.nrofcurves); + for (i = 0; i < part.nrofcurves; i++) + { + TRACE_(dmfiledat)("=> curve[%i]: mtGridStart = %li; dwVariation = %ld; mtDuration = %li; mtResetDuration = %li; nTimeOffset = %i; nStartValue = %i; nEndValue = %i; nResetValue = %i; bEventType = %i; bCurveShape = %i; bCCData = %i; bFlags = %i; wParamType = %d;wMergeIndex = %d\n", \ + i, part.curves[i].mtGridStart, part.curves[i].dwVariation, part.curves[i].mtDuration, part.curves[i].mtResetDuration, part.curves[i].nTimeOffset, part.curves[i].nStartValue, part.curves[i].nEndValue, \ + part.curves[i].nResetValue, part.curves[i].bEventType, part.curves[i].bCurveShape, part.curves[i].bCCData, part.curves[i].bFlags, part.curves[i].wParamType, part.curves[i].wMergeIndex); + } + break; + } case DMUS_FOURCC_MARKER_CHUNK: { + TRACE("'mrkr': markers (size = %ld)\n", chunk.size); + part.nrofmarkers = chunk.size - sizeof(DWORD); /* pure contents of 'mrkr' (without first DWORD) */ + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); /* read sizeof (DMUS_IO_STYLEMARKER) */ + part.nrofmarkers /= chunk.size; /* nrofnotes = pure contents / sizeof (DMUS_IO_STYLEMARKER) */ + part.markers = (DMUS_IO_STYLEMARKER*) HeapAlloc (GetProcessHeap (), 0, chunk.size * part.nrofmarkers); + ReadFile (fd, part.markers, chunk.size * part.nrofmarkers, &BytesRead, NULL); + TRACE_(dmfiledat)("=> number of markers = %ld\n", part.nrofmarkers); + for (i = 0; i < part.nrofmarkers; i++) + { + TRACE_(dmfiledat)("=> marker[%i]: mtGridStart = %li; dwVariation = %ld; wMarkerFlags = %d\n", \ + i, part.markers[i].mtGridStart, part.markers[i].dwVariation, part.markers[i].wMarkerFlags); + } + break; + } case DMUS_FOURCC_RESOLUTION_CHUNK: { + TRACE("'rsln': resolutions (size = %ld)\n", chunk.size); + part.nrofresolutions = chunk.size - sizeof(DWORD); /* pure contents of 'rsln' (without first DWORD) */ + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); /* read sizeof (DMUS_IO_STYLERESOLUTION) */ + part.nrofresolutions /= chunk.size; /* nrofnotes = pure contents / sizeof (DMUS_IO_STYLERESOLUTION) */ + part.resolutions = (DMUS_IO_STYLERESOLUTION*) HeapAlloc (GetProcessHeap (), 0, chunk.size * part.nrofresolutions); + ReadFile (fd, part.resolutions, chunk.size * part.nrofresolutions, &BytesRead, NULL); + TRACE_(dmfiledat)("=> number of resolutions = %ld\n", part.nrofresolutions); + for (i = 0; i < part.nrofresolutions; i++) + { + TRACE_(dmfiledat)("=> resolution[%i]: dwVariation = %ld; wMusicValue = %d; bInversionID = %i; bPlayModeFlags = %i", \ + i, part.resolutions[i].dwVariation, part.resolutions[i].wMusicValue, part.resolutions[i].bInversionID, part.resolutions[i].bPlayModeFlags); + } + break; + } case DMUS_FOURCC_ANTICIPATION_CHUNK: { + TRACE("'anpn': anticipations (size = %ld)\n", chunk.size); + part.nrofanticipations = chunk.size - sizeof(DWORD); /* pure contents of 'anpn' (without first DWORD) */ + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); /* read sizeof (DMUS_IO_STYLE_ANTICIPATION) */ + part.nrofanticipations /= chunk.size; /* nrofnotes = pure contents / sizeof (DMUS_IO_STYLE_ANTICIPATION) */ + part.anticipations = (DMUS_IO_STYLE_ANTICIPATION*) HeapAlloc (GetProcessHeap (), 0, chunk.size * part.nrofanticipations); + ReadFile (fd, part.anticipations, chunk.size * part.nrofanticipations, &BytesRead, NULL); + TRACE_(dmfiledat)("=> number of anticipations = %ld\n", part.nrofanticipations); + for (i = 0; i < part.nrofanticipations; i++) + { + TRACE_(dmfiledat)("=> anticipation[%i]: mtGridStart = %li; dwVariation = %ld; nTimeOffset = %i; bTimeRange = %i\n", \ + i, part.anticipations[i].mtGridStart, part.anticipations[i].dwVariation, part.anticipations[i].nTimeOffset, part.anticipations[i].bTimeRange); + } + break; + } case FOURCC_LIST: { + TRACE("'LIST': list chunk (size = %ld)\n", chunk.size); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_UNFO_LIST) { + TRACE("'UNFO': UNFO list (forward to DMUSIC_FillUNFOFromFileHandle(...))\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* set pointer at beginning of list */ + DMUSIC_FillUNFOFromFileHandle (part.UNFO, fd); + } else WARN("invalid chunk (only 'UNFO' chunk allowed\n"); + break; + } default: { + WARN("invalid chunk (only 'prth','note', 'crve', 'mrkr', 'rsln', 'anpn' and 'LIST' chunks allowed\n"); + break; + } + } + TRACE("ListCount (%ld) < ListSize (%ld)\n", ListCount, ListSize); + } while (ListCount < ListSize); + break; + } case DMUS_FOURCC_PATTERN_LIST: { + TRACE("'pttn': patterns list (content size = %ld)\n", ListSize); + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + switch (chunk.id) + { + case DMUS_FOURCC_PATTERN_CHUNK: { + TRACE("'ptnh': pattern header\n"); + ReadFile (fd, &pattern.header, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> timeSig.bBeatsPerMeasure = %i; timeSig.bBeat = %i; timeSig.wGridsPerBeat = %d; bGrooveBottom = %i; bGrooveTop = %i; wEmbellishment = %d; wNbrMeasures = %d; bDestGrooveBottom = %i; bDestGrooveTop = %i; dwFlags = %ld\n", \ + pattern.header.timeSig.bBeatsPerMeasure, pattern.header.timeSig.bBeat, pattern.header.timeSig.wGridsPerBeat, pattern.header.bGrooveBottom, pattern.header.bGrooveTop, pattern.header.wEmbellishment, \ + pattern.header.wNbrMeasures, pattern.header.bDestGrooveBottom, pattern.header.bDestGrooveTop, pattern.header.dwFlags); + break; + } case DMUS_FOURCC_RHYTHM_CHUNK: { + TRACE("'rhtm': rhytms\n"); + pattern.nrofrhytms = chunk.size / sizeof(DWORD); + TRACE_(dmfiledat)("=> number of rhytms = %ld\n", pattern.nrofrhytms); + pattern.rhytms = (DWORD*) HeapAlloc (GetProcessHeap (), 0, sizeof(DWORD) * pattern.nrofrhytms); + ReadFile (fd, pattern.rhytms, sizeof(DWORD) * pattern.nrofrhytms, &BytesRead, NULL); + for (i = 0; i < pattern.nrofrhytms; i++) + { + TRACE_(dmfiledat)("=> rhytm[%i] = %ld\n", i, pattern.rhytms[i]); + } + break; + } case DMUS_FOURCC_MOTIFSETTINGS_CHUNK: { + TRACE("'mtfs': motif settings\n"); + ReadFile (fd, &pattern.motsettings, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> dwRepeats = %ld; mtPlayStart = %li; mtLoopStart = %li; mtLoopEnd = %li; dwResolution = %ld\n", \ + pattern.motsettings.dwRepeats, pattern.motsettings.mtPlayStart, pattern.motsettings.mtLoopStart, pattern.motsettings.mtLoopEnd, pattern.motsettings.dwResolution); + break; + } case FOURCC_LIST: { + TRACE("'LIST': list chunk (size = %ld)\n", chunk.size); + ListSize2 = chunk.size - sizeof(FOURCC); /* list content size = size of 'LIST' chunk - FOURCC ID of the list */ + ListCount2 = 0; + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + switch (chunk.id) + { + case DMUS_FOURCC_UNFO_LIST: { + TRACE("'UNFO': UNFO list (forward to DMUSIC_FillUNFOFromFileHandle(...))\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before the 'LIST' chunk */ + DMUSIC_FillUNFOFromFileHandle (UNFO, fd); + break; + } case DMUS_FOURCC_PARTREF_LIST: { + TRACE("'pref': part references list (content size = %ld)\n", ListSize2); + do { + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + ReadFile (fd, &chunk.size, sizeof(DWORD), &BytesRead, NULL); + ListCount2 += sizeof(FOURCC) + sizeof(DWORD) + chunk.size; + switch (chunk.id) + { + case DMUS_FOURCC_PARTREF_CHUNK: { + TRACE("'prfc': part reference\n"); + ReadFile (fd, &pattern.partref, chunk.size, &BytesRead, NULL); + TRACE_(dmfiledat)("=> guidPartID = %s; wLogicalPartID = %d; bVariationLockID = %i; bSubChordLevel = %i; bPriority = %i; bRandomVariation = %i; wPad = %d; dwPChannel = %ld\n", \ + debugstr_guid (&pattern.partref.guidPartID), pattern.partref.wLogicalPartID, pattern.partref.bVariationLockID, pattern.partref.bSubChordLevel, \ + pattern.partref.bPriority, pattern.partref.bRandomVariation, pattern.partref.wPad, pattern.partref.dwPChannel); + break; + } case FOURCC_LIST: { + TRACE("'LIST': list chunk (MSDN doesn't mention it)\n"); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_UNFO_LIST) { + TRACE("'UNFO': UNFO list (forward to DMUSIC_FillUNFOFromFileHandle(...))\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before the 'LIST' chunk */ + DMUSIC_FillUNFOFromFileHandle (UNFO, fd); + } else { + WARN("invalid chunk (only 'UNFO' chunk allowed)\n"); + } + break; + } default: { + WARN("invalid chunk (only 'prfc' and 'UNFO'chunk allowed)\n"); + } + } + TRACE("ListCount2 (%ld) < ListSize2 (%ld)\n", ListCount2, ListSize2); + } while (ListCount2 < ListSize2); + break; + } default: { + WARN("invalid chunk (only 'UNFO' and 'pref' chunks allowed\n"); + break; + } + } + break; + } case FOURCC_RIFF: { + TRACE("'RIFF': embedded RIFF (size = %ld; could be embedded band form)\n", chunk.size); + ReadFile (fd, &chunk.id, sizeof(FOURCC), &BytesRead, NULL); + if (chunk.id == DMUS_FOURCC_BAND_FORM) { + TRACE("'DMBD': embedded band form (forward to DMUSIC_FillBandFromFileHandle(...))\n"); + SetFilePointer (fd, -(sizeof(DWORD) + 2*sizeof(FOURCC)), NULL, FILE_CURRENT); /* place pointer before 'RIFF' chunk */ + DMUSIC_FillBandFromFileHandle (NULL, fd); + } else WARN("invalid chunk (only 'DMBD' chunk allowed)\n"); + break; + } default: { + WARN("invalid chunk (only 'prnh','rhtm', 'mtfs', 'LIST' and 'RIFF' chunks allowed\n"); + break; + } + } + TRACE("ListCount (%ld) < ListSize (%ld)\n", ListCount, ListSize); + } while (ListCount < ListSize); + break; + } default: { + WARN("invalid chunk (only 'UNFO', 'part', 'pttn' and 'RIFF' chunks allowed)\n"); + } + } + break; + } default: { + WARN("invalid chunk (only 'styh', 'guid', 'vers', 'LIST', and 'RIFF' chunks allowed)\n"); + break; + } + } + TRACE("FileCount (%ld) < FileSize (%ld)\n", FileCount, FileSize); + } while (FileCount < FileSize); + } else { + WARN("invalid chunk (only 'DMST' chunk allowed)\n"); + } + } else { + WARN("'RIFF' not found: not a RIFF file\n"); + } + + return S_OK; +}