2 * PROJECT: ReactOS Sound System "MME Buddy" Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/sound/mmebuddy/devicelist.c
6 * PURPOSE: Manages lists of sound devices.
8 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
18 ULONG SoundDeviceCounts
[SOUND_DEVICE_TYPES
];
19 PSOUND_DEVICE SoundDeviceListHeads
[SOUND_DEVICE_TYPES
];
20 PSOUND_DEVICE SoundDeviceListTails
[SOUND_DEVICE_TYPES
];
23 Handles the allocation and initialisation of a SOUND_DEVICE structure.
27 IN MMDEVICE_TYPE DeviceType
,
28 OUT PSOUND_DEVICE
* SoundDevice
)
30 PSOUND_DEVICE NewDevice
;
32 SND_ASSERT( IsValidSoundDeviceType(DeviceType
) );
33 SND_ASSERT( SoundDevice
);
35 SND_TRACE(L
"Allocating a SOUND_DEVICE structure\n");
37 NewDevice
= AllocateStruct(SOUND_DEVICE
);
40 return MMSYSERR_NOMEM
;
42 NewDevice
->Type
= DeviceType
;
44 /* Return the new structure to the caller and report success */
45 *SoundDevice
= NewDevice
;
47 return MMSYSERR_NOERROR
;
51 Handles the cleanup and freeing of a SOUND_DEVICE structure.
55 IN PSOUND_DEVICE SoundDevice
)
57 SND_ASSERT( SoundDevice
);
59 SND_TRACE(L
"Freeing a SOUND_DEVICE structure");
61 /* For safety the whole struct gets zeroed */
62 ZeroMemory(SoundDevice
, sizeof(SOUND_DEVICE
));
63 FreeMemory(SoundDevice
);
67 Returns the number of devices of the specified type which have been added
68 to the device lists. If an invalid device type is specified, the function
73 IN MMDEVICE_TYPE DeviceType
)
75 ULONG Index
= SOUND_DEVICE_TYPE_TO_INDEX(DeviceType
);
77 if ( ! IsValidSoundDeviceType(DeviceType
) )
82 SND_TRACE(L
"Returning a count of %d devices\n", SoundDeviceCounts
[Index
]);
83 return SoundDeviceCounts
[Index
];
87 Determines if a sound device structure pointer is valid, firstly by
88 ensuring that it is not NULL, and then by checking that the device itself
89 exists in one of the device lists.
93 IN PSOUND_DEVICE SoundDevice
)
96 PSOUND_DEVICE CurrentDevice
;
101 /* Go through all the device lists */
102 for ( TypeIndex
= 0; TypeIndex
< SOUND_DEVICE_TYPES
; ++ TypeIndex
)
104 CurrentDevice
= SoundDeviceListHeads
[TypeIndex
];
106 while ( CurrentDevice
)
108 if ( CurrentDevice
== SoundDevice
)
110 /* Found the device */
114 CurrentDevice
= CurrentDevice
->Next
;
118 /* If we get here, nothing was found */
123 Informs the MME-Buddy library that it should take ownership of a device.
124 The DevicePath is typically used for storing a device path (for subsequent
125 opening using CreateFile) but it can be a wide-string representing any
126 information that makes sense to your MME driver implementation.
128 MME components which operate solely in user-mode (for example, MIDI
129 loopback devices) won't need to communicate with a kernel-mode device,
130 so in these situations DevicePath is likely to be NULL.
132 Upon successful addition to the sound device list, the pointer to the new
133 device's SOUND_DEVICE structure is returned via SoundDevice.
137 IN MMDEVICE_TYPE DeviceType
,
138 IN PVOID Identifier OPTIONAL
,
139 OUT PSOUND_DEVICE
* SoundDevice OPTIONAL
)
142 PSOUND_DEVICE NewDevice
;
143 UCHAR TypeIndex
= SOUND_DEVICE_TYPE_TO_INDEX(DeviceType
);
145 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType
) );
147 Result
= AllocateSoundDevice(DeviceType
, &NewDevice
);
149 if ( ! MMSUCCESS(Result
) )
151 SND_ERR(L
"Failed to allocate SOUND_DEVICE structure\n");
155 if ( ! SoundDeviceListHeads
[TypeIndex
] )
157 SND_TRACE(L
"Putting first entry into device list %d\n", DeviceType
);
158 SoundDeviceListHeads
[TypeIndex
] = NewDevice
;
159 SoundDeviceListTails
[TypeIndex
] = NewDevice
;
163 SND_TRACE(L
"Putting another entry into device list %d\n", DeviceType
);
164 SoundDeviceListTails
[TypeIndex
]->Next
= NewDevice
;
165 SoundDeviceListTails
[TypeIndex
] = NewDevice
;
168 /* Add to the count */
169 ++ SoundDeviceCounts
[TypeIndex
];
171 /* Set up the default function table */
172 SetSoundDeviceFunctionTable(NewDevice
, NULL
);
174 /* Set up other members of the structure */
175 NewDevice
->Identifier
= Identifier
;
176 NewDevice
->HeadInstance
= NULL
;
177 NewDevice
->TailInstance
= NULL
;
179 /* Fill in the caller's PSOUND_DEVICE */
182 *SoundDevice
= NewDevice
;
185 return MMSYSERR_NOERROR
;
189 Removes a sound device from the list, and frees the memory associated
190 with its description.
194 IN MMDEVICE_TYPE DeviceType
,
195 IN PSOUND_DEVICE SoundDevice
)
197 PSOUND_DEVICE CurrentDevice
, PreviousDevice
;
199 UCHAR TypeIndex
= SOUND_DEVICE_TYPE_TO_INDEX(DeviceType
);
201 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType
) );
202 VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice
) );
204 PreviousDevice
= NULL
;
205 CurrentDevice
= SoundDeviceListHeads
[TypeIndex
];
207 while ( CurrentDevice
)
209 if ( CurrentDevice
== SoundDevice
)
211 if ( ! PreviousDevice
)
213 /* This is the head node */
214 SND_TRACE(L
"Removing head node from device list %d\n", DeviceType
);
215 SoundDeviceListHeads
[TypeIndex
] =
216 SoundDeviceListHeads
[TypeIndex
]->Next
;
220 SND_TRACE(L
"Removing node from device list %d\n", DeviceType
);
221 /* There are nodes before this one - cut our device out */
222 PreviousDevice
->Next
= CurrentDevice
->Next
;
225 if ( ! CurrentDevice
->Next
)
227 /* This is the tail node */
228 SND_TRACE(L
"Removing tail node from device list %d\n", DeviceType
);
229 SoundDeviceListTails
[TypeIndex
] = PreviousDevice
;
233 PreviousDevice
= CurrentDevice
;
234 CurrentDevice
= CurrentDevice
->Next
;
237 /* Subtract from the count */
238 -- SoundDeviceCounts
[TypeIndex
];
240 /* Finally, free up the deleted entry */
241 FreeSoundDevice(SoundDevice
);
243 return MMSYSERR_NOERROR
;
247 Removes all devices from one of the device lists.
251 IN MMDEVICE_TYPE DeviceType
)
254 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType
) );
256 SND_TRACE(L
"Unlisting all sound devices of type %d\n", DeviceType
);
258 TypeIndex
= SOUND_DEVICE_TYPE_TO_INDEX(DeviceType
);
260 /* Munch away at the head of the list until it's drained */
261 while ( SoundDeviceCounts
[TypeIndex
] > 0 )
264 Result
= UnlistSoundDevice(DeviceType
, SoundDeviceListHeads
[TypeIndex
]);
265 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
268 return MMSYSERR_NOERROR
;
272 Removes all devices from all lists.
275 UnlistAllSoundDevices()
279 SND_TRACE(L
"Unlisting all sound devices\n");
281 for ( Type
= MIN_SOUND_DEVICE_TYPE
; Type
<= MAX_SOUND_DEVICE_TYPE
; ++ Type
)
284 Result
= UnlistSoundDevices(Type
);
285 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
290 Provides the caller with a pointer to its desired sound device, based on
291 the device type and index.
295 IN MMDEVICE_TYPE DeviceType
,
296 IN DWORD DeviceIndex
,
297 OUT PSOUND_DEVICE
* SoundDevice
)
299 UCHAR TypeIndex
= SOUND_DEVICE_TYPE_TO_INDEX(DeviceType
);
300 DWORD CurrentIndex
= 0;
301 PSOUND_DEVICE CurrentDevice
;
303 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType
) );
305 if ( DeviceIndex
>= SoundDeviceCounts
[TypeIndex
] )
307 SND_ERR(L
"Invalid device ID %d for type %d\n", DeviceIndex
, DeviceType
);
308 return MMSYSERR_BADDEVICEID
;
311 CurrentDevice
= SoundDeviceListHeads
[TypeIndex
];
313 /* Following the earlier checks, the index should be valid here. */
314 for ( CurrentIndex
= 0; CurrentIndex
!= DeviceIndex
; ++ CurrentIndex
)
316 SND_ASSERT( CurrentDevice
);
317 CurrentDevice
= CurrentDevice
->Next
;
320 SND_TRACE(L
"Returning sound device %x\n", CurrentDevice
);
322 *SoundDevice
= CurrentDevice
;
324 return MMSYSERR_NOERROR
;
328 Provides the caller with the device path of the specified sound device.
329 This will normally be the path to a device provided by a kernel-mode
333 GetSoundDeviceIdentifier(
334 IN PSOUND_DEVICE SoundDevice
,
335 OUT PVOID
* Identifier
)
337 VALIDATE_MMSYS_PARAMETER( SoundDevice
);
338 VALIDATE_MMSYS_PARAMETER( Identifier
);
340 /* The caller should not modify this! */
341 *Identifier
= SoundDevice
->Identifier
;
343 return MMSYSERR_NOERROR
;
347 Provides the caller with the device type of the specified sound device.
348 This will be, for example, WAVE_OUT_DEVICE_TYPE, WAVE_IN_DEVICE_TYPE ...
352 IN PSOUND_DEVICE SoundDevice
,
353 OUT PMMDEVICE_TYPE DeviceType
)
355 VALIDATE_MMSYS_PARAMETER( SoundDevice
);
356 VALIDATE_MMSYS_PARAMETER( DeviceType
);
358 *DeviceType
= SoundDevice
->Type
;
360 return MMSYSERR_NOERROR
;