Rust Programming By Example by Guillaume Gomez Antoni Boucher

Rust Programming By Example by Guillaume Gomez Antoni Boucher

Author:Guillaume Gomez,Antoni Boucher [Guillaume Gomez]
Language: eng
Format: epub
Tags: COM051280 - COMPUTERS / Programming Languages / Java, COM074000 - COMPUTERS / Hardware / Mobile Devices, COM051220 - COMPUTERS / Programming / Parallel
Publisher: Packt Publishing
Published: 2018-01-10T06:27:37+00:00


That's why we need a new field in our Playlist structure:

pub struct Playlist { current_song: RefCell<Option<String>>, model: ListStore, player: Player, treeview: TreeView, }

We added a field that will contain the path of the currently playing song. Here we wrap the Option<String> into a RefCell, which is another way to have interior mutability. We cannot use a Cell because the String type does not implement the Copy trait. So, what is the difference between Cell and RefCell? The RefCell type will check the borrowing rules at runtime: if two borrows happen at the same time, it will panic. We have to be careful when using RefCell: it is better to have compile-time borrowing checks if possible. But when using gtk-rs, we sometimes need to share a mutable state with the event handler and the best way to do that is to use RefCell.

In the next chapter, we'll learn how to use a library that abstracts the state management so that you won't need to use RefCell and you won't get any panic at runtime. This requires a new import statement:

use std::cell::RefCell;

We need to update the constructor to initialize this value:

impl Playlist { pub(crate) fn new(state: Arc<Mutex<State>>) -> Self { // … Playlist { current_song: RefCell::new(None), model, player: Player::new(state.clone()), treeview, } } }

There's one more method to add in Playlist before we move on to update the play() method:

pub fn path(&self) -> Option<String> { self.current_song.borrow().clone() }

This method returns a copy of the current song path. Since the field is a RefCell, we need to call borrow() in order to get access to the inner value. This method returns the equivalent of an immutable reference. We'll soon see how to have a mutable reference. As with Mutex, the borrow is lexical and the borrow will end at the end of the function. We're now ready to update the play() method:

pub fn play(&self) -> bool { if let Some(path) = self.selected_path() { if self.player.is_paused() && Some(&path) ==

self.path().as_ref() { self.player.resume(); } else { self.player.load(&path); *self.current_song.borrow_mut() = Some(path.into()); } true } else { false } }

We call resume() if the song was paused and if the selected path is the same as the currently playing song path. If this condition is false, we load the specified path and save this path in our field. To do so, we call borrow_mut() to get a mutable reference. Once again, we need to prefix the expression with * so that DerefMut::deref_mut() gets called. Run the project and you'll see that you can pause and resume the song.

Let's now add a way to stop the song. We'll start by adding a method to the Player, as usual:

pub fn stop(&self) { self.paused.set(false); self.app_state.lock().unwrap().stopped = true; self.emit(Stop); self.set_playing(false); }

We first set the paused field to false so that the playlist won't try to resume the song the next time the play button is clicked. We then set the stopped field to true, this will cause the next click of this button to play the song instead of trying to pause it. We



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.