pub(crate) enum CommandOptions {
+Show 14 variants
Play {
+ index: Option<usize>,
+ },
+ Pause,
+ Stop,
+ Next,
+ Prev,
+ Seek {
+ seconds: i32,
+ },
+ Move {
+ index1: usize,
+ index2: usize,
+ },
+ Remove {
+ index: Option<usize>,
+ },
+ Clear,
+ List,
+ Add {
+ filenames: Vec<String>,
+ },
+ Replace {
+ filenames: Vec<String>,
+ },
+ Prop {
+ properties: Vec<String>,
+ },
+ Interactive,
+}Play media at the specified index in the playlist
+Pause the currently playing media
+Stop the playback and quit MPV
+Skip to the next item in the playlist
+Skip to the previous item in the playlist
+Seek to a specific position in the currently playing media
+Move an item in the playlist from one index to another
+Remove an item from the playlist
+If invoked while playlist has no entries, or if the only entry +is the active video, then this will exit MPV.
+Clear the entire playlist
+List all the items in the playlist
+Add files to the playlist
+Needs at least one file to be passed.
+Replace the current playlist with new files
+Fetch properties of the current playback or playlist
+Enter interactive mode to send commands to MPV IPC
+ArgMatches to self.ArgMatches to self.Command] so it can instantiate Self via
+[FromArgMatches::from_arg_matches_mut] Read moreCommand] so it can instantiate self via
+[FromArgMatches::update_from_arg_matches_mut] Read moreSelf can parse a specific subcommandSubscriber to this type, returning a
+[WithDispatch] wrapper. Read morepub(crate) struct Cli {
+ pub(crate) debug: bool,
+ pub(crate) command: CommandOptions,
+}debug: bool§command: CommandOptionsArgGroup::id][crate::ArgGroup::id] for this set of argumentsCommand] so it can instantiate Self via
+[FromArgMatches::from_arg_matches_mut] Read moreCommand] so it can instantiate self via
+[FromArgMatches::update_from_arg_matches_mut] Read moreArgMatches to self.ArgMatches to self.Subscriber to this type, returning a
+[WithDispatch] wrapper. Read morepub enum MpvCommand {
+ SetProperty,
+ PlaylistNext,
+ PlaylistPrev,
+ Seek,
+ Quit,
+ PlaylistMove,
+ PlaylistRemove,
+ PlaylistClear,
+ GetProperty,
+ LoadFile,
+}Represents common MPV commands.
+This enum provides variants for frequently used MPV commands, which can be converted to their
+string equivalents using the as_str method.
Returns an error if the connection to the socket fails or the command execution encounters issues.
+Sets a property to a specified value in MPV.
+Moves to the next item in the playlist.
+Moves to the previous item in the playlist.
+Seeks to a specific time in the current media.
+Quits the MPV application.
+Moves an item in the playlist from one index to another.
+Removes an item from the playlist.
+Clears all items from the playlist.
+Retrieves the value of a property in MPV.
+Loads a file into MPV.
+Subscriber to this type, returning a
+[WithDispatch] wrapper. Read morepub async fn get_property(
+ property: &str,
+ socket_path: Option<&str>,
+) -> Result<Option<Value>>Sends the get_property command to retrieve a property value from MPV.
property: The name of the property to retrieve.socket_path: An optional custom socket path.A Result containing the response data.
Returns an error if the connection to the socket fails or the command execution encounters issues.
+pub async fn loadfile(
+ filename: &str,
+ append: bool,
+ socket_path: Option<&str>,
+) -> Result<Option<Value>>Sends the loadfile command to load a file into MPV.
filename: The name of the file to load.append: Whether to append the file to the playlist (true) or replace the current file (false).socket_path: An optional custom socket path.A Result containing the response data.
Returns an error if the connection to the socket fails or the command execution encounters issues.
+pub async fn playlist_move(
+ from_index: usize,
+ to_index: usize,
+ socket_path: Option<&str>,
+) -> Result<Option<Value>>Sends the playlist-move command to move a playlist item from one index to another.
from_index: The index of the item to move.to_index: The index to move the item to.socket_path: An optional custom socket path.A Result containing the response data.
Returns an error if the connection to the socket fails or the command execution encounters issues.
+pub async fn playlist_remove(
+ index: Option<usize>,
+ socket_path: Option<&str>,
+) -> Result<Option<Value>>Sends the playlist-remove command to remove an item from the playlist.
index: The index of the item to remove, or None to remove the current item.socket_path: An optional custom socket path.A Result containing the response data.
Returns an error if the connection to the socket fails or the command execution encounters issues.
+pub async fn seek(
+ seconds: f64,
+ socket_path: Option<&str>,
+) -> Result<Option<Value>>Sends the seek command to seek the media playback by a given number of seconds.
seconds: The number of seconds to seek.socket_path: An optional custom socket path.A Result containing the response data.
Returns an error if the connection to the socket fails or the command execution encounters issues.
+pub async fn send_ipc_command(
+ command: &str,
+ args: &[Value],
+ socket_path: Option<&str>,
+) -> Result<Option<Value>>Sends a generic IPC command to the specified socket and returns the parsed response data.
+command: The name of the command to send to MPV.args: A slice of Value arguments to include in the command.socket_path: An optional custom path to the MPV IPC socket. If None, the default path is used.A Result containing an Option<Value> with the parsed response data if successful.
Returns an error if the connection to the socket fails or if the response cannot be parsed.
+pub async fn set_property(
+ property: &str,
+ value: &Value,
+ socket_path: Option<&str>,
+) -> Result<Option<Value>>Sends the set_property command to MPV to change a property value.
property: The name of the property to set.value: The new value to assign to the property.socket_path: An optional custom socket path.A Result containing the response data.
Returns an error if the connection to the socket fails or the command execution encounters issues.
+MRC +A library for interacting with the MPV media player using its JSON IPC (Inter-Process Communication) protocol.
+This crate provides a set of utilities to communicate with MPV’s IPC socket, enabling you to send commands +and retrieve responses in a structured format.
+set_property, seek, and playlist-nextuse serde_json::json;
+use tokio;
+use mrc::{send_ipc_command, playlist_next, set_property};
+
+#[tokio::main]
+async fn main() {
+ let result = playlist_next(None).await;
+ match result {
+ Ok(response) => println!("Playlist moved to next: {:?}", response),
+ Err(err) => eprintln!("Error: {:?}", err),
+ }
+
+ let property_result = set_property("volume", &json!(50), None).await;
+ match property_result {
+ Ok(response) => println!("Volume set: {:?}", response),
+ Err(err) => eprintln!("Error: {:?}", err),
+ }
+}SOCKET_PATHDefault path for the MPV IPC socket: /tmp/mpvsocket
get_property command to retrieve a property value from MPV.loadfile command to load a file into MPV.playlist-clear command to clear the playlist.playlist-move command to move a playlist item from one index to another.playlist-next command to move to the next playlist item.playlist-prev command to move to the previous playlist item.playlist-remove command to remove an item from the playlist.quit command to terminate MPV.seek command to seek the media playback by a given number of seconds.set_property command to MPV to change a property value.U::from(self).\nCalls U::from(self).\nThe filenames of the files to add\nThe filenames of the files to replace the playlist with\nThe index of the media to play\nThe index of the item to remove (optional)\nThe index of the item to move\nThe index to move the item to\nThe properties to fetch\nThe number of seconds to seek to")
\ No newline at end of file
diff --git a/search.desc/mrc/mrc-desc-0-.js b/search.desc/mrc/mrc-desc-0-.js
new file mode 100644
index 00000000..aebd50c2
--- /dev/null
+++ b/search.desc/mrc/mrc-desc-0-.js
@@ -0,0 +1 @@
+searchState.loadedDescShard("mrc", 0, "MRC A library for interacting with the MPV media player …\nRetrieves the value of a property in MPV.\nLoads a file into MPV.\nRepresents common MPV commands.\nClears all items from the playlist.\nMoves an item in the playlist from one index to another.\nMoves to the next item in the playlist.\nMoves to the previous item in the playlist.\nRemoves an item from the playlist.\nQuits the MPV application.\nSeeks to a specific time in the current media.\nSets a property to a specified value in MPV.\nConverts MPV commands to their string equivalents.\nReturns the argument unchanged.\nSends the get_property command to retrieve a property …\nCalls U::from(self).\nSends the loadfile command to load a file into MPV.\nSends the playlist-clear command to clear the playlist.\nSends the playlist-move command to move a playlist item …\nSends the playlist-next command to move to the next …\nSends the playlist-prev command to move to the previous …\nSends the playlist-remove command to remove an item from …\nSends the quit command to terminate MPV.\nSends the seek command to seek the media playback by a …\nSends a generic IPC command to the specified socket and …\nSends the set_property command to MPV to change a property …")
\ No newline at end of file
diff --git a/search.desc/server/server-desc-0-.js b/search.desc/server/server-desc-0-.js
new file mode 100644
index 00000000..c4a2bfb8
--- /dev/null
+++ b/search.desc/server/server-desc-0-.js
@@ -0,0 +1 @@
+searchState.loadedDescShard("server", 0, "The IP address and port to bind the server to\nReturns the argument unchanged.\nCalls U::from(self).\nPath to MPV IPC socket")
\ No newline at end of file
diff --git a/server/all.html b/server/all.html
new file mode 100644
index 00000000..aff4217d
--- /dev/null
+++ b/server/all.html
@@ -0,0 +1 @@
+pub(crate) struct Config {
+ pub(crate) bind: String,
+ pub(crate) socket: String,
+}bind: StringThe IP address and port to bind the server to
+socket: StringPath to MPV IPC socket
+ArgGroup::id][crate::ArgGroup::id] for this set of argumentsCommand] so it can instantiate Self via
+[FromArgMatches::from_arg_matches_mut] Read moreCommand] so it can instantiate self via
+[FromArgMatches::update_from_arg_matches_mut] Read moreArgMatches to self.ArgMatches to self.Subscriber to this type, returning a
+[WithDispatch] wrapper. Read more1use clap::{Parser, Subcommand};
+2use mrc::set_property;
+3use mrc::SOCKET_PATH;
+4use mrc::{
+5 get_property, loadfile, playlist_clear, playlist_move, playlist_next, playlist_prev,
+6 playlist_remove, quit, seek,
+7};
+8use serde_json::json;
+9use std::io::{self, Write};
+10use std::path::PathBuf;
+11use tracing::{debug, error, info};
+12
+13#[derive(Parser)]
+14#[command(author, version, about)]
+15struct Cli {
+16 #[arg(short, long, global = true)]
+17 debug: bool,
+18
+19 #[command(subcommand)]
+20 command: CommandOptions,
+21}
+22
+23#[derive(Subcommand)]
+24enum CommandOptions {
+25 /// Play media at the specified index in the playlist
+26 Play {
+27 /// The index of the media to play
+28 index: Option<usize>,
+29 },
+30
+31 /// Pause the currently playing media
+32 Pause,
+33
+34 /// Stop the playback and quit MPV
+35 Stop,
+36
+37 /// Skip to the next item in the playlist
+38 Next,
+39
+40 /// Skip to the previous item in the playlist
+41 Prev,
+42
+43 /// Seek to a specific position in the currently playing media
+44 Seek {
+45 /// The number of seconds to seek to
+46 seconds: i32,
+47 },
+48
+49 /// Move an item in the playlist from one index to another
+50 Move {
+51 /// The index of the item to move
+52 index1: usize,
+53
+54 /// The index to move the item to
+55 index2: usize,
+56 },
+57
+58 /// Remove an item from the playlist
+59 ///
+60 /// If invoked while playlist has no entries, or if the only entry
+61 /// is the active video, then this will exit MPV.
+62 Remove {
+63 /// The index of the item to remove (optional)
+64 index: Option<usize>,
+65 },
+66
+67 /// Clear the entire playlist
+68 Clear,
+69
+70 /// List all the items in the playlist
+71 List,
+72
+73 /// Add files to the playlist
+74 ///
+75 /// Needs at least one file to be passed.
+76 Add {
+77 /// The filenames of the files to add
+78 filenames: Vec<String>,
+79 },
+80
+81 /// Replace the current playlist with new files
+82 Replace {
+83 /// The filenames of the files to replace the playlist with
+84 filenames: Vec<String>,
+85 },
+86
+87 /// Fetch properties of the current playback or playlist
+88 Prop {
+89 /// The properties to fetch
+90 properties: Vec<String>,
+91 },
+92
+93 /// Enter interactive mode to send commands to MPV IPC
+94 Interactive,
+95}
+96
+97#[tokio::main]
+98async fn main() -> io::Result<()> {
+99 tracing_subscriber::fmt::init();
+100 let cli = Cli::parse();
+101
+102 if !PathBuf::from(SOCKET_PATH).exists() {
+103 debug!(SOCKET_PATH);
+104 error!("Error: MPV socket not found. Is MPV running?");
+105 return Ok(());
+106 }
+107
+108 match cli.command {
+109 CommandOptions::Play { index } => {
+110 if let Some(idx) = index {
+111 info!("Playing media at index: {}", idx);
+112 set_property("playlist-pos", &json!(idx), None).await?;
+113 }
+114 info!("Unpausing playback");
+115 set_property("pause", &json!(false), None).await?;
+116 }
+117
+118 CommandOptions::Pause => {
+119 info!("Pausing playback");
+120 set_property("pause", &json!(true), None).await?;
+121 }
+122
+123 CommandOptions::Stop => {
+124 info!("Stopping playback and quitting MPV");
+125 quit(None).await?;
+126 }
+127
+128 CommandOptions::Next => {
+129 info!("Skipping to next item in the playlist");
+130 playlist_next(None).await?;
+131 }
+132
+133 CommandOptions::Prev => {
+134 info!("Skipping to previous item in the playlist");
+135 playlist_prev(None).await?;
+136 }
+137
+138 CommandOptions::Seek { seconds } => {
+139 info!("Seeking to {} seconds", seconds);
+140 seek(seconds.into(), None).await?;
+141 }
+142
+143 CommandOptions::Move { index1, index2 } => {
+144 info!("Moving item from index {} to {}", index1, index2);
+145 playlist_move(index1, index2, None).await?;
+146 }
+147
+148 CommandOptions::Remove { index } => {
+149 if let Some(idx) = index {
+150 info!("Removing item at index {}", idx);
+151 playlist_remove(Some(idx), None).await?;
+152 } else {
+153 info!("Removing current item from playlist");
+154 playlist_remove(None, None).await?;
+155 }
+156 }
+157
+158 CommandOptions::Clear => {
+159 info!("Clearing the playlist");
+160 playlist_clear(None).await?;
+161 }
+162
+163 CommandOptions::List => {
+164 info!("Listing playlist items");
+165 if let Some(data) = get_property("playlist", None).await? {
+166 println!("{}", serde_json::to_string_pretty(&data)?);
+167 }
+168 }
+169
+170 CommandOptions::Add { filenames } => {
+171 if filenames.is_empty() {
+172 let e = "No files provided to add to the playlist";
+173 error!("{}", e);
+174 return Err(io::Error::new(io::ErrorKind::InvalidInput, e));
+175 }
+176
+177 info!("Adding {} files to the playlist", filenames.len());
+178 for filename in filenames {
+179 loadfile(&filename, true, None).await?;
+180 }
+181 }
+182
+183 CommandOptions::Replace { filenames } => {
+184 info!("Replacing current playlist with {} files", filenames.len());
+185 if let Some(first_file) = filenames.first() {
+186 loadfile(first_file, false, None).await?;
+187 for filename in &filenames[1..] {
+188 loadfile(filename, true, None).await?;
+189 }
+190 }
+191 }
+192
+193 CommandOptions::Prop { properties } => {
+194 info!("Fetching properties: {:?}", properties);
+195 for property in properties {
+196 if let Some(data) = get_property(&property, None).await? {
+197 println!("{property}: {data}");
+198 }
+199 }
+200 }
+201
+202 CommandOptions::Interactive => {
+203 println!("Entering interactive mode. Type 'exit' to quit.");
+204 let stdin = io::stdin();
+205 let mut stdout = io::stdout();
+206
+207 loop {
+208 print!("mpv> ");
+209 stdout.flush()?;
+210 let mut input = String::new();
+211 stdin.read_line(&mut input)?;
+212 let trimmed = input.trim();
+213
+214 if trimmed.eq_ignore_ascii_case("exit") {
+215 println!("Exiting interactive mode.");
+216 break;
+217 }
+218
+219 // I don't like this either, but it looks cleaner than a multi-line
+220 // print macro just cramped in here.
+221 let commands = vec![
+222 (
+223 "play [index]",
+224 "Play or unpause playback, optionally at the specified index",
+225 ),
+226 ("pause", "Pause playback"),
+227 ("stop", "Stop playback and quit MPV"),
+228 ("next", "Skip to the next item in the playlist"),
+229 ("prev", "Skip to the previous item in the playlist"),
+230 ("seek <seconds>", "Seek to the specified position"),
+231 ("clear", "Clear the playlist"),
+232 ("list", "List all items in the playlist"),
+233 ("add <files>", "Add files to the playlist"),
+234 ("get <property>", "Get the specified property"),
+235 (
+236 "set <property> <value>",
+237 "Set the specified property to a value",
+238 ),
+239 ("exit", "Quit interactive mode"),
+240 ];
+241
+242 if trimmed.eq_ignore_ascii_case("help") {
+243 println!("Valid commands:");
+244 for (command, description) in commands {
+245 println!(" {} - {}", command, description);
+246 }
+247 continue;
+248 }
+249
+250 let parts: Vec<&str> = trimmed.split_whitespace().collect();
+251 match parts.as_slice() {
+252 ["play"] => {
+253 info!("Unpausing playback");
+254 set_property("pause", &json!(false), None).await?;
+255 }
+256
+257 ["play", index] => {
+258 if let Ok(idx) = index.parse::<usize>() {
+259 info!("Playing media at index: {}", idx);
+260 set_property("playlist-pos", &json!(idx), None).await?;
+261 set_property("pause", &json!(false), None).await?;
+262 } else {
+263 println!("Invalid index: {}", index);
+264 }
+265 }
+266
+267 ["pause"] => {
+268 info!("Pausing playback");
+269 set_property("pause", &json!(true), None).await?;
+270 }
+271
+272 ["stop"] => {
+273 info!("Pausing playback");
+274 quit(None).await?;
+275 }
+276
+277 ["next"] => {
+278 info!("Skipping to next item in the playlist");
+279 playlist_next(None).await?;
+280 }
+281
+282 ["prev"] => {
+283 info!("Skipping to previous item in the playlist");
+284 playlist_prev(None).await?;
+285 }
+286
+287 ["seek", seconds] => {
+288 if let Ok(sec) = seconds.parse::<i32>() {
+289 info!("Seeking to {} seconds", sec);
+290 seek(sec.into(), None).await?;
+291 } else {
+292 println!("Invalid seconds: {}", seconds);
+293 }
+294 }
+295
+296 ["clear"] => {
+297 info!("Clearing the playlist");
+298 playlist_clear(None).await?;
+299 }
+300
+301 ["list"] => {
+302 info!("Listing playlist items");
+303 if let Some(data) = get_property("playlist", None).await? {
+304 println!("{}", serde_json::to_string_pretty(&data)?);
+305 }
+306 }
+307
+308 ["add", files @ ..] => {
+309 if files.is_empty() {
+310 println!("No files provided to add to the playlist");
+311 } else {
+312 info!("Adding {} files to the playlist", files.len());
+313 for file in files {
+314 loadfile(file, true, None).await?;
+315 }
+316 }
+317 }
+318
+319 ["get", property] => {
+320 if let Some(data) = get_property(property, None).await? {
+321 println!("{property}: {data}");
+322 }
+323 }
+324
+325 ["set", property, value] => {
+326 let json_value = serde_json::from_str::<serde_json::Value>(value)
+327 .unwrap_or_else(|_| json!(value));
+328 set_property(property, &json_value, None).await?;
+329 println!("Set {property} to {value}");
+330 }
+331
+332 _ => {
+333 println!("Unknown command: {}", trimmed);
+334 println!("Valid commands: play <index>, pause, stop, next, prev, seek <seconds>, clear, list, add <files>, get <property>, set <property> <value>, exit");
+335 }
+336 }
+337 }
+338 }
+339 }
+340
+341 Ok(())
+342}