Read and write binary files in binary mode on Windows.
[wine/multimedia.git] / dlls / dmusic / dmusic.c
blobe279d5cdac3404a9cfb35a7d521cabf1e37e9049
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.
20 #include <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winreg.h"
25 #include "winuser.h"
26 #include "wingdi.h"
27 #include "winerror.h"
28 #include "mmsystem.h"
29 #include "winternl.h"
30 #include "mmddk.h"
31 #include "wine/windef16.h"
32 #include "wine/winbase16.h"
33 #include "wine/debug.h"
34 #include "dsound.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);
49 *ppobj = This;
50 return S_OK;
53 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
54 return E_NOINTERFACE;
57 ULONG WINAPI IDirectMusic8Impl_AddRef (LPDIRECTMUSIC8 iface)
59 ICOM_THIS(IDirectMusic8Impl,iface);
60 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
61 return ++(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);
69 if (ref == 0) {
70 HeapFree(GetProcessHeap(), 0, This);
72 return ref;
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 */
82 if (dwIndex == 0)
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);
89 return S_OK;
92 /* it seems that the rest of devices are obtained thru dmusic32.EnumLegacyDevices...*sigh*...which is undocumented*/
93 #if 0
94 int numMIDI = midiOutGetNumDevs();
95 int numWAVE = waveOutGetNumDevs();
96 int i;
97 /* then return digital sound ports */
98 for (i = 1; i <= numWAVE; i++)
100 TRACE("enumerating 'digital sound' ports\n");
101 if (i == dwIndex)
103 DirectSoundEnumerateA((LPDSENUMCALLBACKA) register_waveport, (VOID*) pPortCaps);
104 return S_OK;
107 /* finally, list all *real* MIDI ports*/
108 for (i = numWAVE + 1; i <= numWAVE + numMIDI; i++)
110 TRACE("enumerating 'real MIDI' ports\n");
111 if (i == dwIndex)
112 FIXME("Found MIDI port, but *real* MIDI ports not supported yet\n");
114 #endif
115 return S_FALSE;
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);
124 return S_OK;
127 HRESULT WINAPI IDirectMusic8Impl_CreatePort (LPDIRECTMUSIC8 iface, REFCLSID rclsidPort, LPDMUS_PORTPARAMS pPortParams, LPDIRECTMUSICPORT* ppPort, LPUNKNOWN pUnkOuter)
129 ICOM_THIS(IDirectMusic8Impl,iface);
130 int i/*, j*/;
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);
149 #if 0
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;
173 #endif
174 *ppPort = (LPDIRECTMUSICPORT) This->ppPorts[This->nrofports];
175 This->nrofports++;
176 return S_OK;
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);
189 return S_FALSE;
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);
197 if (pguidClock)
198 *pguidClock = This->pMasterClock->pClockInfo.guidClock;
199 if(ppReferenceClock)
200 *ppReferenceClock = (IReferenceClock *)This->pMasterClock;
202 return S_OK;
205 HRESULT WINAPI IDirectMusic8Impl_SetMasterClock (LPDIRECTMUSIC8 iface, REFGUID rguidClock)
207 ICOM_THIS(IDirectMusic8Impl,iface);
209 FIXME("(%p, %s): stub\n", This, debugstr_guid(rguidClock));
211 return S_OK;
214 HRESULT WINAPI IDirectMusic8Impl_Activate (LPDIRECTMUSIC8 iface, BOOL fEnable)
216 ICOM_THIS(IDirectMusic8Impl,iface);
217 int i;
219 FIXME("(%p, %d): stub\n", This, fEnable);
220 for (i = 0; i < This->nrofports; i++)
222 This->ppPorts[i]->fActive = fEnable;
225 return S_OK;
228 HRESULT WINAPI IDirectMusic8Impl_GetDefaultPort (LPDIRECTMUSIC8 iface, LPGUID pguidPort)
230 ICOM_THIS(IDirectMusic8Impl,iface);
231 HKEY hkGUID;
232 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
233 char returnBuffer[51];
234 GUID defaultPortGUID;
235 WCHAR buff[51];
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;
243 return S_OK;
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;
250 return S_OK;
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);
259 return S_OK;
262 HRESULT WINAPI IDirectMusic8Impl_SetExternalMasterClock (LPDIRECTMUSIC8 iface, IReferenceClock* pClock)
264 ICOM_THIS(IDirectMusic8Impl,iface);
266 FIXME("(%p, %p): stub\n", This, pClock);
268 return S_OK;
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
289 /* helper stuff */
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;
322 dmusic->ref = 1;
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;
329 return S_OK;
332 WARN("No interface found\n");
333 return E_NOINTERFACE;