diff --git a/dmp-core/src/music_controller/connections.rs b/dmp-core/src/music_controller/connections.rs index d6dccb5..da02cb9 100644 --- a/dmp-core/src/music_controller/connections.rs +++ b/dmp-core/src/music_controller/connections.rs @@ -364,7 +364,6 @@ fn last_fm_scrobble(scrobbler: Scrobbler, now_playing_tx: Receiver, scrobb // TODO: Add support for scrobble storage for later let mut song: Option = None; - let mut last_song: Option = None; LAST_FM_ACTIVE.store(true, Ordering::Relaxed); println!("last.fm connected"); diff --git a/dmp-core/src/music_controller/controller.rs b/dmp-core/src/music_controller/controller.rs index 261d633..53d7942 100644 --- a/dmp-core/src/music_controller/controller.rs +++ b/dmp-core/src/music_controller/controller.rs @@ -175,6 +175,7 @@ pub struct ControllerHandle { pub(super) player_mail_rx: async_channel::Sender, pub(super) queue_mail_rx: async_channel::Sender, pub(super) connections_rx: crossbeam_channel::Sender, + pub config: Arc>, } impl ControllerHandle { @@ -199,6 +200,7 @@ impl ControllerHandle { player_mail_rx: player_mail_rx.clone(), queue_mail_rx: queue_mail_rx.clone(), connections_rx: connections_mail_rx.clone(), + config: config.clone(), }, ControllerInput { player_mail: (player_mail_rx, player_mail_tx), diff --git a/dmp-core/src/music_controller/controller_handle.rs b/dmp-core/src/music_controller/controller_handle.rs index e31ed04..8a12539 100644 --- a/dmp-core/src/music_controller/controller_handle.rs +++ b/dmp-core/src/music_controller/controller_handle.rs @@ -182,7 +182,7 @@ impl ControllerHandle { self.connections_rx.send(super::connections::ConnectionsNotification::TryEnableConnection(super::connections::TryConnectionType::Discord(client_id))).unwrap(); } - pub fn listenbrainz_scrobble(&self, token: String) { + pub fn listenbrainz_scrobble_auth(&self, token: String) { self.connections_rx.send(super::connections::ConnectionsNotification::TryEnableConnection(super::connections::TryConnectionType::ListenBrainz(token))).unwrap(); } diff --git a/package.json b/package.json index a0a8c5f..752bfc0 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,8 @@ "tauri": "tauri" }, "dependencies": { - "@jprochazk/cbor": "github:jprochazk/cbor", "@tauri-apps/api": "^2", "@tauri-apps/plugin-shell": "^2", - "cbor": "github:jprochazk/cbor", - "cbor-x": "^1.6.0", "node-fetch": "^3.3.2", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/src-tauri/src/config.rs b/src-tauri/src/config.rs new file mode 100644 index 0000000..f85e95a --- /dev/null +++ b/src-tauri/src/config.rs @@ -0,0 +1,38 @@ +use std::path::PathBuf; + +use dmp_core::{config::Config, music_controller::controller::ControllerHandle}; +use tauri::{State, WebviewWindowBuilder, Window, Wry}; + +#[tauri::command] +pub async fn open_config_window(app: tauri::AppHandle) -> Result<(), String> { + WebviewWindowBuilder::new(&app, "editdmpconfig", tauri::WebviewUrl::App(PathBuf::from("src/config/index.html"))) + .title("Edit Dango Music Player") + .build() + .unwrap(); + Ok(()) +} + +#[tauri::command] +pub async fn get_config(ctrl_handle: State<'_, ControllerHandle>) -> Result { + Ok(ctrl_handle.config.read().clone()) +} + +#[tauri::command] +pub async fn save_config(ctrl_handle: State<'_, ControllerHandle>, config: Config) -> Result<(), String> { + let config_original = ctrl_handle.config.read().clone(); + + if config.connections.listenbrainz_token.as_ref().is_some_and(|t| Some(t) != config_original.connections.listenbrainz_token.as_ref()) { + let token = config.connections.listenbrainz_token.clone().unwrap(); + ctrl_handle.listenbrainz_scrobble_auth(dbg!(token)); + } + + *ctrl_handle.config.write() = config; + ctrl_handle.config.read().write_file().unwrap(); + Ok(()) +} + +#[tauri::command] +pub async fn close_window(window: Window) -> Result<(), String> { + window.close().unwrap(); + Ok(()) +} \ No newline at end of file diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 03da998..c38b223 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -8,16 +8,13 @@ use std::{ time::Duration, }; +use config::{close_window, get_config, open_config_window, save_config}; use crossbeam::channel::{bounded, unbounded, Receiver, Sender}; use dmp_core::{ config::{Config, ConfigLibrary}, - music_controller::{ - connections::ConnectionsInput, - controller::{Controller, ControllerHandle, PlaybackInfo}, - }, + music_controller::{connections::LastFMAuth, controller::{Controller, ControllerHandle, PlaybackInfo}}, music_storage::library::{MusicLibrary, Song}, }; -use futures::channel::oneshot; use parking_lot::RwLock; use tauri::{http::Response, Emitter, Manager, State, Wry}; use uuid::Uuid; @@ -27,23 +24,28 @@ use crate::wrappers::{ get_library, get_playlist, get_playlists, get_queue, get_song, import_playlist, next, pause, play, prev, remove_from_queue, seek, set_volume, }; -use commands::{add_song_to_queue, display_album_art, play_now}; +use commands::{add_song_to_queue, display_album_art, last_fm_init_auth, play_now}; pub mod commands; pub mod wrappers; +pub mod config; const DEFAULT_IMAGE: &[u8] = include_bytes!("../icons/icon.png"); +const DISCORD_CLIENT_ID: u64 = 1198868728243290152; +const LAST_FM_API_KEY: &str = env!("LAST_FM_API_KEY", "None"); +const LAST_FM_API_SECRET: &str = env!("LAST_FM_API_SECRET", "None"); + #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { - let (rx, tx) = unbounded::(); + let (config_rx, config_tx) = unbounded::(); let (lib_rx, lib_tx) = unbounded::>(); let (handle_rx, handle_tx) = unbounded::(); let (playback_info_rx, playback_info_tx) = bounded(1); let (next_rx, next_tx) = bounded(1); let _controller_thread = spawn(move || { - let mut config = { tx.recv().unwrap() }; + let mut config = { config_tx.recv().unwrap() }; let scan_path = { lib_tx.recv().unwrap() }; let _temp_config = ConfigLibrary::default(); let _lib = config.libraries.get_default().unwrap_or(&_temp_config); @@ -97,25 +99,35 @@ pub fn run() { library.save(save_path).unwrap(); + let last_fm_session = config.connections.last_fm_session.clone(); + let listenbrainz_token = config.connections.listenbrainz_token.clone(); + let (handle, input, playback_info, next_song_notification) = ControllerHandle::new( library, - std::sync::Arc::new(RwLock::new(config)), - Some(ConnectionsInput { - discord_rpc_client_id: std::option_env!("DISCORD_CLIENT_ID") - .map(|id| id.parse::().unwrap()), - }), + std::sync::Arc::new(RwLock::new(config)) ); + handle.discord_rpc(DISCORD_CLIENT_ID); + if let Some(token) = listenbrainz_token { + handle.listenbrainz_scrobble_auth(token); + } else { + println!("No ListenBrainz token found"); + } + if let Some(session) = last_fm_session { + handle.last_fm_scrobble_auth(LAST_FM_API_KEY.to_string(), LAST_FM_API_SECRET.to_string(), LastFMAuth::Session(Some(session))); + } + handle_rx.send(handle).unwrap(); playback_info_rx.send(playback_info).unwrap(); next_rx.send(next_song_notification).unwrap(); let _controller = futures::executor::block_on(Controller::start(input)).unwrap(); }); + let app = tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .invoke_handler(tauri::generate_handler![ - get_config, + init_get_config, create_new_library, get_library, play, @@ -135,8 +147,13 @@ pub fn run() { remove_from_queue, display_album_art, seek, + last_fm_init_auth, + open_config_window, + get_config, + save_config, + close_window, ]) - .manage(ConfigRx(rx)) + .manage(ConfigRx(config_rx)) .manage(LibRx(lib_rx)) .manage(HandleTx(handle_tx)) .manage(tempfile::TempDir::new().unwrap()) @@ -238,7 +255,7 @@ struct LibRx(Sender>); struct HandleTx(Receiver); #[tauri::command] -async fn get_config(state: State<'_, ConfigRx>) -> Result { +async fn init_get_config(state: State<'_, ConfigRx>) -> Result { if let Some(dir) = directories::ProjectDirs::from("", "Dangoware", "dmp") { let path = dir.config_dir(); fs::create_dir_all(path) @@ -268,6 +285,7 @@ async fn get_config(state: State<'_, ConfigRx>) -> Result { state.inner().0.send(config.clone()).unwrap(); + println!("got config"); Ok(config) } else { panic!("No config dir for DMP") diff --git a/src/App.tsx b/src/App.tsx index fec7a13..c85e1d5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -200,6 +200,7 @@ function PlaylistHead({ playlists, setPlaylists, setViewName, setLibrary }: Play } }>Library { playlists } + ) } @@ -312,12 +313,6 @@ function PlayBar({ playing, setPlaying }: PlayBarProps) { invoke('seek', { time: Math.round(val * 1000) }).then() }; - const lastFmLogin = () => { - invoke('last_fm_init_auth').then(() => { - setLastFmLoggedIn(true); - }) - } - return (
@@ -334,7 +329,6 @@ function PlayBar({ playing, setPlaying }: PlayBarProps) {
- { @@ -414,7 +408,7 @@ function QueueSong({ song, location, index }: QueueSongProps) { } function getConfig(): any { - invoke('get_config').then( (_config) => { + invoke('init_get_config').then( (_config) => { let config = _config as Config; if (config.libraries.libraries.length == 0) { invoke('create_new_library').then(() => {}) diff --git a/src/config/code.tsx b/src/config/code.tsx new file mode 100644 index 0000000..269ac28 --- /dev/null +++ b/src/config/code.tsx @@ -0,0 +1,71 @@ +import { invoke } from "@tauri-apps/api/core"; +import { ChangeEvent, useEffect, useRef, useState } from "react"; +import ReactDOM from "react-dom/client"; +import { Config, ConfigConnections } from "../types"; +import { TauriEvent } from "@tauri-apps/api/event"; + +ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( + <> + + , +); + +function App() { + let [config, setConfig] = useState(); + useEffect(() => { + invoke('get_config').then((_config) => { + let config = _config as Config; + console.log(config); + + setConfig(config); + }); + }, []) + + const last_fm_login = () => { + invoke('last_fm_init_auth').then(() => {}) + } + const save_config = () => { + invoke('save_config', { config: config }).then(() => { + // invoke('close_window').then(() => {}) + }) + } + + return ( + <> +

Config

+ + { config?.connections.last_fm_session ? (" already signed in") : () } +
+
+ + +
+
+ + + ) +} + +interface ListenBrainzProps { + config: Config | undefined, + setConfig: React.Dispatch>, +} +function ListenBrainz({ config, setConfig }: ListenBrainzProps) { + const [token, setToken] = useState(""); + + useEffect( () => { + console.log("Token: " + token); + + config? setConfig((prev) => ({...prev!, connections: {...config.connections, listenbrainz_token: token}})) : {} + }, [token]) + + const updateToken = (e: ChangeEvent)=> { + setToken(e.currentTarget.value); + } + return ( + <> + + + + ) +} \ No newline at end of file diff --git a/src/create_library_window/index.html b/src/config/index.html similarity index 85% rename from src/create_library_window/index.html rename to src/config/index.html index b17777c..4214059 100644 --- a/src/create_library_window/index.html +++ b/src/config/index.html @@ -3,7 +3,7 @@ - Library Thing + Edit Config
diff --git a/src/create_library_window/code.tsx b/src/create_library_window/code.tsx deleted file mode 100644 index a9b4490..0000000 --- a/src/create_library_window/code.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { invoke } from "@tauri-apps/api/core"; -import { useRef } from "react"; -import ReactDOM from "react-dom/client"; - -ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( - , -); - - -function App() { - let x = useRef('') - return ( - <> -

Insert your music folder path here

-
- x.current = event.target.value as string } /> - { - event.preventDefault(); - invoke('create_library', { path: x.current }).then(() => {}) - }} /> -
- - ) -} diff --git a/src/types.ts b/src/types.ts index 5c3a261..0f2b034 100644 --- a/src/types.ts +++ b/src/types.ts @@ -20,6 +20,8 @@ export interface Config { } export interface ConfigConnections { + discord_rpc_client_id?: number, + last_fm_session?: string, listenbrainz_token?: string }