|
| 1 | +use crate::settings; |
| 2 | + |
1 | 3 | use enigo::Enigo; |
2 | 4 | use enigo::Key; |
3 | 5 | use enigo::Keyboard; |
4 | 6 | use enigo::Settings; |
5 | 7 |
|
| 8 | +use rodio::{Decoder, OutputStream, Sink}; |
| 9 | +use std::fs::File; |
| 10 | +use std::io::BufReader; |
| 11 | +use std::thread; |
6 | 12 | use tauri::image::Image; |
7 | 13 | use tauri::tray::TrayIcon; |
8 | 14 | use tauri::AppHandle; |
@@ -80,3 +86,68 @@ pub fn change_tray_icon(app: &AppHandle, icon: TrayIconState) { |
80 | 86 | .expect("failed to set icon"), |
81 | 87 | )); |
82 | 88 | } |
| 89 | + |
| 90 | +/// Plays an audio resource from the resources directory. |
| 91 | +/// Checks if audio feedback is enabled in settings before playing. |
| 92 | +pub fn play_sound(app: &AppHandle, resource_path: &str) { |
| 93 | + // Check if audio feedback is enabled |
| 94 | + let settings = settings::get_settings(app); |
| 95 | + if !settings.audio_feedback { |
| 96 | + return; |
| 97 | + } |
| 98 | + |
| 99 | + let app_handle = app.clone(); |
| 100 | + let resource_path = resource_path.to_string(); |
| 101 | + |
| 102 | + // Spawn a new thread to play the audio without blocking the main thread |
| 103 | + thread::spawn(move || { |
| 104 | + // Get the path to the audio file in resources |
| 105 | + let audio_path = match app_handle |
| 106 | + .path() |
| 107 | + .resolve(&resource_path, tauri::path::BaseDirectory::Resource) |
| 108 | + { |
| 109 | + Ok(path) => path, |
| 110 | + Err(e) => { |
| 111 | + eprintln!( |
| 112 | + "Failed to resolve audio file path '{}': {}", |
| 113 | + resource_path, e |
| 114 | + ); |
| 115 | + return; |
| 116 | + } |
| 117 | + }; |
| 118 | + |
| 119 | + // Try to play the audio file |
| 120 | + if let Err(e) = play_audio_file(&audio_path) { |
| 121 | + eprintln!("Failed to play sound '{}': {}", resource_path, e); |
| 122 | + } |
| 123 | + }); |
| 124 | +} |
| 125 | + |
| 126 | +/// Convenience function to play the recording start sound |
| 127 | +pub fn play_recording_start_sound(app: &AppHandle) { |
| 128 | + play_sound(app, "resources/rec_start.wav"); |
| 129 | +} |
| 130 | + |
| 131 | +/// Convenience function to play the recording stop sound |
| 132 | +pub fn play_recording_stop_sound(app: &AppHandle) { |
| 133 | + play_sound(app, "resources/rec_stop.wav"); |
| 134 | +} |
| 135 | + |
| 136 | +fn play_audio_file(path: &std::path::Path) -> Result<(), Box<dyn std::error::Error>> { |
| 137 | + // Get a output stream handle to the default physical sound device |
| 138 | + let (_stream, stream_handle) = OutputStream::try_default()?; |
| 139 | + |
| 140 | + // Load the audio file |
| 141 | + let file = File::open(path)?; |
| 142 | + let buf_reader = BufReader::new(file); |
| 143 | + let source = Decoder::new(buf_reader)?; |
| 144 | + |
| 145 | + // Create a sink to play the audio |
| 146 | + let sink = Sink::try_new(&stream_handle)?; |
| 147 | + sink.append(source); |
| 148 | + |
| 149 | + // Wait for the audio to finish playing |
| 150 | + sink.sleep_until_end(); |
| 151 | + |
| 152 | + Ok(()) |
| 153 | +} |
0 commit comments