27c7ed45bfc129e57ce890f0b20d467240e8ea58
[reactos.git] / reactos / lib / drivers / sound / mment4 / control.c
1 /*
2 * PROJECT: ReactOS Sound System "MME Buddy" NT4 Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/sound/mment4/control.c
5 *
6 * PURPOSE: Device control for NT4 audio devices
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 <mmebuddy.h>
16 #include <mment4.h>
17
18 /*
19 Convenience routine for getting the path of a device and opening it.
20 */
21 MMRESULT
22 OpenNt4KernelSoundDevice(
23 IN PSOUND_DEVICE SoundDevice,
24 IN BOOLEAN ReadOnly,
25 OUT PHANDLE Handle)
26 {
27 PWSTR Path;
28 MMRESULT Result;
29
30 VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) );
31 VALIDATE_MMSYS_PARAMETER( Handle );
32
33 Result = GetSoundDeviceIdentifier(SoundDevice, (PVOID*) &Path);
34 if ( ! MMSUCCESS(Result) )
35 {
36 SND_ERR(L"Unable to get sound device path");
37 return TranslateInternalMmResult(Result);
38 }
39
40 SND_ASSERT( Path );
41
42 return OpenKernelSoundDeviceByName(Path, ReadOnly, Handle);
43 }
44
45 /*
46 Device open/close. These are basically wrappers for the MME-Buddy
47 open and close routines, which provide a Windows device handle.
48 These may seem simple but as you can return pretty much anything
49 as the handle, we could just as easily return a structure etc.
50 */
51 MMRESULT
52 OpenNt4SoundDevice(
53 IN PSOUND_DEVICE SoundDevice,
54 OUT PVOID* Handle)
55 {
56 SND_TRACE(L"Opening NT4 style sound device\n");
57
58 VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) );
59 VALIDATE_MMSYS_PARAMETER( Handle );
60
61 return OpenNt4KernelSoundDevice(SoundDevice, FALSE, Handle);
62 }
63
64 MMRESULT
65 CloseNt4SoundDevice(
66 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
67 IN PVOID Handle)
68 {
69 SND_TRACE(L"Closing NT4 style sound device\n");
70
71 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
72 return CloseKernelSoundDevice((HANDLE) Handle);
73 }
74
75 /*
76 Provides an implementation for the "get capabilities" request,
77 using the standard IOCTLs used by NT4 sound drivers.
78 */
79 MMRESULT
80 GetNt4SoundDeviceCapabilities(
81 IN PSOUND_DEVICE SoundDevice,
82 OUT PVOID Capabilities,
83 IN DWORD CapabilitiesSize)
84 {
85 MMRESULT Result;
86 MMDEVICE_TYPE DeviceType;
87 DWORD IoCtl;
88 HANDLE DeviceHandle;
89
90 /* If these are bad there's an internal error with MME-Buddy! */
91 SND_ASSERT( SoundDevice );
92 SND_ASSERT( Capabilities );
93 SND_ASSERT( CapabilitiesSize > 0 );
94
95 SND_TRACE(L"NT4 get-capabilities routine called\n");
96
97 /* Get the device type */
98 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
99 SND_ASSERT( Result == MMSYSERR_NOERROR );
100
101 if ( ! MMSUCCESS(Result) );
102 return TranslateInternalMmResult(Result);
103
104 /* Choose the appropriate IOCTL */
105 if ( IS_WAVE_DEVICE_TYPE(DeviceType) )
106 {
107 IoCtl = IOCTL_WAVE_GET_CAPABILITIES;
108 }
109 else if ( IS_MIDI_DEVICE_TYPE(DeviceType) )
110 {
111 IoCtl = IOCTL_MIDI_GET_CAPABILITIES;
112 }
113 else
114 {
115 /* FIXME - need to support AUX and mixer devices */
116 SND_ASSERT( FALSE );
117 }
118
119 /* Get the capabilities information from the driver */
120 Result = OpenNt4KernelSoundDevice(SoundDevice, TRUE, &DeviceHandle);
121
122 if ( ! MMSUCCESS(Result) )
123 {
124 SND_ERR(L"Failed to open device");
125 return TranslateInternalMmResult(Result);
126 }
127
128 Result = SyncOverlappedDeviceIoControl(DeviceHandle,
129 IoCtl,
130 Capabilities,
131 CapabilitiesSize,
132 NULL,
133 0,
134 NULL);
135
136 CloseKernelSoundDevice(DeviceHandle);
137
138 if ( ! MMSUCCESS(Result) )
139 {
140 SND_ERR(L"Retrieval of capabilities information failed\n");
141 Result = TranslateInternalMmResult(Result);
142 }
143
144 return Result;
145 }
146
147 /*
148 Querying/setting the format of a wave device. Querying format support
149 requires us to first open the device, whereas setting format is done
150 on an already opened device.
151 */
152 MMRESULT
153 QueryNt4WaveDeviceFormatSupport(
154 IN PSOUND_DEVICE SoundDevice,
155 IN LPWAVEFORMATEX Format,
156 IN DWORD FormatSize)
157 {
158 MMRESULT Result;
159 HANDLE Handle;
160
161 SND_TRACE(L"NT4 wave format support querying routine called\n");
162
163 VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) );
164 VALIDATE_MMSYS_PARAMETER( Format );
165 VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) );
166
167 /* Get the device path */
168 Result = OpenNt4KernelSoundDevice(SoundDevice,
169 FALSE,
170 &Handle);
171
172 if ( ! MMSUCCESS(Result) )
173 {
174 SND_ERR(L"Unable to open kernel sound device\n");
175 return TranslateInternalMmResult(Result);
176 }
177
178 Result = SyncOverlappedDeviceIoControl(Handle,
179 IOCTL_WAVE_QUERY_FORMAT,
180 (LPVOID) Format,
181 FormatSize,
182 NULL,
183 0,
184 NULL);
185
186 if ( ! MMSUCCESS(Result) )
187 {
188 SND_ERR(L"Sync overlapped I/O failed - MMSYS_ERROR %d\n", Result);
189 Result = TranslateInternalMmResult(Result);
190 }
191
192 CloseKernelSoundDevice(Handle);
193
194 return MMSYSERR_NOERROR;
195 }
196
197 MMRESULT
198 SetNt4WaveDeviceFormat(
199 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
200 IN LPWAVEFORMATEX Format,
201 IN DWORD FormatSize)
202 {
203 MMRESULT Result;
204 HANDLE Handle;
205
206 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
207 VALIDATE_MMSYS_PARAMETER( Format );
208 VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) );
209
210 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
211
212 if ( ! MMSUCCESS(Result) )
213 return TranslateInternalMmResult(Result);
214
215 SND_TRACE(L"Setting wave device format on handle %x\n", Handle);
216
217 Result = SyncOverlappedDeviceIoControl(Handle,
218 IOCTL_WAVE_SET_FORMAT,
219 (LPVOID) Format,
220 FormatSize,
221 NULL,
222 0,
223 NULL);
224
225 if ( ! MMSUCCESS(Result) )
226 return TranslateInternalMmResult(Result);
227
228 return MMSYSERR_NOERROR;
229 }
230