Refactored MpvEventHandler and implemented basic event listener

This commit is contained in:
Ryze 2023-02-04 06:03:33 +03:00
parent 89852c039f
commit 90ac811a32
4 changed files with 158 additions and 16 deletions

51
src/basic_listener.rs Normal file
View file

@ -0,0 +1,51 @@
use crate::mpv_event_handler::events::{MpvEvent, Listener, FileInfo};
pub struct MpvListener;
impl MpvListener {
fn print_file_info(&self, file_info: FileInfo) {
let FileInfo {filename, metadata} = file_info;
println!("[RPC] FILENAME: {filename}");
if let Some(artist) = metadata.artist {
println!("[RPC] ARTIST: {artist}");
}
if let Some(album) = metadata.album {
println!("[RPC] ALBUM: {album}");
}
if let Some(title) = metadata.title {
println!("[RPC] TITLE: {title}");
}
if let Some(track) = metadata.track {
println!("[RPC] TRACK: {track}");
}
}
fn print_seek_time(&self, time: i64) {
println!("[RPC] SEEKING: {time}");
}
fn print_play(&self) {
println!("[RPC] PLAY");
}
fn print_pause(&self) {
println!("[RPC] PAUSE");
}
}
impl Listener for MpvListener {
fn handle_event(&self, event: MpvEvent) {
match event {
MpvEvent::FileLoaded(file_info) => self.print_file_info(file_info),
MpvEvent::Seek(time) => self.print_seek_time(time),
MpvEvent::Pause => self.print_pause(),
MpvEvent::Play => self.print_play(),
}
}
}

View file

@ -1,10 +1,17 @@
use mpv_client::mpv_handle; use mpv_client::mpv_handle;
mod mpv_event_handler; mod mpv_event_handler;
mod basic_listener; // For testing purposes
#[no_mangle] #[no_mangle]
fn mpv_open_cplugin(handle: *mut mpv_handle) -> std::os::raw::c_int { fn mpv_open_cplugin(handle: *mut mpv_handle) -> std::os::raw::c_int {
let client = mpv_event_handler::MpvHandler::from_ptr(handle); let listener = Box::new(basic_listener::MpvListener);
let client = mpv_event_handler::MpvEventHandler::from_ptr(handle, listener);
if let Err(e) = client.initialize() {
println!("[RPC] Error initializing mpv client: {e}")
}
while client.poll_events() { while client.poll_events() {
} }

View file

@ -1,21 +1,33 @@
use mpv_client::{Handle, Event, Property, mpv_handle}; use mpv_client::{Handle, Event, Property, Format, mpv_handle};
pub struct MpvHandler { pub mod events;
mpv: Handle use events::{MpvEvent, Listener, FileInfo, FileMetadata};
const NAME_PAUSE_PROP: &str = "pause";
const REPL_PAUSE_PROP: u64 = 1;
pub struct MpvEventHandler {
mpv: Handle,
listener: Box<dyn Listener>
} }
impl MpvHandler { impl MpvEventHandler {
pub fn new(mpv: Handle) -> Self { pub fn new<'a>(mpv: Handle, listener: Box<dyn Listener>) -> Self {
Self { Self {
mpv mpv,
listener
} }
} }
pub fn from_ptr(handle: *mut mpv_handle) -> Self { pub fn from_ptr<'a>(handle: *mut mpv_handle, listener: Box<dyn Listener>) -> Self {
MpvHandler::new(Handle::from_ptr(handle)) MpvEventHandler::new(Handle::from_ptr(handle), listener)
}
pub fn initialize(&self) -> Result<(), String> {
self.observe_property(REPL_PAUSE_PROP, NAME_PAUSE_PROP, bool::MPV_FORMAT)
} }
#[allow(dead_code)]
fn observe_property(&self, id: u64, name: &str, format: i32) -> Result<(), String>{ fn observe_property(&self, id: u64, name: &str, format: i32) -> Result<(), String>{
match self.mpv.observe_property(id, name, format) { match self.mpv.observe_property(id, name, format) {
Ok(_) => Ok(()), Ok(_) => Ok(()),
@ -23,10 +35,10 @@ impl MpvHandler {
} }
} }
#[allow(dead_code)] fn on_property_change(&self, prop_id: u64, prop: Property) {
fn on_property_change(&self, prop_id: u64, _prop: Property) {
println!("[RPC] Property changed: {prop_id}"); println!("[RPC] Property changed: {prop_id}");
match prop_id { match prop_id {
REPL_PAUSE_PROP => self.handle_pause_change(prop.data().unwrap()),
_ => () _ => ()
} }
} }
@ -34,12 +46,62 @@ impl MpvHandler {
fn handle_event(&self, event: Event) { fn handle_event(&self, event: Event) {
println!("[RPC] Event: {event}"); println!("[RPC] Event: {event}");
match event { match event {
Event::FileLoaded => self.handle_file_loaded(),
Event::PlaybackRestart => self.handle_playback_restart(),
_ => () _ => ()
} }
} }
// TODO
// Replace unwrap with error handling
fn handle_file_loaded(&self) {
let filename = self.mpv.get_property("filename").unwrap();
let artist = self.mpv.get_property("metadata/by-key/artist").ok();
let album = self.mpv.get_property("metadata/by-key/album").ok();
let title = self.mpv.get_property("metadata/by-key/title").ok();
let track = self.mpv.get_property("metadata/by-key/Artist").ok();
let metadata = FileMetadata {
artist,
album,
title,
track
};
let file_info = FileInfo {
filename,
metadata
};
let event = MpvEvent::FileLoaded(file_info);
self.listener.handle_event(event);
}
fn handle_playback_restart(&self) {
let res = self.mpv.get_property("playback-time").ok();
match res {
Some(time) => {
let event = MpvEvent::Seek(time);
self.listener.handle_event(event);
}
None => {
println!("[RPC] Failed retrieving playback-time.");
println!("[RPC] This usually happens seeking into file end. Possibly mpv bug?");
},
}
}
fn handle_pause_change(&self, pause: bool) {
let event = match pause {
false => MpvEvent::Play,
true => MpvEvent::Pause
};
self.listener.handle_event(event);
}
// TODO! // TODO!
// Add logging // Add logging and error handling,
// yes unwrap on property changes and events
pub fn poll_events(&self) -> bool { pub fn poll_events(&self) -> bool {
match self.mpv.wait_event(0.0) { match self.mpv.wait_event(0.0) {
Event::None => (), Event::None => (),

View file

@ -0,0 +1,22 @@
pub struct FileInfo {
pub filename: String,
pub metadata: FileMetadata
}
pub struct FileMetadata {
pub artist: Option<String>,
pub album: Option<String>,
pub title: Option<String>,
pub track: Option<String>
}
pub enum MpvEvent {
FileLoaded(FileInfo),
Seek(i64),
Pause,
Play
}
pub trait Listener {
fn handle_event(&self, event: MpvEvent);
}