Compare commits
No commits in common. "main" and "1.0.0" have entirely different histories.
12 changed files with 68 additions and 571 deletions
|
@ -1,2 +0,0 @@
|
||||||
[build]
|
|
||||||
target = ["x86_64-unknown-linux-gnu", "x86_64-pc-windows-gnu", "aarch64-unknown-linux-gnu"]
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
/Cargo.lock
|
||||||
|
|
230
Cargo.lock
generated
230
Cargo.lock
generated
|
@ -1,230 +0,0 @@
|
||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "equivalent"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ff2mpv-rust"
|
|
||||||
version = "1.1.4"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"windows",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.14.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "indexmap"
|
|
||||||
version = "2.2.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
|
||||||
dependencies = [
|
|
||||||
"equivalent",
|
|
||||||
"hashbrown",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itoa"
|
|
||||||
version = "1.0.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro2"
|
|
||||||
version = "1.0.81"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quote"
|
|
||||||
version = "1.0.36"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde"
|
|
||||||
version = "1.0.199"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a"
|
|
||||||
dependencies = [
|
|
||||||
"serde_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_derive"
|
|
||||||
version = "1.0.199"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_json"
|
|
||||||
version = "1.0.116"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
|
|
||||||
dependencies = [
|
|
||||||
"indexmap",
|
|
||||||
"itoa",
|
|
||||||
"ryu",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "2.0.60"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-ident"
|
|
||||||
version = "1.0.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows"
|
|
||||||
version = "0.56.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132"
|
|
||||||
dependencies = [
|
|
||||||
"windows-core",
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-core"
|
|
||||||
version = "0.56.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6"
|
|
||||||
dependencies = [
|
|
||||||
"windows-implement",
|
|
||||||
"windows-interface",
|
|
||||||
"windows-result",
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-implement"
|
|
||||||
version = "0.56.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-interface"
|
|
||||||
version = "0.56.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-result"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-targets"
|
|
||||||
version = "0.52.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
|
||||||
dependencies = [
|
|
||||||
"windows_aarch64_gnullvm",
|
|
||||||
"windows_aarch64_msvc",
|
|
||||||
"windows_i686_gnu",
|
|
||||||
"windows_i686_gnullvm",
|
|
||||||
"windows_i686_msvc",
|
|
||||||
"windows_x86_64_gnu",
|
|
||||||
"windows_x86_64_gnullvm",
|
|
||||||
"windows_x86_64_msvc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.52.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.52.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.52.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnullvm"
|
|
||||||
version = "0.52.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.52.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.52.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.52.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.52.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
|
18
Cargo.toml
18
Cargo.toml
|
@ -1,21 +1,13 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ff2mpv-rust"
|
name = "ff2mpv-rust"
|
||||||
version = "1.1.5"
|
version = "1.0.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "1.0.*", features = ["derive"] }
|
serde = { version = "1.0.152", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.*", features = ["preserve_order"] }
|
serde_json = "1.0.93"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[profile.release-full]
|
||||||
windows = { version = "0.56", features = ["Win32_System_Threading"] }
|
inherits = "release"
|
||||||
|
|
||||||
[profile.dev-optimized]
|
|
||||||
inherits = "dev"
|
|
||||||
opt-level = 3
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
strip = "symbols"
|
strip = "symbols"
|
||||||
lto = "fat"
|
lto = "fat"
|
||||||
panic = "abort"
|
|
||||||
codegen-units = 1
|
|
||||||
|
|
35
README.md
35
README.md
|
@ -11,41 +11,6 @@ This is a native compiled binary, so it runs much faster and doesn't require ext
|
||||||
# What is this?
|
# What is this?
|
||||||
This is a script for hooking mpv and [ff2mpv](https://github.com/woodruffw/ff2mpv), that allows opening any video link in mpv straight from the browser.
|
This is a script for hooking mpv and [ff2mpv](https://github.com/woodruffw/ff2mpv), that allows opening any video link in mpv straight from the browser.
|
||||||
|
|
||||||
# Installation
|
|
||||||
First, install ff2mpv extension from [AMO](https://addons.mozilla.org/en-US/firefox/addon/ff2mpv) or [Chrome Store](https://chrome.google.com/webstore/detail/ff2mpv/ephjcajbkgplkjmelpglennepbpmdpjg).
|
|
||||||
|
|
||||||
After that get native messasing host manifest:
|
|
||||||
```
|
|
||||||
ff2mpv-rust manifest
|
|
||||||
```
|
|
||||||
Or for Chromium/Chrome:
|
|
||||||
```
|
|
||||||
ff2mpv-rust manifest_chromium
|
|
||||||
```
|
|
||||||
|
|
||||||
Install it following manual installation instructions on [ff2mpv wiki](https://github.com/woodruffw/ff2mpv/wiki).
|
|
||||||
|
|
||||||
# Configuration
|
|
||||||
On Linux configuration file is searched in such order:
|
|
||||||
|
|
||||||
1. $XDG_CONFIG_HOME/ff2mpv-rust.json
|
|
||||||
2. $HOME/.config/ff2mpv-rust.json
|
|
||||||
3. /etc/ff2mpv-rust.json
|
|
||||||
|
|
||||||
On Windows configuration file should be placed at: %APPDATA%/ff2mpv-rust.json.
|
|
||||||
|
|
||||||
See [example configuration](ff2mpv-rust.json).
|
|
||||||
|
|
||||||
# Command line interface
|
|
||||||
ff2mpv-rust provides command line interface with following commands:
|
|
||||||
```
|
|
||||||
help: prints help message
|
|
||||||
manifest: prints manifest for Firefox configuration
|
|
||||||
manifest_chromium: prints manifest for Chromium/Chrome configuration
|
|
||||||
validate: checks configration file for validity
|
|
||||||
```
|
|
||||||
Note that it won't fail on invalid commands, but instead assume it is called from browser, blocking the input.
|
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
All issues and pull requests are welcome! Feel free to open an issue if you've got an idea or a problem. You can open a pull request if you are able to implement it yourself.
|
All issues and pull requests are welcome! Feel free to open an issue if you've got an idea or a problem. You can open a pull request if you are able to implement it yourself.
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"player_command": "mpv",
|
|
||||||
"player_args": ["--no-config", "--fullscreen"]
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
use std::io::{self, Read, Write};
|
|
||||||
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
use crate::error::FF2MpvError;
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct FF2MpvMessage {
|
|
||||||
pub url: String,
|
|
||||||
pub options: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_reply() -> Result<(), io::Error> {
|
|
||||||
// "ok" formatted as a JSON string
|
|
||||||
send_message("\"ok\"")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_mpv_message() -> Result<FF2MpvMessage, FF2MpvError> {
|
|
||||||
let message = read_message()?;
|
|
||||||
let ff2mpv_message = serde_json::from_str(&message)?;
|
|
||||||
Ok(ff2mpv_message)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_message() -> Result<String, io::Error> {
|
|
||||||
let mut stdin = io::stdin().lock();
|
|
||||||
|
|
||||||
let mut len = 0_u32.to_ne_bytes();
|
|
||||||
stdin.read_exact(&mut len)?;
|
|
||||||
let len = u32::from_ne_bytes(len);
|
|
||||||
|
|
||||||
let mut reader = stdin.take(len as u64);
|
|
||||||
let mut msg = String::with_capacity(len as usize);
|
|
||||||
reader.read_to_string(&mut msg)?;
|
|
||||||
Ok(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_message(message: &str) -> Result<(), io::Error> {
|
|
||||||
let length = (message.len() as u32).to_ne_bytes();
|
|
||||||
let message = message.as_bytes();
|
|
||||||
|
|
||||||
let mut stdout = io::stdout().lock();
|
|
||||||
stdout.write_all(&length)?;
|
|
||||||
stdout.write_all(message)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
117
src/command.rs
117
src/command.rs
|
@ -1,117 +0,0 @@
|
||||||
use std::env;
|
|
||||||
use std::io;
|
|
||||||
use std::process;
|
|
||||||
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use crate::browser;
|
|
||||||
use crate::config::Config;
|
|
||||||
use crate::error::FF2MpvError;
|
|
||||||
|
|
||||||
pub enum Command {
|
|
||||||
ShowHelp,
|
|
||||||
ShowManifest,
|
|
||||||
ShowManifestChromium,
|
|
||||||
ValidateConfig,
|
|
||||||
FF2Mpv,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Command {
|
|
||||||
pub fn execute(&self) -> Result<(), FF2MpvError> {
|
|
||||||
match self {
|
|
||||||
Command::ShowHelp => Self::show_help(),
|
|
||||||
Command::ShowManifest => Self::show_manifest(false),
|
|
||||||
Command::ShowManifestChromium => Self::show_manifest(true),
|
|
||||||
Command::ValidateConfig => Self::validate_config(),
|
|
||||||
Command::FF2Mpv => Self::ff2mpv(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn show_help() -> Result<(), FF2MpvError> {
|
|
||||||
println!("Usage: ff2mpv-rust <command>");
|
|
||||||
println!("Commands:");
|
|
||||||
println!(" help: prints help message");
|
|
||||||
println!(" manifest: prints manifest for Firefox configuration");
|
|
||||||
println!(" manifest_chromium: prints manifest for Chromium/Chrome configuration");
|
|
||||||
println!(" validate: checks configration file for validity");
|
|
||||||
println!("Note: Invalid commands won't fail");
|
|
||||||
println!("Note: It will assume that binary is called from browser, blocking for input");
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn show_manifest(chromium: bool) -> Result<(), FF2MpvError> {
|
|
||||||
let executable_path = env::current_exe()?;
|
|
||||||
let allowed_keyvalue = if chromium {
|
|
||||||
(
|
|
||||||
"allowed_origins",
|
|
||||||
"chrome-extension://ephjcajbkgplkjmelpglennepbpmdpjg/",
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
("allowed_extensions", "ff2mpv@yossarian.net")
|
|
||||||
};
|
|
||||||
|
|
||||||
let manifest = json!({
|
|
||||||
"name": "ff2mpv",
|
|
||||||
"description": "ff2mpv's external manifest",
|
|
||||||
"path": executable_path,
|
|
||||||
"type": "stdio",
|
|
||||||
allowed_keyvalue.0: [allowed_keyvalue.1]
|
|
||||||
});
|
|
||||||
|
|
||||||
let manifest = serde_json::to_string_pretty(&manifest)?;
|
|
||||||
println!("{manifest}");
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_config() -> Result<(), FF2MpvError> {
|
|
||||||
Config::parse_config_file()?;
|
|
||||||
println!("Config is valid!");
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ff2mpv() -> Result<(), FF2MpvError> {
|
|
||||||
let config = Config::build();
|
|
||||||
let ff2mpv_message = browser::get_mpv_message()?;
|
|
||||||
let args = [config.player_args, ff2mpv_message.options].concat();
|
|
||||||
Command::launch_mpv(config.player_command, args, &ff2mpv_message.url)?;
|
|
||||||
browser::send_reply()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn launch_mpv(command: String, args: Vec<String>, url: &str) -> Result<(), io::Error> {
|
|
||||||
let mut command = process::Command::new(command);
|
|
||||||
|
|
||||||
command.stdout(process::Stdio::null());
|
|
||||||
command.stderr(process::Stdio::null());
|
|
||||||
command.arg("--no-terminal");
|
|
||||||
command.args(args);
|
|
||||||
command.arg("--");
|
|
||||||
command.arg(url);
|
|
||||||
|
|
||||||
Command::detach_mpv(&mut command);
|
|
||||||
|
|
||||||
command.spawn()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Make sure the subprocess is not killed.
|
|
||||||
// See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#closing_the_native_app
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
fn detach_mpv(command: &mut process::Command) {
|
|
||||||
use std::os::unix::process::CommandExt;
|
|
||||||
command.process_group(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
fn detach_mpv(command: &mut process::Command) {
|
|
||||||
use std::os::windows::process::CommandExt;
|
|
||||||
use windows::Win32::System::Threading::CREATE_BREAKAWAY_FROM_JOB;
|
|
||||||
command.creation_flags(CREATE_BREAKAWAY_FROM_JOB.0);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
use std::env;
|
|
||||||
use std::fs;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
use crate::error::FF2MpvError;
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
#[serde(default)]
|
|
||||||
pub struct Config {
|
|
||||||
pub player_command: String,
|
|
||||||
pub player_args: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Config {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
player_command: "mpv".to_owned(),
|
|
||||||
player_args: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config {
|
|
||||||
const CONFIG_FILENAME: &'static str = "ff2mpv-rust.json";
|
|
||||||
|
|
||||||
pub fn build() -> Self {
|
|
||||||
Config::parse_config_file().unwrap_or_default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_config_file() -> Result<Self, FF2MpvError> {
|
|
||||||
let config_path = Config::get_config_location();
|
|
||||||
if !config_path.exists() {
|
|
||||||
return Err(FF2MpvError::NoConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
let string = fs::read_to_string(config_path)?;
|
|
||||||
let config = serde_json::from_str(&string)?;
|
|
||||||
|
|
||||||
Ok(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
fn get_config_location() -> PathBuf {
|
|
||||||
let mut path = PathBuf::new();
|
|
||||||
|
|
||||||
if let Ok(home) = env::var("XDG_CONFIG_HOME") {
|
|
||||||
path.push(home);
|
|
||||||
} else if let Ok(home) = env::var("HOME") {
|
|
||||||
path.push(home);
|
|
||||||
path.push(".config");
|
|
||||||
} else {
|
|
||||||
path.push("/etc");
|
|
||||||
}
|
|
||||||
|
|
||||||
path.push(Self::CONFIG_FILENAME);
|
|
||||||
path
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
fn get_config_location() -> PathBuf {
|
|
||||||
let mut path = PathBuf::new();
|
|
||||||
let appdata = env::var("APPDATA").unwrap();
|
|
||||||
|
|
||||||
path.push(appdata);
|
|
||||||
path.push(Self::CONFIG_FILENAME);
|
|
||||||
path
|
|
||||||
}
|
|
||||||
}
|
|
31
src/error.rs
31
src/error.rs
|
@ -1,31 +0,0 @@
|
||||||
use std::fmt;
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
pub enum FF2MpvError {
|
|
||||||
NoConfig,
|
|
||||||
IOError(io::Error),
|
|
||||||
JSONError(serde_json::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<io::Error> for FF2MpvError {
|
|
||||||
fn from(value: io::Error) -> Self {
|
|
||||||
Self::IOError(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<serde_json::Error> for FF2MpvError {
|
|
||||||
fn from(value: serde_json::Error) -> Self {
|
|
||||||
Self::JSONError(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for FF2MpvError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::NoConfig => write!(f, "Config doesn't exist"),
|
|
||||||
Self::IOError(e) => write!(f, "IO Error: {e}"),
|
|
||||||
Self::JSONError(e) => write!(f, "JSON Error: {e}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
46
src/lib.rs
46
src/lib.rs
|
@ -1,4 +1,42 @@
|
||||||
pub mod browser;
|
use std::io::{self, Read, Write};
|
||||||
pub mod command;
|
use serde::Deserialize;
|
||||||
pub mod config;
|
|
||||||
pub mod error;
|
#[derive(Deserialize)]
|
||||||
|
pub struct MpvMessage {
|
||||||
|
pub url: String
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mpv_message() -> Result<MpvMessage, String> {
|
||||||
|
let message = match get_browser_message() {
|
||||||
|
Ok(msg) => msg,
|
||||||
|
Err(e) => return Err(format!("IO Error: {}", e))
|
||||||
|
};
|
||||||
|
|
||||||
|
match serde_json::from_str(&message) {
|
||||||
|
Ok(msg) => Ok(msg),
|
||||||
|
Err(e) => Err(format!("JSON Error: {}", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_browser_message() -> io::Result<String> {
|
||||||
|
let mut stdin = io::stdin();
|
||||||
|
let mut buf: [u8; 4] = [0; 4];
|
||||||
|
stdin.read_exact(&mut buf)?;
|
||||||
|
|
||||||
|
let length = u32::from_ne_bytes(buf);
|
||||||
|
let mut reader = io::BufReader::new(stdin.take(length as u64));
|
||||||
|
|
||||||
|
let mut string = String::with_capacity(length as usize);
|
||||||
|
reader.read_to_string(&mut string)?;
|
||||||
|
Ok(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_browser_message(message: &str) -> io::Result<()> {
|
||||||
|
let length = (message.len() as u32).to_ne_bytes();
|
||||||
|
let message = message.as_bytes();
|
||||||
|
|
||||||
|
let mut stdout = io::stdout();
|
||||||
|
stdout.write(&length)?;
|
||||||
|
stdout.write(&message)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
40
src/main.rs
40
src/main.rs
|
@ -1,26 +1,26 @@
|
||||||
use std::env;
|
use std::process::{Command, self};
|
||||||
use std::process;
|
use ff2mpv_rust::{get_mpv_message, send_browser_message};
|
||||||
|
|
||||||
use ff2mpv_rust::command::Command;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut args = env::args();
|
let message = match get_mpv_message() {
|
||||||
args.next(); // Skip binary path
|
Ok(msg) => msg,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
process::exit(-1)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let command_name = args.next().unwrap_or_default();
|
let mpv = Command::new("mpv")
|
||||||
let command = get_command(&command_name);
|
.arg(message.url)
|
||||||
if let Err(e) = command.execute() {
|
.spawn();
|
||||||
eprintln!("{e}");
|
|
||||||
|
if let Err(e) = mpv {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
process::exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = send_browser_message("ok") {
|
||||||
|
eprintln!("{}", e);
|
||||||
process::exit(-1);
|
process::exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_command(name: &str) -> Command {
|
|
||||||
match name {
|
|
||||||
"help" => Command::ShowHelp,
|
|
||||||
"manifest" => Command::ShowManifest,
|
|
||||||
"manifest_chromium" => Command::ShowManifestChromium,
|
|
||||||
"validate" => Command::ValidateConfig,
|
|
||||||
_ => Command::FF2Mpv,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue