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 TRACE("(%p): AddRef from %ld\n", This
, This
->ref
);
47 ULONG WINAPI
IDirectMusic8Impl_Release (LPDIRECTMUSIC8 iface
) {
48 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
49 ULONG ref
= --This
->ref
;
50 TRACE("(%p): ReleaseRef to %ld\n", This
, This
->ref
);
52 HeapFree(GetProcessHeap(), 0, This
);
57 /* IDirectMusic8Impl IDirectMusic part: */
58 HRESULT WINAPI
IDirectMusic8Impl_EnumPort(LPDIRECTMUSIC8 iface
, DWORD dwIndex
, LPDMUS_PORTCAPS pPortCaps
) {
59 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
61 TRACE("(%p, %ld, %p)\n", This
, dwIndex
, pPortCaps
);
62 /* i guess the first port shown is always software synthesizer */
65 IDirectMusicSynth8
* synth
;
66 TRACE("enumerating 'Microsoft Software Synthesizer' port\n");
67 CoCreateInstance (&CLSID_DirectMusicSynth
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicSynth8
, (void**)&synth
);
68 IDirectMusicSynth8_GetPortCaps (synth
, pPortCaps
);
69 IDirectMusicSynth8_Release (synth
);
73 /* it seems that the rest of devices are obtained thru dmusic32.EnumLegacyDevices...*sigh*...which is undocumented*/
75 int numMIDI
= midiOutGetNumDevs();
76 int numWAVE
= waveOutGetNumDevs();
78 /* then return digital sound ports */
79 for (i
= 1; i
<= numWAVE
; i
++)
81 TRACE("enumerating 'digital sound' ports\n");
84 DirectSoundEnumerateA((LPDSENUMCALLBACKA
) register_waveport
, (VOID
*) pPortCaps
);
88 /* finally, list all *real* MIDI ports*/
89 for (i
= numWAVE
+ 1; i
<= numWAVE
+ numMIDI
; i
++)
91 TRACE("enumerating 'real MIDI' ports\n");
93 FIXME("Found MIDI port, but *real* MIDI ports not supported yet\n");
99 HRESULT WINAPI
IDirectMusic8Impl_CreateMusicBuffer (LPDIRECTMUSIC8 iface
, LPDMUS_BUFFERDESC pBufferDesc
, LPDIRECTMUSICBUFFER
** ppBuffer
, LPUNKNOWN pUnkOuter
) {
100 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
101 FIXME("(%p, %p, %p, %p): stub\n", This
, pBufferDesc
, ppBuffer
, pUnkOuter
);
105 HRESULT WINAPI
IDirectMusic8Impl_CreatePort (LPDIRECTMUSIC8 iface
, REFCLSID rclsidPort
, LPDMUS_PORTPARAMS pPortParams
, LPDIRECTMUSICPORT
* ppPort
, LPUNKNOWN pUnkOuter
) {
106 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
108 DMUS_PORTCAPS PortCaps
;
110 TRACE("(%p, %s, %p, %p, %p)\n", This
, debugstr_dmguid(rclsidPort
), pPortParams
, ppPort
, pUnkOuter
);
111 for (i
= 0; S_FALSE
!= IDirectMusic8Impl_EnumPort(iface
, i
, &PortCaps
); i
++) {
112 if (IsEqualCLSID (rclsidPort
, &PortCaps
.guidPort
)) {
113 if(!This
->ppPorts
) This
->ppPorts
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPDIRECTMUSICPORT
) * This
->nrofports
);
114 else This
->ppPorts
= HeapReAlloc(GetProcessHeap(), 0, This
->ppPorts
, sizeof(LPDIRECTMUSICPORT
) * This
->nrofports
);
115 if (NULL
== This
->ppPorts
[This
->nrofports
]) {
116 *ppPort
= (LPDIRECTMUSICPORT
)NULL
;
117 return E_OUTOFMEMORY
;
119 This
->ppPorts
[This
->nrofports
]->lpVtbl
= &DirectMusicPort_Vtbl
;
120 This
->ppPorts
[This
->nrofports
]->ref
= 1;
121 This
->ppPorts
[This
->nrofports
]->fActive
= FALSE
;
122 This
->ppPorts
[This
->nrofports
]->pCaps
= &PortCaps
;
123 This
->ppPorts
[This
->nrofports
]->pParams
= pPortParams
; /* this one is here just because there's a funct. which retrieves it back */
124 This
->ppPorts
[This
->nrofports
]->pDirectSound
= NULL
;
125 DMUSIC_CreateReferenceClockImpl (&IID_IReferenceClock
, (LPVOID
*)&This
->ppPorts
[This
->nrofports
]->pLatencyClock
, NULL
);
128 if (pPortParams
->dwValidParams
& DMUS_PORTPARAMS_CHANNELGROUPS
) {
129 This
->ports
[This
->nrofports
]->nrofgroups
= pPortParams
->dwChannelGroups
;
130 /* setting default priorities */
131 for (j
= 0; j
< This
->ports
[This
->nrofports
]->nrofgroups
; j
++) {
132 TRACE ("Setting default channel priorities on channel group %i\n", j
+ 1);
133 This
->ports
[This
->nrofports
]->group
[j
].channel
[0].priority
= DAUD_CHAN1_DEF_VOICE_PRIORITY
;
134 This
->ports
[This
->nrofports
]->group
[j
].channel
[1].priority
= DAUD_CHAN2_DEF_VOICE_PRIORITY
;
135 This
->ports
[This
->nrofports
]->group
[j
].channel
[2].priority
= DAUD_CHAN3_DEF_VOICE_PRIORITY
;
136 This
->ports
[This
->nrofports
]->group
[j
].channel
[3].priority
= DAUD_CHAN4_DEF_VOICE_PRIORITY
;
137 This
->ports
[This
->nrofports
]->group
[j
].channel
[4].priority
= DAUD_CHAN5_DEF_VOICE_PRIORITY
;
138 This
->ports
[This
->nrofports
]->group
[j
].channel
[5].priority
= DAUD_CHAN6_DEF_VOICE_PRIORITY
;
139 This
->ports
[This
->nrofports
]->group
[j
].channel
[6].priority
= DAUD_CHAN7_DEF_VOICE_PRIORITY
;
140 This
->ports
[This
->nrofports
]->group
[j
].channel
[7].priority
= DAUD_CHAN8_DEF_VOICE_PRIORITY
;
141 This
->ports
[This
->nrofports
]->group
[j
].channel
[8].priority
= DAUD_CHAN9_DEF_VOICE_PRIORITY
;
142 This
->ports
[This
->nrofports
]->group
[j
].channel
[9].priority
= DAUD_CHAN10_DEF_VOICE_PRIORITY
;
143 This
->ports
[This
->nrofports
]->group
[j
].channel
[10].priority
= DAUD_CHAN11_DEF_VOICE_PRIORITY
;
144 This
->ports
[This
->nrofports
]->group
[j
].channel
[11].priority
= DAUD_CHAN12_DEF_VOICE_PRIORITY
;
145 This
->ports
[This
->nrofports
]->group
[j
].channel
[12].priority
= DAUD_CHAN13_DEF_VOICE_PRIORITY
;
146 This
->ports
[This
->nrofports
]->group
[j
].channel
[13].priority
= DAUD_CHAN14_DEF_VOICE_PRIORITY
;
147 This
->ports
[This
->nrofports
]->group
[j
].channel
[14].priority
= DAUD_CHAN15_DEF_VOICE_PRIORITY
;
148 This
->ports
[This
->nrofports
]->group
[j
].channel
[15].priority
= DAUD_CHAN16_DEF_VOICE_PRIORITY
;
152 *ppPort
= (LPDIRECTMUSICPORT
) This
->ppPorts
[This
->nrofports
];
157 /* FIXME: place correct error here */
158 return E_NOINTERFACE
;
161 HRESULT WINAPI
IDirectMusic8Impl_EnumMasterClock (LPDIRECTMUSIC8 iface
, DWORD dwIndex
, LPDMUS_CLOCKINFO lpClockInfo
) {
162 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
163 FIXME("(%p, %ld, %p): stub\n", This
, dwIndex
, lpClockInfo
);
167 HRESULT WINAPI
IDirectMusic8Impl_GetMasterClock (LPDIRECTMUSIC8 iface
, LPGUID pguidClock
, IReferenceClock
** ppReferenceClock
) {
168 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
170 TRACE("(%p, %p, %p)\n", This
, pguidClock
, ppReferenceClock
);
172 *pguidClock
= This
->pMasterClock
->pClockInfo
.guidClock
;
174 *ppReferenceClock
= (IReferenceClock
*)This
->pMasterClock
;
179 HRESULT WINAPI
IDirectMusic8Impl_SetMasterClock (LPDIRECTMUSIC8 iface
, REFGUID rguidClock
) {
180 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
181 FIXME("(%p, %s): stub\n", This
, debugstr_dmguid(rguidClock
));
185 HRESULT WINAPI
IDirectMusic8Impl_Activate (LPDIRECTMUSIC8 iface
, BOOL fEnable
) {
186 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
189 FIXME("(%p, %d): stub\n", This
, fEnable
);
190 for (i
= 0; i
< This
->nrofports
; i
++) {
191 This
->ppPorts
[i
]->fActive
= fEnable
;
197 HRESULT WINAPI
IDirectMusic8Impl_GetDefaultPort (LPDIRECTMUSIC8 iface
, LPGUID pguidPort
) {
198 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
200 DWORD returnTypeGUID
, sizeOfReturnBuffer
= 50;
201 char returnBuffer
[51];
202 GUID defaultPortGUID
;
205 TRACE("(%p, %p)\n", This
, pguidPort
);
206 if ((RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\DirectMusic\\Defaults" , 0, KEY_READ
, &hkGUID
) != ERROR_SUCCESS
) ||
207 (RegQueryValueExA(hkGUID
, "DefaultOutputPort", NULL
, &returnTypeGUID
, returnBuffer
, &sizeOfReturnBuffer
) != ERROR_SUCCESS
))
209 WARN(": registry entry missing\n" );
210 *pguidPort
= CLSID_DirectMusicSynth
;
213 /* FIXME: Check return types to ensure we're interpreting data right */
214 MultiByteToWideChar(CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
) / sizeof(WCHAR
));
215 CLSIDFromString(buff
, &defaultPortGUID
);
216 *pguidPort
= defaultPortGUID
;
221 HRESULT WINAPI
IDirectMusic8Impl_SetDirectSound (LPDIRECTMUSIC8 iface
, LPDIRECTSOUND pDirectSound
, HWND hWnd
) {
222 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
223 FIXME("(%p, %p, %p): stub\n", This
, pDirectSound
, hWnd
);
227 HRESULT WINAPI
IDirectMusic8Impl_SetExternalMasterClock (LPDIRECTMUSIC8 iface
, IReferenceClock
* pClock
) {
228 IDirectMusic8Impl
*This
= (IDirectMusic8Impl
*)iface
;
229 FIXME("(%p, %p): stub\n", This
, pClock
);
233 IDirectMusic8Vtbl DirectMusic8_Vtbl
= {
234 IDirectMusic8Impl_QueryInterface
,
235 IDirectMusic8Impl_AddRef
,
236 IDirectMusic8Impl_Release
,
237 IDirectMusic8Impl_EnumPort
,
238 IDirectMusic8Impl_CreateMusicBuffer
,
239 IDirectMusic8Impl_CreatePort
,
240 IDirectMusic8Impl_EnumMasterClock
,
241 IDirectMusic8Impl_GetMasterClock
,
242 IDirectMusic8Impl_SetMasterClock
,
243 IDirectMusic8Impl_Activate
,
244 IDirectMusic8Impl_GetDefaultPort
,
245 IDirectMusic8Impl_SetDirectSound
,
246 IDirectMusic8Impl_SetExternalMasterClock
250 void register_waveport (LPGUID lpGUID
, LPCSTR lpszDesc
, LPCSTR lpszDrvName
, LPVOID lpContext
) {
251 LPDMUS_PORTCAPS pPortCaps
= (LPDMUS_PORTCAPS
)lpContext
;
253 pPortCaps
->dwSize
= sizeof(DMUS_PORTCAPS
);
254 pPortCaps
->dwFlags
= DMUS_PC_DLS
| DMUS_PC_SOFTWARESYNTH
| DMUS_PC_DIRECTSOUND
| DMUS_PC_DLS2
| DMUS_PC_AUDIOPATH
| DMUS_PC_WAVE
;
255 pPortCaps
->guidPort
= *lpGUID
;
256 pPortCaps
->dwClass
= DMUS_PC_OUTPUTCLASS
;
257 pPortCaps
->dwType
= DMUS_PORT_WINMM_DRIVER
;
258 pPortCaps
->dwMemorySize
= DMUS_PC_SYSTEMMEMORY
;
259 pPortCaps
->dwMaxChannelGroups
= 2;
260 pPortCaps
->dwMaxVoices
= -1;
261 pPortCaps
->dwMaxAudioChannels
= -1;
262 pPortCaps
->dwEffectFlags
= DMUS_EFFECT_REVERB
| DMUS_EFFECT_CHORUS
| DMUS_EFFECT_DELAY
;
263 MultiByteToWideChar (CP_ACP
, 0, lpszDesc
, -1, pPortCaps
->wszDescription
, sizeof(pPortCaps
->wszDescription
)/sizeof(WCHAR
));
266 /* for ClassFactory */
267 HRESULT WINAPI
DMUSIC_CreateDirectMusicImpl (LPCGUID lpcGUID
, LPVOID
* ppobj
, LPUNKNOWN pUnkOuter
) {
268 IDirectMusic8Impl
*dmusic
;
270 TRACE("(%p,%p,%p)\n",lpcGUID
, ppobj
, pUnkOuter
);
272 dmusic
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusic8Impl
));
273 if (NULL
== dmusic
) {
274 *ppobj
= (LPDIRECTMUSIC8
) NULL
;
275 return E_OUTOFMEMORY
;
277 dmusic
->lpVtbl
= &DirectMusic8_Vtbl
;
278 dmusic
->ref
= 0; /* will be inited with QueryInterface */
279 dmusic
->pMasterClock
= NULL
;
280 dmusic
->ppPorts
= NULL
;
281 dmusic
->nrofports
= 0;
282 DMUSIC_CreateReferenceClockImpl (&IID_IReferenceClock
, (LPVOID
*)&dmusic
->pMasterClock
, NULL
);
284 return IDirectMusic8Impl_QueryInterface ((LPDIRECTMUSIC8
)dmusic
, lpcGUID
, ppobj
);