diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index de74be3..7d0dc7c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3113,10 +3113,14 @@ name = "moonsound" version = "0.1.0" dependencies = [ "base64 0.22.1", + "block2", "cocoa 0.26.0", "dirs", "entity", "migration", + "objc2", + "objc2-foundation", + "objc2-media-player", "rodio", "sea-orm", "serde", @@ -3492,6 +3496,19 @@ dependencies = [ "objc2-foundation", ] +[[package]] +name = "objc2-media-player" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeee7e398f352d50d8016c73969878942efb422030884a744180a2d2b8b341de" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + [[package]] name = "objc2-metal" version = "0.2.2" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 26e6cdc..52b27a2 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -37,9 +37,12 @@ base64 = "0.22.1" sea-orm = { version = "1.1.2", features = [ "sqlx-sqlite", "runtime-async-std-rustls", "macros" ] } dirs = "5.0.1" tokio = { version = "1.42.0", features = ["full"] } +objc2-media-player = { version = "0.2.2", features = ["all"] } +block2 = "0.5.1" +objc2 = "0.5.2" +objc2-foundation = "0.2.2" [target."cfg(target_os = \"macos\")".dependencies] cocoa = "0.26" [workspace] -members = [".", "migration", "entity"] diff --git a/src-tauri/entity/src/lib.rs b/src-tauri/entity/src/lib.rs index 4927598..c9a5203 100644 --- a/src-tauri/entity/src/lib.rs +++ b/src-tauri/entity/src/lib.rs @@ -1,2 +1,2 @@ +pub mod metadata; pub mod song; -pub mod metadata; \ No newline at end of file diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 762b4d0..ce60636 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -3,11 +3,12 @@ mod music; mod state; +mod macos_interop; use migration::{Migrator, MigratorTrait}; +use rodio::OutputStream; use sea_orm::Database; use state::AppDataNew; -use rodio::OutputStream; use tauri::{Manager, Theme}; use tauri_plugin_decorum::WebviewWindowExt; use window_vibrancy::{apply_mica, apply_vibrancy, NSVisualEffectMaterial}; diff --git a/src-tauri/src/macos_interop/mod.rs b/src-tauri/src/macos_interop/mod.rs new file mode 100644 index 0000000..e80c9df --- /dev/null +++ b/src-tauri/src/macos_interop/mod.rs @@ -0,0 +1 @@ +mod now_playing; \ No newline at end of file diff --git a/src-tauri/src/macos_interop/now_playing.rs b/src-tauri/src/macos_interop/now_playing.rs new file mode 100644 index 0000000..c04ec45 --- /dev/null +++ b/src-tauri/src/macos_interop/now_playing.rs @@ -0,0 +1,40 @@ +use objc2::runtime::AnyObject; +use objc2_media_player::{MPNowPlayingInfoCenter, + MPNowPlayingInfoPropertyAssetURL, + MPNowPlayingInfoPropertyMediaType, + MPNowPlayingInfoPropertyIsLiveStream, + MPMediaItemPropertyTitle, + MPMediaItemPropertyArtist, + MPMediaItemPropertyArtwork, + MPMediaItemPropertyAlbumArtist, + MPMediaItemPropertyAlbumTitle}; +use objc2_foundation::{ns_string, NSMutableDictionary, NSMutableString, NSString}; + +pub fn set_now_playing() { + unsafe { + let default = MPNowPlayingInfoCenter::defaultCenter(); + MPNowPlayingInfoCenter::setNowPlayingInfo(&*default, { + let keys = &[ + MPNowPlayingInfoPropertyAssetURL, + MPNowPlayingInfoPropertyMediaType, + MPNowPlayingInfoPropertyIsLiveStream, + MPMediaItemPropertyTitle, + MPMediaItemPropertyArtist, + MPMediaItemPropertyArtwork, + MPMediaItemPropertyAlbumArtist, + MPMediaItemPropertyAlbumTitle + ]; + let owned_objects = &[ + NSString::from_str("https://example.com"), + NSString::from_str("1"), + NSString::from_str("false"), + NSString::from_str("Title"), + NSString::from_str("Artist"), + NSString::from_str("Artwork"), + NSString::from_str("Album Artist"), + NSString::from_str("Album Title") + ]; + Some(objc2_foundation::NSDictionary::from_id_slice(keys, owned_objects).as_ref()) + }); + } +} diff --git a/src-tauri/src/music/commands.rs b/src-tauri/src/music/commands.rs index 9aed37f..d25d1dc 100644 --- a/src-tauri/src/music/commands.rs +++ b/src-tauri/src/music/commands.rs @@ -25,7 +25,10 @@ pub fn play(app: AppHandle, path: &str, state: State<'_, AppData>) -> Result<(), let app_handle = app.clone(); let callback = Box::new(move |_source: &mut Decoder>| { app_handle - .emit("PLAYBACK_POSITION_UPDATE", app_handle.state::().sink.get_pos()) + .emit( + "PLAYBACK_POSITION_UPDATE", + app_handle.state::().sink.get_pos(), + ) .unwrap(); }); diff --git a/src-tauri/src/music/core.rs b/src-tauri/src/music/core.rs index 55d6f71..30d829d 100644 --- a/src-tauri/src/music/core.rs +++ b/src-tauri/src/music/core.rs @@ -1,3 +1,4 @@ +use crate::music::tags::get_keys_for_standard_tag; use crate::music::types::PeriodicCallback; use crate::state::AppData; use base64::{engine::general_purpose::STANDARD as BASE64, Engine}; @@ -13,7 +14,6 @@ use symphonia::core::formats::probe::Hint; use symphonia::core::formats::FormatOptions; use symphonia::core::io::MediaSourceStream; use symphonia::core::meta::{MetadataOptions, StandardTag}; -use crate::music::tags::get_keys_for_standard_tag; #[derive(Serialize)] pub struct PlayerState { @@ -35,10 +35,10 @@ pub async fn import_file(app_data: &AppData, path: &str) -> Result<(), String> { path: Set(path.parse().unwrap()), ..Default::default() } - .save(&app_data.db) - .await - .map(|_| ()) - .map_err(|e| e.to_string()) + .save(&app_data.db) + .await + .map(|_| ()) + .map_err(|e| e.to_string()) } pub fn read_metadata(path: &str) -> Result { diff --git a/src-tauri/src/music/mod.rs b/src-tauri/src/music/mod.rs index 02eff0d..b718353 100644 --- a/src-tauri/src/music/mod.rs +++ b/src-tauri/src/music/mod.rs @@ -1,6 +1,6 @@ mod commands; mod core; -pub(crate) mod types; mod tags; +pub(crate) mod types; pub use commands::*; diff --git a/src-tauri/src/music/types.rs b/src-tauri/src/music/types.rs index b207fde..845a4a7 100644 --- a/src-tauri/src/music/types.rs +++ b/src-tauri/src/music/types.rs @@ -1,5 +1,5 @@ +use rodio::Decoder; use std::fs::File; use std::io::BufReader; -use rodio::Decoder; pub type PeriodicCallback = Box>) + Send + 'static>; diff --git a/src-tauri/src/state.rs b/src-tauri/src/state.rs index fdff795..1a4deea 100644 --- a/src-tauri/src/state.rs +++ b/src-tauri/src/state.rs @@ -1,10 +1,6 @@ -use std::fs::File; -use std::io::BufReader; -use rodio::{Decoder, OutputStreamHandle, Sink}; +use rodio::{OutputStreamHandle, Sink}; use sea_orm::DatabaseConnection; use std::sync::Mutex; -use rodio::source::PeriodicAccess; -use crate::music::types::PeriodicCallback; pub struct AppMetadata { pub currently_playing_file_path: Option, @@ -35,7 +31,7 @@ impl AppData { currently_playing_file_path: None, }), sink, - stream_handle + stream_handle, } } }