Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ readme = "README.md"
version = "0.62"
features = ["Foundation",
"Win32_Media_Audio",
"Win32_Media_Audio_Endpoints",
"Win32_Foundation",
"Win32_Devices_FunctionDiscovery",
"Win32_Devices_Properties",
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The following is a selection of the functionality currently available in the lib
- Event-driven and polled buffering
- Loopback capture
- Notifications for volume change, device disconnect etc
- Notifications when devices are added or removed, or when the default device changes
- …and additional features beyond this list


Expand All @@ -36,6 +37,7 @@ The following is a selection of the functionality currently available in the lib
| `loopback` | Shows how to simultaneously capture and render sound, with separate threads for capture and render. |
| `record` | Records audio from the default device, and saves the raw samples to a file. |
| `devices` | Lists all available audio devices and displays the default devices. |
| `processes` | Lists all available audio capture devices and lists the processes that are using them. |
| `processes` | Lists all audio devices and the processes that are using them, with the peak level of each session. |
| `record_application` | Records audio from a single application, and saves the raw samples to a file. |
| `aec` | Captures audio with Acoustic Echo Cancellation (AEC) enabled and saves the raw data to a file. |
| `device_notifications` | Listens for devices being added, removed or changed, and for changes of the default device. |
34 changes: 34 additions & 0 deletions examples/device_notifications.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::thread;
use std::time::Duration;
use wasapi::*;

// Listen to device change notifications for one minute.
// Plug or unplug a device, or change the default device in the
// Windows sound settings, to see the notifications arrive.
fn main() {
initialize_mta().unwrap();

let enumerator = DeviceEnumerator::new().unwrap();

let mut callbacks = DeviceEventCallbacks::new();

callbacks.set_device_added_callback(|id| println!("Device added: {id}"));
callbacks.set_device_removed_callback(|id| println!("Device removed: {id}"));
callbacks.set_device_state_callback(|id, state| println!("Device {id} is now {state}"));
callbacks.set_default_device_callback(|direction, role, id| match id {
Some(id) => println!("New default {direction} device for role {role}: {id}"),
None => println!("There is no longer a default {direction} device for role {role}"),
});
callbacks.set_property_value_callback(|id, key| {
println!("Property {:?} of device {id} changed", key.fmtid)
});

// The notifications are unregistered when this value is dropped,
// so it must be kept in scope for as long as they are needed.
let _registered_events = enumerator
.register_notification_callback(callbacks)
.unwrap();

println!("Listening for device changes for 60 seconds...");
thread::sleep(Duration::from_secs(60));
}
39 changes: 26 additions & 13 deletions examples/processes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,35 @@ fn main() {

let enumerator = DeviceEnumerator::new().unwrap();

println!("The following input devices are being used by:");
for device in &enumerator
.get_device_collection(&Direction::Capture)
.unwrap()
{
let dev = device.unwrap();
let manager = dev.get_iaudiosessionmanager().unwrap();
let enumerator = manager.get_audiosessionenumerator().unwrap();
for direction in [Direction::Capture, Direction::Render] {
println!("The following {direction} devices are being used by:");
for device in &enumerator.get_device_collection(&direction).unwrap() {
let dev = device.unwrap();
let manager = dev.get_iaudiosessionmanager().unwrap();
let sessions = manager.get_audiosessionenumerator().unwrap();

println!("Device: {:?}", dev.get_friendlyname().unwrap());
let dev_meter = dev.get_audiometerinformation().unwrap();
let dev_peak = dev_meter.get_peak_value().unwrap();

for i in 0..enumerator.get_count().unwrap() {
let control = enumerator.get_session(i).unwrap();
let process_id = control.get_process_id().unwrap();
println!(
"Device: {:?}, peak: {dev_peak:.3}",
dev.get_friendlyname().unwrap()
);

println!(" - In use by process: {:?}", process_id);
for i in 0..sessions.get_count().unwrap() {
let control = sessions.get_session(i).unwrap();
let state = control.get_state().unwrap();
if state != SessionState::Active {
continue;
}
let process_id = control.get_process_id().unwrap();
let identifier = control.get_session_identifier().unwrap();
let meter = control.get_audiometerinformation().unwrap();
let peak = meter.get_peak_value().unwrap();

println!(" - In use by process: {process_id}, peak: {peak:.3}");
println!(" session: {identifier}");
}
}
}
}
Loading