synth.c 20.6 KB
Newer Older
1 2
/*
 * IDirectMusicSynth8 Implementation
3
 *
4
 * Copyright (C) 2003-2004 Rok Mandeljc
5
 * Copyright (C) 2012 Christian Costa
6
 *
7 8 9 10
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
11 12 13
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
16
 *
17 18 19
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 21
 */

22 23
#define COBJMACROS

24 25
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
26 27 28 29
#include "objbase.h"
#include "initguid.h"
#include "dmksctrl.h"

30
#include "dmsynth_private.h"
31

32
WINE_DEFAULT_DEBUG_CHANNEL(dmsynth);
33

34 35 36 37 38
static inline IDirectMusicSynth8Impl *impl_from_IDirectMusicSynth8(IDirectMusicSynth8 *iface)
{
    return CONTAINING_RECORD(iface, IDirectMusicSynth8Impl, IDirectMusicSynth8_iface);
}

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 47 48 49 50 51 52 53 54 55 56 57 58
    if (IsEqualIID (riid, &IID_IUnknown) ||
        IsEqualIID (riid, &IID_IDirectMusicSynth) ||
        IsEqualIID (riid, &IID_IDirectMusicSynth8))
    {
        IUnknown_AddRef(iface);
        *ret_iface = iface;
        return S_OK;
    }
    else if (IsEqualIID(riid, &IID_IKsControl))
    {
        IUnknown_AddRef(iface);
        *ret_iface = &This->IKsControl_iface;
        return S_OK;
59 60
    }

61 62 63 64 65
    *ret_iface = NULL;

    WARN("(%p)->(%s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);

    return E_NOINTERFACE;
66 67
}

68 69
static ULONG WINAPI IDirectMusicSynth8Impl_AddRef(LPDIRECTMUSICSYNTH8 iface)
{
70 71
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
    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 81
static ULONG WINAPI IDirectMusicSynth8Impl_Release(LPDIRECTMUSICSYNTH8 iface)
{
82 83
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
    ULONG ref = InterlockedDecrement(&This->ref);
84

85
    TRACE("(%p)->(): new ref = %u\n", This, ref);
86

87 88 89 90 91 92 93
    if (!ref) {
        if (This->pLatencyClock)
            IReferenceClock_Release(This->pLatencyClock);
        HeapFree(GetProcessHeap(), 0, This);
    }

    DMSYNTH_UnlockModule();
94

95
    return ref;
96 97
}

98
/* IDirectMusicSynth8Impl IDirectMusicSynth part: */
99 100 101 102 103 104 105
static HRESULT WINAPI IDirectMusicSynth8Impl_Open(LPDIRECTMUSICSYNTH8 iface, LPDMUS_PORTPARAMS pPortParams)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(%p): stub\n", This, pPortParams);

    return S_OK;
106 107
}

108 109 110 111 112 113 114
static HRESULT WINAPI IDirectMusicSynth8Impl_Close(LPDIRECTMUSICSYNTH8 iface)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(): stub\n", This);

    return S_OK;
115 116
}

117 118 119 120 121 122 123
static HRESULT WINAPI IDirectMusicSynth8Impl_SetNumChannelGroups(LPDIRECTMUSICSYNTH8 iface, DWORD groups)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p->(%d): stub\n", This, groups);

    return S_OK;
124 125
}

126 127 128
static HRESULT WINAPI IDirectMusicSynth8Impl_Download(LPDIRECTMUSICSYNTH8 iface, LPHANDLE hDownload, LPVOID data, LPBOOL free)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);
129
    LPBYTE buffer = data;
130 131 132
    DMUS_DOWNLOADINFO *info = (DMUS_DOWNLOADINFO*)buffer;
    ULONG *offsets = ((DMUS_OFFSETTABLE*)(buffer + sizeof(DMUS_DOWNLOADINFO)))->ulOffsetTable;
    LPBYTE object = buffer + sizeof(DMUS_DOWNLOADINFO) + info->dwNumOffsetTableEntries * sizeof(ULONG);
133 134 135

    FIXME("(%p)->(%p, %p, %p): stub\n", This, hDownload, data, free);

136 137
    /* FIXME: Currently we only dump data which is very useful to known how native dmusic behave and debug builtin dmusic */

