mirror of
https://github.com/NotAShelf/mpvrc.git
synced 2026-05-09 00:45:33 +00:00
meta: rename to 'mpvrc'
mrc is taken :( Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I2cf0cab8dce04cd04981177d43b9b9b76a6a6964
This commit is contained in:
parent
8c48acf693
commit
1f1a94f747
9 changed files with 375 additions and 255 deletions
51
src/cli.rs
51
src/cli.rs
|
|
@ -1,9 +1,10 @@
|
|||
use std::{
|
||||
io::{self, Write},
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use clap::{CommandFactory, Parser, Subcommand, ValueEnum};
|
||||
use mrc::commands::Commands;
|
||||
use mrc::interactive::InteractiveMode;
|
||||
use mrc::{MrcError, Result, SOCKET_PATH};
|
||||
use std::io::{self, Write};
|
||||
use std::path::PathBuf;
|
||||
use mpvrc::{MrcError, Result, SOCKET_PATH, commands::Commands, interactive::InteractiveMode};
|
||||
use tracing::{debug, error};
|
||||
|
||||
#[derive(Parser)]
|
||||
|
|
@ -115,27 +116,42 @@ pub enum Shell {
|
|||
impl Shell {
|
||||
pub fn generate(&self, app: &mut clap::Command) {
|
||||
match self {
|
||||
Shell::Bash => {
|
||||
clap_complete::generate(clap_complete::Shell::Bash, app, "mrc", &mut io::stdout())
|
||||
Self::Bash => {
|
||||
clap_complete::generate(
|
||||
clap_complete::Shell::Bash,
|
||||
app,
|
||||
"mpvrc",
|
||||
&mut io::stdout(),
|
||||
);
|
||||
}
|
||||
|
||||
Shell::Elvish => {
|
||||
clap_complete::generate(clap_complete::Shell::Elvish, app, "mrc", &mut io::stdout())
|
||||
Self::Elvish => {
|
||||
clap_complete::generate(
|
||||
clap_complete::Shell::Elvish,
|
||||
app,
|
||||
"mpvrc",
|
||||
&mut io::stdout(),
|
||||
);
|
||||
}
|
||||
|
||||
Shell::Fish => {
|
||||
clap_complete::generate(clap_complete::Shell::Fish, app, "mrc", &mut io::stdout())
|
||||
Self::Fish => {
|
||||
clap_complete::generate(
|
||||
clap_complete::Shell::Fish,
|
||||
app,
|
||||
"mpvrc",
|
||||
&mut io::stdout(),
|
||||
);
|
||||
}
|
||||
|
||||
Shell::PowerShell => clap_complete::generate(
|
||||
Self::PowerShell => clap_complete::generate(
|
||||
clap_complete::Shell::PowerShell,
|
||||
app,
|
||||
"mrc",
|
||||
"mpvrc",
|
||||
&mut io::stdout(),
|
||||
),
|
||||
|
||||
Shell::Zsh => {
|
||||
clap_complete::generate(clap_complete::Shell::Zsh, app, "mrc", &mut io::stdout())
|
||||
Self::Zsh => {
|
||||
clap_complete::generate(clap_complete::Shell::Zsh, app, "mpvrc", &mut io::stdout());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -151,7 +167,7 @@ fn confirm(prompt: &str, yes: bool) -> bool {
|
|||
if yes {
|
||||
return true;
|
||||
}
|
||||
print!("{} [y/N] ", prompt);
|
||||
print!("{prompt} [y/N] ");
|
||||
io::stdout().flush().unwrap();
|
||||
let mut input = String::new();
|
||||
io::stdin().read_line(&mut input).unwrap();
|
||||
|
|
@ -220,7 +236,7 @@ async fn main() -> Result<()> {
|
|||
|
||||
CommandOptions::Remove { index } => {
|
||||
if confirm(
|
||||
&format!("This will remove item at index {:?}. Continue?", index),
|
||||
&format!("This will remove item at index {index:?}. Continue?"),
|
||||
cli.yes,
|
||||
) {
|
||||
Commands::remove_item(index, Some(&socket_path)).await?;
|
||||
|
|
@ -262,4 +278,3 @@ async fn main() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
//! # Examples
|
||||
//!
|
||||
//! ```rust
|
||||
//! use mrc::commands::Commands;
|
||||
//! use mpvrc::commands::Commands;
|
||||
//!
|
||||
//! # async fn example() -> mrc::Result<()> {
|
||||
//! # async fn example() -> mpvrc::Result<()> {
|
||||
//! // Play media at a specific playlist index
|
||||
//! Commands::play(Some(0), None).await;
|
||||
//!
|
||||
|
|
@ -39,6 +39,10 @@ impl Commands {
|
|||
/// # Arguments
|
||||
///
|
||||
/// * `index` - Optional playlist index to play from
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn play(index: Option<usize>, socket_path: Option<&str>) -> Result<()> {
|
||||
if let Some(idx) = index {
|
||||
info!("Playing media at index: {}", idx);
|
||||
|
|
@ -50,6 +54,10 @@ impl Commands {
|
|||
}
|
||||
|
||||
/// Pauses the currently playing media.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn pause(socket_path: Option<&str>) -> Result<()> {
|
||||
info!("Pausing playback");
|
||||
set_property("pause", &json!(true), socket_path).await?;
|
||||
|
|
@ -59,6 +67,10 @@ impl Commands {
|
|||
/// Stops playback and quits MPV.
|
||||
///
|
||||
/// This is a destructive operation that will terminate the MPV process.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn stop(socket_path: Option<&str>) -> Result<()> {
|
||||
info!("Stopping playback and quitting MPV");
|
||||
quit(socket_path).await?;
|
||||
|
|
@ -66,6 +78,10 @@ impl Commands {
|
|||
}
|
||||
|
||||
/// Advances to the next item in the playlist.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn next(socket_path: Option<&str>) -> Result<()> {
|
||||
info!("Skipping to next item in the playlist");
|
||||
playlist_next(socket_path).await?;
|
||||
|
|
@ -73,6 +89,10 @@ impl Commands {
|
|||
}
|
||||
|
||||
/// Goes back to the previous item in the playlist.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn prev(socket_path: Option<&str>) -> Result<()> {
|
||||
info!("Skipping to previous item in the playlist");
|
||||
playlist_prev(socket_path).await?;
|
||||
|
|
@ -84,6 +104,10 @@ impl Commands {
|
|||
/// # Arguments
|
||||
///
|
||||
/// * `seconds` - The position in seconds to seek to
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn seek_to(seconds: f64, socket_path: Option<&str>) -> Result<()> {
|
||||
info!("Seeking to {} seconds", seconds);
|
||||
seek(seconds, socket_path).await?;
|
||||
|
|
@ -96,6 +120,10 @@ impl Commands {
|
|||
///
|
||||
/// * `from_index` - The current index of the item
|
||||
/// * `to_index` - The desired new index for the item
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn move_item(
|
||||
from_index: usize,
|
||||
to_index: usize,
|
||||
|
|
@ -113,6 +141,10 @@ impl Commands {
|
|||
/// # Arguments
|
||||
///
|
||||
/// * `index` - Optional specific index to remove
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn remove_item(index: Option<usize>, socket_path: Option<&str>) -> Result<()> {
|
||||
if let Some(idx) = index {
|
||||
info!("Removing item at index {}", idx);
|
||||
|
|
@ -125,6 +157,10 @@ impl Commands {
|
|||
}
|
||||
|
||||
/// Clears the entire playlist.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn clear_playlist(socket_path: Option<&str>) -> Result<()> {
|
||||
info!("Clearing the playlist");
|
||||
playlist_clear(socket_path).await?;
|
||||
|
|
@ -132,6 +168,10 @@ impl Commands {
|
|||
}
|
||||
|
||||
/// Lists all items in the playlist.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn list_playlist(socket_path: Option<&str>) -> Result<()> {
|
||||
info!("Listing playlist items");
|
||||
if let Some(data) = get_property("playlist", socket_path).await? {
|
||||
|
|
@ -145,6 +185,10 @@ impl Commands {
|
|||
/// # Arguments
|
||||
///
|
||||
/// * `filenames` - List of file paths to add
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if no files are provided or socket communication fails.
|
||||
pub async fn add_files(filenames: &[String], socket_path: Option<&str>) -> Result<()> {
|
||||
if filenames.is_empty() {
|
||||
let e = "No files provided to add to the playlist";
|
||||
|
|
@ -163,6 +207,10 @@ impl Commands {
|
|||
/// # Arguments
|
||||
///
|
||||
/// * `filenames` - List of file paths to replace the playlist with
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn replace_playlist(filenames: &[String], socket_path: Option<&str>) -> Result<()> {
|
||||
info!("Replacing current playlist with {} files", filenames.len());
|
||||
if let Some(first_file) = filenames.first() {
|
||||
|
|
@ -179,6 +227,10 @@ impl Commands {
|
|||
/// # Arguments
|
||||
///
|
||||
/// * `properties` - List of property names to fetch
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn get_properties(properties: &[String], socket_path: Option<&str>) -> Result<()> {
|
||||
info!("Fetching properties: {:?}", properties);
|
||||
for property in properties {
|
||||
|
|
@ -194,6 +246,10 @@ impl Commands {
|
|||
/// # Arguments
|
||||
///
|
||||
/// * `property` - The property name to fetch
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn get_single_property(property: &str, socket_path: Option<&str>) -> Result<()> {
|
||||
if let Some(data) = get_property(property, socket_path).await? {
|
||||
println!("{property}: {data}");
|
||||
|
|
@ -207,6 +263,10 @@ impl Commands {
|
|||
///
|
||||
/// * `property` - The property name to set
|
||||
/// * `value` - The JSON value to set
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails.
|
||||
pub async fn set_single_property(
|
||||
property: &str,
|
||||
value: &serde_json::Value,
|
||||
|
|
@ -236,15 +296,15 @@ fn print_playlist(data: &serde_json::Value) {
|
|||
.unwrap_or("unknown");
|
||||
let current = item
|
||||
.get("current")
|
||||
.and_then(|v| v.as_bool())
|
||||
.and_then(serde_json::Value::as_bool)
|
||||
.unwrap_or(false);
|
||||
|
||||
let marker = if current { ">" } else { " " };
|
||||
println!("{} {:3} | {} | {}", marker, i, title, filename);
|
||||
println!("{marker} {i:3} | {title} | {filename}");
|
||||
}
|
||||
} else {
|
||||
let pretty_json = serde_json::to_string_pretty(data).unwrap_or_else(|_| data.to_string());
|
||||
println!("{}", pretty_json);
|
||||
println!("{pretty_json}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -274,4 +334,4 @@ mod tests {
|
|||
let result = Commands::get_properties(&[], None).await;
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,23 @@
|
|||
use crate::commands::Commands;
|
||||
use crate::{MrcError, Result};
|
||||
use rustyline::config::EditMode;
|
||||
use rustyline::{Cmd, Config, Editor, KeyEvent};
|
||||
use std::{io::Error, path::PathBuf};
|
||||
|
||||
use rustyline::{Cmd, Config, Editor, KeyEvent, config::EditMode};
|
||||
use serde_json::json;
|
||||
use std::io::Error;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::{MrcError, Result, commands::Commands};
|
||||
|
||||
pub struct InteractiveMode;
|
||||
|
||||
impl InteractiveMode {
|
||||
/// Runs the interactive mode REPL.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the socket communication fails or the REPL encounters an error.
|
||||
pub async fn run(socket_path: Option<&str>) -> Result<()> {
|
||||
let hist_path = dirs::data_local_dir()
|
||||
.map(|p| p.join("mrc").join("history.txt"))
|
||||
.unwrap_or_else(|| PathBuf::from("history.txt"));
|
||||
let hist_path = dirs::data_local_dir().map_or_else(
|
||||
|| PathBuf::from("history.txt"),
|
||||
|p| p.join("mpvrc").join("history.txt"),
|
||||
);
|
||||
|
||||
let config = Config::builder().edit_mode(EditMode::Vi).build();
|
||||
|
||||
|
|
@ -48,19 +53,18 @@ impl InteractiveMode {
|
|||
}
|
||||
|
||||
if let Err(e) = Self::process_command(trimmed, socket_path).await {
|
||||
eprintln!("Error: {}", e);
|
||||
eprintln!("Error: {e}");
|
||||
}
|
||||
}
|
||||
Err(rustyline::error::ReadlineError::Interrupted) => {
|
||||
println!("(interrupted)");
|
||||
continue;
|
||||
}
|
||||
Err(rustyline::error::ReadlineError::Eof) => {
|
||||
println!("Exiting interactive mode.");
|
||||
break;
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("Error: {:?}", err);
|
||||
eprintln!("Error: {err:?}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -95,7 +99,7 @@ impl InteractiveMode {
|
|||
];
|
||||
|
||||
for (command, description) in commands {
|
||||
println!(" {:<22} - {}", command, description);
|
||||
println!(" {command:<22} - {description}");
|
||||
}
|
||||
|
||||
println!("\nKeyboard shortcuts:");
|
||||
|
|
@ -116,7 +120,7 @@ impl InteractiveMode {
|
|||
if let Ok(idx) = index.parse::<usize>() {
|
||||
Commands::play(Some(idx), socket_path).await?;
|
||||
} else {
|
||||
println!("Invalid index: {}", index);
|
||||
println!("Invalid index: {index}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +144,7 @@ impl InteractiveMode {
|
|||
if let Ok(sec) = seconds.parse::<i32>() {
|
||||
Commands::seek_to(sec.into(), socket_path).await?;
|
||||
} else {
|
||||
println!("Invalid seconds: {}", seconds);
|
||||
println!("Invalid seconds: {seconds}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +157,8 @@ impl InteractiveMode {
|
|||
}
|
||||
|
||||
["add", files @ ..] => {
|
||||
let file_strings: Vec<String> = files.iter().map(|s| s.to_string()).collect();
|
||||
let file_strings: Vec<String> =
|
||||
files.iter().map(std::string::ToString::to_string).collect();
|
||||
if file_strings.is_empty() {
|
||||
println!("No files provided to add to the playlist");
|
||||
} else {
|
||||
|
|
@ -172,7 +177,7 @@ impl InteractiveMode {
|
|||
}
|
||||
|
||||
_ => {
|
||||
println!("Unknown command: {}", input);
|
||||
println!("Unknown command: {input}");
|
||||
println!("Type 'help' for a list of available commands.");
|
||||
}
|
||||
}
|
||||
|
|
@ -180,4 +185,3 @@ impl InteractiveMode {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
28
src/lib.rs
28
src/lib.rs
|
|
@ -15,7 +15,7 @@
|
|||
//! ```rust
|
||||
//! use serde_json::json;
|
||||
//! use tokio;
|
||||
//! use mrc::{send_ipc_command, playlist_next, set_property};
|
||||
//! use mpvrc::{send_ipc_command, playlist_next, set_property};
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
//! async fn main() {
|
||||
|
|
@ -175,10 +175,10 @@ async fn read_response(socket: &mut UnixStream) -> Result<Value> {
|
|||
debug!("Parsed IPC response: {:?}", json_response);
|
||||
|
||||
// Check if MPV returned an error
|
||||
if let Some(error) = json_response.get("error").and_then(|e| e.as_str()) {
|
||||
if !error.is_empty() {
|
||||
return Err(MrcError::MpvError(error.to_string()));
|
||||
}
|
||||
if let Some(error) = json_response.get("error").and_then(|e| e.as_str())
|
||||
&& !error.is_empty()
|
||||
{
|
||||
return Err(MrcError::MpvError(error.to_string()));
|
||||
}
|
||||
|
||||
Ok(json_response)
|
||||
|
|
@ -389,10 +389,7 @@ pub async fn playlist_remove(
|
|||
index: Option<usize>,
|
||||
socket_path: Option<&str>,
|
||||
) -> Result<Option<Value>> {
|
||||
let args = match index {
|
||||
Some(idx) => vec![json!(idx)],
|
||||
None => vec![json!("current")],
|
||||
};
|
||||
let args = index.map_or_else(|| vec![json!("current")], |idx| vec![json!(idx)]);
|
||||
send_ipc_command(MpvCommand::PlaylistRemove.as_str(), &args, socket_path).await
|
||||
}
|
||||
|
||||
|
|
@ -469,20 +466,20 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_mrc_error_display() {
|
||||
fn test_mpvrc_error_display() {
|
||||
let error = MrcError::InvalidInput("test message".to_string());
|
||||
assert_eq!(error.to_string(), "invalid input: test message");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mrc_error_from_io_error() {
|
||||
fn test_mpvrc_error_from_io_error() {
|
||||
let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
|
||||
let mrc_error = MrcError::from(io_error);
|
||||
assert!(matches!(mrc_error, MrcError::ConnectionError(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mrc_error_from_json_error() {
|
||||
fn test_mpvrc_error_from_json_error() {
|
||||
let json_error = serde_json::from_str::<serde_json::Value>("invalid json").unwrap_err();
|
||||
let mrc_error = MrcError::from(json_error);
|
||||
assert!(matches!(mrc_error, MrcError::ParseError(_)));
|
||||
|
|
@ -548,12 +545,13 @@ mod tests {
|
|||
#[test]
|
||||
fn test_mpv_command_debug() {
|
||||
let cmd = MpvCommand::SetProperty;
|
||||
let debug_str = format!("{:?}", cmd);
|
||||
let debug_str = format!("{cmd:?}");
|
||||
assert_eq!(debug_str, "SetProperty");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_result_type_alias() {
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn test_function() -> Result<String> {
|
||||
Ok("test".to_string())
|
||||
}
|
||||
|
|
@ -567,7 +565,7 @@ mod tests {
|
|||
fn test_error_variants_exhaustive() {
|
||||
// Test that all error variants are properly handled
|
||||
let errors = vec![
|
||||
MrcError::ConnectionError(std::io::Error::new(std::io::ErrorKind::Other, "test")),
|
||||
MrcError::ConnectionError(std::io::Error::other("test")),
|
||||
MrcError::ParseError(serde_json::from_str::<serde_json::Value>("").unwrap_err()),
|
||||
MrcError::SocketTimeout(10),
|
||||
MrcError::MpvError("test".to_string()),
|
||||
|
|
@ -584,7 +582,7 @@ mod tests {
|
|||
// Ensure all errors implement Display
|
||||
let _ = error.to_string();
|
||||
// Ensure all errors implement Debug
|
||||
let _ = format!("{:?}", error);
|
||||
let _ = format!("{error:?}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::{env, io::Read, sync::Arc};
|
||||
|
||||
use clap::Parser;
|
||||
use mrc::{MrcError, Result as MrcResult, SOCKET_PATH, commands::Commands};
|
||||
use mpvrc::{MrcError, Result as MrcResult, SOCKET_PATH, commands::Commands};
|
||||
use native_tls::{Identity, TlsAcceptor as NativeTlsAcceptor};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio_native_tls::TlsAcceptor;
|
||||
|
|
@ -50,19 +50,14 @@ async fn handle_connection(
|
|||
let token_line = headers
|
||||
.iter()
|
||||
.find(|&&line| line.starts_with("Authorization:"));
|
||||
let token = match token_line {
|
||||
Some(line) => line.split(" ").nth(1).unwrap_or_default(),
|
||||
None => "",
|
||||
};
|
||||
let token = token_line.map_or("", |line| line.split(' ').nth(1).unwrap_or_default());
|
||||
|
||||
let auth_token = match env::var("AUTH_TOKEN") {
|
||||
Ok(token) => token,
|
||||
Err(_) => {
|
||||
warn!("AUTH_TOKEN environment variable not set. Authentication disabled.");
|
||||
let response = "HTTP/1.1 401 Unauthorized\r\nContent-Length: 29\r\n\r\nAuthentication token not set\n";
|
||||
stream.write_all(response.as_bytes()).await?;
|
||||
return Ok(());
|
||||
}
|
||||
let Ok(auth_token) = env::var("AUTH_TOKEN") else {
|
||||
warn!("AUTH_TOKEN environment variable not set. Authentication disabled.");
|
||||
let response =
|
||||
"HTTP/1.1 401 Unauthorized\r\nContent-Length: 29\r\n\r\nAuthentication token not set\n";
|
||||
stream.write_all(response.as_bytes()).await?;
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
if token.is_empty() || token != auth_token {
|
||||
|
|
@ -98,7 +93,7 @@ async fn handle_connection(
|
|||
Ok(response) => ("200 OK", response),
|
||||
Err(e) => {
|
||||
error!("Error processing command '{}': {}", command, e);
|
||||
("400 Bad Request", format!("Error: {}\n", e))
|
||||
("400 Bad Request", format!("Error: {e}\n"))
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -131,9 +126,9 @@ async fn process_command(command: &str, socket_path: &str) -> MrcResult<String>
|
|||
["play", index] => {
|
||||
if let Ok(idx) = index.parse::<usize>() {
|
||||
Commands::play(Some(idx), Some(socket_path)).await?;
|
||||
Ok(format!("Playing from index {}\n", idx))
|
||||
Ok(format!("Playing from index {idx}\n"))
|
||||
} else {
|
||||
Err(MrcError::InvalidInput(format!("Invalid index: {}", index)))
|
||||
Err(MrcError::InvalidInput(format!("Invalid index: {index}")))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,11 +150,10 @@ async fn process_command(command: &str, socket_path: &str) -> MrcResult<String>
|
|||
["seek", seconds] => {
|
||||
if let Ok(sec) = seconds.parse::<f64>() {
|
||||
Commands::seek_to(sec, Some(socket_path)).await?;
|
||||
Ok(format!("Seeking to {} seconds\n", sec))
|
||||
Ok(format!("Seeking to {sec} seconds\n"))
|
||||
} else {
|
||||
Err(MrcError::InvalidInput(format!(
|
||||
"Invalid seconds: {}",
|
||||
seconds
|
||||
"Invalid seconds: {seconds}"
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
|
@ -169,11 +163,11 @@ async fn process_command(command: &str, socket_path: &str) -> MrcResult<String>
|
|||
Ok("Cleared playlist\n".to_string())
|
||||
}
|
||||
|
||||
["list"] => match mrc::get_property("playlist", Some(socket_path)).await? {
|
||||
["list"] => match mpvrc::get_property("playlist", Some(socket_path)).await? {
|
||||
Some(data) => {
|
||||
let pretty_json =
|
||||
serde_json::to_string_pretty(&data).map_err(MrcError::ParseError)?;
|
||||
Ok(format!("Playlist: {}\n", pretty_json))
|
||||
Ok(format!("Playlist: {pretty_json}\n"))
|
||||
}
|
||||
None => Ok("Playlist is empty\n".to_string()),
|
||||
},
|
||||
|
|
@ -216,7 +210,7 @@ async fn main() -> MrcResult<()> {
|
|||
);
|
||||
return Err(MrcError::ConnectionError(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
format!("MPV socket not found at '{}'", socket_path),
|
||||
format!("MPV socket not found at '{socket_path}'"),
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue