Closing of wave output devices is functional and terminates the sound thread
[reactos.git] / reactos / lib / drivers / sound / mmebuddy / mmewrap.c
1 /*
2 * PROJECT: ReactOS Sound System "MME Buddy" Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/sound/mmebuddy/mmewrap.c
5 *
6 * PURPOSE: Interface between MME functions and MME Buddy's own.
7 *
8 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
9 */
10
11 #include <windows.h>
12 #include <mmsystem.h>
13 #include <mmddk.h>
14 #include <ntddsnd.h>
15 #include <sndtypes.h>
16 #include <mmebuddy.h>
17
18 /*
19 Call the client application when something interesting happens (MME API
20 defines "interesting things" as device open, close, and buffer
21 completion.)
22 */
23 VOID
24 NotifyMmeClient(
25 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
26 IN DWORD Message,
27 IN DWORD Parameter)
28 {
29 SND_ASSERT( SoundDeviceInstance );
30
31 SND_TRACE(L"MME client callback - message %d, parameter %d\n",
32 (int) Message,
33 (int) Parameter);
34
35 if ( SoundDeviceInstance->WinMM.ClientCallback )
36 {
37 DriverCallback(SoundDeviceInstance->WinMM.ClientCallback,
38 HIWORD(SoundDeviceInstance->WinMM.Flags),
39 SoundDeviceInstance->WinMM.Handle,
40 Message,
41 SoundDeviceInstance->WinMM.ClientCallbackInstanceData,
42 Parameter,
43 0);
44 }
45 }
46
47 /*
48 This is a helper function to alleviate some of the repetition involved with
49 implementing the various MME message functions.
50 */
51 MMRESULT
52 MmeGetSoundDeviceCapabilities(
53 IN MMDEVICE_TYPE DeviceType,
54 IN DWORD DeviceId,
55 IN PVOID Capabilities,
56 IN DWORD CapabilitiesSize)
57 {
58 PSOUND_DEVICE SoundDevice;
59 MMRESULT Result;
60
61 SND_TRACE(L"MME *_GETCAPS for device %d of type %d\n", DeviceId, DeviceType);
62
63 /* FIXME: Validate device type and ID */
64 VALIDATE_MMSYS_PARAMETER( Capabilities );
65 VALIDATE_MMSYS_PARAMETER( CapabilitiesSize > 0 );
66
67 /* Our parameter checks are done elsewhere */
68 Result = GetSoundDevice(DeviceType, DeviceId, &SoundDevice);
69
70 if ( ! MMSUCCESS(Result) )
71 return Result;
72
73 return GetSoundDeviceCapabilities(SoundDevice,
74 Capabilities,
75 CapabilitiesSize);
76 }
77
78 MMRESULT
79 MmeOpenWaveDevice(
80 IN MMDEVICE_TYPE DeviceType,
81 IN DWORD DeviceId,
82 IN LPWAVEOPENDESC OpenParameters,
83 IN DWORD Flags,
84 OUT DWORD* PrivateHandle)
85 {
86 MMRESULT Result;
87
88 PSOUND_DEVICE SoundDevice;
89 PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
90 LPWAVEFORMATEX Format;
91
92 SND_TRACE(L"Opening wave device (WIDM_OPEN / WODM_OPEN)");
93
94 VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) ); /* FIXME? wave in too? */
95 VALIDATE_MMSYS_PARAMETER( OpenParameters );
96
97 Format = OpenParameters->lpFormat;
98
99 Result = GetSoundDevice(DeviceType, DeviceId, &SoundDevice);
100 if ( ! MMSUCCESS(Result) )
101 return TranslateInternalMmResult(Result);
102
103 /* Does this device support the format? */
104 Result = QueryWaveDeviceFormatSupport(SoundDevice, Format, sizeof(WAVEFORMATEX));
105 if ( ! MMSUCCESS(Result) )
106 {
107 SND_ERR(L"Format not supported\n");
108 return TranslateInternalMmResult(Result);
109 }
110
111 /* If the caller just wanted to know if a format is supported, end here */
112 if ( Flags & WAVE_FORMAT_QUERY )
113 return MMSYSERR_NOERROR;
114
115 /* Check that winmm gave us a private handle to fill */
116 VALIDATE_MMSYS_PARAMETER( PrivateHandle );
117
118 /* Create a sound device instance and open the sound device */
119 Result = CreateSoundDeviceInstance(SoundDevice, &SoundDeviceInstance);
120 if ( ! MMSUCCESS(Result) )
121 return TranslateInternalMmResult(Result);
122
123 Result = SetWaveDeviceFormat(SoundDeviceInstance, Format, sizeof(WAVEFORMATEX));
124 if ( ! MMSUCCESS(Result) )
125 {
126 /* TODO: Destroy sound instance */
127 return TranslateInternalMmResult(Result);
128 }
129
130 /* Store the device instance pointer in the private handle - is DWORD safe here? */
131 *PrivateHandle = (DWORD) SoundDeviceInstance;
132
133 /* Store the additional information we were given - FIXME: Need flags! */
134 SetSoundDeviceInstanceMmeData(SoundDeviceInstance,
135 (HDRVR)OpenParameters->hWave,
136 OpenParameters->dwCallback,
137 OpenParameters->dwInstance,
138 Flags);
139
140 /* Let the application know the device is open */
141 ReleaseEntrypointMutex(DeviceType);
142 NotifyMmeClient(SoundDeviceInstance,
143 DeviceType == WAVE_OUT_DEVICE_TYPE ? WOM_OPEN : WIM_OPEN,
144 0);
145
146 AcquireEntrypointMutex(DeviceType);
147
148 SND_TRACE(L"Wave device now open\n");
149
150 return MMSYSERR_NOERROR;
151 }
152
153 MMRESULT
154 MmeCloseDevice(
155 IN DWORD PrivateHandle)
156 {
157 MMRESULT Result;
158 PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
159 PSOUND_DEVICE SoundDevice;
160 MMDEVICE_TYPE DeviceType;
161
162 SND_TRACE(L"Closing wave device (WIDM_CLOSE / WODM_CLOSE)\n");
163
164 VALIDATE_MMSYS_PARAMETER( PrivateHandle );
165 SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle;
166
167 if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance) )
168 return MMSYSERR_INVALHANDLE;
169
170 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
171 if ( ! MMSUCCESS(Result) )
172 return TranslateInternalMmResult(Result);
173
174 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
175 if ( ! MMSUCCESS(Result) )
176 return TranslateInternalMmResult(Result);
177
178
179 /* TODO: Check device is stopped! */
180
181 ReleaseEntrypointMutex(DeviceType);
182 /* TODO: Work with MIDI devices too */
183 NotifyMmeClient(SoundDeviceInstance,
184 DeviceType == WAVE_OUT_DEVICE_TYPE ? WOM_CLOSE : WIM_CLOSE,
185 0);
186 AcquireEntrypointMutex(DeviceType);
187
188 Result = DestroySoundDeviceInstance(SoundDeviceInstance);
189
190 return Result;
191 }
192
193 MMRESULT
194 MmeResetWavePlayback(
195 IN DWORD PrivateHandle)
196 {
197 PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
198
199 SND_TRACE(L"Resetting wave device (WODM_RESET)\n");
200
201 VALIDATE_MMSYS_PARAMETER( PrivateHandle );
202 SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle;
203
204 return StopStreaming(SoundDeviceInstance);
205 }