diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index f6df8ce4b5e..ec3426b4dac 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -144,6 +144,15 @@ extern HRESULT WINAPI DMUSIC_CreateDirectMusicTimeSigTrack (LPCGUID lpcGUID, LPV extern HRESULT WINAPI DMUSIC_CreateDirectMusicWaveTrack (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter); +/***************************************************************************** + * Auxiliary definitions + */ +typedef struct _DMUS_PRIVATE_SEGMENT_TRACK { + struct list entry; /* for listing elements */ + DWORD dwGroupBits; + IDirectMusicTrack* pTrack; +} DMUS_PRIVATE_SEGMENT_TRACK, *LPDMUS_PRIVATE_SEGMENT_TRACK; + /* some sort of aux. performance channel: as far as i can understand, these are used to represent a particular midi channel in particular group at particular group; so all we need to do is to fill it with parent port, group and midi @@ -266,7 +275,8 @@ struct IDirectMusicSegment8Impl { /* IDirectMusicSegment8Impl fields */ LPDMUS_OBJECTDESC pDesc; DMUS_IO_SEGMENT_HEADER header; - IDirectMusicGraph* pGraph; + IDirectMusicGraph* pGraph; + struct list Tracks; }; /* IUnknown: */ diff --git a/dlls/dmime/segment.c b/dlls/dmime/segment.c index 27f3cba0dee..8e5507382b0 100644 --- a/dlls/dmime/segment.c +++ b/dlls/dmime/segment.c @@ -158,15 +158,64 @@ HRESULT WINAPI IDirectMusicSegment8Impl_IDirectMusicSegment8_GetTrackGroup (LPDI } HRESULT WINAPI IDirectMusicSegment8Impl_IDirectMusicSegment8_InsertTrack (LPDIRECTMUSICSEGMENT8 iface, IDirectMusicTrack* pTrack, DWORD dwGroupBits) { + LPDMUS_PRIVATE_SEGMENT_TRACK pNewSegTrack; ICOM_THIS_MULTI(IDirectMusicSegment8Impl, SegmentVtbl, iface); - FIXME("(%p, %p, %ld): stub\n", This, pTrack, dwGroupBits); + + struct list *pEntry; + DWORD i = 0; + LPDMUS_PRIVATE_SEGMENT_TRACK pIt = NULL; + + TRACE("(%p, %p, %ld)\n", This, pTrack, dwGroupBits); + + LIST_FOR_EACH (pEntry, &This->Tracks) { + i++; + pIt = LIST_ENTRY(pEntry, DMUS_PRIVATE_SEGMENT_TRACK, entry); + TRACE(" - #%lu: %p -> %ld,%p\n", i, pIt, pIt->dwGroupBits, pIt->pTrack); + if (NULL != pIt && pIt->pTrack == pTrack) { + ERR("(%p, %p): track is already in list\n", This, pTrack); + return E_FAIL; + } + } + + pNewSegTrack = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_SEGMENT_TRACK)); + if (NULL == pNewSegTrack) { + ERR(": no more memory\n"); + return E_OUTOFMEMORY; + } + pNewSegTrack->dwGroupBits = dwGroupBits; + pNewSegTrack->pTrack = pTrack; + IDirectMusicTrack_Init(pTrack, iface); + IDirectMusicTrack_AddRef(pTrack); + list_add_tail (&This->Tracks, &pNewSegTrack->entry); + return S_OK; } HRESULT WINAPI IDirectMusicSegment8Impl_IDirectMusicSegment8_RemoveTrack (LPDIRECTMUSICSEGMENT8 iface, IDirectMusicTrack* pTrack) { ICOM_THIS_MULTI(IDirectMusicSegment8Impl, SegmentVtbl, iface); + + struct list *pEntry; + DWORD i = 0; + LPDMUS_PRIVATE_SEGMENT_TRACK pIt = NULL; + FIXME("(%p, %p): stub\n", This, pTrack); - return S_OK; + + LIST_FOR_EACH (pEntry, &This->Tracks) { + i++; + pIt = LIST_ENTRY(pEntry, DMUS_PRIVATE_SEGMENT_TRACK, entry); + if (pIt->pTrack == pTrack) { + TRACE("(%p, %p): track in list\n", This, pTrack); + + list_remove(&pIt->entry); + IDirectMusicTrack_Init(pIt->pTrack, NULL); + IDirectMusicTrack_Release(pIt->pTrack); + HeapFree(GetProcessHeap(), 0, pIt); + + return S_OK; + } + } + + return S_FALSE; } HRESULT WINAPI IDirectMusicSegment8Impl_IDirectMusicSegment8_InitPlay (LPDIRECTMUSICSEGMENT8 iface, IDirectMusicSegmentState** ppSegState, IDirectMusicPerformance* pPerformance, DWORD dwFlags) { @@ -655,7 +704,7 @@ static HRESULT IDirectMusicSegment8Impl_IPersistStream_LoadTrack (LPPERSISTSTREA /* release all loading-related stuff */ IPersistStream_Release (pPersistStream); - hr = IDirectMusicSegment8Impl_IDirectMusicSegment8_InsertTrack ((LPDIRECTMUSICSEGMENT8)This->SegmentVtbl, *ppTrack, pTrack_hdr->dwGroup); /* at dsPosition */ + hr = IDirectMusicSegment8Impl_IDirectMusicSegment8_InsertTrack ((LPDIRECTMUSICSEGMENT8)&This->SegmentVtbl, *ppTrack, pTrack_hdr->dwGroup); /* at dsPosition */ if (FAILED(hr)) { ERR(": could not insert track\n"); return hr; @@ -1099,6 +1148,7 @@ HRESULT WINAPI DMUSIC_CreateDirectMusicSegmentImpl (LPCGUID lpcGUID, LPVOID* ppo obj->pDesc->dwValidData |= DMUS_OBJ_CLASS; memcpy (&obj->pDesc->guidClass, &CLSID_DirectMusicSegment, sizeof (CLSID)); obj->ref = 0; /* will be inited by QueryInterface */ + list_init (&obj->Tracks); return IDirectMusicSegment8Impl_IUnknown_QueryInterface ((LPUNKNOWN)&obj->UnknownVtbl, lpcGUID, ppobj); } diff --git a/dlls/dmstyle/dmstyle_private.h b/dlls/dmstyle/dmstyle_private.h index 91dcc777c77..be904b66f9a 100644 --- a/dlls/dmstyle/dmstyle_private.h +++ b/dlls/dmstyle/dmstyle_private.h @@ -93,6 +93,22 @@ extern ICOM_VTABLE(IPersistStream) DirectMusicStyleTrack_PersistStream_Vtbl; */ extern HRESULT WINAPI DMUSIC_CreateDirectMusicStyleImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter); +/***************************************************************************** + * Auxiliary definitions + */ +typedef struct _DMUS_PRIVATE_STYLE_BAND { + struct list entry; /* for listing elements */ + IDirectMusicBand* pBand; +} DMUS_PRIVATE_STYLE_BAND, *LPDMUS_PRIVATE_STYLE_BAND; + +typedef struct _DMUS_PRIVATE_STYLE_MOTIF { + struct list entry; /* for listing elements */ + DMUS_OBJECTDESC desc; + DMUS_IO_PATTERN pattern; + DMUS_IO_MOTIFSETTINGS settings; + IDirectMusicBand* pBand; +} DMUS_PRIVATE_STYLE_MOTIF, *LPDMUS_PRIVATE_STYLE_MOTIF; + extern HRESULT WINAPI DMUSIC_CreateDirectMusicAuditionTrack (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter); extern HRESULT WINAPI DMUSIC_CreateDirectMusicChordTrack (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter); extern HRESULT WINAPI DMUSIC_CreateDirectMusicCommandTrack (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter); @@ -115,6 +131,10 @@ struct IDirectMusicStyle8Impl { /* IDirectMusicStyle8Impl fields */ LPDMUS_OBJECTDESC pDesc; DMUS_IO_STYLE style; + + /* data */ + struct list Motifs; + struct list Bands; }; /* IUnknown: */ diff --git a/dlls/dmstyle/style.c b/dlls/dmstyle/style.c index 1e6aad35cb9..a9d0d911872 100644 --- a/dlls/dmstyle/style.c +++ b/dlls/dmstyle/style.c @@ -430,7 +430,36 @@ HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_IsDirty (LPPERSISTSTREAM if return S_FALSE; } -static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePartRefList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) { +static HRESULT IDirectMusicStyle8Impl_IPersistStream_LoadBand (LPPERSISTSTREAM iface, IStream* pClonedStream, IDirectMusicBand** ppBand) { + + HRESULT hr = E_FAIL; + IPersistStream* pPersistStream = NULL; + + hr = CoCreateInstance (&CLSID_DirectMusicBand, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicBand, (LPVOID*) ppBand); + if (FAILED(hr)) { + ERR(": could not create object\n"); + return hr; + } + /* acquire PersistStream interface */ + hr = IDirectMusicBand_QueryInterface (*ppBand, &IID_IPersistStream, (LPVOID*) &pPersistStream); + if (FAILED(hr)) { + ERR(": could not acquire IPersistStream\n"); + return hr; + } + /* load */ + hr = IPersistStream_Load (pPersistStream, pClonedStream); + if (FAILED(hr)) { + ERR(": failed to load object\n"); + return hr; + } + + /* release all loading-related stuff */ + IPersistStream_Release (pPersistStream); + + return S_OK; +} + +static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePartRefList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm, LPDMUS_PRIVATE_STYLE_MOTIF pNewMotif) { /*ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);*/ HRESULT hr = E_FAIL; DMUS_PRIVATE_CHUNK Chunk; @@ -457,7 +486,7 @@ static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePartRefList (LPPERSIST liMove.QuadPart = Chunk.dwSize; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); break; - } + } case FOURCC_LIST: { IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID)); @@ -623,17 +652,19 @@ static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePartList (LPPERSISTSTR static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePatternList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) { - /*ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);*/ + ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface); HRESULT hr = E_FAIL; DMUS_PRIVATE_CHUNK Chunk; DWORD ListSize[3], ListCount[3]; LARGE_INTEGER liMove; /* used when skipping chunks */ - DMUS_IO_PATTERN pattern; - DWORD dwRythm = 0; + DWORD dwRythm; DMUS_OBJECTDESC desc; + IDirectMusicBand* pBand = NULL; + LPDMUS_PRIVATE_STYLE_MOTIF pNewMotif = NULL; - memset(&pattern, 0, sizeof(pattern)); + dwRythm = 0; + DM_STRUCT_INIT(&desc); if (pChunk->fccID != DMUS_FOURCC_PATTERN_LIST) { ERR_(dmfile)(": %s chunk should be a PATTERN list\n", debugstr_fourcc (pChunk->fccID)); @@ -650,8 +681,20 @@ static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePatternList (LPPERSIST switch (Chunk.fccID) { case DMUS_FOURCC_PATTERN_CHUNK: { TRACE_(dmfile)(": Pattern chunk\n"); - IStream_Read (pStm, &pattern, Chunk.dwSize, NULL); + /** alloc new motif entry */ + pNewMotif = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_MOTIF)); + list_add_tail (&This->Motifs, &pNewMotif->entry); + if (NULL == pNewMotif) { + ERR(": no more memory\n"); + return E_OUTOFMEMORY; + } + + IStream_Read (pStm, &pNewMotif->pattern, Chunk.dwSize, NULL); /** TODO trace pattern */ + + /** reset all datas, as a new pattern begin */ + dwRythm = 0; + DM_STRUCT_INIT(&pNewMotif->desc); break; } case DMUS_FOURCC_RHYTHM_CHUNK: { @@ -665,8 +708,55 @@ static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePatternList (LPPERSIST } case DMUS_FOURCC_MOTIFSETTINGS_CHUNK: { TRACE_(dmfile)(": MotifSettigns chunk (skipping for now)\n"); - liMove.QuadPart = Chunk.dwSize; - IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); + IStream_Read (pStm, &pNewMotif->settings, Chunk.dwSize, NULL); + /** TODO trace settings */ + break; + } + case FOURCC_RIFF: { + /** + * sould be embededs Bands into pattern + */ + IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL); + TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID)); + ListSize[1] = Chunk.dwSize - sizeof(FOURCC); + ListCount[1] = 0; + switch (Chunk.fccID) { + case DMUS_FOURCC_BAND_FORM: { + LPSTREAM pClonedStream = NULL; + + TRACE_(dmfile)(": BAND RIFF\n"); + + IStream_Clone (pStm, &pClonedStream); + + liMove.QuadPart = 0; + liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD)); + IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL); + + hr = IDirectMusicStyle8Impl_IPersistStream_LoadBand (iface, pClonedStream, &pBand); + if (FAILED(hr)) { + ERR(": could not load track\n"); + return hr; + } + IStream_Release (pClonedStream); + + pNewMotif->pBand = pBand; + IDirectMusicBand_AddRef(pBand); + + IDirectMusicTrack_Release(pBand); pBand = NULL; /* now we can release at as it inserted */ + + /** now safe move the cursor */ + liMove.QuadPart = ListSize[1]; + IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); + + break; + } + default: { + TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n"); + liMove.QuadPart = ListSize[1]; + IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); + break; + } + } break; } case FOURCC_LIST: { @@ -682,7 +772,7 @@ static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePatternList (LPPERSIST ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize; TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize); - hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &desc); + hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &pNewMotif->desc); if (FAILED(hr)) return hr; if (hr == S_FALSE) { @@ -701,7 +791,7 @@ static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePatternList (LPPERSIST } case DMUS_FOURCC_PARTREF_LIST: { TRACE_(dmfile)(": PartRef list\n"); - hr = IDirectMusicStyle8Impl_IPersistStream_ParsePartRefList (iface, &Chunk, pStm); + hr = IDirectMusicStyle8Impl_IPersistStream_ParsePartRefList (iface, &Chunk, pStm, pNewMotif); if (FAILED(hr)) return hr; break; } @@ -735,6 +825,8 @@ static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParseStyleForm (LPPERSISTST DWORD StreamSize, StreamCount, ListSize[3], ListCount[3]; LARGE_INTEGER liMove; /* used when skipping chunks */ + IDirectMusicBand* pBand = NULL; + if (pChunk->fccID != DMUS_FOURCC_STYLE_FORM) { ERR_(dmfile)(": %s chunk should be a STYLE form\n", debugstr_fourcc (pChunk->fccID)); return E_FAIL; @@ -769,10 +861,10 @@ static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParseStyleForm (LPPERSISTST ListSize[0] = Chunk.dwSize - sizeof(FOURCC); ListCount[0] = 0; switch (Chunk.fccID) { - case DMUS_FOURCC_BAND_FORM: { - TRACE_(dmfile)(": BAND RIFF (TODO load it)\n"); - /* + case DMUS_FOURCC_BAND_FORM: { LPSTREAM pClonedStream = NULL; + LPDMUS_PRIVATE_STYLE_BAND pNewBand; + TRACE_(dmfile)(": BAND RIFF\n"); IStream_Clone (pStm, &pClonedStream); @@ -781,15 +873,24 @@ static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParseStyleForm (LPPERSISTST liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD)); IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL); - hr = IDirectMusicStyle8Impl_IPersistStream_LoadBand (iface, pClonedStream, &pBand, &header); + hr = IDirectMusicStyle8Impl_IPersistStream_LoadBand (iface, pClonedStream, &pBand); if (FAILED(hr)) { ERR(": could not load track\n"); return hr; } IStream_Release (pClonedStream); - IDirectMusicTrack_Release(pBand); pBand = NULL; - */ + pNewBand = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_BAND)); + if (NULL == pNewBand) { + ERR(": no more memory\n"); + return E_OUTOFMEMORY; + } + pNewBand->pBand = pBand; + IDirectMusicBand_AddRef(pBand); + list_add_tail (&This->Bands, &pNewBand->entry); + + IDirectMusicTrack_Release(pBand); pBand = NULL; /* now we can release at as it inserted */ + /** now safe move the cursor */ liMove.QuadPart = ListSize[0]; IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); @@ -956,6 +1057,8 @@ HRESULT WINAPI DMUSIC_CreateDirectMusicStyleImpl (LPCGUID lpcGUID, LPVOID* ppobj obj->pDesc->dwValidData |= DMUS_OBJ_CLASS; memcpy (&obj->pDesc->guidClass, &CLSID_DirectMusicStyle, sizeof (CLSID)); obj->ref = 0; /* will be inited by QueryInterface */ - + list_init (&obj->Bands); + list_init (&obj->Motifs); + return IDirectMusicStyle8Impl_IUnknown_QueryInterface ((LPUNKNOWN)&obj->UnknownVtbl, lpcGUID, ppobj); }