Compare commits

..

No commits in common. "main" and "1.0.0" have entirely different histories.
main ... 1.0.0

20 changed files with 49 additions and 1252 deletions

1
.envrc
View file

@ -1 +0,0 @@
use flake

View file

@ -1,54 +0,0 @@
name: build-plugin
on:
workflow_dispatch:
push:
branches: [ main ]
paths:
- "src/**"
- Cargo.lock
- rust-toolchain.toml
- flake.nix
- flake.lock
- shell.nix
pull_request:
branches: [ main ]
paths:
- "src/**"
- Cargo.lock
- rust-toolchain.toml
- flake.nix
- flake.lock
- shell.nix
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
profile: [ "dev", "release" ]
env:
BUILD_NAME: ${{ matrix.profile == 'dev' && 'debug' || matrix.profile }}
steps:
- uses: actions/checkout@v4
- name: Install Nix
uses: nixbuild/nix-quick-install-action@v28
- name: Check
run: nix develop --command cargo clippy --profile ${{ matrix.profile }} -- -D warnings
- name: Build
run: nix develop --command cargo build --profile ${{ matrix.profile }}
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: mpv-rpc_${{ env.BUILD_NAME }}
path: target/${{ env.BUILD_NAME }}/libmpv_rpc.so

2
.gitignore vendored
View file

@ -1,2 +1,2 @@
/target
/.direnv
/Cargo.lock

1005
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
[package]
name = "mpv-rpc"
version = "1.1.1"
version = "1.0.0"
edition = "2021"
[lib]

View file