138
    if (!hDownload || !free)
139 140 141 142 143 144 145 146 147 148 149
        return E_POINTER;

    if (TRACE_ON(dmsynth))
    {
        TRACE("Dump DMUS_DOWNLOADINFO struct:\n");
        TRACE(" - dwDLType                = %u\n", info->dwDLType);
        TRACE(" - dwDLId                  = %u\n", info->dwDLId);
        TRACE(" - dwNumOffsetTableEntries = %u\n", info->dwNumOffsetTableEntries);
        TRACE(" - cbSize                  = %u\n", info->cbSize);
    }

150 151 152 153 154 155 156 157 158 159 160 161 162 163
    /* The struct should have at least one offset corresponding to the donwload object itself */
    if (!info->dwNumOffsetTableEntries)
    {
        FIXME("Offset table is empty\n");
        return DMUS_E_BADOFFSETTABLE;
    }

    /* First offset should point to the download object */
    if ((buffer + offsets[0]) != object)
    {
        FIXME("Object is not at the beginning\n");
        return DMUS_E_BADOFFSETTABLE;
    }

164 165 166 167 168 169
    if (info->dwDLType == DMUS_DOWNLOADINFO_INSTRUMENT)
    {
        FIXME("Download type DMUS_DOWNLOADINFO_INSTRUMENT not yet supported\n");
    }
    else if (info->dwDLType == DMUS_DOWNLOADINFO_WAVE)
    {
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
        DMUS_WAVE *wave = (DMUS_WAVE*)object;
        DMUS_WAVEDATA *wave_data;

        TRACE("Processing download type DMUS_DOWNLOADINFO_WAVE\n");

        if (TRACE_ON(dmsynth))
        {
            TRACE("Dump DMUS_WAVE struct\n");
            TRACE(" - ulFirstExtCkIdx   = %u\n", wave->ulFirstExtCkIdx);
            TRACE(" - ulCopyrightIdx    = %u\n", wave->ulCopyrightIdx);
            TRACE(" - ulWaveDataIdx     = %u\n", wave->ulWaveDataIdx);
            TRACE(" - WaveformatEx:\n");
            TRACE("   - wFormatTag      = %u\n", wave->WaveformatEx.wFormatTag);
            TRACE("   - nChannels       = %u\n", wave->WaveformatEx.nChannels);
            TRACE("   - nSamplesPerSec  = %u\n", wave->WaveformatEx.nSamplesPerSec);
            TRACE("   - nAvgBytesPerSec = %u\n", wave->WaveformatEx.nAvgBytesPerSec);
            TRACE("   - nBlockAlign     = %u\n", wave->WaveformatEx.nBlockAlign);
            TRACE("   - wBitsPerSample  = %u\n", wave->WaveformatEx.wBitsPerSample);
            TRACE("   - cbSize          = %u\n", wave->WaveformatEx.cbSize);

            if (wave->ulCopyrightIdx)
            {
                DMUS_COPYRIGHT *copyright = (DMUS_COPYRIGHT*)(buffer + offsets[wave->ulCopyrightIdx]);
                TRACE("Copyright = '%s'\n",  (char*)copyright->byCopyright);
            }

            wave_data = (DMUS_WAVEDATA*)(buffer + offsets[wave->ulWaveDataIdx]);
            TRACE("Found %u bytes of wave data\n", wave_data->cbSize);
        }
199 200 201
    }
    else if (info->dwDLType == DMUS_DOWNLOADINFO_INSTRUMENT2)
    {
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
        DMUS_INSTRUMENT *instrument = (DMUS_INSTRUMENT*)object;
        ULONG nb_regions = 0;

        TRACE("Processing download type DMUS_DOWNLOADINFO_INSTRUMENT2\n");

        if (TRACE_ON(dmsynth))
        {
            TRACE("Dump DMUS_INSTRUMENT struct\n");
            TRACE(" - ulPatch          = %u\n", instrument->ulPatch);
            TRACE(" - ulFirstRegionIdx = %u\n", instrument->ulFirstRegionIdx);
            TRACE(" - ulGlobalArtIdx   = %u\n", instrument->ulGlobalArtIdx);
            TRACE(" - ulFirstExtCkIdx  = %u\n", instrument->ulFirstExtCkIdx);
            TRACE(" - ulCopyrightIdx   = %u\n", instrument->ulCopyrightIdx);
            TRACE(" - ulFlags          = %u\n", instrument->ulFlags);

            if (instrument->ulCopyrightIdx)
            {
                DMUS_COPYRIGHT *copyright = (DMUS_COPYRIGHT*)(buffer + offsets[instrument->ulCopyrightIdx]);
                TRACE("Copyright = '%s'\n",  (char*)copyright->byCopyright);
            }
        }

        if (instrument->ulFirstRegionIdx)
        {
            ULONG region_idx = instrument->ulFirstRegionIdx;

            while (region_idx)
            {
                DMUS_REGION *region = (DMUS_REGION*)(buffer + offsets[region_idx]);

                region_idx = region->ulNextRegionIdx;
                nb_regions++;
            }
        }

        TRACE("Number of regions = %u\n", nb_regions);
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
    }
    else if (info->dwDLType == DMUS_DOWNLOADINFO_WAVEARTICULATION)
    {
        FIXME("Download type DMUS_DOWNLOADINFO_WAVEARTICULATION not yet supported\n");
    }
    else if (info->dwDLType == DMUS_DOWNLOADINFO_STREAMINGWAVE)
    {
        FIXME("Download type DMUS_DOWNLOADINFO_STREAMINGWAVE not yet supported\n");
    }
    else if (info->dwDLType == DMUS_DOWNLOADINFO_ONESHOTWAVE)
    {
        FIXME("Download type DMUS_DOWNLOADINFO_ONESHOTWAVE not yet supported\n");
    }
    else
    {
        WARN("Unknown download type %u\n", info->dwDLType);
        return DMUS_E_UNKNOWNDOWNLOAD;
    }

