1 /* IDirectMusic8 Implementation
3 * Copyright (C) 2003 Rok Mandeljc
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
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
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include "wine/windef16.h"
32 #include "wine/winbase16.h"
33 #include "wine/debug.h"
36 #include "dmusic_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(dmusic
);
40 /* IDirectMusic8 IUnknown parts follow: */
41 HRESULT WINAPI
IDirectMusic8Impl_QueryInterface (LPDIRECTMUSIC8 iface
, REFIID riid
, LPVOID
*ppobj
)
43 ICOM_THIS(IDirectMusic8Impl
,iface
);
45 if (IsEqualIID (riid
, &IID_IUnknown
) ||
46 IsEqualIID (riid
, &IID_IDirectMusic2
) ||
47 IsEqualIID (riid
, &IID_IDirectMusic8
)) {
48 IDirectMusic8Impl_AddRef(iface
);
53 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppobj
);
57 ULONG WINAPI
IDirectMusic8Impl_AddRef (LPDIRECTMUSIC8 iface
)
59 ICOM_THIS(IDirectMusic8Impl
,iface
);
60 TRACE("(%p) : AddRef from %ld\n", This
, This
->ref
);
64 ULONG WINAPI
IDirectMusic8Impl_Release (LPDIRECTMUSIC8 iface
)
66 ICOM_THIS(IDirectMusic8Impl
,iface
);
67 ULONG ref
= --This
->ref
;
68 TRACE("(%p) : ReleaseRef to %ld\n", This
, This
->ref
);
70 HeapFree(GetProcessHeap(), 0, This
);
75 /* IDirectMusic8 Interface follow: */
76 HRESULT WINAPI
IDirectMusic8Impl_EnumPort(LPDIRECTMUSIC8 iface
, DWORD dwIndex
, LPDMUS_PORTCAPS pPortCaps
)
78 ICOM_THIS(IDirectMusic8Impl
,iface
);
80 TRACE("(%p, %ld, %p)\n", This
, dwIndex
, pPortCaps
);
81 /* i guess the first port shown is always software synthesizer */
84 IDirectMusicSynth8
* synth
;
85 TRACE("enumerating 'Microsoft Software Synthesizer' port\n");
86 CoCreateInstance (&CLSID_DirectMusicSynth
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicSynth8
, (void**)&synth
);
87 IDirectMusicSynth8_GetPortCaps (synth
, pPortCaps
);
88 IDirectMusicSynth8_Release (synth
);
92 /* it seems that the rest of devices are obtained thru dmusic32.EnumLegacyDevices...*sigh*...which is undocumented*/
94 int numMIDI
= midiOutGetNumDevs();
95 int numWAVE
= waveOutGetNumDevs();
97 /* then return digital sound ports */
98 for (i
= 1; i
<= numWAVE
; i
++)
100 TRACE("enumerating 'digital sound' ports\n");
103 DirectSoundEnumerateA((LPDSENUMCALLBACKA
) register_waveport
, (VOID
*) pPortCaps
);
107 /* finally, list all *real* MIDI ports*/
108 for (i
= numWAVE
+ 1; i
<= numWAVE
+ numMIDI
; i
++)
110 TRACE("enumerating 'real MIDI' ports\n");
112 FIXME("Found MIDI port, but *real* MIDI ports not supported yet\n");
118 HRESULT WINAPI
IDirectMusic8Impl_CreateMusicBuffer (LPDIRECTMUSIC8 iface
, LPDMUS_BUFFERDESC pBufferDesc
, LPDIRECTMUSICBUFFER
** ppBuffer
, LPUNKNOWN pUnkOuter
)
120 ICOM_THIS(IDirectMusic8Impl
,iface
);
122 FIXME("(%p, %p, %p, %p): stub\n", This
, pBufferDesc
, ppBuffer
, pUnkOuter
);
127 HRESULT WINAPI
IDirectMusic8Impl_CreatePort (LPDIRECTMUSIC8 iface
, REFCLSID rclsidPort
, LPDMUS_PORTPARAMS pPortParams
, LPDIRECTMUSICPORT
* ppPort
, LPUNKNOWN pUnkOuter
)
129 ICOM_THIS(IDirectMusic8Impl
,iface
);
131 DMUS_PORTCAPS PortCaps
;
133 TRACE("(%p, %s, %p, %p, %p)\n", This
, debugstr_guid(rclsidPort
), pPortParams
, ppPort
, pUnkOuter
);
134 for (i
= 0; S_FALSE
!= IDirectMusic8Impl_EnumPort(iface
, i
, &PortCaps
); i
++) {
135 if (IsEqualCLSID (rclsidPort
, &PortCaps
.guidPort
)) {
136 This
->ppPorts
= HeapReAlloc(GetProcessHeap(), 0, This
->ppPorts
, sizeof(LPDIRECTMUSICPORT
) * This
->nrofports
);
137 if (NULL
== This
->ppPorts
[This
->nrofports
]) {
138 *ppPort
= (LPDIRECTMUSICPORT
)NULL
;
139 return E_OUTOFMEMORY
;
141 This
->ppPorts
[This
->nrofports
]->lpVtbl
= &DirectMusicPort_Vtbl
;
142 This
->ppPorts
[This
->nrofports
]->ref
= 1;
143 This
->ppPorts
[This
->nrofports
]->fActive
= FALSE
;
144 This
->ppPorts
[This
->nrofports
]->pCaps
= &PortCaps
;
145 This
->ppPorts
[This
->nrofports
]->pParams
= pPortParams
; /* this one is here just because there's a funct. which retrieves it back */
146 This
->ppPorts
[This
->nrofports
]->pDirectSound
= NULL
;
147 DMUSIC_CreateReferenceClock (&IID_IReferenceClock
, (IReferenceClock
**)&This
->ppPorts
[This
->nrofports
]->pLatencyClock
, NULL
);
150 if (pPortParams
->dwValidParams
& DMUS_PORTPARAMS_CHANNELGROUPS
) {
151 This
->ports
[This
->nrofports
]->nrofgroups
= pPortParams
->dwChannelGroups
;
152 /* setting default priorities */
153 for (j
= 0; j
< This
->ports
[This
->nrofports
]->nrofgroups
; j
++) {
154 TRACE ("Setting default channel priorities on channel group %i\n", j
+ 1);
155 This
->ports
[This
->nrofports
]->group
[j
].channel
[0].priority
= DAUD_CHAN1_DEF_VOICE_PRIORITY
;
156 This
->ports
[This
->nrofports
]->group
[j
].channel
[1].priority
= DAUD_CHAN2_DEF_VOICE_PRIORITY
;
157 This
->ports
[This
->nrofports
]->group
[j
].channel
[2].priority
= DAUD_CHAN3_DEF_VOICE_PRIORITY
;
158 This
->ports
[This
->nrofports
]->group
[j
].channel
[3].priority
= DAUD_CHAN4_DEF_VOICE_PRIORITY
;
159 This
->ports
[This
->nrofports
]->group
[j
].channel
[4].priority
= DAUD_CHAN5_DEF_VOICE_PRIORITY
;
160 This
->ports
[This
->nrofports
]->group
[j
].channel
[5].priority
= DAUD_CHAN6_DEF_VOICE_PRIORITY
;
161 This
->ports
[This
->nrofports
]->group
[j
].channel
[6].priority
= DAUD_CHAN7_DEF_VOICE_PRIORITY
;
162 This
->ports
[This
->nrofports
]->group
[j
].channel
[7].priority
= DAUD_CHAN8_DEF_VOICE_PRIORITY
;
163 This
->ports
[This
->nrofports
]->group
[j
].channel
[8].priority
= DAUD_CHAN9_DEF_VOICE_PRIORITY
;
164 This
->ports
[This
->nrofports
]->group
[j
].channel
[9].priority
= DAUD_CHAN10_DEF_VOICE_PRIORITY
;
165 This
->ports
[This
->nrofports
]->group
[j
].channel
[10].priority
= DAUD_CHAN11_DEF_VOICE_PRIORITY
;
166 This
->ports
[This
->nrofports
]->group
[j
].channel
[11].priority
= DAUD_CHAN12_DEF_VOICE_PRIORITY
;
167 This
->ports
[This
->nrofports
]->group
[j
].channel
[12].priority
= DAUD_CHAN13_DEF_VOICE_PRIORITY
;
168 This
->ports
[This
->nrofports
]->group
[j
].channel
[13].priority
= DAUD_CHAN14_DEF_VOICE_PRIORITY
;
169 This
->ports
[This
->nrofports
]->group
[j
].channel
[14].priority
= DAUD_CHAN15_DEF_VOICE_PRIORITY
;
170 This
->ports
[This
->nrofports
]->group
[j
].channel
[15].priority
= DAUD_CHAN16_DEF_VOICE_PRIORITY
;
174 *ppPort
= (LPDIRECTMUSICPORT
) This
->ppPorts
[This
->nrofports
];
179 /* FIXME: place correct error here */
180 return E_NOINTERFACE
;
183 HRESULT WINAPI
IDirectMusic8Impl_EnumMasterClock (LPDIRECTMUSIC8 iface
, DWORD dwIndex
, LPDMUS_CLOCKINFO lpClockInfo
)
185 ICOM_THIS(IDirectMusic8Impl
,iface
);
187 FIXME("(%p, %ld, %p): stub\n", This
, dwIndex
, lpClockInfo
);
192 HRESULT WINAPI
IDirectMusic8Impl_GetMasterClock (LPDIRECTMUSIC8 iface
, LPGUID pguidClock
, IReferenceClock
** ppReferenceClock
)
194 ICOM_THIS(IDirectMusic8Impl
,iface
);
196 TRACE("(%p, %p, %p)\n", This
, pguidClock
, ppReferenceClock
);
198 *pguidClock
= This
->pMasterClock
->pClockInfo
.guidClock
;
200 *ppReferenceClock
= (IReferenceClock
*)This
->pMasterClock
;
205 HRESULT WINAPI
IDirectMusic8Impl_SetMasterClock (LPDIRECTMUSIC8 iface
, REFGUID rguidClock
)
207 ICOM_THIS(IDirectMusic8Impl
,iface
);
209 FIXME("(%p, %s): stub\n", This
, debugstr_guid(rguidClock
));
214 HRESULT WINAPI
IDirectMusic8Impl_Activate (LPDIRECTMUSIC8 iface
, BOOL fEnable
)
216 ICOM_THIS(IDirectMusic8Impl
,iface
);
219 FIXME("(%p, %d): stub\n", This
, fEnable
);
220 for (i
= 0; i
< This
->nrofports
; i
++)
222 This
->ppPorts
[i
]->fActive
= fEnable
;
228 HRESULT WINAPI
IDirectMusic8Impl_GetDefaultPort (LPDIRECTMUSIC8 iface
, LPGUID pguidPort
)
230 ICOM_THIS(IDirectMusic8Impl
,iface
);
232 DWORD returnTypeGUID
, sizeOfReturnBuffer
= 50;
233 char returnBuffer
[51];
234 GUID defaultPortGUID
;
237 TRACE("(%p, %p)\n", This
, pguidPort
);
238 if ((RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\DirectMusic\\Defaults" , 0, KEY_READ
, &hkGUID
) != ERROR_SUCCESS
) ||
239 (RegQueryValueExA(hkGUID
, "DefaultOutputPort", NULL
, &returnTypeGUID
, returnBuffer
, &sizeOfReturnBuffer
) != ERROR_SUCCESS
))
241 WARN(": registry entry missing\n" );
242 *pguidPort
= CLSID_DirectMusicSynth
;
245 /* FIXME: Check return types to ensure we're interpreting data right */
246 MultiByteToWideChar(CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
) / sizeof(WCHAR
));
247 CLSIDFromString((LPCOLESTR
) buff
, &defaultPortGUID
);
248 *pguidPort
= defaultPortGUID
;
253 HRESULT WINAPI
IDirectMusic8Impl_SetDirectSound (LPDIRECTMUSIC8 iface
, LPDIRECTSOUND pDirectSound
, HWND hWnd
)
255 ICOM_THIS(IDirectMusic8Impl
,iface
);
257 FIXME("(%p, %p, %p): stub\n", This
, pDirectSound
, hWnd
);
262 HRESULT WINAPI
IDirectMusic8Impl_SetExternalMasterClock (LPDIRECTMUSIC8 iface
, IReferenceClock
* pClock
)
264 ICOM_THIS(IDirectMusic8Impl
,iface
);
266 FIXME("(%p, %p): stub\n", This
, pClock
);
271 ICOM_VTABLE(IDirectMusic8
) DirectMusic8_Vtbl
=
273 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
274 IDirectMusic8Impl_QueryInterface
,
275 IDirectMusic8Impl_AddRef
,
276 IDirectMusic8Impl_Release
,
277 IDirectMusic8Impl_EnumPort
,
278 IDirectMusic8Impl_CreateMusicBuffer
,
279 IDirectMusic8Impl_CreatePort
,
280 IDirectMusic8Impl_EnumMasterClock
,
281 IDirectMusic8Impl_GetMasterClock
,
282 IDirectMusic8Impl_SetMasterClock
,
283 IDirectMusic8Impl_Activate
,
284 IDirectMusic8Impl_GetDefaultPort
,
285 IDirectMusic8Impl_SetDirectSound
,
286 IDirectMusic8Impl_SetExternalMasterClock
290 void register_waveport (LPGUID lpGUID
, LPCSTR lpszDesc
, LPCSTR lpszDrvName
, LPVOID lpContext
)
292 LPDMUS_PORTCAPS pPortCaps
= (LPDMUS_PORTCAPS
)lpContext
;
294 pPortCaps
->dwSize
= sizeof(DMUS_PORTCAPS
);
295 pPortCaps
->dwFlags
= DMUS_PC_DLS
| DMUS_PC_SOFTWARESYNTH
| DMUS_PC_DIRECTSOUND
| DMUS_PC_DLS2
| DMUS_PC_AUDIOPATH
| DMUS_PC_WAVE
;
296 pPortCaps
->guidPort
= *lpGUID
;
297 pPortCaps
->dwClass
= DMUS_PC_OUTPUTCLASS
;
298 pPortCaps
->dwType
= DMUS_PORT_WINMM_DRIVER
;
299 pPortCaps
->dwMemorySize
= DMUS_PC_SYSTEMMEMORY
;
300 pPortCaps
->dwMaxChannelGroups
= 2;
301 pPortCaps
->dwMaxVoices
= -1;
302 pPortCaps
->dwMaxAudioChannels
= -1;
303 pPortCaps
->dwEffectFlags
= DMUS_EFFECT_REVERB
| DMUS_EFFECT_CHORUS
| DMUS_EFFECT_DELAY
;
304 MultiByteToWideChar (CP_ACP
, 0, lpszDesc
, -1, pPortCaps
->wszDescription
, sizeof(pPortCaps
->wszDescription
)/sizeof(WCHAR
));
307 /* for ClassFactory */
308 HRESULT WINAPI
DMUSIC_CreateDirectMusic (LPCGUID lpcGUID
, LPDIRECTMUSIC8
*ppDM
, LPUNKNOWN pUnkOuter
)
310 IDirectMusic8Impl
*dmusic
;
312 TRACE("(%p,%p,%p)\n",lpcGUID
, ppDM
, pUnkOuter
);
313 if (IsEqualIID (lpcGUID
, &IID_IDirectMusic
) ||
314 IsEqualIID (lpcGUID
, &IID_IDirectMusic2
) ||
315 IsEqualIID (lpcGUID
, &IID_IDirectMusic8
)) {
316 dmusic
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusic8Impl
));
317 if (NULL
== dmusic
) {
318 *ppDM
= (LPDIRECTMUSIC8
) NULL
;
319 return E_OUTOFMEMORY
;
321 dmusic
->lpVtbl
= &DirectMusic8_Vtbl
;
323 dmusic
->pMasterClock
= NULL
;
324 dmusic
->ppPorts
= NULL
;
325 dmusic
->nrofports
= 0;
326 DMUSIC_CreateReferenceClock (&IID_IReferenceClock
, (IReferenceClock
**)&dmusic
->pMasterClock
, NULL
);
328 *ppDM
= (LPDIRECTMUSIC8
) dmusic
;
332 WARN("No interface found\n");
333 return E_NOINTERFACE
;