library_usage/
library_usage.rs

1use songrec::{SongRec, Config, OutputFormat, RecognitionOutput};
2use std::path::Path;
3
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5    println!("SongRec Library Usage Examples");
6    println!("===============================\n");
7
8    // Example 1: Basic Configuration
9    println!("Example 1: Configuration");
10    println!("------------------------");
11    
12    let config = Config::default()
13        .with_quiet_mode(true)
14        .with_network_timeout(15)
15        .with_sensitivity(0.7);
16    
17    let songrec = SongRec::new(config);
18    println!("Created SongRec instance with custom settings\n");
19
20    // Example 2: File Recognition and Data Access
21    println!("Example 2: File Recognition");
22    println!("---------------------------");
23    
24    let audio_file = "tests/test_audio.wav";
25    
26    if Path::new(audio_file).exists() {
27        match songrec.recognize_from_file(audio_file) {
28            Ok(result) => {
29                // Direct access to recognition data
30                println!("Recognition data:");
31                println!("  Artist: {}", result.artist_name);
32                println!("  Song: {}", result.song_name);
33                println!("  Album: {}", result.album_name.as_deref().unwrap_or("Unknown"));
34                println!("  Year: {}", result.release_year.as_deref().unwrap_or("Unknown"));
35                println!("  Genre: {}", result.genre.as_deref().unwrap_or("Unknown"));
36                println!("  Track Key: {}", result.track_key);
37                println!("  Timestamp: {}", result.recognition_timestamp);
38                
39                // Example 3: Output Formats
40                println!("\nExample 3: Output Formats");
41                println!("-------------------------");
42                
43                // Simple format
44                let simple = RecognitionOutput::format_result(&result, OutputFormat::Simple);
45                println!("Simple: {}", simple.content);
46                
47                // JSON format
48                let json = RecognitionOutput::format_result(&result, OutputFormat::Json);
49                println!("JSON length: {} characters", json.content.len());
50                
51                // Parse JSON to access fields
52                let parsed: serde_json::Value = serde_json::from_str(&json.content)?;
53                println!("Parsed JSON - Song: {}", parsed["song_name"]);
54                
55                // CSV format
56                let csv = RecognitionOutput::format_result(&result, OutputFormat::Csv);
57                println!("CSV: {}", csv.content);
58                
59                // Example 4: Raw API Response
60                println!("\nExample 4: Raw API Data");
61                println!("-----------------------");
62                
63                // Access raw Shazam API response
64                if let Some(track) = result.raw_response.get("track") {
65                    if let Some(images) = track.get("images") {
66                        println!("Album art available: {}", images.is_object());
67                    }
68                    if let Some(hub) = track.get("hub") {
69                        println!("Streaming links available: {}", hub.is_object());
70                    }
71                }
72                
73            }
74            Err(e) => {
75                println!("Recognition failed: {}", e);
76            }
77        }
78    } else {
79        println!("Audio file not found, skipping recognition");
80    }
81
82    // Example 5: Function for Integration
83    println!("\nExample 5: Integration Function");
84    println!("-------------------------------");
85    
86    fn recognize_audio(file_path: &str) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
87        let config = Config::default().with_quiet_mode(true);
88        let songrec = SongRec::new(config);
89        
90        let result = songrec.recognize_from_file(file_path)?;
91        let json_output = RecognitionOutput::format_result(&result, OutputFormat::Json);
92        let parsed = serde_json::from_str(&json_output.content)?;
93        
94        Ok(parsed)
95    }
96    
97    if Path::new(audio_file).exists() {
98        match recognize_audio(audio_file) {
99            Ok(data) => {
100                println!("Function returned JSON with {} fields", 
101                    data.as_object().map(|o| o.len()).unwrap_or(0));
102            }
103            Err(e) => println!("Function error: {}", e)
104        }
105    }
106
107    // Example 6: Configuration Options
108    println!("\nExample 6: Configuration Options");
109    println!("--------------------------------");
110    
111    let configs = [
112        ("High sensitivity", Config::default().with_sensitivity(0.9)),
113        ("Low sensitivity", Config::default().with_sensitivity(0.3)),
114        ("Fast timeout", Config::default().with_network_timeout(5)),
115        ("Long timeout", Config::default().with_network_timeout(30)),
116        ("Verbose mode", Config::default().with_quiet_mode(false)),
117    ];
118    
119    for (name, config) in configs {
120        let _instance = SongRec::new(config);
121        println!("Created: {}", name);
122    }
123
124    // Example 7: Error Handling
125    println!("\nExample 7: Error Handling");
126    println!("-------------------------");
127    
128    fn safe_recognize(file_path: &str) -> Result<(String, String), String> {
129        if !Path::new(file_path).exists() {
130            return Err(format!("File not found: {}", file_path));
131        }
132        
133        let config = Config::default().with_quiet_mode(true);
134        let songrec = SongRec::new(config);
135        
136        match songrec.recognize_from_file(file_path) {
137            Ok(result) => Ok((result.artist_name, result.song_name)),
138            Err(e) => Err(format!("Recognition error: {}", e)),
139        }
140    }
141    
142    // Test with invalid file
143    match safe_recognize("nonexistent.wav") {
144        Ok((artist, song)) => println!("Result: {} - {}", artist, song),
145        Err(e) => println!("Expected error: {}", e),
146    }
147
148    // Example 8: Data Structure Access
149    println!("\nExample 8: Data Structure Access");
150    println!("--------------------------------");
151    
152    if Path::new(audio_file).exists() {
153        if let Ok(result) = songrec.recognize_from_file(audio_file) {
154            // Access all available fields
155            println!("Available data fields:");
156            println!("  song_name: {}", result.song_name);
157            println!("  artist_name: {}", result.artist_name);
158            println!("  album_name: {:?}", result.album_name);
159            println!("  track_key: {}", result.track_key);
160            println!("  release_year: {:?}", result.release_year);
161            println!("  genre: {:?}", result.genre);
162            println!("  recognition_timestamp: {}", result.recognition_timestamp);
163            println!("  raw_response keys: {:?}", 
164                result.raw_response.as_object().map(|o| o.keys().collect::<Vec<_>>()));
165        }
166    }
167
168    // Example 9: Available Audio Devices
169    println!("\nExample 9: Available Audio Devices");
170    println!("----------------------------------");
171    
172    match songrec::audio::AudioRecorder::list_input_devices() {
173        Ok(devices) => {
174            println!("Found {} audio input devices:", devices.len());
175            for (index, device_name) in devices.iter().enumerate() {
176                println!("  Device {}: {}", index, device_name);
177            }
178            
179            // Show how to use a specific device for live recognition
180            if !devices.is_empty() {
181                println!("\nExample: Using device for live recognition:");
182                println!("let device_name = \"{}\";", devices[0]);
183                println!("let stream = songrec.start_continuous_recognition_with_device(Some(device_name.to_string()))?;");
184                println!("for result in stream {{");
185                println!("    match result {{");
186                println!("        Ok(recognition) => println!(\"Recognized: {{}} - {{}}\", recognition.artist_name, recognition.song_name),");
187                println!("        Err(e) => eprintln!(\"Recognition error: {{}}\", e),");
188                println!("    }}");
189                println!("}}");
190            }
191        }
192        Err(e) => {
193            println!("Error listing audio devices: {}", e);
194            println!("This may occur if no audio devices are available or there are permission issues.");
195        }
196    }
197
198    // Example 10: Device Selection Function
199    println!("\nExample 10: Device Selection Function");
200    println!("------------------------------------");
201    
202    fn select_audio_device(device_name_pattern: &str) -> Result<String, String> {
203        let devices = songrec::audio::AudioRecorder::list_input_devices()
204            .map_err(|e| format!("Failed to list devices: {}", e))?;
205        
206        // Find device by name pattern
207        for device in devices {
208            if device.to_lowercase().contains(&device_name_pattern.to_lowercase()) {
209                return Ok(device);
210            }
211        }
212        
213        Err(format!("No device found matching pattern: {}", device_name_pattern))
214    }
215    
216    // Test device selection
217    match select_audio_device("microphone") {
218        Ok(device) => println!("Found microphone device: {}", device),
219        Err(e) => println!("Device selection result: {}", e),
220    }
221    
222    match select_audio_device("voicemeeter") {
223        Ok(device) => println!("Found Voicemeeter device: {}", device),
224        Err(e) => println!("Voicemeeter search result: {}", e),
225    }
226
227    // Example 11: Complete Device Integration Example
228    println!("\nExample 11: Complete Device Integration");
229    println!("--------------------------------------");
230    
231    fn get_best_audio_device() -> Result<String, String> {
232        let devices = songrec::audio::AudioRecorder::list_input_devices()
233            .map_err(|e| format!("Cannot access audio devices: {}", e))?;
234        
235        if devices.is_empty() {
236            return Err("No audio devices available".to_string());
237        }
238        
239        // Priority order for device selection
240        let preferred_patterns = ["voicemeeter", "stereo mix", "microphone", "mic"];
241        
242        for pattern in preferred_patterns {
243            for device in &devices {
244                if device.to_lowercase().contains(pattern) {
245                    return Ok(device.clone());
246                }
247            }
248        }
249        
250        // Fallback to first available device
251        Ok(devices[0].clone())
252    }
253    
254    match get_best_audio_device() {
255        Ok(device) => {
256            println!("Selected audio device: {}", device);
257            println!("This device can be used for live recognition:");
258            println!("  songrec.start_continuous_recognition_with_device(Some(\"{}\".to_string()))", device);
259        }
260        Err(e) => println!("Device selection failed: {}", e),
261    }
262
263    println!("\nLibrary demonstration complete.");
264    
265    Ok(())
266}