257
    return S_OK;
258 259
}

260 261 262 263 264 265 266
static HRESULT WINAPI IDirectMusicSynth8Impl_Unload(LPDIRECTMUSICSYNTH8 iface, HANDLE hDownload, HRESULT (CALLBACK* lpFreeHandle)(HANDLE,HANDLE), HANDLE hUserData)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(%p, %p, %p): stub\n", This, hDownload, lpFreeHandle, hUserData);

    return S_OK;
267 268
}

269 270 271 272 273 274 275
static HRESULT WINAPI IDirectMusicSynth8Impl_PlayBuffer(LPDIRECTMUSICSYNTH8 iface, REFERENCE_TIME rt, LPBYTE buffer, DWORD size)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(0x%s, %p, %u): stub\n", This, wine_dbgstr_longlong(rt), buffer, size);

    return S_OK;
276 277
}

278 279 280 281 282 283 284
static HRESULT WINAPI IDirectMusicSynth8Impl_GetRunningStats(LPDIRECTMUSICSYNTH8 iface, LPDMUS_SYNTHSTATS stats)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(%p): stub\n", This, stats);

    return S_OK;
285 286
}

287 288 289 290 291 292 293 294 295
static HRESULT WINAPI IDirectMusicSynth8Impl_GetPortCaps(LPDIRECTMUSICSYNTH8 iface, LPDMUS_PORTCAPS caps)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    TRACE("(%p)->(%p)\n", This, caps);

    *caps = This->pCaps;

    return S_OK;
296 297
}

298 299 300 301 302 303 304
static HRESULT WINAPI IDirectMusicSynth8Impl_SetMasterClock(LPDIRECTMUSICSYNTH8 iface, IReferenceClock* clock)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(%p): stub\n", This, clock);

    return S_OK;
305 306
}

307 308 309 310
static HRESULT WINAPI IDirectMusicSynth8Impl_GetLatencyClock(LPDIRECTMUSICSYNTH8 iface, IReferenceClock** clock)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

311 312 313 314 315 316 317
    TRACE("(%p)->(%p)\n", iface, clock);

    if (!clock)
        return E_POINTER;

    if (!This->pSynthSink)
        return DMUS_E_NOSYNTHSINK;
318 319

    *clock = This->pLatencyClock;
320
    IReferenceClock_AddRef(This->pLatencyClock);
321 322

    return S_OK;
323 324
}

