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)
13 ULONG SoundDeviceCounts
[SOUND_DEVICE_TYPES
];
14 PSOUND_DEVICE SoundDeviceListHeads
[SOUND_DEVICE_TYPES
];
15 PSOUND_DEVICE SoundDeviceListTails
[SOUND_DEVICE_TYPES
];
18 Handles the allocation and initialisation of a SOUND_DEVICE structure.
22 IN MMDEVICE_TYPE DeviceType
,
23 OUT PSOUND_DEVICE
* SoundDevice
)
25 PSOUND_DEVICE NewDevice
;
27 SND_ASSERT( IsValidSoundDeviceType(DeviceType
) );
28 SND_ASSERT( SoundDevice
);
30 SND_TRACE(L
"Allocating a SOUND_DEVICE structure\n");
32 NewDevice
= AllocateStruct(SOUND_DEVICE
);
35 return MMSYSERR_NOMEM
;
37 NewDevice
->Type
= DeviceType
;
39 /* Return the new structure to the caller and report success */
40 *SoundDevice
= NewDevice
;
42 return MMSYSERR_NOERROR
;
46 Handles the cleanup and freeing of a SOUND_DEVICE structure.
50 IN PSOUND_DEVICE SoundDevice
)
52 SND_ASSERT( SoundDevice
);
54 SND_TRACE(L
"Freeing a SOUND_DEVICE structure");
56 /* For safety the whole struct gets zeroed */
57 ZeroMemory(SoundDevice
, sizeof(SOUND_DEVICE
));
58 FreeMemory(SoundDevice
);
62 Returns the number of devices of the specified type which have been added
63 to the device lists. If an invalid device type is specified, the function
68 IN MMDEVICE_TYPE DeviceType
)
70 ULONG Index
= SOUND_DEVICE_TYPE_TO_INDEX(DeviceType
);
72 if ( ! IsValidSoundDeviceType(DeviceType
) )
77 SND_TRACE(L
"Returning a count of %d devices\n", SoundDeviceCounts
[Index
]);
78 return SoundDeviceCounts
[Index
];
82 Determines if a sound device structure pointer is valid, firstly by
83 ensuring that it is not NULL, and then by checking that the device itself
84 exists in one of the device lists.
88 IN PSOUND_DEVICE SoundDevice
)
91 PSOUND_DEVICE CurrentDevice
;
96 /* Go through all the device lists */
97 for ( TypeIndex
= 0; TypeIndex
< SOUND_DEVICE_TYPES
; ++ TypeIndex
)
99 CurrentDevice
= SoundDeviceListHeads
[TypeIndex
];
101 while ( CurrentDevice
)
103 if ( CurrentDevice
== SoundDevice
)
105 /* Found the device */
109 CurrentDevice
= CurrentDevice
->Next
;
113 /* If we get here, nothing was found */
118 Informs the MME-Buddy library that it should take ownership of a device.
119 The DevicePath is typically used for storing a device path (for subsequent
120 opening using CreateFile) but it can be a wide-string representing any
121 information that makes sense to your MME driver implementation.
123 MME components which operate solely in user-mode (for example, MIDI
124 loopback devices) won't need to communicate with a kernel-mode device,
125 so in these situations DevicePath is likely to be NULL.
127 Upon successful addition to the sound device list, the pointer to the new
128 device's SOUND_DEVICE structure is returned via SoundDevice.
132 IN MMDEVICE_TYPE DeviceType
,
133 IN PVOID Identifier OPTIONAL
,
134 OUT PSOUND_DEVICE
* SoundDevice OPTIONAL
)
137 PSOUND_DEVICE NewDevice
;
138 UCHAR TypeIndex
= SOUND_DEVICE_TYPE_TO_INDEX(DeviceType
);
140 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType
) );
142 Result
= AllocateSoundDevice(DeviceType
, &NewDevice
);
144 if ( ! MMSUCCESS(Result
) )
146 SND_ERR(L
"Failed to allocate SOUND_DEVICE structure\n");
150 if ( ! SoundDeviceListHeads
[TypeIndex
] )
152 SND_TRACE(L
"Putting first entry into device list %d\n", DeviceType
);
153 SoundDeviceListHeads
[TypeIndex
] = NewDevice
;
154 SoundDeviceListTails
[TypeIndex
] = NewDevice
;
158 SND_TRACE(L
"Putting another entry into device list %d\n", DeviceType
);
159 SoundDeviceListTails
[TypeIndex
]->Next
= NewDevice
;
160 SoundDeviceListTails
[TypeIndex
] = NewDevice
;
163 /* Add to the count */
164 ++ SoundDeviceCounts
[TypeIndex
];
166 /* Set up the default function table */
167 SetSoundDeviceFunctionTable(NewDevice
, NULL
);
169 /* Set up other members of the structure */
170 NewDevice
->Identifier
= Identifier
;
171 NewDevice
->HeadInstance
= NULL
;
172 NewDevice
->TailInstance
= NULL
;
174 /* Fill in the caller's PSOUND_DEVICE */
177 *SoundDevice
= NewDevice
;
180 return MMSYSERR_NOERROR
;
184 Removes a sound device from the list, and frees the memory associated
185 with its description.
189 IN MMDEVICE_TYPE DeviceType
,
190 IN PSOUND_DEVICE SoundDevice
)
192 PSOUND_DEVICE CurrentDevice
, PreviousDevice
;
194 UCHAR TypeIndex
= SOUND_DEVICE_TYPE_TO_INDEX(DeviceType
);
196 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType
) );
197 VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice
) );
199 PreviousDevice
= NULL
;
200 CurrentDevice
= SoundDeviceListHeads
[TypeIndex
];
202 while ( CurrentDevice
)
204 if ( CurrentDevice
== SoundDevice
)
206 if ( ! PreviousDevice
)
208 /* This is the head node */
209 SND_TRACE(L
"Removing head node from device list %d\n", DeviceType
);
210 SoundDeviceListHeads
[TypeIndex
] =
211 SoundDeviceListHeads
[TypeIndex
]->Next
;
215 SND_TRACE(L
"Removing node from device list %d\n", DeviceType
);
216 /* There are nodes before this one - cut our device out */
217 PreviousDevice
->Next
= CurrentDevice
->Next
;
220 if ( ! CurrentDevice
->Next
)
222 /* This is the tail node */
223 SND_TRACE(L
"Removing tail node from device list %d\n", DeviceType
);
224 SoundDeviceListTails
[TypeIndex
] = PreviousDevice
;
228 PreviousDevice
= CurrentDevice
;
229 CurrentDevice
= CurrentDevice
->Next
;
232 /* Subtract from the count */
233 -- SoundDeviceCounts
[TypeIndex
];
235 /* Finally, free up the deleted entry */
236 FreeSoundDevice(SoundDevice
);
238 return MMSYSERR_NOERROR
;
242 Removes all devices from one of the device lists.
246 IN MMDEVICE_TYPE DeviceType
)
249 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType
) );
251 SND_TRACE(L
"Unlisting all sound devices of type %d\n", DeviceType
);
253 TypeIndex
= SOUND_DEVICE_TYPE_TO_INDEX(DeviceType
);
255 /* Munch away at the head of the list until it's drained */
256 while ( SoundDeviceCounts
[TypeIndex
] > 0 )
259 Result
= UnlistSoundDevice(DeviceType
, SoundDeviceListHeads
[TypeIndex
]);
260 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
263 return MMSYSERR_NOERROR
;
267 Removes all devices from all lists.
270 UnlistAllSoundDevices()
274 SND_TRACE(L
"Unlisting all sound devices\n");
276 for ( Type
= MIN_SOUND_DEVICE_TYPE
; Type
<= MAX_SOUND_DEVICE_TYPE
; ++ Type
)
279 Result
= UnlistSoundDevices(Type
);
280 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
285 Provides the caller with a pointer to its desired sound device, based on
286 the device type and index.
290 IN MMDEVICE_TYPE DeviceType
,
291 IN DWORD DeviceIndex
,
292 OUT PSOUND_DEVICE
* SoundDevice
)
294 UCHAR TypeIndex
= SOUND_DEVICE_TYPE_TO_INDEX(DeviceType
);
295 DWORD CurrentIndex
= 0;
296 PSOUND_DEVICE CurrentDevice
;
298 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceType(DeviceType
) );
300 if ( DeviceIndex
>= SoundDeviceCounts
[TypeIndex
] )
302 SND_ERR(L
"Invalid device ID %d for type %d\n", DeviceIndex
, DeviceType
);
303 return MMSYSERR_BADDEVICEID
;
306 CurrentDevice
= SoundDeviceListHeads
[TypeIndex
];
308 /* Following the earlier checks, the index should be valid here. */
309 for ( CurrentIndex
= 0; CurrentIndex
!= DeviceIndex
; ++ CurrentIndex
)
311 SND_ASSERT( CurrentDevice
);
312 CurrentDevice
= CurrentDevice
->Next
;
315 SND_TRACE(L
"Returning sound device %x\n", CurrentDevice
);
317 *SoundDevice
= CurrentDevice
;
319 return MMSYSERR_NOERROR
;
323 Provides the caller with the device path of the specified sound device.
324 This will normally be the path to a device provided by a kernel-mode
328 GetSoundDeviceIdentifier(
329 IN PSOUND_DEVICE SoundDevice
,
330 OUT PVOID
* Identifier
)
332 VALIDATE_MMSYS_PARAMETER( SoundDevice
);
333 VALIDATE_MMSYS_PARAMETER( Identifier
);
335 /* The caller should not modify this! */
336 *Identifier
= SoundDevice
->Identifier
;
338 return MMSYSERR_NOERROR
;
342 Provides the caller with the device type of the specified sound device.
343 This will be, for example, WAVE_OUT_DEVICE_TYPE, WAVE_IN_DEVICE_TYPE ...
347 IN PSOUND_DEVICE SoundDevice
,
348 OUT PMMDEVICE_TYPE DeviceType
)
350 VALIDATE_MMSYS_PARAMETER( SoundDevice
);
351 VALIDATE_MMSYS_PARAMETER( DeviceType
);
353 *DeviceType
= SoundDevice
->Type
;
355 return MMSYSERR_NOERROR
;