First of all I would like to apologize as I am new to reporting issues and this may be bad.
My repository where my code is located is: https://github.com/jernejmarcic/RustyPlayer
My metadata does not update (it only shows the metadata from the first song after the program is ran), I used the code straight from examples and pasted it in, when I had my music logic all in a loop it worked, however now it no longer works.
Old working code
Working code example, I apologize if I uploaded more than was needed:
pub(crate) fn play_random_song(music_list: &[String], debug_mode: bool /*, config_path: &PathBuf*/) -> std::io::Result<()> {
if music_list.is_empty() {
println!("No songs found in the specified directory.");
return Ok(());
}
let mut rng = rand::thread_rng();
let mut played_songs:Vec<usize> = Vec::new();
// let mut last_paused_state = IS_PAUSED.load(Ordering::SeqCst);
loop {
// let current_paused_state = IS_PAUSED.load(Ordering::SeqCst);
let randint = rng.gen_range(0..music_list.len());
// Your actual logic goes here.
played_songs.push(randint); // Track played songs
if debug_mode {println!("Playing song number: {}",randint)}
if debug_mode {println!("Song numbers played: {:?}", played_songs)}
if debug_mode{ println!("Playing song file: {}", music_list[randint]);}
// println!("Played songs index: {:?}", played_songs);
// Get an output stream handle to the default physical sound device
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
let file = BufReader::new(File::open(&music_list[randint]).unwrap());
let sink = Sink::try_new(&stream_handle).unwrap();
let tag = Tag::new().read_from_path(&music_list[randint]).unwrap();
let title = tag.title().unwrap_or_else(|| "Unknown".into());
// let album_cover = tag.album_cover();
let duration_seconds: Option<f64> = tag.duration(); // Example duration in seconds
let duration: Option<Duration> = convert_to_duration(duration_seconds);
let artists = tag
.artists()
.map(|a| a.join(", "))
.unwrap_or_else(|| "Unknown".into());
let album = tag.album_title().unwrap_or_else(|| "Unknown".into());
// Add a dummy source of the sake of the example.
let source = Decoder::new(file).unwrap();
sink.append(source);
// Construct the path to the directory where the .jpg files are located
let cover_output_path = format!("/tmp/{}.jpg", album);
let cover_output_path_clone = cover_output_path.clone();
if debug_mode {println!("Cover export path is: {}", cover_output_path)}
terminal_ui(&music_list, randint, title, album, artists.clone(), debug_mode, cover_output_path_clone);
// let played_songs_clone = played_songs.clone(); // Clone played_songs for the closure
// let music_list_clone = music_list;
#[cfg(not(target_os = "windows"))]
let hwnd = None;
#[cfg(target_os = "windows")]
let hwnd = {
use raw_window_handle::windows::WindowsHandle;
let handle: WindowsHandle = unimplemented!();
Some(handle.hwnd)
};
let config = PlatformConfig {
dbus_name: "rustyplayer",
display_name: "Rusty Player",
hwnd,
};
let mut controls = MediaControls::new(config).unwrap();
// The closure must be Send and have a static lifetime.
// let played_songs_clone = Arc::clone(&played_songs);
controls
.attach(
move |event: MediaControlEvent| match event {
MediaControlEvent::Play => {
if debug_mode {println!("{:?} event received via MPRIS",event)}
let current_state = IS_PAUSED.load(Ordering::SeqCst);
IS_PAUSED.store(!current_state, Ordering::SeqCst); // Toggle the state
},
MediaControlEvent::Pause => {
if debug_mode {println!("{:?} event received via MPRIS",event)}
// Logic to pause the music
let current_state = IS_PAUSED.load(Ordering::SeqCst);
IS_PAUSED.store(!current_state, Ordering::SeqCst); // Toggle the state
},
MediaControlEvent::Toggle => {
if debug_mode {println!("{:?} event received via MPRIS",event)}
// Toggle logic here
let current_state = IS_PAUSED.load(Ordering::SeqCst);
IS_PAUSED.store(!current_state, Ordering::SeqCst); // Toggle the state
},
MediaControlEvent::Next => {
if debug_mode {println!("{:?} event received via MPRIS",event)}
// Logic to skip to the next track
// You might need to signal your playback loop to move to the next song
SHOULD_SKIP.store(true, Ordering::SeqCst);
},
MediaControlEvent::Previous => {
if debug_mode {println!("{:?} event received via MPRIS",event)}
// TODO: Well make it work. LOL
// If only it was not so FUCKING HARD.
},
// Add more event handlers as needed
_ => println!("Event received: {:?}. If you see this message contact me I probably just haven't added support yet for it", event),
})
.unwrap();
// Update the media metadata.
controls
.set_metadata(MediaMetadata {
title: Some(title),
artist: Some(&*artists),
album: Some(album),
duration: duration,
cover_url: Some(&*format!("file://{}", cover_output_path)),
..Default::default()
})
.unwrap();
while !sink.empty() && !SHOULD_SKIP.load(Ordering::SeqCst) {
// Check and handle play/pause state...
let current_paused_state = IS_PAUSED.load(Ordering::SeqCst);
if current_paused_state != LAST_PAUSED_STATE.load(Ordering::SeqCst) {
if current_paused_state {
if debug_mode {println!("Attempting to pause")}
sink.pause();
if debug_mode {println!("Track should be paused")}
// println!("Paused");
} else if !current_paused_state { // Changed from 'else' to 'else if' to explicitly check the condition
if debug_mode {println!("Attempting to resume/play")}
sink.play();
if debug_mode {println!("Track should be resumed")}
// println!("Play");
}
// Update the last paused state to the current state
LAST_PAUSED_STATE.store(current_paused_state, Ordering::SeqCst);
}
thread::sleep(Duration::from_millis(50));
}
// Check again for skip in case it was set during playback
if SHOULD_SKIP.load(Ordering::SeqCst) {
SHOULD_SKIP.store(false, Ordering::SeqCst); // Reset the flag
println!("Attempting to skip to the next track...");
// No need for 'continue;' here as it's the end of the loop
continue;
}
sink.sleep_until_end();
// The sound plays in a separate thread. This call will block the current thread until the sink
// has finished playing all its queued sounds.
}
}
Now this implementation is lacking as It did not allow me to have support to play the previous song.
New not working code
This is the function of my new code:
fn music_player(music_list: &[String], debug_mode: bool, song_history: &mut Vec<Vec<usize>>, song_index: usize) {
if debug_mode { println!("Playing song number: {}", song_index) }
if debug_mode { println!("Song numbers played: {:?}", song_history) }
if debug_mode { println!("Playing song file: {}", music_list[song_index]); }
// println!("Played songs index: {:?}", song_history);
// Get an output stream handle to the default physical sound device
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
let file = BufReader::new(File::open(&music_list[song_index]).unwrap());
let sink = Sink::try_new(&stream_handle).unwrap();
let tag = Tag::new().read_from_path(&music_list[song_index]).unwrap();
let title = tag.title().unwrap_or_else(|| "Unknown".into());
// let album_cover = tag.album_cover();
let duration_seconds: Option<f64> = tag.duration(); // Example duration in miliseconds
let duration: Option<Duration> = convert_to_duration(duration_seconds);
let artists = tag
.artists()
.map(|a| a.join(", "))
.unwrap_or_else(|| "Unknown".into());
let album = tag.album_title().unwrap_or_else(|| "Unknown".into());
// Add a dummy source of the sake of the example.
let source = Decoder::new(file).unwrap();
sink.append(source);
// Construct the path to the directory where the .jpg files are located
let cover_output_path = format!("/tmp/{}-cover-{}.jpg",PACKAGE_NAME, song_index);
let cover_output_path_clone = cover_output_path.clone();
if debug_mode { println!("Cover export path is: {}", cover_output_path) }
terminal_ui(&music_list, song_index, title, album, artists.clone(), debug_mode, cover_output_path_clone);
#[cfg(not(target_os = "windows"))]
let hwnd = None;
#[cfg(target_os = "windows")]
let hwnd = {
use raw_window_handle::windows::WindowsHandle;
let handle: WindowsHandle = unimplemented!();
Some(handle.hwnd)
};
let config = PlatformConfig {
dbus_name: PACKAGE_NAME,
display_name: "Rusty Player",
hwnd,
};
let mut controls = MediaControls::new(config).unwrap();
controls
.attach(
move |event: MediaControlEvent| match event {
MediaControlEvent::Play => {
if debug_mode { println!("{:?} event received via MPRIS", event) }
let current_state = IS_PAUSED.load(Ordering::SeqCst);
IS_PAUSED.store(!current_state, Ordering::SeqCst); // Toggle the state
}
MediaControlEvent::Pause => {
if debug_mode { println!("{:?} event received via MPRIS", event) }
// Logic to pause the music
let current_state = IS_PAUSED.load(Ordering::SeqCst);
IS_PAUSED.store(!current_state, Ordering::SeqCst); // Toggle the state
}
MediaControlEvent::Toggle => {
if debug_mode { println!("{:?} event received via MPRIS", event) }
// Toggle logic here
let current_state = IS_PAUSED.load(Ordering::SeqCst);
IS_PAUSED.store(!current_state, Ordering::SeqCst); // Toggle the state
}
MediaControlEvent::Next => {
if debug_mode { println!("{:?} event received via MPRIS", event) }
// Logic to skip to the next track
// You might need to signal your playback loop to move to the next song
SHOULD_SKIP.store(true, Ordering::SeqCst);
}
MediaControlEvent::Previous => {
if debug_mode { println!("{:?} event received via MPRIS", event) }
SHOULD_PLAY_PREVIOUS.store(true, Ordering::SeqCst);
}
// Add more event handlers as needed
_ => println!("Event received: {:?}. If you see this message contact me I probably just haven't added support yet for it", event),
})
.unwrap();
controls
.set_metadata(MediaMetadata {
title: Some(title),
artist: Some(&*artists),
album: Some(album),
duration: duration,
cover_url: Some(&*format!("file://{}", cover_output_path)),
..Default::default()
})
.unwrap();
// println!("TEST, {album}, {title}, {:?}", artists);
while !sink.empty() && !SHOULD_SKIP.load(Ordering::SeqCst) && !SHOULD_PLAY_PREVIOUS.load(Ordering::SeqCst){
// Check and handle play/pause state...
let current_paused_state = IS_PAUSED.load(Ordering::SeqCst);
if current_paused_state != LAST_PAUSED_STATE.load(Ordering::SeqCst) {
if current_paused_state {
if debug_mode { println!("Attempting to pause") }
sink.pause();
if debug_mode { println!("Track should be paused") }
// println!("Paused");
} else if !current_paused_state { // Changed from 'else' to 'else if' to explicitly check the condition
if debug_mode { println!("Attempting to resume/play") }
sink.play();
if debug_mode { println!("Track should be resumed") }
// println!("Play");
}
// Update the last paused state to the current state
LAST_PAUSED_STATE.store(current_paused_state, Ordering::SeqCst);
}
thread::sleep(Duration::from_millis(50));
}
// Inside your playback loop
while !sink.empty() {
if SHOULD_SKIP.load(Ordering::SeqCst) {
SHOULD_SKIP.store(false, Ordering::SeqCst); // Reset the flag
if debug_mode { println!("Attempting to skip to the next track..."); }
sink.clear();
if song_history[1].len() >= 1 {
let song_index = song_history[1][song_history[1].len()-1];
song_history[1].pop();
music_player(music_list, debug_mode,song_history, song_index/*&mut rng*/);
} else {
random_passer(music_list, debug_mode,song_history, /*&mut rng*/);
}
// Logic to skip to the next track, adjust `current_index` as needed
random_passer(music_list, debug_mode,song_history, /*&mut rng*/);
}
if SHOULD_PLAY_PREVIOUS.load(Ordering::SeqCst) {
SHOULD_PLAY_PREVIOUS.store(false, Ordering::SeqCst); // Reset the flag
if debug_mode { println!("Attempting to go back to the previous track..."); }
// Logic to play the previous track, adjust `current_index` as needed
if song_history[0].len() >= 2 {
sink.clear();
song_history[1].push(song_index);
let song_index = song_history[0][song_history[0].len()-2];
song_history[0].pop();
music_player(music_list, debug_mode,song_history, song_index/*&mut rng*/);
} else {
println!("Not enough songs in the play queue")
}
}
// Continue existing play/pause state checks here...
thread::sleep(Duration::from_millis(50));
}
sink.sleep_until_end();
if song_history[1].len() >= 1 {
let song_index = song_history[1][song_history[1].len()-1];
song_history[1].pop();
music_player(music_list, debug_mode,song_history, song_index/*&mut rng*/);
} else {
random_passer(music_list, debug_mode,song_history, /*&mut rng*/);
}
// Logic to skip to the next track, adjust `current_index` as needed
// The sound plays in a separate thread. This call will block the current thread until the sink
// has finished playing all its queued sounds.
}
This code fixes my issue and allows me to traverse my song queue however when I ran it I notices that my metadata is no longer updated
How I tried fixing the issue:
First of all I made sure my variables (title, artist, album_url, duration) were being updated and they were.
I tried-making sure metadata is ran so I put it in a loop repeating several times, I tried putting it above the mediakey listener but that just broke it, I tried putting the varaible (let mut controls = MediaControls::new(config).unwrap();
) in a loop several times and it did not worked.
As of now no solutions that I thought of have worked.
I would like to thank you for all the help in advance :)