325 326 327 328 329 330 331 332 333
static HRESULT WINAPI IDirectMusicSynth8Impl_Activate(LPDIRECTMUSICSYNTH8 iface, BOOL enable)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    TRACE("(%p)->(%d)\n", This, enable);

    This->fActive = enable;

    return S_OK;
334 335
}

336 337 338 339
static HRESULT WINAPI IDirectMusicSynth8Impl_SetSynthSink(LPDIRECTMUSICSYNTH8 iface, IDirectMusicSynthSink* synth_sink)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

340
    TRACE("(%p)->(%p)\n", iface, synth_sink);
341 342 343

    This->pSynthSink = (IDirectMusicSynthSinkImpl*)synth_sink;

344 345 346
    if (synth_sink)
        return IDirectMusicSynthSink_GetLatencyClock(synth_sink, &This->pLatencyClock);

347
    return S_OK;
348 349
}

350 351 352 353 354 355 356
static HRESULT WINAPI IDirectMusicSynth8Impl_Render(LPDIRECTMUSICSYNTH8 iface, short* buffer, DWORD length, LONGLONG position)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(%p, %d, 0x%s): stub\n", This, buffer, length, wine_dbgstr_longlong(position));

    return S_OK;
357 358
}

359 360 361 362 363 364 365 366
static HRESULT WINAPI IDirectMusicSynth8Impl_SetChannelPriority(LPDIRECTMUSICSYNTH8 iface, DWORD channel_group, DWORD channel, DWORD priority)
{
    /* IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface); */

    /* Silenced because of too many messages - 1000 groups * 16 channels ;=) */
    /* FIXME("(%p)->(%ld, %ld, %ld): stub\n", This, channel_group, channel, priority); */

    return S_OK;
367 368
}

369 370 371 372 373 374 375
static HRESULT WINAPI IDirectMusicSynth8Impl_GetChannelPriority(LPDIRECTMUSICSYNTH8 iface, DWORD channel_group, DWORD channel, LPDWORD priority)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(%d, %d, %p): stub\n", This, channel_group, channel, priority);

    return S_OK;
376 377
}

378 379 380 381 382 383 384
static HRESULT WINAPI IDirectMusicSynth8Impl_GetFormat(LPDIRECTMUSICSYNTH8 iface, LPWAVEFORMATEX wave_format, LPDWORD wave_format_size)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(%p, %p): stub\n", This, wave_format, wave_format_size);

    return S_OK;
385 386
}

387 388
static HRESULT WINAPI IDirectMusicSynth8Impl_GetAppend(LPDIRECTMUSICSYNTH8 iface, DWORD* append)
{
389
    TRACE("(%p)->(%p)\n", iface, append);
390

391 392
    /* We don't need extra space at the end of buffers passed to us for now */
    *append = 0;
393 394

    return S_OK;
395 396
}

397
/* IDirectMusicSynth8Impl IDirectMusicSynth8 part: */
398 399 400 401 402 403 404 405 406 407
static HRESULT WINAPI IDirectMusicSynth8Impl_PlayVoice(LPDIRECTMUSICSYNTH8 iface, REFERENCE_TIME ref_time, DWORD voice_id, DWORD channel_group, DWORD channel,
                                                       DWORD dwDLId, LONG prPitch, LONG vrVolume, SAMPLE_TIME stVoiceStart, SAMPLE_TIME stLoopStart, SAMPLE_TIME stLoopEnd)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(0x%s, %d, %d, %d, %d, %i, %i,0x%s, 0x%s, 0x%s): stub\n",
          This, wine_dbgstr_longlong(ref_time), voice_id, channel_group, channel, dwDLId, prPitch, vrVolume,
          wine_dbgstr_longlong(stVoiceStart), wine_dbgstr_longlong(stLoopStart), wine_dbgstr_longlong(stLoopEnd));

    return S_OK;
408 409
}

410 411 412 413 414 415 416
static HRESULT WINAPI IDirectMusicSynth8Impl_StopVoice(LPDIRECTMUSICSYNTH8 iface, REFERENCE_TIME ref_time, DWORD voice_id)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(0x%s, %d): stub\n", This, wine_dbgstr_longlong(ref_time), voice_id);

    return S_OK;
417 418
}

