1 /* IDirectMusic8 Implementation
3 * Copyright (C) 2003-2004 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.
19 #include "dmusic_private.h"
21 WINE_DEFAULT_DEBUG_CHANNEL(dmusic
);
23 /* IDirectMusic8Impl IUnknown part: */
24 HRESULT WINAPI
IDirectMusic8Impl_QueryInterface (LPDIRECTMUSIC8 iface
, REFIID riid
, LPVOID
*ppobj
) {
25 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
26 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ppobj
);
28 if (IsEqualIID (riid
, &IID_IUnknown
) ||
29 IsEqualIID (riid
, &IID_IDirectMusic
) ||
30 IsEqualIID (riid
, &IID_IDirectMusic2
) ||
31 IsEqualIID (riid
, &IID_IDirectMusic8
)) {
32 IDirectMusic8Impl_AddRef(iface
);
37 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ppobj
);
41 ULONG WINAPI
IDirectMusic8Impl_AddRef (LPDIRECTMUSIC8 iface
) {
42 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
43 ULONG refCount
= InterlockedIncrement(&This
->ref
);
45 TRACE("(%p)->(ref before=%lu)\n", This
, refCount
- 1);
52 ULONG WINAPI
IDirectMusic8Impl_Release (LPDIRECTMUSIC8 iface
) {
53 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
54 ULONG refCount
= InterlockedDecrement(&This
->ref
);
56 TRACE("(%p)->(ref before=%lu)\n", This
, refCount
+ 1);
59 HeapFree(GetProcessHeap(), 0, This
);
62 DMUSIC_UnlockModule();
67 /* IDirectMusic8Impl IDirectMusic part: */
68 HRESULT WINAPI
IDirectMusic8Impl_EnumPort(LPDIRECTMUSIC8 iface
, DWORD dwIndex
, LPDMUS_PORTCAPS pPortCaps
) {
69 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
71 TRACE("(%p, %ld, %p)\n", This
, dwIndex
, pPortCaps
);
72 /* i guess the first port shown is always software synthesizer */
75 IDirectMusicSynth8
* synth
;
76 TRACE("enumerating 'Microsoft Software Synthesizer' port\n");
77 CoCreateInstance (&CLSID_DirectMusicSynth
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicSynth8
, (void**)&synth
);
78 IDirectMusicSynth8_GetPortCaps (synth
, pPortCaps
);
79 IDirectMusicSynth8_Release (synth
);
83 /* it seems that the rest of devices are obtained thru dmusic32.EnumLegacyDevices...*sigh*...which is undocumented*/
85 int numMIDI
= midiOutGetNumDevs();
86 int numWAVE
= waveOutGetNumDevs();
88 /* then return digital sound ports */
89 for (i
= 1; i
<= numWAVE
; i
++)
91 TRACE("enumerating 'digital sound' ports\n");
94 DirectSoundEnumerateA((LPDSENUMCALLBACKA
) register_waveport
, (VOID
*) pPortCaps
);
98 /* finally, list all *real* MIDI ports*/
99 for (i
= numWAVE
+ 1; i
<= numWAVE
+ numMIDI
; i
++)
101 TRACE("enumerating 'real MIDI' ports\n");
103 FIXME("Found MIDI port, but *real* MIDI ports not supported yet\n");
109 HRESULT WINAPI
IDirectMusic8Impl_CreateMusicBuffer (LPDIRECTMUSIC8 iface
, LPDMUS_BUFFERDESC pBufferDesc
, LPDIRECTMUSICBUFFER
** ppBuffer
, LPUNKNOWN pUnkOuter
) {
110 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
111 FIXME("(%p, %p, %p, %p): stub\n", This
, pBufferDesc
, ppBuffer
, pUnkOuter
);
115 HRESULT WINAPI
IDirectMusic8Impl_CreatePort (LPDIRECTMUSIC8 iface
, REFCLSID rclsidPort
, LPDMUS_PORTPARAMS pPortParams
, LPDIRECTMUSICPORT
* ppPort
, LPUNKNOWN pUnkOuter
) {
116 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
118 DMUS_PORTCAPS PortCaps
;
120 TRACE("(%p, %s, %p, %p, %p)\n", This
, debugstr_dmguid(rclsidPort
), pPortParams
, ppPort
, pUnkOuter
);
121 for (i
= 0; S_FALSE
!= IDirectMusic8Impl_EnumPort(iface
, i
, &PortCaps
); i
++) {
122 if (IsEqualCLSID (rclsidPort
, &PortCaps
.guidPort
)) {
123 if(!This
->ppPorts
) This
->ppPorts
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPDIRECTMUSICPORT
) * This
->nrofports
);
124 else This
->ppPorts
= HeapReAlloc(GetProcessHeap(), 0, This
->ppPorts
, sizeof(LPDIRECTMUSICPORT
) * This
->nrofports
);
125 if (NULL
== This
->ppPorts
[This
->nrofports
]) {
126 *ppPort
= (LPDIRECTMUSICPORT
)NULL
;
127 return E_OUTOFMEMORY
;
129 This
->ppPorts
[This
->nrofports
]->lpVtbl
= &DirectMusicPort_Vtbl
;
130 This
->ppPorts
[This
->nrofports
]->ref
= 1;
131 This
->ppPorts
[This
->nrofports
]->fActive
= FALSE
;
132 This
->ppPorts
[This
->nrofports
]->pCaps
= &PortCaps
;
133 This
->ppPorts
[This
->nrofports
]->pParams
= pPortParams
; /* this one is here just because there's a funct. which retrieves it back */
134 This
->ppPorts
[This
->nrofports
]->pDirectSound
= NULL
;
135 DMUSIC_CreateReferenceClockImpl (&IID_IReferenceClock
, (LPVOID
*)&This
->ppPorts
[This
->nrofports
]->pLatencyClock
, NULL
);
138 if (pPortParams
->dwValidParams
& DMUS_PORTPARAMS_CHANNELGROUPS
) {
139 This
->ports
[This
->nrofports
]->nrofgroups
= pPortParams
->dwChannelGroups
;
140 /* setting default priorities */
141 for (j
= 0; j
< This
->ports
[This
->nrofports
]->nrofgroups
; j
++) {
142 TRACE ("Setting default channel priorities on channel group %i\n", j
+ 1);
143 This
->ports
[This
->nrofports
]->group
[j
].channel
[0].priority
= DAUD_CHAN1_DEF_VOICE_PRIORITY
;
144 This
->ports
[This
->nrofports
]->group
[j
].channel
[1].priority
= DAUD_CHAN2_DEF_VOICE_PRIORITY
;
145 This
->ports
[This
->nrofports
]->group
[j
].channel
[2].priority
= DAUD_CHAN3_DEF_VOICE_PRIORITY
;
146 This
->ports
[This
->nrofports
]->group
[j
].channel
[3].priority
= DAUD_CHAN4_DEF_VOICE_PRIORITY
;
147 This
->ports
[This
->nrofports
]->group
[j
].channel
[4].priority
= DAUD_CHAN5_DEF_VOICE_PRIORITY
;
148 This
->ports
[This
->nrofports
]->group
[j
].channel
[5].priority
= DAUD_CHAN6_DEF_VOICE_PRIORITY
;
149 This
->ports
[This
->nrofports
]->group
[j
].channel
[6].priority
= DAUD_CHAN7_DEF_VOICE_PRIORITY
;
150 This
->ports
[This
->nrofports
]->group
[j
].channel
[7].priority
= DAUD_CHAN8_DEF_VOICE_PRIORITY
;
151 This
->ports
[This
->nrofports
]->group
[j
].channel
[8].priority
= DAUD_CHAN9_DEF_VOICE_PRIORITY
;
152 This
->ports
[This
->nrofports
]->group
[j
].channel
[9].priority
= DAUD_CHAN10_DEF_VOICE_PRIORITY
;
153 This
->ports
[This
->nrofports
]->group
[j
].channel
[10].priority
= DAUD_CHAN11_DEF_VOICE_PRIORITY
;
154 This
->ports
[This
->nrofports
]->group
[j
].channel
[11].priority
= DAUD_CHAN12_DEF_VOICE_PRIORITY
;
155 This
->ports
[This
->nrofports
]->group
[j
].channel
[12].priority
= DAUD_CHAN13_DEF_VOICE_PRIORITY
;
156 This
->ports
[This
->nrofports
]->group
[j
].channel
[13].priority
= DAUD_CHAN14_DEF_VOICE_PRIORITY
;
157 This
->ports
[This
->nrofports
]->group
[j
].channel
[14].priority
= DAUD_CHAN15_DEF_VOICE_PRIORITY
;
158 This
->ports
[This
->nrofports
]->group
[j
].channel
[15].priority
= DAUD_CHAN16_DEF_VOICE_PRIORITY
;
162 *ppPort
= (LPDIRECTMUSICPORT
) This
->ppPorts
[This
->nrofports
];
167 /* FIXME: place correct error here */
168 return E_NOINTERFACE
;
171 HRESULT WINAPI
IDirectMusic8Impl_EnumMasterClock (LPDIRECTMUSIC8 iface
, DWORD dwIndex
, LPDMUS_CLOCKINFO lpClockInfo
) {
172 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
173 FIXME("(%p, %ld, %p): stub\n", This
, dwIndex
, lpClockInfo
);
177 HRESULT WINAPI
IDirectMusic8Impl_GetMasterClock (LPDIRECTMUSIC8 iface
, LPGUID pguidClock
, IReferenceClock
** ppReferenceClock
) {
178 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
180 TRACE("(%p, %p, %p)\n", This
, pguidClock
, ppReferenceClock
);
182 *pguidClock
= This
->pMasterClock
->pClockInfo
.guidClock
;
184 *ppReferenceClock
= (IReferenceClock
*)This
->pMasterClock
;
189 HRESULT WINAPI
IDirectMusic8Impl_SetMasterClock (LPDIRECTMUSIC8 iface
, REFGUID rguidClock
) {
190 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
191 FIXME("(%p, %s): stub\n", This
, debugstr_dmguid(rguidClock
));
195 HRESULT WINAPI
IDirectMusic8Impl_Activate (LPDIRECTMUSIC8 iface
, BOOL fEnable
) {
196 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
199 FIXME("(%p, %d): stub\n", This
, fEnable
);
200 for (i
= 0; i
< This
->nrofports
; i
++) {
201 This
->ppPorts
[i
]->fActive
= fEnable
;
207 HRESULT WINAPI
IDirectMusic8Impl_GetDefaultPort (LPDIRECTMUSIC8 iface
, LPGUID pguidPort
) {
208 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
210 DWORD returnTypeGUID
, sizeOfReturnBuffer
= 50;
211 char returnBuffer
[51];
212 GUID defaultPortGUID
;
215 TRACE("(%p, %p)\n", This
, pguidPort
);
216 if ((RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\DirectMusic\\Defaults" , 0, KEY_READ
, &hkGUID
) != ERROR_SUCCESS
) ||
217 (RegQueryValueExA(hkGUID
, "DefaultOutputPort", NULL
, &returnTypeGUID
, returnBuffer
, &sizeOfReturnBuffer
) != ERROR_SUCCESS
))
219 WARN(": registry entry missing\n" );
220 *pguidPort
= CLSID_DirectMusicSynth
;
223 /* FIXME: Check return types to ensure we're interpreting data right */
224 MultiByteToWideChar(CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
) / sizeof(WCHAR
));
225 CLSIDFromString(buff
, &defaultPortGUID
);
226 *pguidPort
= defaultPortGUID
;
231 HRESULT WINAPI
IDirectMusic8Impl_SetDirectSound (LPDIRECTMUSIC8 iface
, LPDIRECTSOUND pDirectSound
, HWND hWnd
) {
232 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
233 FIXME("(%p, %p, %p): stub\n", This
, pDirectSound
, hWnd
);
237 HRESULT WINAPI
IDirectMusic8Impl_SetExternalMasterClock (LPDIRECTMUSIC8 iface
, IReferenceClock
* pClock
) {
238 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
239 FIXME("(%p, %p): stub\n", This
, pClock
);
243 IDirectMusic8Vtbl DirectMusic8_Vtbl
= {
244 IDirectMusic8Impl_QueryInterface
,
245 IDirectMusic8Impl_AddRef
,
246 IDirectMusic8Impl_Release
,
247 IDirectMusic8Impl_EnumPort
,
248 IDirectMusic8Impl_CreateMusicBuffer
,
249 IDirectMusic8Impl_CreatePort
,
250 IDirectMusic8Impl_EnumMasterClock
,
251 IDirectMusic8Impl_GetMasterClock
,
252 IDirectMusic8Impl_SetMasterClock
,
253 IDirectMusic8Impl_Activate
,
254 IDirectMusic8Impl_GetDefaultPort
,
255 IDirectMusic8Impl_SetDirectSound
,
256 IDirectMusic8Impl_SetExternalMasterClock
260 void register_waveport (LPGUID lpGUID
, LPCSTR lpszDesc
, LPCSTR lpszDrvName
, LPVOID lpContext
) {
261 LPDMUS_PORTCAPS pPortCaps
= (LPDMUS_PORTCAPS
)lpContext
;
263 pPortCaps
->dwSize
= sizeof(DMUS_PORTCAPS
);
264 pPortCaps
->dwFlags
= DMUS_PC_DLS
| DMUS_PC_SOFTWARESYNTH
| DMUS_PC_DIRECTSOUND
| DMUS_PC_DLS2
| DMUS_PC_AUDIOPATH
| DMUS_PC_WAVE
;
265 pPortCaps
->guidPort
= *lpGUID
;
266 pPortCaps
->dwClass
= DMUS_PC_OUTPUTCLASS
;
267 pPortCaps
->dwType
= DMUS_PORT_WINMM_DRIVER
;
268 pPortCaps
->dwMemorySize
= DMUS_PC_SYSTEMMEMORY
;
269 pPortCaps
->dwMaxChannelGroups
= 2;
270 pPortCaps
->dwMaxVoices
= -1;
271 pPortCaps
->dwMaxAudioChannels
= -1;
272 pPortCaps
->dwEffectFlags
= DMUS_EFFECT_REVERB
| DMUS_EFFECT_CHORUS
| DMUS_EFFECT_DELAY
;
273 MultiByteToWideChar (CP_ACP
, 0, lpszDesc
, -1, pPortCaps
->wszDescription
, sizeof(pPortCaps
->wszDescription
)/sizeof(WCHAR
));
276 /* for ClassFactory */
277 HRESULT WINAPI
DMUSIC_CreateDirectMusicImpl (LPCGUID lpcGUID
, LPVOID
* ppobj
, LPUNKNOWN pUnkOuter
) {
278 IDirectMusic8Impl
*dmusic
;
280 TRACE("(%p,%p,%p)\n",lpcGUID
, ppobj
, pUnkOuter
);
282 dmusic
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusic8Impl
));
283 if (NULL
== dmusic
) {
284 *ppobj
= (LPDIRECTMUSIC8
) NULL
;
285 return E_OUTOFMEMORY
;
287 dmusic
->lpVtbl
= &DirectMusic8_Vtbl
;
288 dmusic
->ref
= 0; /* will be inited with QueryInterface */
289 dmusic
->pMasterClock
= NULL
;
290 dmusic
->ppPorts
= NULL
;
291 dmusic
->nrofports
= 0;
292 DMUSIC_CreateReferenceClockImpl (&IID_IReferenceClock
, (LPVOID
*)&dmusic
->pMasterClock
, NULL
);
294 return IDirectMusic8Impl_QueryInterface ((LPDIRECTMUSIC8
)dmusic
, lpcGUID
, ppobj
);