rudimentary command parsing

This commit is contained in:
lif 2023-11-12 17:55:21 -08:00
parent 94f99e9f84
commit 65e42c2f2a
5 changed files with 89 additions and 4 deletions

1
Cargo.lock generated
View file

@ -2380,6 +2380,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"futures", "futures",
"libmpv", "libmpv",
"serde_json",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"tubest-common", "tubest-common",

View file

@ -1 +1,47 @@
use std::time::Duration;
use serde::{Deserialize, Serialize};
pub const PROG_NAME: &str = "tubest"; 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 }),
}
}
}

View file

@ -7,5 +7,6 @@ edition = "2021"
tubest-common.workspace = true tubest-common.workspace = true
futures.workspace = true futures.workspace = true
libmpv.workspace = true libmpv.workspace = true
serde_json.workspace = true
tokio.workspace = true tokio.workspace = true
tokio-stream.workspace = true tokio-stream.workspace = true

View file

@ -4,6 +4,7 @@ use std::process::Stdio;
use tokio::io::{AsyncBufReadExt, AsyncRead, BufReader}; use tokio::io::{AsyncBufReadExt, AsyncRead, BufReader};
use tokio::process::Command; use tokio::process::Command;
use tokio_stream::wrappers::LinesStream; use tokio_stream::wrappers::LinesStream;
use tubest_common::*;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
@ -33,9 +34,45 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
mpv.load_config(home.join(".config/mpv/mpv.conf").to_str().unwrap()) mpv.load_config(home.join(".config/mpv/mpv.conf").to_str().unwrap())
.unwrap(); .unwrap();
// TODO: handle other cases of combined.next().await appropriately
while let Some(Ok(line)) = combined.next().await { while let Some(Ok(line)) = combined.next().await {
mpv.playlist_load_files(&[(&line, FileState::AppendPlay, None)]) // TODO: remove ? and unwrap so stuff is nonfatal
.expect("couldn't load path"); 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(()) Ok(())
} }

View file

@ -9,7 +9,7 @@ use matrix_sdk::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use tubest_common::PROG_NAME; use tubest_common::{Action, PROG_NAME};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct Config { struct Config {
@ -114,7 +114,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
SyncRoomMessageEvent::Original(orig) => { SyncRoomMessageEvent::Original(orig) => {
let body = orig.content.body(); let body = orig.content.body();
// TODO: my own IPC wrapper // TODO: my own IPC wrapper
println!("{}", body); println!("{}", serde_json::to_string(&Action::from_line(body)).unwrap());
eprintln!("{}", body); eprintln!("{}", body);
} }
SyncRoomMessageEvent::Redacted(_) => {} SyncRoomMessageEvent::Redacted(_) => {}