419 420 421 422 423 424 425
static HRESULT WINAPI IDirectMusicSynth8Impl_GetVoiceState(LPDIRECTMUSICSYNTH8 iface, DWORD dwVoice[], DWORD cbVoice, DMUS_VOICE_STATE dwVoiceState[])
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(%p, %d, %p): stub\n", This, dwVoice, cbVoice, dwVoiceState);

    return S_OK;
426 427
}

428 429 430 431 432 433 434
static HRESULT WINAPI IDirectMusicSynth8Impl_Refresh(LPDIRECTMUSICSYNTH8 iface, DWORD download_id, DWORD flags)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(%d, %d): stub\n", This, download_id, flags);

    return S_OK;
435 436
}

437 438 439 440 441 442 443
static HRESULT WINAPI IDirectMusicSynth8Impl_AssignChannelToBuses(LPDIRECTMUSICSYNTH8 iface, DWORD channel_group, DWORD channel, LPDWORD pdwBuses, DWORD cBuses)
{
    IDirectMusicSynth8Impl *This = impl_from_IDirectMusicSynth8(iface);

    FIXME("(%p)->(%d, %d, %p, %d): stub\n", This, channel_group, channel, pdwBuses, cBuses);

    return S_OK;
444 445
}

446
static const IDirectMusicSynth8Vtbl DirectMusicSynth8_Vtbl = {
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
	IDirectMusicSynth8Impl_QueryInterface,
	IDirectMusicSynth8Impl_AddRef,
	IDirectMusicSynth8Impl_Release,
	IDirectMusicSynth8Impl_Open,
	IDirectMusicSynth8Impl_Close,
	IDirectMusicSynth8Impl_SetNumChannelGroups,
	IDirectMusicSynth8Impl_Download,
	IDirectMusicSynth8Impl_Unload,
	IDirectMusicSynth8Impl_PlayBuffer,
	IDirectMusicSynth8Impl_GetRunningStats,
	IDirectMusicSynth8Impl_GetPortCaps,
	IDirectMusicSynth8Impl_SetMasterClock,
	IDirectMusicSynth8Impl_GetLatencyClock,
	IDirectMusicSynth8Impl_Activate,
	IDirectMusicSynth8Impl_SetSynthSink,
	IDirectMusicSynth8Impl_Render,
	IDirectMusicSynth8Impl_SetChannelPriority,
	IDirectMusicSynth8Impl_GetChannelPriority,
	IDirectMusicSynth8Impl_GetFormat,
	IDirectMusicSynth8Impl_GetAppend,
	IDirectMusicSynth8Impl_PlayVoice,
	IDirectMusicSynth8Impl_StopVoice,
	IDirectMusicSynth8Impl_GetVoiceState,
	IDirectMusicSynth8Impl_Refresh,
	IDirectMusicSynth8Impl_AssignChannelToBuses
};

474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
static inline IDirectMusicSynth8Impl *impl_from_IKsControl(IKsControl *iface)
{
    return CONTAINING_RECORD(iface, IDirectMusicSynth8Impl, IKsControl_iface);
}

static HRESULT WINAPI DMSynthImpl_IKsControl_QueryInterface(IKsControl* iface, REFIID riid, LPVOID *ppobj)
{
    IDirectMusicSynth8Impl *This = impl_from_IKsControl(iface);

    return IDirectMusicSynth8Impl_QueryInterface(&This->IDirectMusicSynth8_iface, riid, ppobj);
}

static ULONG WINAPI DMSynthImpl_IKsControl_AddRef(IKsControl* iface)
{
    IDirectMusicSynth8Impl *This = impl_from_IKsControl(iface);

    return IDirectMusicSynth8Impl_AddRef(&This->IDirectMusicSynth8_iface);
}

static ULONG WINAPI DMSynthImpl_IKsControl_Release(IKsControl* iface)
{
    IDirectMusicSynth8Impl *This = impl_from_IKsControl(iface);

    return IDirectMusicSynth8Impl_Release(&This->IDirectMusicSynth8_iface);
}

static HRESULT WINAPI DMSynthImpl_IKsControl_KsProperty(IKsControl* iface, PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData,
                                                        ULONG DataLength, ULONG* BytesReturned)
{
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 511 512 513 514 515
        return S_FALSE;
    }

    if (DataLength <  sizeof(DWORD))
        return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);

