Compare commits

..

20 commits

Author SHA1 Message Date
38f5182d7a
Bump version: 1.1.4 -> 1.1.5 2024-05-25 00:14:43 +03:00
8d7de6c2f5
Add support for ARM64 2024-05-23 22:24:01 +03:00
eNV25
b3369ed9f3 Make absolutely sure subprocess is not killed 2024-05-20 19:06:27 +00:00
eNV25
4ed5078aa8 cargo fmt 2024-05-20 19:06:27 +00:00
063acaaf03
Bump dependencies and version 1.1.3 -> 1.1.4 2024-04-27 22:04:52 +03:00
f295724227
Fix chromium manifest: add required trailing slash 2024-04-27 22:04:35 +03:00
2e352b62d5
Bump dependencies and version 1.1.2 -> 1.1.3 2024-02-16 12:27:54 +03:00
1ff2a7a1ea
Optimize binary size more 2024-02-16 12:26:43 +03:00
eNV25
dbc4e5c8f0
Refactor {send,read}_message() (#11)
* Refactor {send,read}_message()

* Use binding for Take

---------

Co-authored-by: Ryze <50497128+ryze312@users.noreply.github.com>
2024-02-16 08:53:21 +00:00
eNV25
ce98b95008
Respect options passed by ff2mpv extension (#12)
* Respect options passed by ff2mpv extension

The upstream ff2mpv extension started passing `options`. Respect
those by passing them after our `config.player_args`.

* Restore the order of imports

---------

Co-authored-by: Ryze <50497128+ryze312@users.noreply.github.com>
2024-02-16 08:33:12 +00:00
a971c7c35b Pass --no-terminal to mpv (#10) 2024-02-14 18:44:34 +03:00
738015c947 Add manifest_chromium to README and help message 2024-02-14 16:52:45 +03:00
a10e8706b8 Bump version and dependencies 2024-02-14 16:34:35 +03:00
a3388efb97 Add command for Chromium manifest 2024-02-14 16:30:22 +03:00
1c47fe8c98 Use cargo config to build multiple targets 2024-02-14 14:30:17 +03:00
550bd3a818 Use -- to separate args and URL
Fixes #10
2024-02-14 10:52:24 +03:00
44cf917ecf Specify static lifetime in CONFIG_FILENAME 2024-02-14 09:32:00 +03:00
3566df75e7
Config improvements from #8
- Use #[serde(default)] on the whole struct instead of defaults for separate fields
- Use unwrap_or_default() instead of matching
- Wrap config filename in constant

Co-authored-by: Markus Pettersson <mpettersson@tutanota.com>
2023-11-28 22:29:03 +03:00
392c7937b1
Change release profile directly and add dev profile with optimizations. Fixes #9 2023-10-31 02:14:33 +03:00
4fcc2ac31f Spawn player with CREATE_BREAKAWAY_FROM_JOB on Windows 2023-10-21 21:39:12 +03:00
9 changed files with 230 additions and 84 deletions

2
.cargo/config.toml Normal file
View file

@ -0,0 +1,2 @@
[build]
target = ["x86_64-unknown-linux-gnu", "x86_64-pc-windows-gnu", "aarch64-unknown-linux-gnu"]

164
Cargo.lock generated
View file

@ -10,23 +10,24 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "ff2mpv-rust"
version = "1.1.0"
version = "1.1.4"
dependencies = [
"serde",
"serde_json",
"windows",
]
[[package]]
name = "hashbrown"
version = "0.14.0"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "indexmap"
version = "2.0.0"
version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [
"equivalent",
"hashbrown",
@ -34,48 +35,48 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.9"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "proc-macro2"
version = "1.0.66"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.15"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "serde"
version = "1.0.188"
version = "1.0.199"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.188"
version = "1.0.199"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc"
dependencies = [
"proc-macro2",
"quote",
@ -84,9 +85,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.105"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
dependencies = [
"indexmap",
"itoa",
@ -96,9 +97,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.31"
version = "2.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398"
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
dependencies = [
"proc-macro2",
"quote",
@ -107,6 +108,123 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.11"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
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"

View file

@ -1,13 +1,21 @@
[package]
name = "ff2mpv-rust"
version = "1.1.0"
version = "1.1.5"
edition = "2021"
[dependencies]
serde = { version = "1.0.152", features = ["derive"] }
serde_json = { version = "1.0.93", features = ["preserve_order"] }
serde = { version = "1.0.*", features = ["derive"] }
serde_json = { version = "1.0.*", features = ["preserve_order"] }
[profile.release-full]
inherits = "release"
[target.'cfg(windows)'.dependencies]
windows = { version = "0.56", features = ["Win32_System_Threading"] }
[profile.dev-optimized]
inherits = "dev"
opt-level = 3
[profile.release]
strip = "symbols"
lto = "fat"
panic = "abort"
codegen-units = 1

View file

@ -18,6 +18,11 @@ 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
@ -35,7 +40,8 @@ See [example configuration](ff2mpv-rust.json).
ff2mpv-rust provides command line interface with following commands:
```
help: prints help message
manifest: prints manifest for browser configuration
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.

View file

@ -1,13 +1,13 @@
use std::io::{self, Read, Write};
use serde::Deserialize;
use std::io;
use std::io::BufReader;
use std::io::{Read, Write};
use crate::error::FF2MpvError;
#[derive(Deserialize)]
pub struct FF2MpvMessage {
pub url: String,
pub options: Vec<String>,
}
pub fn send_reply() -> Result<(), io::Error> {
@ -22,23 +22,23 @@ pub fn get_mpv_message() -> Result<FF2MpvMessage, FF2MpvError> {
}
fn read_message() -> Result<String, io::Error> {
let mut stdin = io::stdin();
let mut buf: [u8; 4] = [0; 4];
stdin.read_exact(&mut buf)?;
let mut stdin = io::stdin().lock();
let length = u32::from_ne_bytes(buf);
let mut reader = BufReader::new(stdin.take(length as u64));
let mut len = 0_u32.to_ne_bytes();
stdin.read_exact(&mut len)?;
let len = u32::from_ne_bytes(len);
let mut string = String::with_capacity(length as usize);
reader.read_to_string(&mut string)?;
Ok(string)
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();
let mut stdout = io::stdout().lock();
stdout.write_all(&length)?;
stdout.write_all(message)?;
Ok(())

View file

@ -1,7 +1,8 @@
use std::env;
use std::io;
use std::process;
use serde_json::{self, json};
use serde_json::json;
use crate::browser;
use crate::config::Config;
@ -10,18 +11,19 @@ use crate::error::FF2MpvError;
pub enum Command {
ShowHelp,
ShowManifest,
ShowManifestChromium,
ValidateConfig,
FF2Mpv
FF2Mpv,
}
impl Command {
pub fn execute(&self) -> Result<(), FF2MpvError> {
match self {
Command::ShowHelp => Self::show_help(),
Command::ShowManifest => Self::show_manifest(),
Command::ShowManifest => Self::show_manifest(false),
Command::ShowManifestChromium => Self::show_manifest(true),
Command::ValidateConfig => Self::validate_config(),
Command::FF2Mpv => Self::ff2mpv()
Command::FF2Mpv => Self::ff2mpv(),
}
}
@ -29,7 +31,8 @@ impl Command {
println!("Usage: ff2mpv-rust <command>");
println!("Commands:");
println!(" help: prints help message");
println!(" manifest: prints manifest for browser configuration");
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");
@ -37,14 +40,23 @@ impl Command {
Ok(())
}
fn show_manifest() -> Result<(), FF2MpvError>{
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_extensions": ["ff2mpv@yossarian.net"]
allowed_keyvalue.0: [allowed_keyvalue.1]
});
let manifest = serde_json::to_string_pretty(&manifest)?;
@ -63,9 +75,10 @@ impl Command {
fn ff2mpv() -> Result<(), FF2MpvError> {
let config = Config::build();
let ff2mpv_message = browser::get_mpv_message()?;
Command::launch_mpv(config.player_command, config.player_args, &ff2mpv_message.url)?;
let args = [config.player_args, ff2mpv_message.options].concat();
Command::launch_mpv(config.player_command, args, &ff2mpv_message.url)?;
browser::send_reply()?;
Ok(())
}
@ -74,22 +87,31 @@ impl Command {
command.stdout(process::Stdio::null());
command.stderr(process::Stdio::null());
command.arg("--no-terminal");
command.args(args);
command.arg("--");
command.arg(url);
// NOTE: On Windows, browser spawns process into a Job object.
// NOTE: We need to detach player from the job, so it won't get killed after we're done,
// NOTE: See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#closing_the_native_app
#[cfg(target_family = "windows")]
{
use std::os::windows::process::CommandExt;
const CREATE_BREAKAWAY_FROM_JOB: u32 = 0x01000000;
command.creation_flags(CREATE_BREAKAWAY_FROM_JOB);
}
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);
}
}

View file

@ -1,35 +1,32 @@
use std::env;
use std::fs;
use std::path::PathBuf;
use serde::Deserialize;
use crate::error::FF2MpvError;
#[derive(Deserialize)]
#[serde(default)]
pub struct Config {
#[serde(default = "default_player_command")]
pub player_command: String,
#[serde(default = "default_player_args")]
pub player_args: Vec<String>,
}
impl Default for Config {
fn default() -> Self {
Self {
player_command: default_player_command(),
player_args: default_player_args(),
player_command: "mpv".to_owned(),
player_args: vec![],
}
}
}
impl Config {
const CONFIG_FILENAME: &'static str = "ff2mpv-rust.json";
pub fn build() -> Self {
if let Ok(config) = Config::parse_config_file() {
config
} else {
Config::default()
}
Config::parse_config_file().unwrap_or_default()
}
pub fn parse_config_file() -> Result<Self, FF2MpvError> {
@ -44,7 +41,7 @@ impl Config {
Ok(config)
}
#[cfg(target_family = "unix")]
#[cfg(unix)]
fn get_config_location() -> PathBuf {
let mut path = PathBuf::new();
@ -57,25 +54,17 @@ impl Config {
path.push("/etc");
}
path.push("ff2mpv-rust.json");
path.push(Self::CONFIG_FILENAME);
path
}
#[cfg(target_family = "windows")]
#[cfg(windows)]
fn get_config_location() -> PathBuf {
let mut path = PathBuf::new();
let appdata = env::var("APPDATA").unwrap();
path.push(appdata);
path.push("ff2mpv-rust.json");
path.push(Self::CONFIG_FILENAME);
path
}
}
fn default_player_command() -> String {
"mpv".to_owned()
}
fn default_player_args() -> Vec<String> {
vec![]
}

View file

@ -1,6 +1,6 @@
use std::io;
use std::fmt;
use std::fmt::Display;
use std::io;
pub enum FF2MpvError {
NoConfig,

View file

@ -19,6 +19,7 @@ fn get_command(name: &str) -> Command {
match name {
"help" => Command::ShowHelp,
"manifest" => Command::ShowManifest,
"manifest_chromium" => Command::ShowManifestChromium,
"validate" => Command::ValidateConfig,
_ => Command::FF2Mpv,
}