xmllite: Implement PI parsing.
[wine] / dlls / dmsynth / synth.c
1 /*
2  * IDirectMusicSynth8 Implementation
3  *
4  * Copyright (C) 2003-2004 Rok Mandeljc
5  * Copyright (C) 2012 Christian Costa
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #define COBJMACROS
23
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26 #include "objbase.h"
27 #include "initguid.h"
28 #include "dmksctrl.h"
29
30 #include "dmsynth_private.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(dmsynth);
33
34 static inline IDirectMusicSynth8Impl *impl_from_IDirectMusicSynth8(IDirectMusicSynth8 *iface)
35 {
36     return CONTAINING_RECORD(iface, IDirectMusicSynth8Impl, IDirectMusicSynth8_iface);
37 }
38
39 /* IDirectMusicSynth8Impl IUnknown part: */
40 static HRESULT WINAPI IDirectMusicSynth8Impl_QueryInterface(LPDIRECTMUSICSYNTH8 iface, REFIID riid, LPVOID *ret_iface)
41 {
42     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
43
44     TRACE("(%p)->(%s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
45
46     if (IsEqualIID (riid, &IID_IUnknown) ||
47         IsEqualIID (riid, &IID_IDirectMusicSynth) ||
48         IsEqualIID (riid, &IID_IDirectMusicSynth8))
49     {
50         IUnknown_AddRef(iface);
51         *ret_iface = iface;
52         return S_OK;
53     }
54     else if (IsEqualIID(riid, &IID_IKsControl))
55     {
56         IUnknown_AddRef(iface);
57         *ret_iface = &This->IKsControl_iface;
58         return S_OK;
59     }
60
61     *ret_iface = NULL;
62
63     WARN("(%p)->(%s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
64
65     return E_NOINTERFACE;
66 }
67
68 static ULONG WINAPI IDirectMusicSynth8Impl_AddRef(LPDIRECTMUSICSYNTH8 iface)
69 {
70     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
71     ULONG ref = InterlockedIncrement(&This->ref);
72
73     TRACE("(%p)->(): new ref = %u\n", This, ref);
74
75     DMSYNTH_LockModule();
76
77     return ref;
78 }
79
80 static ULONG WINAPI IDirectMusicSynth8Impl_Release(LPDIRECTMUSICSYNTH8 iface)
81 {
82     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
83     ULONG ref = InterlockedDecrement(&This->ref);
84
85     TRACE("(%p)->(): new ref = %u\n", This, ref);
86
87     if (!ref) {
88         if (This->pLatencyClock)
89             IReferenceClock_Release(This->pLatencyClock);
90         HeapFree(GetProcessHeap(), 0, This);
91     }
92
93     DMSYNTH_UnlockModule();
94
95     return ref;
96 }
97
98 /* IDirectMusicSynth8Impl IDirectMusicSynth part: */
99 static HRESULT WINAPI IDirectMusicSynth8Impl_Open(LPDIRECTMUSICSYNTH8 iface, LPDMUS_PORTPARAMS pPortParams)
100 {
101     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
102
103     FIXME("(%p)->(%p): stub\n", This, pPortParams);
104
105     return S_OK;
106 }
107
108 static HRESULT WINAPI IDirectMusicSynth8Impl_Close(LPDIRECTMUSICSYNTH8 iface)
109 {
110     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
111
112     FIXME("(%p)->(): stub\n", This);
113
114     return S_OK;
115 }
116
117 static HRESULT WINAPI IDirectMusicSynth8Impl_SetNumChannelGroups(LPDIRECTMUSICSYNTH8 iface, DWORD groups)
118 {
119     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
120
121     FIXME("(%p->(%d): stub\n", This, groups);
122
123     return S_OK;
124 }
125
126 static HRESULT WINAPI IDirectMusicSynth8Impl_Download(LPDIRECTMUSICSYNTH8 iface, LPHANDLE hDownload, LPVOID data, LPBOOL free)
127 {
128     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
129     LPBYTE buffer = (LPBYTE)data;
130     DMUS_DOWNLOADINFO *info = (DMUS_DOWNLOADINFO*)buffer;
131     ULONG *offsets = ((DMUS_OFFSETTABLE*)(buffer + sizeof(DMUS_DOWNLOADINFO)))->ulOffsetTable;
132     LPBYTE object = buffer + sizeof(DMUS_DOWNLOADINFO) + info->dwNumOffsetTableEntries * sizeof(ULONG);
133
134     FIXME("(%p)->(%p, %p, %p): stub\n", This, hDownload, data, free);
135
136     /* FIXME: Currently we only dump data which is very useful to known how native dmusic behave and debug builtin dmusic */
137
138     if (!hDownload || !data || !free)
139         return E_POINTER;
140
141     if (TRACE_ON(dmsynth))
142     {
143         TRACE("Dump DMUS_DOWNLOADINFO struct:\n");
144         TRACE(" - dwDLType                = %u\n", info->dwDLType);
145         TRACE(" - dwDLId                  = %u\n", info->dwDLId);
146         TRACE(" - dwNumOffsetTableEntries = %u\n", info->dwNumOffsetTableEntries);
147         TRACE(" - cbSize                  = %u\n", info->cbSize);
148     }
149
150     /* The struct should have at least one offset corresponding to the donwload object itself */
151     if (!info->dwNumOffsetTableEntries)
152     {
153         FIXME("Offset table is empty\n");
154         return DMUS_E_BADOFFSETTABLE;
155     }
156
157     /* First offset should point to the download object */
158     if ((buffer + offsets[0]) != object)
159     {
160         FIXME("Object is not at the beginning\n");
161         return DMUS_E_BADOFFSETTABLE;
162     }
163
164     if (info->dwDLType == DMUS_DOWNLOADINFO_INSTRUMENT)
165     {
166         FIXME("Download type DMUS_DOWNLOADINFO_INSTRUMENT not yet supported\n");
167     }
168     else if (info->dwDLType == DMUS_DOWNLOADINFO_WAVE)
169     {
170         DMUS_WAVE *wave = (DMUS_WAVE*)object;
171         DMUS_WAVEDATA *wave_data;
172
173         TRACE("Processing download type DMUS_DOWNLOADINFO_WAVE\n");
174
175         if (TRACE_ON(dmsynth))
176         {
177             TRACE("Dump DMUS_WAVE struct\n");
178             TRACE(" - ulFirstExtCkIdx   = %u\n", wave->ulFirstExtCkIdx);
179             TRACE(" - ulCopyrightIdx    = %u\n", wave->ulCopyrightIdx);
180             TRACE(" - ulWaveDataIdx     = %u\n", wave->ulWaveDataIdx);
181             TRACE(" - WaveformatEx:\n");
182             TRACE("   - wFormatTag      = %u\n", wave->WaveformatEx.wFormatTag);
183             TRACE("   - nChannels       = %u\n", wave->WaveformatEx.nChannels);
184             TRACE("   - nSamplesPerSec  = %u\n", wave->WaveformatEx.nSamplesPerSec);
185             TRACE("   - nAvgBytesPerSec = %u\n", wave->WaveformatEx.nAvgBytesPerSec);
186             TRACE("   - nBlockAlign     = %u\n", wave->WaveformatEx.nBlockAlign);
187             TRACE("   - wBitsPerSample  = %u\n", wave->WaveformatEx.wBitsPerSample);
188             TRACE("   - cbSize          = %u\n", wave->WaveformatEx.cbSize);
189
190             if (wave->ulCopyrightIdx)
191             {
192                 DMUS_COPYRIGHT *copyright = (DMUS_COPYRIGHT*)(buffer + offsets[wave->ulCopyrightIdx]);
193                 TRACE("Copyright = '%s'\n",  (char*)copyright->byCopyright);
194             }
195
196             wave_data = (DMUS_WAVEDATA*)(buffer + offsets[wave->ulWaveDataIdx]);
197             TRACE("Found %u bytes of wave data\n", wave_data->cbSize);
198         }
199     }
200     else if (info->dwDLType == DMUS_DOWNLOADINFO_INSTRUMENT2)
201     {
202         DMUS_INSTRUMENT *instrument = (DMUS_INSTRUMENT*)object;
203         ULONG nb_regions = 0;
204
205         TRACE("Processing download type DMUS_DOWNLOADINFO_INSTRUMENT2\n");
206
207         if (TRACE_ON(dmsynth))
208         {
209             TRACE("Dump DMUS_INSTRUMENT struct\n");
210             TRACE(" - ulPatch          = %u\n", instrument->ulPatch);
211             TRACE(" - ulFirstRegionIdx = %u\n", instrument->ulFirstRegionIdx);
212             TRACE(" - ulGlobalArtIdx   = %u\n", instrument->ulGlobalArtIdx);
213             TRACE(" - ulFirstExtCkIdx  = %u\n", instrument->ulFirstExtCkIdx);
214             TRACE(" - ulCopyrightIdx   = %u\n", instrument->ulCopyrightIdx);
215             TRACE(" - ulFlags          = %u\n", instrument->ulFlags);
216
217             if (instrument->ulCopyrightIdx)
218             {
219                 DMUS_COPYRIGHT *copyright = (DMUS_COPYRIGHT*)(buffer + offsets[instrument->ulCopyrightIdx]);
220                 TRACE("Copyright = '%s'\n",  (char*)copyright->byCopyright);
221             }
222         }
223
224         if (instrument->ulFirstRegionIdx)
225         {
226             ULONG region_idx = instrument->ulFirstRegionIdx;
227
228             while (region_idx)
229             {
230                 DMUS_REGION *region = (DMUS_REGION*)(buffer + offsets[region_idx]);
231
232                 region_idx = region->ulNextRegionIdx;
233                 nb_regions++;
234             }
235         }
236
237         TRACE("Number of regions = %u\n", nb_regions);
238     }
239     else if (info->dwDLType == DMUS_DOWNLOADINFO_WAVEARTICULATION)
240     {
241         FIXME("Download type DMUS_DOWNLOADINFO_WAVEARTICULATION not yet supported\n");
242     }
243     else if (info->dwDLType == DMUS_DOWNLOADINFO_STREAMINGWAVE)
244     {
245         FIXME("Download type DMUS_DOWNLOADINFO_STREAMINGWAVE not yet supported\n");
246     }
247     else if (info->dwDLType == DMUS_DOWNLOADINFO_ONESHOTWAVE)
248     {
249         FIXME("Download type DMUS_DOWNLOADINFO_ONESHOTWAVE not yet supported\n");
250     }
251     else
252     {
253         WARN("Unknown download type %u\n", info->dwDLType);
254         return DMUS_E_UNKNOWNDOWNLOAD;
255     }
256
257     return S_OK;
258 }
259
260 static HRESULT WINAPI IDirectMusicSynth8Impl_Unload(LPDIRECTMUSICSYNTH8 iface, HANDLE hDownload, HRESULT (CALLBACK* lpFreeHandle)(HANDLE,HANDLE), HANDLE hUserData)
261 {
262     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
263
264     FIXME("(%p)->(%p, %p, %p): stub\n", This, hDownload, lpFreeHandle, hUserData);
265
266     return S_OK;
267 }
268
269 static HRESULT WINAPI IDirectMusicSynth8Impl_PlayBuffer(LPDIRECTMUSICSYNTH8 iface, REFERENCE_TIME rt, LPBYTE buffer, DWORD size)
270 {
271     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
272
273     FIXME("(%p)->(0x%s, %p, %u): stub\n", This, wine_dbgstr_longlong(rt), buffer, size);
274
275     return S_OK;
276 }
277
278 static HRESULT WINAPI IDirectMusicSynth8Impl_GetRunningStats(LPDIRECTMUSICSYNTH8 iface, LPDMUS_SYNTHSTATS stats)
279 {
280     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
281
282     FIXME("(%p)->(%p): stub\n", This, stats);
283
284     return S_OK;
285 }
286
287 static HRESULT WINAPI IDirectMusicSynth8Impl_GetPortCaps(LPDIRECTMUSICSYNTH8 iface, LPDMUS_PORTCAPS caps)
288 {
289     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
290
291     TRACE("(%p)->(%p)\n", This, caps);
292
293     *caps = This->pCaps;
294
295     return S_OK;
296 }
297
298 static HRESULT WINAPI IDirectMusicSynth8Impl_SetMasterClock(LPDIRECTMUSICSYNTH8 iface, IReferenceClock* clock)
299 {
300     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
301
302     FIXME("(%p)->(%p): stub\n", This, clock);
303
304     return S_OK;
305 }
306
307 static HRESULT WINAPI IDirectMusicSynth8Impl_GetLatencyClock(LPDIRECTMUSICSYNTH8 iface, IReferenceClock** clock)
308 {
309     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
310
311     TRACE("(%p)->(%p)\n", iface, clock);
312
313     if (!clock)
314         return E_POINTER;
315
316     if (!This->pSynthSink)
317         return DMUS_E_NOSYNTHSINK;
318
319     *clock = This->pLatencyClock;
320     IReferenceClock_AddRef(This->pLatencyClock);
321
322     return S_OK;
323 }
324
325 static HRESULT WINAPI IDirectMusicSynth8Impl_Activate(LPDIRECTMUSICSYNTH8 iface, BOOL enable)
326 {
327     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
328
329     TRACE("(%p)->(%d)\n", This, enable);
330
331     This->fActive = enable;
332
333     return S_OK;
334 }
335
336 static HRESULT WINAPI IDirectMusicSynth8Impl_SetSynthSink(LPDIRECTMUSICSYNTH8 iface, IDirectMusicSynthSink* synth_sink)
337 {
338     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
339
340     TRACE("(%p)->(%p)\n", iface, synth_sink);
341
342     This->pSynthSink = (IDirectMusicSynthSinkImpl*)synth_sink;
343
344     if (synth_sink)
345         return IDirectMusicSynthSink_GetLatencyClock(synth_sink, &This->pLatencyClock);
346
347     return S_OK;
348 }
349
350 static HRESULT WINAPI IDirectMusicSynth8Impl_Render(LPDIRECTMUSICSYNTH8 iface, short* buffer, DWORD length, LONGLONG position)
351 {
352     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
353
354     FIXME("(%p)->(%p, %d, 0x%s): stub\n", This, buffer, length, wine_dbgstr_longlong(position));
355
356     return S_OK;
357 }
358
359 static HRESULT WINAPI IDirectMusicSynth8Impl_SetChannelPriority(LPDIRECTMUSICSYNTH8 iface, DWORD channel_group, DWORD channel, DWORD priority)
360 {
361     /* IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface); */
362
363     /* Silenced because of too many messages - 1000 groups * 16 channels ;=) */
364     /* FIXME("(%p)->(%ld, %ld, %ld): stub\n", This, channel_group, channel, priority); */
365
366     return S_OK;
367 }
368
369 static HRESULT WINAPI IDirectMusicSynth8Impl_GetChannelPriority(LPDIRECTMUSICSYNTH8 iface, DWORD channel_group, DWORD channel, LPDWORD priority)
370 {
371     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
372
373     FIXME("(%p)->(%d, %d, %p): stub\n", This, channel_group, channel, priority);
374
375     return S_OK;
376 }
377
378 static HRESULT WINAPI IDirectMusicSynth8Impl_GetFormat(LPDIRECTMUSICSYNTH8 iface, LPWAVEFORMATEX wave_format, LPDWORD wave_format_size)
379 {
380     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
381
382     FIXME("(%p)->(%p, %p): stub\n", This, wave_format, wave_format_size);
383
384     return S_OK;
385 }
386
387 static HRESULT WINAPI IDirectMusicSynth8Impl_GetAppend(LPDIRECTMUSICSYNTH8 iface, DWORD* append)
388 {
389     TRACE("(%p)->(%p)\n", iface, append);
390
391     /* We don't need extra space at the end of buffers passed to us for now */
392     *append = 0;
393
394     return S_OK;
395 }
396
397 /* IDirectMusicSynth8Impl IDirectMusicSynth8 part: */
398 static HRESULT WINAPI IDirectMusicSynth8Impl_PlayVoice(LPDIRECTMUSICSYNTH8 iface, REFERENCE_TIME ref_time, DWORD voice_id, DWORD channel_group, DWORD channel,
399                                                        DWORD dwDLId, LONG prPitch, LONG vrVolume, SAMPLE_TIME stVoiceStart, SAMPLE_TIME stLoopStart, SAMPLE_TIME stLoopEnd)
400 {
401     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
402
403     FIXME("(%p)->(0x%s, %d, %d, %d, %d, %i, %i,0x%s, 0x%s, 0x%s): stub\n",
404           This, wine_dbgstr_longlong(ref_time), voice_id, channel_group, channel, dwDLId, prPitch, vrVolume,
405           wine_dbgstr_longlong(stVoiceStart), wine_dbgstr_longlong(stLoopStart), wine_dbgstr_longlong(stLoopEnd));
406
407     return S_OK;
408 }
409
410 static HRESULT WINAPI IDirectMusicSynth8Impl_StopVoice(LPDIRECTMUSICSYNTH8 iface, REFERENCE_TIME ref_time, DWORD voice_id)
411 {
412     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
413
414     FIXME("(%p)->(0x%s, %d): stub\n", This, wine_dbgstr_longlong(ref_time), voice_id);
415
416     return S_OK;
417 }
418
419 static HRESULT WINAPI IDirectMusicSynth8Impl_GetVoiceState(LPDIRECTMUSICSYNTH8 iface, DWORD dwVoice[], DWORD cbVoice, DMUS_VOICE_STATE dwVoiceState[])
420 {
421     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
422
423     FIXME("(%p)->(%p, %d, %p): stub\n", This, dwVoice, cbVoice, dwVoiceState);
424
425     return S_OK;
426 }
427
428 static HRESULT WINAPI IDirectMusicSynth8Impl_Refresh(LPDIRECTMUSICSYNTH8 iface, DWORD download_id, DWORD flags)
429 {
430     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
431
432     FIXME("(%p)->(%d, %d): stub\n", This, download_id, flags);
433
434     return S_OK;
435 }
436
437 static HRESULT WINAPI IDirectMusicSynth8Impl_AssignChannelToBuses(LPDIRECTMUSICSYNTH8 iface, DWORD channel_group, DWORD channel, LPDWORD pdwBuses, DWORD cBuses)
438 {
439     IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
440
441     FIXME("(%p)->(%d, %d, %p, %d): stub\n", This, channel_group, channel, pdwBuses, cBuses);
442
443     return S_OK;
444 }
445
446 static const IDirectMusicSynth8Vtbl DirectMusicSynth8_Vtbl = {
447         IDirectMusicSynth8Impl_QueryInterface,
448         IDirectMusicSynth8Impl_AddRef,
449         IDirectMusicSynth8Impl_Release,
450         IDirectMusicSynth8Impl_Open,
451         IDirectMusicSynth8Impl_Close,
452         IDirectMusicSynth8Impl_SetNumChannelGroups,
453         IDirectMusicSynth8Impl_Download,
454         IDirectMusicSynth8Impl_Unload,
455         IDirectMusicSynth8Impl_PlayBuffer,
456         IDirectMusicSynth8Impl_GetRunningStats,
457         IDirectMusicSynth8Impl_GetPortCaps,
458         IDirectMusicSynth8Impl_SetMasterClock,
459         IDirectMusicSynth8Impl_GetLatencyClock,
460         IDirectMusicSynth8Impl_Activate,
461         IDirectMusicSynth8Impl_SetSynthSink,
462         IDirectMusicSynth8Impl_Render,
463         IDirectMusicSynth8Impl_SetChannelPriority,
464         IDirectMusicSynth8Impl_GetChannelPriority,
465         IDirectMusicSynth8Impl_GetFormat,
466         IDirectMusicSynth8Impl_GetAppend,
467         IDirectMusicSynth8Impl_PlayVoice,
468         IDirectMusicSynth8Impl_StopVoice,
469         IDirectMusicSynth8Impl_GetVoiceState,
470         IDirectMusicSynth8Impl_Refresh,
471         IDirectMusicSynth8Impl_AssignChannelToBuses
472 };
473
474 static inline IDirectMusicSynth8Impl *impl_from_IKsControl(IKsControl *iface)
475 {
476     return CONTAINING_RECORD(iface, IDirectMusicSynth8Impl, IKsControl_iface);
477 }
478
479 static HRESULT WINAPI DMSynthImpl_IKsControl_QueryInterface(IKsControl* iface, REFIID riid, LPVOID *ppobj)
480 {
481     IDirectMusicSynth8Impl *This = impl_from_IKsControl(iface);
482
483     return IDirectMusicSynth8Impl_QueryInterface(&This->IDirectMusicSynth8_iface, riid, ppobj);
484 }
485
486 static ULONG WINAPI DMSynthImpl_IKsControl_AddRef(IKsControl* iface)
487 {
488     IDirectMusicSynth8Impl *This = impl_from_IKsControl(iface);
489
490     return IDirectMusicSynth8Impl_AddRef(&This->IDirectMusicSynth8_iface);
491 }
492
493 static ULONG WINAPI DMSynthImpl_IKsControl_Release(IKsControl* iface)
494 {
495     IDirectMusicSynth8Impl *This = impl_from_IKsControl(iface);
496
497     return IDirectMusicSynth8Impl_Release(&This->IDirectMusicSynth8_iface);
498 }
499
500 static HRESULT WINAPI DMSynthImpl_IKsControl_KsProperty(IKsControl* iface, PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData,
501                                                         ULONG DataLength, ULONG* BytesReturned)
502 {
503     TRACE("(%p)->(%p, %u, %p, %u, %p)\n", iface, Property, PropertyLength, PropertyData, DataLength, BytesReturned);
504
505     TRACE("Property = %s - %u - %u\n", debugstr_guid(&Property->u.s.Set), Property->u.s.Id, Property->u.s.Flags);
506
507     if (Property->u.s.Flags != KSPROPERTY_TYPE_GET)
508     {
509         FIXME("Property flags %u not yet supported\n", Property->u.s.Flags);
510         return S_FALSE;
511     }
512
513     if (DataLength <  sizeof(DWORD))
514         return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
515
516     if (IsEqualGUID(&Property->u.s.Set, &GUID_DMUS_PROP_INSTRUMENT2))
517     {
518         *(DWORD*)PropertyData = TRUE;
519         *BytesReturned = sizeof(DWORD);
520     }
521     else if (IsEqualGUID(&Property->u.s.Set, &GUID_DMUS_PROP_DLS2))
522     {
523         *(DWORD*)PropertyData = TRUE;
524         *BytesReturned = sizeof(DWORD);
525     }
526     else if (IsEqualGUID(&Property->u.s.Set, &GUID_DMUS_PROP_GM_Hardware))
527     {
528         *(DWORD*)PropertyData = FALSE;
529         *BytesReturned = sizeof(DWORD);
530     }
531     else if (IsEqualGUID(&Property->u.s.Set, &GUID_DMUS_PROP_GS_Hardware))
532     {
533         *(DWORD*)PropertyData = FALSE;
534         *BytesReturned = sizeof(DWORD);
535     }
536     else if (IsEqualGUID(&Property->u.s.Set, &GUID_DMUS_PROP_XG_Hardware))
537     {
538         *(DWORD*)PropertyData = FALSE;
539         *BytesReturned = sizeof(DWORD);
540     }
541     else
542     {
543         FIXME("Unknown property %s\n", debugstr_guid(&Property->u.s.Set));
544         *(DWORD*)PropertyData = FALSE;
545         *BytesReturned = sizeof(DWORD);
546     }
547
548     return S_OK;
549 }
550
551 static HRESULT WINAPI DMSynthImpl_IKsControl_KsMethod(IKsControl* iface, PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData,
552                                                       ULONG DataLength, ULONG* BytesReturned)
553 {
554     FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, Method, MethodLength, MethodData, DataLength, BytesReturned);
555
556     return E_NOTIMPL;
557 }
558
559 static HRESULT WINAPI DMSynthImpl_IKsControl_KsEvent(IKsControl* iface, PKSEVENT Event, ULONG EventLength, LPVOID EventData,
560                                                      ULONG DataLength, ULONG* BytesReturned)
561 {
562     FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, Event, EventLength, EventData, DataLength, BytesReturned);
563
564     return E_NOTIMPL;
565 }
566
567
568 static const IKsControlVtbl DMSynthImpl_IKsControl_Vtbl = {
569     DMSynthImpl_IKsControl_QueryInterface,
570     DMSynthImpl_IKsControl_AddRef,
571     DMSynthImpl_IKsControl_Release,
572     DMSynthImpl_IKsControl_KsProperty,
573     DMSynthImpl_IKsControl_KsMethod,
574     DMSynthImpl_IKsControl_KsEvent
575 };
576
577 /* for ClassFactory */
578 HRESULT WINAPI DMUSIC_CreateDirectMusicSynthImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter)
579 {
580         IDirectMusicSynth8Impl *obj;
581         
582         TRACE("(%p,%p,%p)\n", lpcGUID, ppobj, pUnkOuter);
583         obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicSynth8Impl));
584         if (NULL == obj) {
585                 *ppobj = NULL;
586                 return E_OUTOFMEMORY;
587         }
588         obj->IDirectMusicSynth8_iface.lpVtbl = &DirectMusicSynth8_Vtbl;
589         obj->IKsControl_iface.lpVtbl = &DMSynthImpl_IKsControl_Vtbl;
590         obj->ref = 0;
591         /* fill in caps */
592         obj->pCaps.dwSize = sizeof(DMUS_PORTCAPS);
593         obj->pCaps.dwFlags = DMUS_PC_DLS | DMUS_PC_SOFTWARESYNTH | DMUS_PC_DIRECTSOUND | DMUS_PC_DLS2 | DMUS_PC_AUDIOPATH | DMUS_PC_WAVE;
594         obj->pCaps.guidPort = CLSID_DirectMusicSynth;
595         obj->pCaps.dwClass = DMUS_PC_OUTPUTCLASS;
596         obj->pCaps.dwType = DMUS_PORT_USER_MODE_SYNTH;
597         obj->pCaps.dwMemorySize = DMUS_PC_SYSTEMMEMORY;
598         obj->pCaps.dwMaxChannelGroups = 1000;
599         obj->pCaps.dwMaxVoices = 1000;
600         obj->pCaps.dwMaxAudioChannels = 2;
601         obj->pCaps.dwEffectFlags = DMUS_EFFECT_REVERB;
602         MultiByteToWideChar (CP_ACP, 0, "Microsoft Synthesizer", -1, obj->pCaps.wszDescription, sizeof(obj->pCaps.wszDescription)/sizeof(WCHAR));
603
604         return IDirectMusicSynth8Impl_QueryInterface ((LPDIRECTMUSICSYNTH8)obj, lpcGUID, ppobj);
605 }