516
    if (IsEqualGUID(&Property->u.s.Set, &GUID_DMUS_PROP_INSTRUMENT2))
517 518 519 520
    {
        *(DWORD*)PropertyData = TRUE;
        *BytesReturned = sizeof(DWORD);
    }
521
    else if (IsEqualGUID(&Property->u.s.Set, &GUID_DMUS_PROP_DLS2))
522 523 524 525
    {
        *(DWORD*)PropertyData = TRUE;
        *BytesReturned = sizeof(DWORD);
    }
526
    else if (IsEqualGUID(&Property->u.s.Set, &GUID_DMUS_PROP_GM_Hardware))
527 528 529 530
    {
        *(DWORD*)PropertyData = FALSE;
        *BytesReturned = sizeof(DWORD);
    }
531
    else if (IsEqualGUID(&Property->u.s.Set, &GUID_DMUS_PROP_GS_Hardware))
532 533 534 535
    {
        *(DWORD*)PropertyData = FALSE;
        *BytesReturned = sizeof(DWORD);
    }
536
    else if (IsEqualGUID(&Property->u.s.Set, &GUID_DMUS_PROP_XG_Hardware))
537 538 539 540 541 542
    {
        *(DWORD*)PropertyData = FALSE;
        *BytesReturned = sizeof(DWORD);
    }
    else
    {
543
        FIXME("Unknown property %s\n", debugstr_guid(&Property->u.s.Set));
544 545 546 547 548
        *(DWORD*)PropertyData = FALSE;
        *BytesReturned = sizeof(DWORD);
    }

    return S_OK;
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
}

static HRESULT WINAPI DMSynthImpl_IKsControl_KsMethod(IKsControl* iface, PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData,
                                                      ULONG DataLength, ULONG* BytesReturned)
{
    FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, Method, MethodLength, MethodData, DataLength, BytesReturned);

    return E_NOTIMPL;
}

static HRESULT WINAPI DMSynthImpl_IKsControl_KsEvent(IKsControl* iface, PKSEVENT Event, ULONG EventLength, LPVOID EventData,
                                                     ULONG DataLength, ULONG* BytesReturned)
{
    FIXME("(%p)->(%p, %u, %p, %u, %p): stub\n", iface, Event, EventLength, EventData, DataLength, BytesReturned);

    return E_NOTIMPL;
}


static const IKsControlVtbl DMSynthImpl_IKsControl_Vtbl = {
    DMSynthImpl_IKsControl_QueryInterface,
    DMSynthImpl_IKsControl_AddRef,
    DMSynthImpl_IKsControl_Release,
    DMSynthImpl_IKsControl_KsProperty,
    DMSynthImpl_IKsControl_KsMethod,
    DMSynthImpl_IKsControl_KsEvent
};

577
/* for ClassFactory */
578 579
HRESULT WINAPI DMUSIC_CreateDirectMusicSynthImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter)
{
580
	IDirectMusicSynth8Impl *obj;
581
	
582 583 584
	TRACE("(%p,%p,%p)\n", lpcGUID, ppobj, pUnkOuter);
	obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicSynth8Impl));
	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 591 592 593 594 595
	obj->ref = 0;
	/* fill in caps */
	obj->pCaps.dwSize = sizeof(DMUS_PORTCAPS);
	obj->pCaps.dwFlags = DMUS_PC_DLS | DMUS_PC_SOFTWARESYNTH | DMUS_PC_DIRECTSOUND | DMUS_PC_DLS2 | DMUS_PC_AUDIOPATH | DMUS_PC_WAVE;
	obj->pCaps.guidPort = CLSID_DirectMusicSynth;
	obj->pCaps.dwClass = DMUS_PC_OUTPUTCLASS;
596
	obj->pCaps.dwType = DMUS_PORT_USER_MODE_SYNTH;
597 598 599
	obj->pCaps.dwMemorySize = DMUS_PC_SYSTEMMEMORY;
	obj->pCaps.dwMaxChannelGroups = 1000;
	obj->pCaps.dwMaxVoices = 1000;
600 601
	obj->pCaps.dwMaxAudioChannels = 2;
	obj->pCaps.dwEffectFlags = DMUS_EFFECT_REVERB;
Jeff Zaroyko's avatar
Jeff Zaroyko committed
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
}