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