diff --git a/Cargo.lock b/Cargo.lock index 1d19495..0ce6009 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2380,6 +2380,7 @@ version = "0.1.0" dependencies = [ "futures", "libmpv", + "serde_json", "tokio", "tokio-stream", "tubest-common", diff --git a/common/src/lib.rs b/common/src/lib.rs index d0d62cc..3c20df8 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -1 +1,47 @@ +use std::time::Duration; +use serde::{Deserialize, Serialize}; + pub const PROG_NAME: &str = "tubest"; +const DEFAULT_SEEK: Duration = Duration::from_secs(30); + +#[derive(Serialize, Deserialize)] +pub enum Action { + Media(MediaAction), +} + +#[derive(Serialize, Deserialize)] +pub enum MediaAction { + Enqueue { + path: String, + replace: bool, + }, + Pause, + Unpause, + FastForward(Duration), + Rewind(Duration), + Next, + Stop, +} + +impl Action { + pub fn from_line(line: &str) -> Self { + let split: Vec<&str> = line.split_whitespace().collect(); + match &split[..] { + ["pause", ..] => Action::Media(MediaAction::Pause), + ["unpause", ..] => Action::Media(MediaAction::Unpause), + ["rewind", ..] => { + if split.len() > 1 { + // TODO + } + Action::Media(MediaAction::Rewind(DEFAULT_SEEK)) + }, + ["forward", ..] => { + // TODO: as above + Action::Media(MediaAction::FastForward(DEFAULT_SEEK)) + }, + ["next" | "skip", ..] => Action::Media(MediaAction::Next), + ["stop", ..] => Action::Media(MediaAction::Stop), + _ => Action::Media(MediaAction::Enqueue { path: line.to_string(), replace: true }), + } + } +} diff --git a/driver/Cargo.toml b/driver/Cargo.toml index 83237c2..d95fa70 100644 --- a/driver/Cargo.toml +++ b/driver/Cargo.toml @@ -7,5 +7,6 @@ edition = "2021" tubest-common.workspace = true futures.workspace = true libmpv.workspace = true +serde_json.workspace = true tokio.workspace = true tokio-stream.workspace = true diff --git a/driver/src/bin/driver.rs b/driver/src/bin/driver.rs index b48140f..fb05cf3 100644 --- a/driver/src/bin/driver.rs +++ b/driver/src/bin/driver.rs @@ -4,6 +4,7 @@ use std::process::Stdio; use tokio::io::{AsyncBufReadExt, AsyncRead, BufReader}; use tokio::process::Command; use tokio_stream::wrappers::LinesStream; +use tubest_common::*; #[tokio::main] async fn main() -> Result<(), Box> { @@ -33,9 +34,45 @@ async fn main() -> Result<(), Box> { mpv.load_config(home.join(".config/mpv/mpv.conf").to_str().unwrap()) .unwrap(); + // TODO: handle other cases of combined.next().await appropriately while let Some(Ok(line)) = combined.next().await { - mpv.playlist_load_files(&[(&line, FileState::AppendPlay, None)]) - .expect("couldn't load path"); + // TODO: remove ? and unwrap so stuff is nonfatal + let cmd: Action = serde_json::from_str(line.trim())?; + do_action(&mpv, cmd).unwrap(); + } + Ok(()) +} + +fn do_action(mpv: &Mpv, cmd: Action) -> Result<(), libmpv::Error> { + match cmd { + Action::Media(mcmd) => match mcmd { + MediaAction::Enqueue { path, replace } => { + let action = if replace { + FileState::Replace + } else { + FileState::AppendPlay + }; + mpv.playlist_load_files(&[(&path, action, None)])?; + } + MediaAction::Pause => { + mpv.pause()?; + } + MediaAction::Unpause => { + mpv.unpause()?; + } + MediaAction::FastForward(duration) => { + mpv.seek_forward(duration.as_secs_f64())?; + } + MediaAction::Rewind(duration) => { + mpv.seek_backward(duration.as_secs_f64())?; + } + MediaAction::Next => { + mpv.playlist_next_weak()?; + } + MediaAction::Stop => { + mpv.playlist_clear()?; + } + } } Ok(()) } diff --git a/matrix/src/bin/matrix.rs b/matrix/src/bin/matrix.rs index c5c6181..3bbae74 100644 --- a/matrix/src/bin/matrix.rs +++ b/matrix/src/bin/matrix.rs @@ -9,7 +9,7 @@ use matrix_sdk::{ use serde::{Deserialize, Serialize}; use std::io::Write; use std::path::PathBuf; -use tubest_common::PROG_NAME; +use tubest_common::{Action, PROG_NAME}; #[derive(Serialize, Deserialize)] struct Config { @@ -114,7 +114,7 @@ async fn main() -> Result<(), Box> { SyncRoomMessageEvent::Original(orig) => { let body = orig.content.body(); // TODO: my own IPC wrapper - println!("{}", body); + println!("{}", serde_json::to_string(&Action::from_line(body)).unwrap()); eprintln!("{}", body); } SyncRoomMessageEvent::Redacted(_) => {}