@ -25,7 +25,6 @@
- Rusty! 🦀
# Installation
*Only Linux is supported at the moment, see MPV docs, regarding C plugins*
1. Download [latest release](https://github.com/ryze312/mpv-rpc/releases/latest) and unzip it
2. Run the installer script
3. Keybindings can be changed in input.conf

Binary file not shown.

View file

@ -1,65 +0,0 @@
{
"nodes": {
"fenix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1720938532,
"narHash": "sha256-Q2ldXS7ZUJWDqdF+GjgRQPlDfdM6NyJ1aw7xUdzjY+4=",
"owner": "nix-community",
"repo": "fenix",
"rev": "e761b522381d124fdc3ba20cecb2be2abec1d8cf",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "fenix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1720955038,
"narHash": "sha256-GaliJqfFwyYxReFywxAa8orCO+EnDq2NK2F+5aSc8vo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "aa247c0c90ecf4ae7a032c54fdc21b91ca274062",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixpkgs-unstable",
"type": "indirect"
}
},
"root": {
"inputs": {
"fenix": "fenix",
"nixpkgs": "nixpkgs"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1720717809,
"narHash": "sha256-6I+fm+nTLF/iaj7ffiFGlSY7POmubwUaPA/Wq0Bm53M=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "ffbc5ad993d5cd2f3b8bcf9a511165470944ab91",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,32 +0,0 @@
{
inputs = {
nixpkgs.url = "nixpkgs/nixpkgs-unstable";
fenix = {
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, fenix }:
let
overlays = [ fenix.overlays.default ];
getPkgsFor = (system: import nixpkgs {
inherit system overlays;
});
forEachSystem = func: nixpkgs.lib.genAttrs [
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
"x86_64-darwin"
] (system: func (getPkgsFor system));
in {
devShells = forEachSystem (pkgs: {
default = pkgs.callPackage ./shell.nix {};
});
};
}

View file

@ -1,7 +1,5 @@
#!/bin/bash
key='D'
script_binding='script-binding "libmpv_rpc/toggle-rpc"'
mpv_home="${MPV_HOME:-${XDG_CONFIG_HOME:-${HOME}/.config}/mpv}"
scripts_dir="$mpv_home/scripts"
@ -13,14 +11,10 @@ echo -n "Copying script..."
cp ./bin/libmpv_rpc.so "$scripts_dir"
echo "Done!"
if [ ! -f "$mpv_home/rpc.json" ]; then
echo -n "Copying default config..."
cp ./config/rpc.json "$mpv_home"
echo "Done!"
fi
echo -n "Copying default config..."
cp ./config/rpc.json "$mpv_home"
echo "Done!"
if ! grep -q "$script_binding" "$mpv_home/input.conf"; then
echo -n "Adding keybinding entry to input.conf..."
echo "$key $script_binding" >> "$mpv_home/input.conf"
echo "Done!"
fi
echo -n "Adding keybinding entry to input.conf..."
echo 'D script-binding "libmpv_rpc/toggle-rpc"' > "$mpv_home/input.conf"
echo "Done!"

View file

@ -1,4 +0,0 @@
[toolchain]
channel = "stable"
profile = "default"
targets = ["x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]

View file

@ -1,12 +0,0 @@
{ mkShell, fenix }:
let
toolchain = fenix.fromToolchainFile {
file = ./rust-toolchain.toml;
sha256 = "Ngiz76YP4HTY75GGdH2P+APE/DEIx2R/Dn+BwwOyzZU=";
};
in
mkShell {
packages = [ toolchain ];
}

View file

@ -26,6 +26,13 @@ const fn cover_art_default() -> bool {
}
impl Config {
pub fn default() -> Self {
Self {
active: active_default(),
cover_art: cover_art_default()
}
}
pub fn from_config_file(logger: &Logger) -> Self {
let path = Config::get_config_path();
logging::info!(logger, "Config path {path}");
@ -77,12 +84,3 @@ impl Config {
"/etc/mpv/".to_owned()
}
}
impl Default for Config {
fn default() -> Self {
Self {
active: active_default(),
cover_art: cover_art_default()
}
}
}

View file

@ -157,7 +157,7 @@ impl DiscordClient {
return ("logo".to_string(), "mpv".to_string())
}
let cover_art_url = music_brainz::get_cover_art_url(&metadata.title, &metadata.album, &metadata.artist, &metadata.album_artist);
let cover_art_url = music_brainz::get_cover_art_url(&metadata.title, &metadata.album, &metadata.artist);
let large_image = match cover_art_url {
Some(url) => url,
None => "logo".to_string()
@ -265,7 +265,7 @@ impl MpvEventHandler for DiscordClient {
MpvEvent::FileLoaded(file_info) => self.set_presence(file_info),
MpvEvent::Seek(remaining_time) => self.set_timestamps(remaining_time),
MpvEvent::Play(remaining_time) => self.set_timestamps(remaining_time),
MpvEvent::Pause => self.clear_timestamps(),
MpvEvent::Pause(_) => self.clear_timestamps(),
MpvEvent::Buffering => self.clear_timestamps(),
MpvEvent::Toggle => self.toggle_activity(),
MpvEvent::Exit => self.close(),

View file

@ -2,52 +2,32 @@ use musicbrainz_rs::entity::release_group::{ReleaseGroup, ReleaseGroupSearchQuer
use musicbrainz_rs::entity::CoverartResponse;
use musicbrainz_rs::{Search, FetchCoverart};
pub fn get_cover_art_url(title: &Option<String>, album: &Option<String>, artist: &Option<String>, album_artist: &Option<String>) -> Option<String>{
get_track_cover_art(artist, title).or(
get_album_cover_art(album_artist, album)
)
}
fn get_track_cover_art(artist: &Option<String>, title: &Option<String>) -> Option<String> {
pub fn get_cover_art_url(title: &Option<String>, album: &Option<String>, artist: &Option<String>) -> Option<String>{
let mut builder = ReleaseGroupSearchQuery::query_builder();
if let Some(ref title) = title {
builder.release_group(title);
}
if let Some(ref album) = album {
builder.or().release_group(album);
}
if let Some(ref artist) = artist {
// Some artist fields might contain + characters
// Pointing at multiple artists
for part in artist.split('+') {
builder.and().artist(part);
}
}
get_cover_art_from_query(builder.build())
}
fn get_album_cover_art(album_artist: &Option<String>, album: &Option<String>) -> Option<String> {
let mut builder = ReleaseGroupSearchQuery::query_builder();
if let Some(ref album) = album {
builder.release_group(album);
}
if let Some(ref album_artist) = album_artist {
// Some artist fields might contain + characters
// Pointing at multiple artists
for part in album_artist.split('+') {
for part in artist.split("+") {
builder.and().artist(part);
}
}
get_cover_art_from_query(builder.build())
}
let query = builder.build();
fn get_cover_art_from_query(query: String) -> Option<String> {
let result = match ReleaseGroup::search(query).execute() {
Ok(res) => res,
Err(_) => return None
};
let release = match result.entities.first() {
let release = match result.entities.get(0) {
Some(group) => group,
None => return None
};

View file

@ -22,5 +22,5 @@ fn mpv_open_cplugin(handle: *mut mpv_handle) -> std::os::raw::c_int {
};
plugin.run();
0
return 0;
}

View file

@ -1,8 +1,6 @@
use std::env;
pub mod macros;
#[allow(unused_imports)]
pub use macros::{error, warning, info};
#[allow(dead_code)]
@ -51,19 +49,19 @@ impl Logger {
pub fn info(&self, message: &str) {
if self.log_level >= LogLevel::Info {
println!("[mpv-rpc (INFO)] {message}");
println!("[mpv-rpc (INFO)] {}", message);
}
}
pub fn warning(&self, message: &str) {
if self.log_level >= LogLevel::Warn {
println!("[mpv-rpc (WARN)] {message}");
println!("[mpv-rpc (WARN)] {}", message);
}
}
pub fn error(&self, message: &str) {
if self.log_level >= LogLevel::Error {
println!("[mpv-rpc (ERROR)] {message}");
println!("[mpv-rpc (ERROR)] {}", message);
}
}
}

View file

@ -25,7 +25,7 @@ impl MpvEventQueue {
Ok(new_self)
}
pub fn from_ptr(handle: *mut mpv_handle, logger: Rc<Logger>) -> Result<Self, &'static str> {
pub fn from_ptr<'a>(handle: *mut mpv_handle, logger: Rc<Logger>) -> Result<Self, &'static str> {
MpvEventQueue::new(Handle::from_ptr(handle), logger)
}
@ -41,8 +41,9 @@ impl MpvEventQueue {
}
pub fn next_event(&mut self) -> Option<MpvEvent> {
let event = self.mpv.wait_event(-1.0);
self.convert_event(event)
let event = self.mpv.wait_event(0.0);
let mpv_event = self.convert_event(event);
mpv_event
}
pub fn handle_request(&self, request: MpvRequest) -> Result<(), &'static str> {
@ -77,14 +78,12 @@ impl MpvEventQueue {
fn get_file_info_event(&self) -> Option<MpvEvent> {
let filename = self.mpv.get_property("filename").unwrap();
let artist = self.mpv.get_property("metadata/by-key/artist").ok();
let album_artist = self.mpv.get_property("metadata/by-key/album_artist").ok();
let album = self.mpv.get_property("metadata/by-key/album").ok();
let title = self.mpv.get_property("metadata/by-key/title").ok();
let track = self.mpv.get_property("metadata/by-key/track").ok();
let metadata = FileMetadata {
artist,
album_artist,
album,
title,
track
@ -111,7 +110,7 @@ impl MpvEventQueue {
let time = self.get_remaining_time();
match pause {
false => Some(MpvEvent::Play(time)),
true => Some(MpvEvent::Pause)
true => Some(MpvEvent::Pause(time))
}
}

View file

@ -5,7 +5,6 @@ pub struct FileInfo {
pub struct FileMetadata {
pub artist: Option<String>,
pub album_artist: Option<String>,
pub album: Option<String>,
pub title: Option<String>,
pub track: Option<String>
@ -17,7 +16,7 @@ pub enum MpvEvent {
Exit,
FileLoaded(FileInfo),
Play(i64),
Pause,
Pause(i64),
Seek(i64)
}
@ -30,5 +29,5 @@ pub trait MpvEventHandler {
}
pub trait MpvRequester {
fn next_request(&mut self) -> Option<MpvRequest>;
fn next_request<'a>(&mut self) -> Option<MpvRequest>;
}

View file

@ -48,7 +48,10 @@ impl RPCPlugin {
}
fn handle_event(&mut self, event: MpvEvent) -> bool {
let exit = matches!(event, MpvEvent::Exit);
let exit = match event {
MpvEvent::Exit => true,
_ => false
};
if let Err(e) = self.discord.handle_event(event) {
logging::error!(self.logger, "Failed to handle event: {e}");