clean: add docstrings, move a few things around
This commit is contained in:
parent
60802e1158
commit
2056afe002
|
@ -1,3 +1,5 @@
|
||||||
|
//! The core API for interacting with [`Mpv`].
|
||||||
|
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
@ -13,6 +15,16 @@ use crate::{
|
||||||
Error, ErrorCode, Event,
|
Error, ErrorCode, Event,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// All possible commands that can be sent to mpv.
|
||||||
|
///
|
||||||
|
/// Not all commands are guaranteed to be implemented.
|
||||||
|
/// If something is missing, please open an issue.
|
||||||
|
///
|
||||||
|
/// You can also use the `run_command_raw` function to run commands
|
||||||
|
/// that are not implemented here.
|
||||||
|
///
|
||||||
|
/// See <https://mpv.io/manual/master/#list-of-input-commands> for
|
||||||
|
/// the upstream list of commands.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum MpvCommand {
|
pub enum MpvCommand {
|
||||||
LoadFile {
|
LoadFile {
|
||||||
|
@ -50,10 +62,12 @@ pub enum MpvCommand {
|
||||||
Unobserve(isize),
|
Unobserve(isize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper trait to keep track of the string literals that mpv expects.
|
||||||
pub(crate) trait IntoRawCommandPart {
|
pub(crate) trait IntoRawCommandPart {
|
||||||
fn into_raw_command_part(self) -> String;
|
fn into_raw_command_part(self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generic data type representing all possible data types that mpv can return.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum MpvDataType {
|
pub enum MpvDataType {
|
||||||
Array(Vec<MpvDataType>),
|
Array(Vec<MpvDataType>),
|
||||||
|
@ -66,6 +80,20 @@ pub enum MpvDataType {
|
||||||
Usize(usize),
|
Usize(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A mpv playlist.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct Playlist(pub Vec<PlaylistEntry>);
|
||||||
|
|
||||||
|
/// A single entry in the mpv playlist.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct PlaylistEntry {
|
||||||
|
pub id: usize,
|
||||||
|
pub filename: String,
|
||||||
|
pub title: String,
|
||||||
|
pub current: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Options for [`MpvCommand::LoadFile`] and [`MpvCommand::LoadList`].
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
pub enum PlaylistAddOptions {
|
pub enum PlaylistAddOptions {
|
||||||
Replace,
|
Replace,
|
||||||
|
@ -81,12 +109,7 @@ impl IntoRawCommandPart for PlaylistAddOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
/// Options for [`MpvCommand::Seek`].
|
||||||
pub enum PlaylistAddTypeOptions {
|
|
||||||
File,
|
|
||||||
Playlist,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
pub enum SeekOptions {
|
pub enum SeekOptions {
|
||||||
Relative,
|
Relative,
|
||||||
|
@ -106,17 +129,7 @@ impl IntoRawCommandPart for SeekOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
/// A trait for specifying how to extract and parse a value returned through [`Mpv::get_property`].
|
||||||
pub struct PlaylistEntry {
|
|
||||||
pub id: usize,
|
|
||||||
pub filename: String,
|
|
||||||
pub title: String,
|
|
||||||
pub current: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
||||||
pub struct Playlist(pub Vec<PlaylistEntry>);
|
|
||||||
|
|
||||||
pub trait GetPropertyTypeHandler: Sized {
|
pub trait GetPropertyTypeHandler: Sized {
|
||||||
// TODO: fix this
|
// TODO: fix this
|
||||||
#[allow(async_fn_in_trait)]
|
#[allow(async_fn_in_trait)]
|
||||||
|
@ -135,6 +148,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait for specifying how to serialize and set a value through [`Mpv::set_property`].
|
||||||
pub trait SetPropertyTypeHandler<T> {
|
pub trait SetPropertyTypeHandler<T> {
|
||||||
// TODO: fix this
|
// TODO: fix this
|
||||||
#[allow(async_fn_in_trait)]
|
#[allow(async_fn_in_trait)]
|
||||||
|
@ -169,6 +183,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The main struct for interacting with mpv.
|
||||||
|
///
|
||||||
|
/// This struct provides the core API for interacting with mpv.
|
||||||
|
/// These functions are the building blocks for the higher-level API provided by the `MpvExt` trait.
|
||||||
|
/// They can also be used directly to interact with mpv in a more flexible way, mostly returning JSON values.
|
||||||
|
///
|
||||||
|
/// The `Mpv` struct can be cloned freely, and shared anywhere.
|
||||||
|
/// It only contains a message passing channel to the tokio task that handles the IPC communication with mpv.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Mpv {
|
pub struct Mpv {
|
||||||
command_sender: mpsc::Sender<(MpvIpcCommand, oneshot::Sender<MpvIpcResponse>)>,
|
command_sender: mpsc::Sender<(MpvIpcCommand, oneshot::Sender<MpvIpcResponse>)>,
|
||||||
|
@ -226,7 +248,7 @@ impl Mpv {
|
||||||
pub async fn get_event_stream(&self) -> impl futures::Stream<Item = Result<Event, Error>> {
|
pub async fn get_event_stream(&self) -> impl futures::Stream<Item = Result<Event, Error>> {
|
||||||
tokio_stream::wrappers::BroadcastStream::new(self.broadcast_channel.subscribe()).map(
|
tokio_stream::wrappers::BroadcastStream::new(self.broadcast_channel.subscribe()).map(
|
||||||
|event| match event {
|
|event| match event {
|
||||||
Ok(event) => crate::event_parser::map_event(event),
|
Ok(event) => crate::event_parser::parse_event(event),
|
||||||
Err(_) => Err(Error(ErrorCode::ConnectError(
|
Err(_) => Err(Error(ErrorCode::ConnectError(
|
||||||
"Failed to receive event".to_string(),
|
"Failed to receive event".to_string(),
|
||||||
))),
|
))),
|
||||||
|
@ -281,7 +303,7 @@ impl Mpv {
|
||||||
/// ## Input arguments
|
/// ## Input arguments
|
||||||
///
|
///
|
||||||
/// - **command** defines the mpv command that should be executed
|
/// - **command** defines the mpv command that should be executed
|
||||||
/// - **args** a slice of &str's which define the arguments
|
/// - **args** a slice of `&str`'s which define the arguments
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -405,12 +427,12 @@ impl Mpv {
|
||||||
/// Retrieves the property value from mpv.
|
/// Retrieves the property value from mpv.
|
||||||
///
|
///
|
||||||
/// ## Supported types
|
/// ## Supported types
|
||||||
/// - String
|
/// - `String`
|
||||||
/// - bool
|
/// - `bool`
|
||||||
/// - HashMap<String, String> (e.g. for the 'metadata' property)
|
/// - `HashMap<String, String>` (e.g. for the 'metadata' property)
|
||||||
/// - Vec<PlaylistEntry> (for the 'playlist' property)
|
/// - `Vec<PlaylistEntry>` (for the 'playlist' property)
|
||||||
/// - usize
|
/// - `usize`
|
||||||
/// - f64
|
/// - `f64`
|
||||||
///
|
///
|
||||||
/// ## Input arguments
|
/// ## Input arguments
|
||||||
///
|
///
|
||||||
|
@ -472,18 +494,18 @@ impl Mpv {
|
||||||
|
|
||||||
/// # Description
|
/// # Description
|
||||||
///
|
///
|
||||||
/// Sets the mpv property _<property>_ to _<value>_.
|
/// Sets the mpv property _`<property>`_ to _`<value>`_.
|
||||||
///
|
///
|
||||||
/// ## Supported types
|
/// ## Supported types
|
||||||
/// - String
|
/// - `String`
|
||||||
/// - bool
|
/// - `bool`
|
||||||
/// - f64
|
/// - `f64`
|
||||||
/// - usize
|
/// - `usize`
|
||||||
///
|
///
|
||||||
/// ## Input arguments
|
/// ## Input arguments
|
||||||
///
|
///
|
||||||
/// - **property** defines the mpv property that should be retrieved
|
/// - **property** defines the mpv property that should be retrieved
|
||||||
/// - **value** defines the value of the given mpv property _<property>_
|
/// - **value** defines the value of the given mpv property _`<property>`_
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
//! Library specific error messages.
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// All possible errors that can occur when interacting with mpv.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum ErrorCode {
|
pub enum ErrorCode {
|
||||||
MpvError(String),
|
MpvError(String),
|
||||||
|
@ -21,6 +24,7 @@ pub enum ErrorCode {
|
||||||
ValueDoesNotContainUsize,
|
ValueDoesNotContainUsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Any error that can occur when interacting with mpv.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct Error(pub ErrorCode);
|
pub struct Error(pub ErrorCode);
|
||||||
|
|
||||||
|
@ -65,4 +69,4 @@ impl Display for ErrorCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,21 @@
|
||||||
|
//! JSON parsing logic for events from [`MpvIpc`](crate::ipc::MpvIpc).
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
use crate::{ipc::MpvIpcEvent, Error, ErrorCode, MpvDataType};
|
use crate::{ipc::MpvIpcEvent, Error, ErrorCode, MpvDataType};
|
||||||
|
|
||||||
|
/// All possible properties that can be observed through the event system.
|
||||||
|
///
|
||||||
|
/// Not all properties are guaranteed to be implemented.
|
||||||
|
/// If something is missing, please open an issue.
|
||||||
|
///
|
||||||
|
/// Otherwise, the property will be returned as a `Property::Unknown` variant.
|
||||||
|
///
|
||||||
|
/// See <https://mpv.io/manual/master/#properties> for
|
||||||
|
/// the upstream list of properties.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum Property {
|
pub enum Property {
|
||||||
Path(Option<String>),
|
Path(Option<String>),
|
||||||
|
@ -14,6 +26,15 @@ pub enum Property {
|
||||||
Unknown { name: String, data: MpvDataType },
|
Unknown { name: String, data: MpvDataType },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// All possible events that can be sent by mpv.
|
||||||
|
///
|
||||||
|
/// Not all event types are guaranteed to be implemented.
|
||||||
|
/// If something is missing, please open an issue.
|
||||||
|
///
|
||||||
|
/// Otherwise, the event will be returned as an `Event::Unimplemented` variant.
|
||||||
|
///
|
||||||
|
/// See <https://mpv.io/manual/master/#list-of-events> for
|
||||||
|
/// the upstream list of events.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Shutdown,
|
Shutdown,
|
||||||
|
@ -37,7 +58,8 @@ pub enum Event {
|
||||||
Unimplemented,
|
Unimplemented,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn map_event(raw_event: MpvIpcEvent) -> Result<Event, Error> {
|
/// Parse a highlevel [`Event`] objects from json.
|
||||||
|
pub(crate) fn parse_event(raw_event: MpvIpcEvent) -> Result<Event, Error> {
|
||||||
let MpvIpcEvent(event) = raw_event;
|
let MpvIpcEvent(event) = raw_event;
|
||||||
|
|
||||||
event
|
event
|
||||||
|
@ -66,59 +88,8 @@ pub(crate) fn map_event(raw_event: MpvIpcEvent) -> Result<Event, Error> {
|
||||||
"metadata-update" => Ok(Event::MetadataUpdate),
|
"metadata-update" => Ok(Event::MetadataUpdate),
|
||||||
"seek" => Ok(Event::Seek),
|
"seek" => Ok(Event::Seek),
|
||||||
"playback-restart" => Ok(Event::PlaybackRestart),
|
"playback-restart" => Ok(Event::PlaybackRestart),
|
||||||
"property-change" => {
|
"property-change" => parse_event_property(event)
|
||||||
let id = event
|
.and_then(|(id, property)| Ok(Event::PropertyChange { id, property })),
|
||||||
.get("id")
|
|
||||||
.ok_or(Error(ErrorCode::MissingValue))?
|
|
||||||
.as_u64()
|
|
||||||
.ok_or(Error(ErrorCode::ValueDoesNotContainUsize))?
|
|
||||||
as usize;
|
|
||||||
let property_name = event
|
|
||||||
.get("name")
|
|
||||||
.ok_or(Error(ErrorCode::MissingValue))?
|
|
||||||
.as_str()
|
|
||||||
.ok_or(Error(ErrorCode::ValueDoesNotContainString))?;
|
|
||||||
|
|
||||||
match property_name {
|
|
||||||
"path" => {
|
|
||||||
let path = event
|
|
||||||
.get("data")
|
|
||||||
.ok_or(Error(ErrorCode::MissingValue))?
|
|
||||||
.as_str()
|
|
||||||
.map(|s| s.to_string());
|
|
||||||
Ok(Event::PropertyChange {
|
|
||||||
id,
|
|
||||||
property: Property::Path(path),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
"pause" => {
|
|
||||||
let pause = event
|
|
||||||
.get("data")
|
|
||||||
.ok_or(Error(ErrorCode::MissingValue))?
|
|
||||||
.as_bool()
|
|
||||||
.ok_or(Error(ErrorCode::ValueDoesNotContainBool))?;
|
|
||||||
Ok(Event::PropertyChange {
|
|
||||||
id,
|
|
||||||
property: Property::Pause(pause),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// TODO: missing cases
|
|
||||||
_ => {
|
|
||||||
let data = event
|
|
||||||
.get("data")
|
|
||||||
.ok_or(Error(ErrorCode::MissingValue))?
|
|
||||||
.clone();
|
|
||||||
Ok(Event::PropertyChange {
|
|
||||||
id,
|
|
||||||
property: Property::Unknown {
|
|
||||||
name: property_name.to_string(),
|
|
||||||
// TODO: fix
|
|
||||||
data: MpvDataType::Double(data.as_f64().unwrap_or(0.0)),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"chapter-change" => Ok(Event::ChapterChange),
|
"chapter-change" => Ok(Event::ChapterChange),
|
||||||
"client-message" => {
|
"client-message" => {
|
||||||
let args = event
|
let args = event
|
||||||
|
@ -139,3 +110,51 @@ pub(crate) fn map_event(raw_event: MpvIpcEvent) -> Result<Event, Error> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a highlevel [`Property`] object from json, used for [`Event::PropertyChange`].
|
||||||
|
fn parse_event_property(event: &Map<String, Value>) -> Result<(usize, Property), Error> {
|
||||||
|
let id = event
|
||||||
|
.get("id")
|
||||||
|
.ok_or(Error(ErrorCode::MissingValue))?
|
||||||
|
.as_u64()
|
||||||
|
.ok_or(Error(ErrorCode::ValueDoesNotContainUsize))? as usize;
|
||||||
|
let property_name = event
|
||||||
|
.get("name")
|
||||||
|
.ok_or(Error(ErrorCode::MissingValue))?
|
||||||
|
.as_str()
|
||||||
|
.ok_or(Error(ErrorCode::ValueDoesNotContainString))?;
|
||||||
|
|
||||||
|
match property_name {
|
||||||
|
"path" => {
|
||||||
|
let path = event
|
||||||
|
.get("data")
|
||||||
|
.ok_or(Error(ErrorCode::MissingValue))?
|
||||||
|
.as_str()
|
||||||
|
.map(|s| s.to_string());
|
||||||
|
Ok((id, Property::Path(path)))
|
||||||
|
}
|
||||||
|
"pause" => {
|
||||||
|
let pause = event
|
||||||
|
.get("data")
|
||||||
|
.ok_or(Error(ErrorCode::MissingValue))?
|
||||||
|
.as_bool()
|
||||||
|
.ok_or(Error(ErrorCode::ValueDoesNotContainBool))?;
|
||||||
|
Ok((id, Property::Pause(pause)))
|
||||||
|
}
|
||||||
|
// TODO: missing cases
|
||||||
|
_ => {
|
||||||
|
let data = event
|
||||||
|
.get("data")
|
||||||
|
.ok_or(Error(ErrorCode::MissingValue))?
|
||||||
|
.clone();
|
||||||
|
Ok((
|
||||||
|
id,
|
||||||
|
Property::Unknown {
|
||||||
|
name: property_name.to_string(),
|
||||||
|
// TODO: fix
|
||||||
|
data: MpvDataType::Double(data.as_f64().unwrap_or(0.0)),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
|
//! High-level API extension for [`Mpv`].
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Error, IntoRawCommandPart, Mpv, MpvCommand, MpvDataType, Playlist, PlaylistAddOptions,
|
Error, IntoRawCommandPart, Mpv, MpvCommand, MpvDataType, Playlist, PlaylistAddOptions,
|
||||||
PlaylistAddTypeOptions, PlaylistEntry, SeekOptions,
|
PlaylistEntry, SeekOptions,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// Generic high-level command for changing a number property.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum NumberChangeOptions {
|
pub enum NumberChangeOptions {
|
||||||
Absolute,
|
Absolute,
|
||||||
|
@ -22,6 +25,7 @@ impl IntoRawCommandPart for NumberChangeOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generic high-level switch for toggling boolean properties.
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
pub enum Switch {
|
pub enum Switch {
|
||||||
On,
|
On,
|
||||||
|
@ -29,7 +33,14 @@ pub enum Switch {
|
||||||
Toggle,
|
Toggle,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `MpvExt` trait provides a set of typesafe high-level functions to interact with mpv.
|
/// Options for [`MpvExt::playlist_add`].
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
pub enum PlaylistAddTypeOptions {
|
||||||
|
File,
|
||||||
|
Playlist,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A set of typesafe high-level functions to interact with [`Mpv`].
|
||||||
// TODO: fix this
|
// TODO: fix this
|
||||||
#[allow(async_fn_in_trait)]
|
#[allow(async_fn_in_trait)]
|
||||||
pub trait MpvExt {
|
pub trait MpvExt {
|
||||||
|
|
28
src/ipc.rs
28
src/ipc.rs
|
@ -1,19 +1,28 @@
|
||||||
use super::*;
|
//! IPC handling thread/task. Handles communication between [`Mpv`](crate::Mpv) instances and mpv's unix socket
|
||||||
|
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use tokio::net::UnixStream;
|
use tokio::{
|
||||||
use tokio::sync::mpsc;
|
net::UnixStream,
|
||||||
use tokio::sync::{broadcast, oneshot, Mutex};
|
sync::{broadcast, mpsc, oneshot, Mutex},
|
||||||
|
};
|
||||||
use tokio_util::codec::{Framed, LinesCodec, LinesCodecError};
|
use tokio_util::codec::{Framed, LinesCodec, LinesCodecError};
|
||||||
|
|
||||||
|
use crate::{Error, ErrorCode};
|
||||||
|
|
||||||
|
/// Container for all state that regards communication with the mpv IPC socket
|
||||||
|
/// and message passing with [`Mpv`](crate::Mpv) controllers.
|
||||||
pub(crate) struct MpvIpc {
|
pub(crate) struct MpvIpc {
|
||||||
socket: Framed<UnixStream, LinesCodec>,
|
socket: Framed<UnixStream, LinesCodec>,
|
||||||
command_channel: mpsc::Receiver<(MpvIpcCommand, oneshot::Sender<MpvIpcResponse>)>,
|
// I had trouble with reading and writing to the socket when it was wrapped
|
||||||
|
// in a MutexGuard, so I'm using a separate Mutex to lock the socket when needed.
|
||||||
socket_lock: Mutex<()>,
|
socket_lock: Mutex<()>,
|
||||||
|
command_channel: mpsc::Receiver<(MpvIpcCommand, oneshot::Sender<MpvIpcResponse>)>,
|
||||||
event_channel: broadcast::Sender<MpvIpcEvent>,
|
event_channel: broadcast::Sender<MpvIpcEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Commands that can be sent to [`MpvIpc`]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub(crate) enum MpvIpcCommand {
|
pub(crate) enum MpvIpcCommand {
|
||||||
Command(Vec<String>),
|
Command(Vec<String>),
|
||||||
|
@ -24,9 +33,11 @@ pub(crate) enum MpvIpcCommand {
|
||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [`MpvIpc`]'s response to a [`MpvIpcCommand`].
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct MpvIpcResponse(pub(crate) Result<Option<Value>, Error>);
|
pub(crate) struct MpvIpcResponse(pub(crate) Result<Option<Value>, Error>);
|
||||||
|
|
||||||
|
/// A deserialized and partially parsed event from mpv.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct MpvIpcEvent(pub(crate) Value);
|
pub(crate) struct MpvIpcEvent(pub(crate) Value);
|
||||||
|
|
||||||
|
@ -88,10 +99,6 @@ impl MpvIpc {
|
||||||
property: &str,
|
property: &str,
|
||||||
value: Value,
|
value: Value,
|
||||||
) -> Result<Option<Value>, Error> {
|
) -> Result<Option<Value>, Error> {
|
||||||
// let str_value = match &value {
|
|
||||||
// Value::String(s) => s,
|
|
||||||
// v => &serde_json::to_string(&v).unwrap(),
|
|
||||||
// };
|
|
||||||
self.send_command(&[json!("set_property"), json!(property), value])
|
self.send_command(&[json!("set_property"), json!(property), value])
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -177,6 +184,9 @@ impl MpvIpc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This function does the most basic JSON parsing and error handling
|
||||||
|
/// for status codes and errors that all responses from mpv are
|
||||||
|
/// expected to contain.
|
||||||
fn parse_mpv_response_data(value: Value) -> Result<Option<Value>, Error> {
|
fn parse_mpv_response_data(value: Value) -> Result<Option<Value>, Error> {
|
||||||
log::trace!("Parsing mpv response data: {:?}", value);
|
log::trace!("Parsing mpv response data: {:?}", value);
|
||||||
let result = value
|
let result = value
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
mod highlevel_api_extension;
|
#![doc = include_str!("../README.md")]
|
||||||
|
|
||||||
mod core_api;
|
mod core_api;
|
||||||
mod error;
|
mod error;
|
||||||
mod event_parser;
|
mod event_parser;
|
||||||
|
mod highlevel_api_extension;
|
||||||
mod ipc;
|
mod ipc;
|
||||||
mod message_parser;
|
mod message_parser;
|
||||||
|
|
||||||
pub use highlevel_api_extension::*;
|
|
||||||
pub use core_api::*;
|
pub use core_api::*;
|
||||||
pub use error::*;
|
pub use error::*;
|
||||||
pub use event_parser::*;
|
pub use event_parser::*;
|
||||||
|
pub use highlevel_api_extension::*;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! JSON parsing logic for command responses from [`MpvIpc`](crate::ipc::MpvIpc).
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
Loading…
Reference in New Issue