msi: win95 returns ERROR_BAD_PATHNAME.
[wine] / dlls / dmstyle / commandtrack.c
1 /* IDirectMusicCommandTrack Implementation
2  *
3  * Copyright (C) 2003-2004 Rok Mandeljc
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include "dmstyle_private.h"
21
22 WINE_DEFAULT_DEBUG_CHANNEL(dmstyle);
23 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
24
25 static ULONG WINAPI IDirectMusicCommandTrack_IUnknown_AddRef (LPUNKNOWN iface);
26 static ULONG WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_AddRef (LPDIRECTMUSICTRACK8 iface);
27 static ULONG WINAPI IDirectMusicCommandTrack_IPersistStream_AddRef (LPPERSISTSTREAM iface);
28
29 /*****************************************************************************
30  * IDirectMusicCommandTrack implementation
31  */
32 /* IDirectMusicCommandTrack IUnknown part: */
33 static HRESULT WINAPI IDirectMusicCommandTrack_IUnknown_QueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID *ppobj) {
34         ICOM_THIS_MULTI(IDirectMusicCommandTrack, UnknownVtbl, iface);
35         TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
36
37         if (IsEqualIID (riid, &IID_IUnknown)) {
38                 *ppobj = (LPUNKNOWN)&This->UnknownVtbl;
39                 IDirectMusicCommandTrack_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
40                 return S_OK;
41         } else if (IsEqualIID (riid, &IID_IDirectMusicTrack)
42           || IsEqualIID (riid, &IID_IDirectMusicTrack8)) {
43                 *ppobj = (LPDIRECTMUSICTRACK8)&This->TrackVtbl;
44                 IDirectMusicCommandTrack_IDirectMusicTrack_AddRef ((LPDIRECTMUSICTRACK8)&This->TrackVtbl);
45                 return S_OK;
46         } else if (IsEqualIID (riid, &IID_IPersistStream)) {
47                 *ppobj = (LPPERSISTSTREAM)&This->PersistStreamVtbl;
48                 IDirectMusicCommandTrack_IPersistStream_AddRef ((LPPERSISTSTREAM)&This->PersistStreamVtbl);
49                 return S_OK;
50         }
51         
52         WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj);
53         return E_NOINTERFACE;
54 }
55
56 static ULONG WINAPI IDirectMusicCommandTrack_IUnknown_AddRef (LPUNKNOWN iface) {
57         ICOM_THIS_MULTI(IDirectMusicCommandTrack, UnknownVtbl, iface);
58         ULONG ref = InterlockedIncrement(&This->ref);
59
60         TRACE("(%p): AddRef from %d\n", This, ref - 1);
61
62         DMSTYLE_LockModule();
63
64         return ref;
65 }
66
67 static ULONG WINAPI IDirectMusicCommandTrack_IUnknown_Release (LPUNKNOWN iface) {
68         ICOM_THIS_MULTI(IDirectMusicCommandTrack, UnknownVtbl, iface);
69         ULONG ref = InterlockedDecrement(&This->ref);
70
71         TRACE("(%p): ReleaseRef to %d\n", This, ref);
72
73         if (ref == 0) {
74                 HeapFree(GetProcessHeap(), 0, This);
75         }
76         
77         DMSTYLE_UnlockModule();
78         
79         return ref;
80 }
81
82 static const IUnknownVtbl DirectMusicCommandTrack_Unknown_Vtbl = {
83         IDirectMusicCommandTrack_IUnknown_QueryInterface,
84         IDirectMusicCommandTrack_IUnknown_AddRef,
85         IDirectMusicCommandTrack_IUnknown_Release
86 };
87
88 /* IDirectMusicCommandTrack IDirectMusicTrack8 part: */
89 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_QueryInterface (LPDIRECTMUSICTRACK8 iface, REFIID riid, LPVOID *ppobj) {
90         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
91         return IDirectMusicCommandTrack_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
92 }
93
94 static ULONG WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_AddRef (LPDIRECTMUSICTRACK8 iface) {
95         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
96         return IDirectMusicCommandTrack_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
97 }
98
99 static ULONG WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_Release (LPDIRECTMUSICTRACK8 iface) {
100         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
101         return IDirectMusicCommandTrack_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
102 }
103
104 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_Init (LPDIRECTMUSICTRACK8 iface, IDirectMusicSegment* pSegment)
105 {
106         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
107         FIXME("(%p, %p): stub\n", This, pSegment);
108         return S_OK;
109 }
110
111 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_InitPlay (LPDIRECTMUSICTRACK8 iface, IDirectMusicSegmentState* pSegmentState, IDirectMusicPerformance* pPerformance, void** ppStateData, DWORD dwVirtualTrack8ID, DWORD dwFlags)
112 {
113         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
114         FIXME("(%p, %p, %p, %p, %d, %d): stub\n", This, pSegmentState, pPerformance, ppStateData, dwVirtualTrack8ID, dwFlags);
115         return S_OK;
116 }
117
118 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_EndPlay (LPDIRECTMUSICTRACK8 iface, void* pStateData)
119 {
120         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
121         FIXME("(%p, %p): stub\n", This, pStateData);
122         return S_OK;
123 }
124
125 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_Play (LPDIRECTMUSICTRACK8 iface, void* pStateData, MUSIC_TIME mtStart, MUSIC_TIME mtEnd, MUSIC_TIME mtOffset, DWORD dwFlags, IDirectMusicPerformance* pPerf, IDirectMusicSegmentState* pSegSt, DWORD dwVirtualID)
126 {
127         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
128         FIXME("(%p, %p, %ld, %ld, %ld, %d, %p, %p, %d): stub\n", This, pStateData, mtStart, mtEnd, mtOffset, dwFlags, pPerf, pSegSt, dwVirtualID);
129         return S_OK;
130 }
131
132 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_GetParam (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, MUSIC_TIME mtTime, MUSIC_TIME* pmtNext, void* pParam) {
133         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
134         FIXME("(%p, %s, %ld, %p, %p): stub\n", This, debugstr_dmguid(rguidType), mtTime, pmtNext, pParam);
135         return S_OK;
136 }
137
138 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_SetParam (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, MUSIC_TIME mtTime, void* pParam) {
139         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
140         FIXME("(%p, %s, %ld, %p): stub\n", This, debugstr_dmguid(rguidType), mtTime, pParam);
141         return S_OK;
142 }
143
144 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_IsParamSupported (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType) {
145         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
146
147         TRACE("(%p, %s)\n", This, debugstr_dmguid(rguidType));
148         if (IsEqualGUID (rguidType, &GUID_CommandParam)
149                 || IsEqualGUID (rguidType, &GUID_CommandParam2)
150                 || IsEqualGUID (rguidType, &GUID_CommandParamNext)) {
151                 TRACE("param supported\n");
152                 return S_OK;
153         }
154         
155         TRACE("param unsupported\n");
156         return DMUS_E_TYPE_UNSUPPORTED;
157 }
158
159 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_AddNotificationType (LPDIRECTMUSICTRACK8 iface, REFGUID rguidNotificationType) {
160         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
161         FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
162         return S_OK;
163 }
164
165 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_RemoveNotificationType (LPDIRECTMUSICTRACK8 iface, REFGUID rguidNotificationType) {
166         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
167         FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
168         return S_OK;
169 }
170
171 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_Clone (LPDIRECTMUSICTRACK8 iface, MUSIC_TIME mtStart, MUSIC_TIME mtEnd, IDirectMusicTrack** ppTrack) {
172         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
173         FIXME("(%p, %ld, %ld, %p): stub\n", This, mtStart, mtEnd, ppTrack);
174         return S_OK;
175 }
176
177 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_PlayEx (LPDIRECTMUSICTRACK8 iface, void* pStateData, REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD dwFlags, IDirectMusicPerformance* pPerf, IDirectMusicSegmentState* pSegSt, DWORD dwVirtualID) {
178         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
179         FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %d, %p, %p, %d): stub\n", This, pStateData, wine_dbgstr_longlong(rtStart),
180             wine_dbgstr_longlong(rtEnd), wine_dbgstr_longlong(rtOffset), dwFlags, pPerf, pSegSt, dwVirtualID);
181         return S_OK;
182 }
183
184 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_GetParamEx (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, REFERENCE_TIME rtTime, REFERENCE_TIME* prtNext, void* pParam, void* pStateData, DWORD dwFlags) {
185         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
186         FIXME("(%p, %s, 0x%s, %p, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
187             wine_dbgstr_longlong(rtTime), prtNext, pParam, pStateData, dwFlags);
188         return S_OK;
189 }
190
191 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_SetParamEx (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, REFERENCE_TIME rtTime, void* pParam, void* pStateData, DWORD dwFlags) {
192         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
193         FIXME("(%p, %s, 0x%s, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
194             wine_dbgstr_longlong(rtTime), pParam, pStateData, dwFlags);
195         return S_OK;
196 }
197
198 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_Compose (LPDIRECTMUSICTRACK8 iface, IUnknown* pContext, DWORD dwTrackGroup, IDirectMusicTrack** ppResultTrack) {
199         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
200         FIXME("(%p, %p, %d, %p): stub\n", This, pContext, dwTrackGroup, ppResultTrack);
201         return S_OK;
202 }
203
204 static HRESULT WINAPI IDirectMusicCommandTrack_IDirectMusicTrack_Join (LPDIRECTMUSICTRACK8 iface, IDirectMusicTrack* pNewTrack, MUSIC_TIME mtJoin, IUnknown* pContext, DWORD dwTrackGroup, IDirectMusicTrack** ppResultTrack) {
205         ICOM_THIS_MULTI(IDirectMusicCommandTrack, TrackVtbl, iface);
206         FIXME("(%p, %p, %ld, %p, %d, %p): stub\n", This, pNewTrack, mtJoin, pContext, dwTrackGroup, ppResultTrack);
207         return S_OK;
208 }
209
210 static const IDirectMusicTrack8Vtbl DirectMusicCommandTrack_Track_Vtbl = {
211         IDirectMusicCommandTrack_IDirectMusicTrack_QueryInterface,
212         IDirectMusicCommandTrack_IDirectMusicTrack_AddRef,
213         IDirectMusicCommandTrack_IDirectMusicTrack_Release,
214         IDirectMusicCommandTrack_IDirectMusicTrack_Init,
215         IDirectMusicCommandTrack_IDirectMusicTrack_InitPlay,
216         IDirectMusicCommandTrack_IDirectMusicTrack_EndPlay,
217         IDirectMusicCommandTrack_IDirectMusicTrack_Play,
218         IDirectMusicCommandTrack_IDirectMusicTrack_GetParam,
219         IDirectMusicCommandTrack_IDirectMusicTrack_SetParam,
220         IDirectMusicCommandTrack_IDirectMusicTrack_IsParamSupported,
221         IDirectMusicCommandTrack_IDirectMusicTrack_AddNotificationType,
222         IDirectMusicCommandTrack_IDirectMusicTrack_RemoveNotificationType,
223         IDirectMusicCommandTrack_IDirectMusicTrack_Clone,
224         IDirectMusicCommandTrack_IDirectMusicTrack_PlayEx,
225         IDirectMusicCommandTrack_IDirectMusicTrack_GetParamEx,
226         IDirectMusicCommandTrack_IDirectMusicTrack_SetParamEx,
227         IDirectMusicCommandTrack_IDirectMusicTrack_Compose,
228         IDirectMusicCommandTrack_IDirectMusicTrack_Join
229 };
230
231 /* IDirectMusicCommandTrack IPersistStream part: */
232 static HRESULT WINAPI IDirectMusicCommandTrack_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
233         ICOM_THIS_MULTI(IDirectMusicCommandTrack, PersistStreamVtbl, iface);
234         return IDirectMusicCommandTrack_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
235 }
236
237 static ULONG WINAPI IDirectMusicCommandTrack_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
238         ICOM_THIS_MULTI(IDirectMusicCommandTrack, PersistStreamVtbl, iface);
239         return IDirectMusicCommandTrack_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
240 }
241
242 static ULONG WINAPI IDirectMusicCommandTrack_IPersistStream_Release (LPPERSISTSTREAM iface) {
243         ICOM_THIS_MULTI(IDirectMusicCommandTrack, PersistStreamVtbl, iface);
244         return IDirectMusicCommandTrack_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
245 }
246
247 static HRESULT WINAPI IDirectMusicCommandTrack_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
248         return E_NOTIMPL;
249 }
250
251 static HRESULT WINAPI IDirectMusicCommandTrack_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
252         return E_NOTIMPL;
253 }
254
255 static HRESULT WINAPI IDirectMusicCommandTrack_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
256         ICOM_THIS_MULTI(IDirectMusicCommandTrack, PersistStreamVtbl, iface);
257         FOURCC chunkID;
258         DWORD chunkSize, dwSizeOfStruct, nrCommands;
259         LARGE_INTEGER liMove; /* used when skipping chunks */
260         
261         IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
262         IStream_Read (pStm, &chunkSize, sizeof(DWORD), NULL);
263         TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (chunkID), chunkSize);
264         switch (chunkID) {
265                 case DMUS_FOURCC_COMMANDTRACK_CHUNK: {
266                         int count;
267                         TRACE_(dmfile)(": command track chunk\n");
268                         IStream_Read (pStm, &dwSizeOfStruct, sizeof(DWORD), NULL);
269                         if (dwSizeOfStruct != sizeof(DMUS_IO_COMMAND)) {
270                                 TRACE_(dmfile)(": declared size of struct (=%d) != actual size; indicates older direct music version\n", dwSizeOfStruct);
271                         }
272                         chunkSize -= sizeof(DWORD); /* now chunk size is one DWORD shorter */
273                         nrCommands = chunkSize/dwSizeOfStruct; /* and this is the number of commands */
274                         /* load each command separately in new entry */
275                         for (count = 0; count < nrCommands; count++) {
276                                 LPDMUS_PRIVATE_COMMAND pNewCommand = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_COMMAND));
277                                 IStream_Read (pStm, &pNewCommand->pCommand, dwSizeOfStruct, NULL);
278                                 list_add_tail (&This->Commands, &pNewCommand->entry);
279                         }
280                         TRACE_(dmfile)(": reading finished\n");
281                         This->pDesc->dwValidData |= DMUS_OBJ_LOADED;
282                         break;
283                 }       
284                 default: {
285                         TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
286                         liMove.QuadPart = chunkSize;
287                         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
288                         return E_FAIL;
289                 }
290         }
291
292         /* DEBUG: dumps whole band track object tree: */
293         if (TRACE_ON(dmstyle)) {
294                 int r = 0;
295                 DMUS_PRIVATE_COMMAND *tmpEntry;
296                 struct list *listEntry;
297                 TRACE("*** IDirectMusicCommandTrack (%p) ***\n", This->TrackVtbl);
298                 TRACE(" - Commands:\n");
299                 LIST_FOR_EACH (listEntry, &This->Commands) {
300                         tmpEntry = LIST_ENTRY (listEntry, DMUS_PRIVATE_COMMAND, entry);
301                         TRACE("    - Command[%i]:\n", r);
302                         TRACE("       - mtTime = %li\n", tmpEntry->pCommand.mtTime);
303                         TRACE("       - wMeasure = %d\n", tmpEntry->pCommand.wMeasure);
304                         TRACE("       - bBeat = %i\n", tmpEntry->pCommand.bBeat);
305                         TRACE("       - bCommand = %i\n", tmpEntry->pCommand.bCommand);
306                         TRACE("       - bGrooveLevel = %i\n", tmpEntry->pCommand.bGrooveLevel);
307                         TRACE("       - bGrooveRange = %i\n", tmpEntry->pCommand.bGrooveRange);
308                         TRACE("       - bRepeatMode = %i\n", tmpEntry->pCommand.bRepeatMode);                   
309                         r++;
310                 }
311         }
312
313         return S_OK;
314 }
315
316 static HRESULT WINAPI IDirectMusicCommandTrack_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
317         return E_NOTIMPL;
318 }
319
320 static HRESULT WINAPI IDirectMusicCommandTrack_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
321         return E_NOTIMPL;
322 }
323
324 static const IPersistStreamVtbl DirectMusicCommandTrack_PersistStream_Vtbl = {
325         IDirectMusicCommandTrack_IPersistStream_QueryInterface,
326         IDirectMusicCommandTrack_IPersistStream_AddRef,
327         IDirectMusicCommandTrack_IPersistStream_Release,
328         IDirectMusicCommandTrack_IPersistStream_GetClassID,
329         IDirectMusicCommandTrack_IPersistStream_IsDirty,
330         IDirectMusicCommandTrack_IPersistStream_Load,
331         IDirectMusicCommandTrack_IPersistStream_Save,
332         IDirectMusicCommandTrack_IPersistStream_GetSizeMax
333 };
334
335 /* for ClassFactory */
336 HRESULT WINAPI DMUSIC_CreateDirectMusicCommandTrack (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter) {
337         IDirectMusicCommandTrack* track;
338         
339         track = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicCommandTrack));
340         if (NULL == track) {
341                 *ppobj = NULL;
342                 return E_OUTOFMEMORY;
343         }
344         track->UnknownVtbl = &DirectMusicCommandTrack_Unknown_Vtbl;
345         track->TrackVtbl = &DirectMusicCommandTrack_Track_Vtbl;
346         track->PersistStreamVtbl = &DirectMusicCommandTrack_PersistStream_Vtbl;
347         track->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
348         DM_STRUCT_INIT(track->pDesc);
349         track->pDesc->dwValidData |= DMUS_OBJ_CLASS;
350         track->pDesc->guidClass = CLSID_DirectMusicCommandTrack;
351         track->ref = 0; /* will be inited by QueryInterface */
352         list_init (&track->Commands);
353
354         return IDirectMusicCommandTrack_IUnknown_QueryInterface ((LPUNKNOWN)&track->UnknownVtbl, lpcGUID, ppobj);
355 }