pub struct Config {
pub sensitivity: f32,
pub network_timeout: u64,
pub min_audio_duration: f32,
pub max_audio_duration: f32,
pub sample_rate: u32,
pub buffer_size: usize,
pub continuous_recognition: bool,
pub recognition_interval: f32,
pub quiet_mode: bool,
pub deduplicate_requests: bool,
pub deduplication_cache_duration: u64,
}Expand description
Configuration for SongRec
Fields§
§sensitivity: f32Recognition sensitivity (0.0 to 1.0)
network_timeout: u64Timeout for network requests in seconds
min_audio_duration: f32Minimum duration of audio to analyze (in seconds)
max_audio_duration: f32Maximum duration of audio to analyze (in seconds)
sample_rate: u32Sample rate for audio processing
buffer_size: usizeBuffer size for audio processing
continuous_recognition: boolWhether to enable continuous recognition
recognition_interval: f32Interval between recognition attempts in continuous mode (seconds)
quiet_mode: boolWhether to suppress verbose debug output
deduplicate_requests: boolWhether to deduplicate requests (prevent sending same signature multiple times)
deduplication_cache_duration: u64Time in seconds to remember signatures for deduplication
Implementations§
Source§impl Config
impl Config
Sourcepub fn with_sensitivity(self, sensitivity: f32) -> Self
pub fn with_sensitivity(self, sensitivity: f32) -> Self
Set the sensitivity level
Examples found in repository?
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}More examples
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}Sourcepub fn with_network_timeout(self, timeout: u64) -> Self
pub fn with_network_timeout(self, timeout: u64) -> Self
Set the network timeout
Examples found in repository?
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}More examples
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}Sourcepub fn with_min_audio_duration(self, duration: f32) -> Self
pub fn with_min_audio_duration(self, duration: f32) -> Self
Set the minimum audio duration
Sourcepub fn with_max_audio_duration(self, duration: f32) -> Self
pub fn with_max_audio_duration(self, duration: f32) -> Self
Set the maximum audio duration
Sourcepub fn with_sample_rate(self, sample_rate: u32) -> Self
pub fn with_sample_rate(self, sample_rate: u32) -> Self
Set the sample rate
Sourcepub fn with_buffer_size(self, buffer_size: usize) -> Self
pub fn with_buffer_size(self, buffer_size: usize) -> Self
Set the buffer size
Sourcepub fn with_continuous_recognition(self, enabled: bool) -> Self
pub fn with_continuous_recognition(self, enabled: bool) -> Self
Enable or disable continuous recognition
Sourcepub fn with_recognition_interval(self, interval: f32) -> Self
pub fn with_recognition_interval(self, interval: f32) -> Self
Set the recognition interval for continuous mode
Sourcepub fn with_quiet_mode(self, quiet: bool) -> Self
pub fn with_quiet_mode(self, quiet: bool) -> Self
Enable or disable quiet mode (suppress verbose output)
Examples found in repository?
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}More examples
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}Sourcepub fn with_deduplication(self, enabled: bool) -> Self
pub fn with_deduplication(self, enabled: bool) -> Self
Enable or disable request deduplication
Sourcepub fn with_deduplication_cache_duration(self, duration: u64) -> Self
pub fn with_deduplication_cache_duration(self, duration: u64) -> Self
Set the deduplication cache duration