device_usage/
device_usage.rs

1use songrec::{SongRec, Config, audio::AudioRecorder};
2
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4    println!("SongRec Device Management and Live Recognition Examples");
5    println!("========================================================\n");
6
7    // Example 1: List Available Audio Devices
8    println!("Example 1: List Available Audio Devices");
9    println!("---------------------------------------");
10    
11    match AudioRecorder::list_input_devices() {
12        Ok(devices) => {
13            if devices.is_empty() {
14                println!("No audio input devices found.");
15                return Ok(());
16            }
17            
18            println!("Found {} audio input devices:", devices.len());
19            for (index, device_name) in devices.iter().enumerate() {
20                println!("  {}: {}", index, device_name);
21            }
22            println!();
23            
24            // Example 2: Device Selection Strategies
25            println!("Example 2: Device Selection Strategies");
26            println!("--------------------------------------");
27            
28            // Strategy 1: Select by exact name
29            let first_device = &devices[0];
30            println!("Strategy 1 - Exact name selection:");
31            println!("  Selected: {}", first_device);
32            
33            // Strategy 2: Select by pattern matching
34            println!("\nStrategy 2 - Pattern matching:");
35            for pattern in &["microphone", "mic", "voicemeeter", "stereo mix"] {
36                if let Some(device) = find_device_by_pattern(&devices, pattern) {
37                    println!("  Pattern '{}' found: {}", pattern, device);
38                }
39            }
40            
41            // Strategy 3: Priority-based selection
42            println!("\nStrategy 3 - Priority-based selection:");
43            let selected_device = select_best_device(&devices);
44            println!("  Best device: {}", selected_device);
45            
46            // Example 3: Live Recognition with Device Selection
47            println!("\nExample 3: Live Recognition Setup");
48            println!("---------------------------------");
49            
50            // Show how to set up live recognition with different devices
51            println!("Setting up live recognition with various devices:\n");
52            
53            for (i, device) in devices.iter().enumerate().take(3) {
54                println!("Device {}: {}", i, device);
55                
56                // Configuration for this device
57                let config = Config::default()
58                    .with_quiet_mode(true)
59                    .with_network_timeout(10)
60                    .with_sensitivity(0.6);
61                
62                let _songrec = SongRec::new(config);
63                
64                println!("  -> Configuration: quiet mode, 10s timeout, 0.6 sensitivity");
65                println!("  -> Usage: songrec.start_continuous_recognition_with_device(Some(\"{}\".to_string()))", device);
66                println!("  -> Ready for live recognition\n");
67            }
68            
69            // Example 4: Complete Live Recognition Example (Commented)
70            println!("Example 4: Complete Live Recognition Code");
71            println!("------------------------------------------");
72            
73            print_live_recognition_example(&selected_device);
74            
75            // Example 5: Device-Specific Configuration
76            println!("\nExample 5: Device-Specific Configuration");
77            println!("----------------------------------------");
78            
79            for device in devices.iter().take(2) {
80                let config = create_device_specific_config(device);
81                println!("Device: {}", device);
82                println!("  Recommended config: quiet={}, timeout={}s, sensitivity={}", 
83                    config.quiet_mode, config.network_timeout, config.sensitivity);
84            }
85            
86            // Example 6: Error Handling for Device Operations
87            println!("\nExample 6: Error Handling");
88            println!("-------------------------");
89            
90            demonstrate_error_handling();
91            
92        }
93        Err(e) => {
94            println!("Error listing audio devices: {}", e);
95            println!("Common causes:");
96            println!("- No audio devices available");
97            println!("- Permission issues");
98            println!("- Audio system not initialized");
99            println!("- Driver problems");
100        }
101    }
102    
103    Ok(())
104}
105
106/// Find a device by pattern matching (case-insensitive)
107fn find_device_by_pattern(devices: &[String], pattern: &str) -> Option<String> {
108    devices.iter()
109        .find(|device| device.to_lowercase().contains(&pattern.to_lowercase()))
110        .cloned()
111}
112
113/// Select the best device based on priority patterns
114fn select_best_device(devices: &[String]) -> String {
115    // Priority order for different device types
116    let priority_patterns = [
117        "voicemeeter",      // Virtual audio cable (great for system audio)
118        "stereo mix",       // Windows stereo mix (system audio)
119        "what u hear",      // Some sound cards' system audio
120        "microphone",       // Physical microphone
121        "mic",             // Short form microphone
122        "line in",         // Line input
123    ];
124    
125    // Try to find device by priority
126    for pattern in &priority_patterns {
127        if let Some(device) = find_device_by_pattern(devices, pattern) {
128            return device;
129        }
130    }
131    
132    // Fallback to first device
133    devices[0].clone()
134}
135
136/// Create device-specific configuration
137fn create_device_specific_config(device_name: &str) -> Config {
138    let device_lower = device_name.to_lowercase();
139    
140    if device_lower.contains("voicemeeter") {
141        // Voicemeeter: System audio, higher sensitivity
142        Config::default()
143            .with_quiet_mode(true)
144            .with_network_timeout(8)
145            .with_sensitivity(0.8)
146    } else if device_lower.contains("microphone") || device_lower.contains("mic") {
147        // Microphone: Lower sensitivity, longer timeout
148        Config::default()
149            .with_quiet_mode(true)
150            .with_network_timeout(15)
151            .with_sensitivity(0.5)
152    } else if device_lower.contains("stereo mix") {
153        // Stereo Mix: System audio, balanced settings
154        Config::default()
155            .with_quiet_mode(true)
156            .with_network_timeout(10)
157            .with_sensitivity(0.7)
158    } else {
159        // Default configuration
160        Config::default()
161            .with_quiet_mode(true)
162            .with_network_timeout(12)
163            .with_sensitivity(0.6)
164    }
165}
166
167/// Print a complete live recognition example
168fn print_live_recognition_example(device_name: &str) {
169    println!("Complete live recognition example with device selection:");
170    println!("```rust");
171    println!("use songrec::{{SongRec, Config}};");
172    println!("use std::time::Duration;");
173    println!();
174    println!("fn start_live_recognition() -> Result<(), Box<dyn std::error::Error>> {{");
175    println!("    // Create configuration");
176    println!("    let config = Config::default()");
177    println!("        .with_quiet_mode(true)");
178    println!("        .with_network_timeout(10)");
179    println!("        .with_sensitivity(0.6);");
180    println!();
181    println!("    let songrec = SongRec::new(config);");
182    println!();
183    println!("    // Start recognition with specific device");
184    println!("    let device_name = \"{}\";", device_name);
185    println!("    let stream = songrec.start_continuous_recognition_with_device(");
186    println!("        Some(device_name.to_string())");
187    println!("    )?;");
188    println!();
189    println!("    println!(\"Starting live recognition with device: {{}}\", device_name);");
190    println!("    println!(\"Listening for audio...\");");
191    println!();
192    println!("    // Process recognition results");
193    println!("    for result in stream {{");
194    println!("        match result {{");
195    println!("            Ok(recognition) => {{");
196    println!("                println!(\"🎵 Recognized: {{}} - {{}}\", ");
197    println!("                    recognition.artist_name, recognition.song_name);");
198    println!("                ");
199    println!("                // Access additional data");
200    println!("                if let Some(album) = &recognition.album_name {{");
201    println!("                    println!(\"   Album: {{}}\", album);");
202    println!("                }}");
203    println!("                if let Some(year) = &recognition.release_year {{");
204    println!("                    println!(\"   Year: {{}}\", year);");
205    println!("                }}");
206    println!("            }}");
207    println!("            Err(e) => {{");
208    println!("                eprintln!(\"Recognition error: {{}}\", e);");
209    println!("                // Decide whether to continue or break");
210    println!("            }}");
211    println!("        }}");
212    println!("    }}");
213    println!();
214    println!("    Ok(())");
215    println!("}}");
216    println!("```");
217}
218
219/// Demonstrate error handling for device operations
220fn demonstrate_error_handling() {
221    println!("Error handling examples:");
222    
223    // 1. Device not found
224    println!("1. Handling device not found:");
225    println!("```rust");
226    println!("match songrec.start_continuous_recognition_with_device(Some(\"NonExistentDevice\".to_string())) {{");
227    println!("    Ok(stream) => {{ /* Handle stream */ }}");
228    println!("    Err(e) => {{");
229    println!("        eprintln!(\"Failed to start recognition: {{}}\", e);");
230    println!("        // Fallback to default device");
231    println!("        let stream = songrec.start_continuous_recognition()?;");
232    println!("    }}");
233    println!("}}");
234    println!("```");
235    
236    // 2. No devices available
237    println!("\n2. Handling no devices available:");
238    println!("```rust");
239    println!("match AudioRecorder::list_input_devices() {{");
240    println!("    Ok(devices) if devices.is_empty() => {{");
241    println!("        eprintln!(\"No audio devices available\");");
242    println!("        return Err(\"No audio hardware found\".into());");
243    println!("    }}");
244    println!("    Ok(devices) => {{ /* Use devices */ }}");
245    println!("    Err(e) => {{");
246    println!("        eprintln!(\"Cannot access audio system: {{}}\", e);");
247    println!("        return Err(e.into());");
248    println!("    }}");
249    println!("}}");
250    println!("```");
251    
252    // 3. Robust device selection
253    println!("\n3. Robust device selection:");
254    println!("```rust");
255    println!("fn select_device_safely() -> Result<String, Box<dyn std::error::Error>> {{");
256    println!("    let devices = AudioRecorder::list_input_devices()?;");
257    println!("    ");
258    println!("    if devices.is_empty() {{");
259    println!("        return Err(\"No audio devices available\".into());");
260    println!("    }}");
261    println!("    ");
262    println!("    // Try preferred devices first");
263    println!("    for pattern in [\"voicemeeter\", \"stereo mix\", \"microphone\"] {{");
264    println!("        if let Some(device) = devices.iter()");
265    println!("            .find(|d| d.to_lowercase().contains(pattern)) {{");
266    println!("            return Ok(device.clone());");
267    println!("        }}");
268    println!("    }}");
269    println!("    ");
270    println!("    // Fallback to first device");
271    println!("    Ok(devices[0].clone())");
272    println!("}}");
273    println!("```");
274}