Closing of wave output devices is functional and terminates the sound thread
[reactos.git] / reactos / dll / win32 / sndblst / sndblst.c
1 /*
2 * PROJECT: ReactOS Sound System
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/sndblst/sndblst.c
5 *
6 * PURPOSE: Sound Blaster MME User-Mode Driver
7 *
8 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
9 *
10 * NOTES: Currently very experimental and being used as a guinea-pig for
11 * changes to the MME-Buddy libraries.
12 * TODO: Adhere to maximum device name length!
13 */
14
15 #include <windows.h>
16 #include <ntddsnd.h>
17 #include <sndtypes.h>
18 #include <mmddk.h>
19 #include <mmebuddy.h>
20 #include <mment4.h>
21 //#include <debug.h>
22
23 PWSTR SBWaveOutDeviceName = L"ROS Sound Blaster Out";
24 PWSTR SBWaveInDeviceName = L"ROS Sound Blaster In";
25 /* TODO: Mixer etc */
26
27 MMRESULT
28 GetSoundBlasterDeviceCapabilities(
29 IN PSOUND_DEVICE SoundDevice,
30 OUT PVOID Capabilities,
31 IN DWORD CapabilitiesSize)
32 {
33 MMRESULT Result;
34 MMDEVICE_TYPE DeviceType;
35
36 SND_ASSERT( SoundDevice );
37 SND_ASSERT( Capabilities );
38
39 SND_TRACE(L"Sndblst - GetSoundBlasterDeviceCapabilities\n");
40
41 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
42 SND_ASSERT( Result == MMSYSERR_NOERROR );
43
44 /* Use the default method of obtaining device capabilities */
45 Result = GetNt4SoundDeviceCapabilities(SoundDevice,
46 Capabilities,
47 CapabilitiesSize);
48
49 if ( ! MMSUCCESS(Result) )
50 return Result;
51
52 /* Inject the appropriate device name */
53 switch ( DeviceType )
54 {
55 case WAVE_OUT_DEVICE_TYPE :
56 {
57 LPWAVEOUTCAPS WaveOutCaps = (LPWAVEOUTCAPS) Capabilities;
58 CopyWideString(WaveOutCaps->szPname, SBWaveOutDeviceName);
59 break;
60 }
61 case WAVE_IN_DEVICE_TYPE :
62 {
63 LPWAVEINCAPS WaveInCaps = (LPWAVEINCAPS) Capabilities;
64 CopyWideString(WaveInCaps->szPname, SBWaveInDeviceName);
65 break;
66 }
67 }
68
69 return MMSYSERR_NOERROR;
70 }
71
72 BOOLEAN FoundDevice(
73 UCHAR DeviceType,
74 PWSTR DevicePath)
75 {
76 MMRESULT Result;
77 PSOUND_DEVICE SoundDevice = NULL;
78 MMFUNCTION_TABLE FuncTable;
79 PWSTR PathCopy;
80
81 SND_TRACE(L"(Callback) Found device: %wS\n", DevicePath);
82
83 PathCopy = AllocateWideString(wcslen(DevicePath));
84
85 if ( ! PathCopy )
86 return FALSE;
87
88 CopyWideString(PathCopy, DevicePath);
89
90 Result = ListSoundDevice(DeviceType, (PVOID) PathCopy, &SoundDevice);
91
92 if ( ! MMSUCCESS(Result) )
93 return FALSE;
94
95 /* Set up our function table */
96 ZeroMemory(&FuncTable, sizeof(MMFUNCTION_TABLE));
97 FuncTable.GetCapabilities = GetSoundBlasterDeviceCapabilities;
98 FuncTable.QueryWaveFormatSupport = QueryNt4WaveDeviceFormatSupport;
99 FuncTable.SetWaveFormat = SetNt4WaveDeviceFormat;
100 FuncTable.Open = OpenNt4SoundDevice;
101 FuncTable.Close = CloseNt4SoundDevice;
102 FuncTable.CommitWaveBuffer = WriteFileEx_Committer;
103 //FuncTable.SubmitWaveHeaderToDevice = SubmitWaveHeaderToDevice;
104
105 SetSoundDeviceFunctionTable(SoundDevice, &FuncTable);
106
107 return TRUE;
108 }
109
110 APIENTRY LONG
111 DriverProc(
112 DWORD DriverId,
113 HANDLE DriverHandle,
114 UINT Message,
115 LONG Parameter1,
116 LONG Parameter2)
117 {
118 MMRESULT Result;
119
120 switch ( Message )
121 {
122 case DRV_LOAD :
123 {
124 SND_TRACE(L"DRV_LOAD\n");
125
126 Result = InitEntrypointMutexes();
127
128 if ( ! MMSUCCESS(Result) )
129 return 0L;
130
131 Result = EnumerateNt4ServiceSoundDevices(L"sndblst",
132 0,
133 FoundDevice);
134
135 if ( ! MMSUCCESS(Result) )
136 {
137 CleanupEntrypointMutexes();
138
139 UnlistAllSoundDevices();
140
141 return 0L;
142 }
143
144 /*
145 PSOUND_DEVICE snd;
146 GetSoundDevice(WAVE_OUT_DEVICE_TYPE, 0, &snd);
147 GetSoundDevice(AUX_DEVICE_TYPE, 0, &snd);
148 GetSoundDevice(AUX_DEVICE_TYPE, 1, &snd);
149 GetSoundDevice(AUX_DEVICE_TYPE, 2, &snd);
150 */
151
152 SND_TRACE(L"Initialisation complete\n");
153
154 return 1L;
155 }
156
157 case DRV_FREE :
158 {
159 SND_TRACE(L"DRV_FREE\n");
160
161 /* TODO: Clean up the path names! */
162 UnlistAllSoundDevices();
163
164 CleanupEntrypointMutexes();
165
166 SND_TRACE(L"Unfreed memory blocks: %d\n",
167 GetMemoryAllocationCount());
168
169 return 1L;
170 }
171
172 case DRV_ENABLE :
173 case DRV_DISABLE :
174 {
175 SND_TRACE(L"DRV_ENABLE / DRV_DISABLE\n");
176 return 1L;
177 }
178
179 case DRV_OPEN :
180 case DRV_CLOSE :
181 {
182 SND_TRACE(L"DRV_OPEN / DRV_CLOSE\n");
183 return 1L;
184 }
185
186 case DRV_QUERYCONFIGURE :
187 {
188 SND_TRACE(L"DRV_QUERYCONFIGURE");
189 return 0L;
190 }
191 case DRV_CONFIGURE :
192 return DRVCNF_OK;
193
194 default :
195 SND_TRACE(L"Unhandled message %d\n", Message);
196 return DefDriverProc(DriverId,
197 DriverHandle,
198 Message,
199 Parameter1,
200 Parameter2);
201 }
202 }
203
204 BOOL WINAPI DllMain(
205 HINSTANCE hinstDLL,
206 DWORD fdwReason,
207 LPVOID lpvReserved)
208 {
209 switch ( fdwReason )
210 {
211 case DLL_PROCESS_ATTACH :
212 SND_TRACE(L"DLL_PROCESS_ATTACH\n");
213 break;
214 case DLL_PROCESS_DETACH :
215 SND_TRACE(L"DLL_PROCESS_DETACH\n");
216 break;
217 case DLL_THREAD_ATTACH :
218 SND_TRACE(L"DLL_THREAD_ATTACH\n");
219 break;
220 case DLL_THREAD_DETACH :
221 SND_TRACE(L"DLL_THREAD_DETACH\n");
222 break;
223 }
224
225 return TRUE;
226 }