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 ICOM_THIS(IDirectMusic8Impl
,iface
);
27 if (IsEqualIID (riid
, &IID_IUnknown
) ||
28 IsEqualIID (riid
, &IID_IDirectMusic
) ||
29 IsEqualIID (riid
, &IID_IDirectMusic2
) ||
30 IsEqualIID (riid
, &IID_IDirectMusic8
)) {
31 IDirectMusic8Impl_AddRef(iface
);
36 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppobj
);
40 ULONG WINAPI
IDirectMusic8Impl_AddRef (LPDIRECTMUSIC8 iface
) {
41 ICOM_THIS(IDirectMusic8Impl
,iface
);
42 TRACE("(%p) : AddRef from %ld\n", This
, This
->ref
);
46 ULONG WINAPI
IDirectMusic8Impl_Release (LPDIRECTMUSIC8 iface
) {
47 ICOM_THIS(IDirectMusic8Impl
,iface
);
48 ULONG ref
= --This
->ref
;
49 TRACE("(%p) : ReleaseRef to %ld\n", This
, This
->ref
);
51 HeapFree(GetProcessHeap(), 0, This
);
56 /* IDirectMusic8Impl IDirectMusic part: */
57 HRESULT WINAPI
IDirectMusic8Impl_EnumPort(LPDIRECTMUSIC8 iface
, DWORD dwIndex
, LPDMUS_PORTCAPS pPortCaps
) {
58 ICOM_THIS(IDirectMusic8Impl
,iface
);
60 TRACE("(%p, %ld, %p)\n", This
, dwIndex
, pPortCaps
);
61 /* i guess the first port shown is always software synthesizer */
64 IDirectMusicSynth8
* synth
;
65 TRACE("enumerating 'Microsoft Software Synthesizer' port\n");
66 CoCreateInstance (&CLSID_DirectMusicSynth
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicSynth8
, (void**)&synth
);
67 IDirectMusicSynth8_GetPortCaps (synth
, pPortCaps
);
68 IDirectMusicSynth8_Release (synth
);
72 /* it seems that the rest of devices are obtained thru dmusic32.EnumLegacyDevices...*sigh*...which is undocumented*/
74 int numMIDI
= midiOutGetNumDevs();
75 int numWAVE
= waveOutGetNumDevs();
77 /* then return digital sound ports */
78 for (i
= 1; i
<= numWAVE
; i
++)
80 TRACE("enumerating 'digital sound' ports\n");
83 DirectSoundEnumerateA((LPDSENUMCALLBACKA
) register_waveport
, (VOID
*) pPortCaps
);
87 /* finally, list all *real* MIDI ports*/
88 for (i
= numWAVE
+ 1; i
<= numWAVE
+ numMIDI
; i
++)
90 TRACE("enumerating 'real MIDI' ports\n");
92 FIXME("Found MIDI port, but *real* MIDI ports not supported yet\n");
98 HRESULT WINAPI
IDirectMusic8Impl_CreateMusicBuffer (LPDIRECTMUSIC8 iface
, LPDMUS_BUFFERDESC pBufferDesc
, LPDIRECTMUSICBUFFER
** ppBuffer
, LPUNKNOWN pUnkOuter
) {
99 ICOM_THIS(IDirectMusic8Impl
,iface
);
100 FIXME("(%p, %p, %p, %p): stub\n", This
, pBufferDesc
, ppBuffer
, pUnkOuter
);
104 HRESULT WINAPI
IDirectMusic8Impl_CreatePort (LPDIRECTMUSIC8 iface
, REFCLSID rclsidPort
, LPDMUS_PORTPARAMS pPortParams
, LPDIRECTMUSICPORT
* ppPort
, LPUNKNOWN pUnkOuter
) {
105 ICOM_THIS(IDirectMusic8Impl
,iface
);
107 DMUS_PORTCAPS PortCaps
;
109 TRACE("(%p, %s, %p, %p, %p)\n", This
, debugstr_guid(rclsidPort
), pPortParams
, ppPort
, pUnkOuter
);
110 for (i
= 0; S_FALSE
!= IDirectMusic8Impl_EnumPort(iface
, i
, &PortCaps
); i
++) {
111 if (IsEqualCLSID (rclsidPort
, &PortCaps
.guidPort
)) {
112 if(!This
->ppPorts
) This
->ppPorts
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPDIRECTMUSICPORT
) * This
->nrofports
);
113 else This
->ppPorts
= HeapReAlloc(GetProcessHeap(), 0, This
->ppPorts
, sizeof(LPDIRECTMUSICPORT
) * This
->nrofports
);
114 if (NULL
== This
->ppPorts
[This
->nrofports
]) {
115 *ppPort
= (LPDIRECTMUSICPORT
)NULL
;
116 return E_OUTOFMEMORY
;
118 This
->ppPorts
[This
->nrofports
]->lpVtbl
= &DirectMusicPort_Vtbl
;
119 This
->ppPorts
[This
->nrofports
]->ref
= 1;
120 This
->ppPorts
[This
->nrofports
]->fActive
= FALSE
;
121 This
->ppPorts
[This
->nrofports
]->pCaps
= &PortCaps
;
122 This
->ppPorts
[This
->nrofports
]->pParams
= pPortParams
; /* this one is here just because there's a funct. which retrieves it back */
123 This
->ppPorts
[This
->nrofports
]->pDirectSound
= NULL
;
124 DMUSIC_CreateReferenceClockImpl (&IID_IReferenceClock
, (LPVOID
*)&This
->ppPorts
[This
->nrofports
]->pLatencyClock
, NULL
);
127 if (pPortParams
->dwValidParams
& DMUS_PORTPARAMS_CHANNELGROUPS
) {
128 This
->ports
[This
->nrofports
]->nrofgroups
= pPortParams
->dwChannelGroups
;
129 /* setting default priorities */
130 for (j
= 0; j
< This
->ports
[This
->nrofports
]->nrofgroups
; j
++) {
131 TRACE ("Setting default channel priorities on channel group %i\n", j
+ 1);
132 This
->ports
[This
->nrofports
]->group
[j
].channel
[0].priority
= DAUD_CHAN1_DEF_VOICE_PRIORITY
;
133 This
->ports
[This
->nrofports
]->group
[j
].channel
[1].priority
= DAUD_CHAN2_DEF_VOICE_PRIORITY
;
134 This
->ports
[This
->nrofports
]->group
[j
].channel
[2].priority
= DAUD_CHAN3_DEF_VOICE_PRIORITY
;
135 This
->ports
[This
->nrofports
]->group
[j
].channel
[3].priority
= DAUD_CHAN4_DEF_VOICE_PRIORITY
;
136 This
->ports
[This
->nrofports
]->group
[j
].channel
[4].priority
= DAUD_CHAN5_DEF_VOICE_PRIORITY
;
137 This
->ports
[This
->nrofports
]->group
[j
].channel
[5].priority
= DAUD_CHAN6_DEF_VOICE_PRIORITY
;
138 This
->ports
[This
->nrofports
]->group
[j
].channel
[6].priority
= DAUD_CHAN7_DEF_VOICE_PRIORITY
;
139 This
->ports
[This
->nrofports
]->group
[j
].channel
[7].priority
= DAUD_CHAN8_DEF_VOICE_PRIORITY
;
140 This
->ports
[This
->nrofports
]->group
[j
].channel
[8].priority
= DAUD_CHAN9_DEF_VOICE_PRIORITY
;
141 This
->ports
[This
->nrofports
]->group
[j
].channel
[9].priority
= DAUD_CHAN10_DEF_VOICE_PRIORITY
;
142 This
->ports
[This
->nrofports
]->group
[j
].channel
[10].priority
= DAUD_CHAN11_DEF_VOICE_PRIORITY
;
143 This
->ports
[This
->nrofports
]->group
[j
].channel
[11].priority
= DAUD_CHAN12_DEF_VOICE_PRIORITY
;
144 This
->ports
[This
->nrofports
]->group
[j
].channel
[12].priority
= DAUD_CHAN13_DEF_VOICE_PRIORITY
;
145 This
->ports
[This
->nrofports
]->group
[j
].channel
[13].priority
= DAUD_CHAN14_DEF_VOICE_PRIORITY
;
146 This
->ports
[This
->nrofports
]->group
[j
].channel
[14].priority
= DAUD_CHAN15_DEF_VOICE_PRIORITY
;
147 This
->ports
[This
->nrofports
]->group
[j
].channel
[15].priority
= DAUD_CHAN16_DEF_VOICE_PRIORITY
;
151 *ppPort
= (LPDIRECTMUSICPORT
) This
->ppPorts
[This
->nrofports
];
156 /* FIXME: place correct error here */
157 return E_NOINTERFACE
;
160 HRESULT WINAPI
IDirectMusic8Impl_EnumMasterClock (LPDIRECTMUSIC8 iface
, DWORD dwIndex
, LPDMUS_CLOCKINFO lpClockInfo
) {
161 ICOM_THIS(IDirectMusic8Impl
,iface
);
162 FIXME("(%p, %ld, %p): stub\n", This
, dwIndex
, lpClockInfo
);
166 HRESULT WINAPI
IDirectMusic8Impl_GetMasterClock (LPDIRECTMUSIC8 iface
, LPGUID pguidClock
, IReferenceClock
** ppReferenceClock
) {
167 ICOM_THIS(IDirectMusic8Impl
,iface
);
169 TRACE("(%p, %p, %p)\n", This
, pguidClock
, ppReferenceClock
);
171 *pguidClock
= This
->pMasterClock
->pClockInfo
.guidClock
;
173 *ppReferenceClock
= (IReferenceClock
*)This
->pMasterClock
;
178 HRESULT WINAPI
IDirectMusic8Impl_SetMasterClock (LPDIRECTMUSIC8 iface
, REFGUID rguidClock
) {
179 ICOM_THIS(IDirectMusic8Impl
,iface
);
180 FIXME("(%p, %s): stub\n", This
, debugstr_guid(rguidClock
));
184 HRESULT WINAPI
IDirectMusic8Impl_Activate (LPDIRECTMUSIC8 iface
, BOOL fEnable
) {
185 ICOM_THIS(IDirectMusic8Impl
,iface
);
188 FIXME("(%p, %d): stub\n", This
, fEnable
);
189 for (i
= 0; i
< This
->nrofports
; i
++) {
190 This
->ppPorts
[i
]->fActive
= fEnable
;
196 HRESULT WINAPI
IDirectMusic8Impl_GetDefaultPort (LPDIRECTMUSIC8 iface
, LPGUID pguidPort
) {
197 ICOM_THIS(IDirectMusic8Impl
,iface
);
199 DWORD returnTypeGUID
, sizeOfReturnBuffer
= 50;
200 char returnBuffer
[51];
201 GUID defaultPortGUID
;
204 TRACE("(%p, %p)\n", This
, pguidPort
);
205 if ((RegOpenKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\DirectMusic\\Defaults" , 0, KEY_READ
, &hkGUID
) != ERROR_SUCCESS
) ||
206 (RegQueryValueExA(hkGUID
, "DefaultOutputPort", NULL
, &returnTypeGUID
, returnBuffer
, &sizeOfReturnBuffer
) != ERROR_SUCCESS
))
208 WARN(": registry entry missing\n" );
209 *pguidPort
= CLSID_DirectMusicSynth
;
212 /* FIXME: Check return types to ensure we're interpreting data right */
213 MultiByteToWideChar(CP_ACP
, 0, returnBuffer
, -1, buff
, sizeof(buff
) / sizeof(WCHAR
));
214 CLSIDFromString(buff
, &defaultPortGUID
);
215 *pguidPort
= defaultPortGUID
;
220 HRESULT WINAPI
IDirectMusic8Impl_SetDirectSound (LPDIRECTMUSIC8 iface
, LPDIRECTSOUND pDirectSound
, HWND hWnd
) {
221 ICOM_THIS(IDirectMusic8Impl
,iface
);
222 FIXME("(%p, %p, %p): stub\n", This
, pDirectSound
, hWnd
);
226 HRESULT WINAPI
IDirectMusic8Impl_SetExternalMasterClock (LPDIRECTMUSIC8 iface
, IReferenceClock
* pClock
) {
227 ICOM_THIS(IDirectMusic8Impl
,iface
);
228 FIXME("(%p, %p): stub\n", This
, pClock
);
232 ICOM_VTABLE(IDirectMusic8
) DirectMusic8_Vtbl
= {
233 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
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
);