From 55c477b84f922a929f8799d85b2e79141e670fcb Mon Sep 17 00:00:00 2001 From: holby Date: Thu, 24 Oct 2024 10:10:26 -0400 Subject: [PATCH] WIP --- Cargo.lock | 1 + examples/boilerplate-solid-ts/dist/index.html | 2 +- .../src/providers/create-provider.ts | 10 +- packages/client-api/src/providers/index.ts | 1 + .../providers/media/create-media-provider.ts | 29 ++++ .../providers/media/media-provider-types.ts | 21 +++ packages/desktop/Cargo.toml | 1 + .../src/providers/media/media_provider.rs | 162 +++++------------- .../desktop/src/providers/provider_ref.rs | 10 +- 9 files changed, 114 insertions(+), 123 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1eafd9b..24737786 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6690,6 +6690,7 @@ dependencies = [ "clap", "cocoa 0.25.0", "komorebi-client", + "lazy_static", "netdev", "regex", "reqwest 0.11.27", diff --git a/examples/boilerplate-solid-ts/dist/index.html b/examples/boilerplate-solid-ts/dist/index.html index d4f5fe0a..26d2bdef 100644 --- a/examples/boilerplate-solid-ts/dist/index.html +++ b/examples/boilerplate-solid-ts/dist/index.html @@ -5,7 +5,7 @@ Zebar - + diff --git a/packages/client-api/src/providers/create-provider.ts b/packages/client-api/src/providers/create-provider.ts index 80dcbd95..7986050f 100644 --- a/packages/client-api/src/providers/create-provider.ts +++ b/packages/client-api/src/providers/create-provider.ts @@ -35,6 +35,11 @@ import type { KomorebiProviderConfig, KomorebiProvider, } from './komorebi/komorebi-provider-types'; +import type { + MediaProviderConfig, + MediaProvider, +} from './media/media-provider-types'; +import { createMediaProvider } from './media/create-media-provider'; import { createMemoryProvider } from './memory/create-memory-provider'; import type { MemoryProviderConfig, @@ -59,7 +64,7 @@ export interface ProviderConfigMap { host: HostProviderConfig; ip: IpProviderConfig; komorebi: KomorebiProviderConfig; - // media: MediaProviderConfig; + media: MediaProviderConfig; memory: MemoryProviderConfig; network: NetworkProviderConfig; weather: WeatherProviderConfig; @@ -74,6 +79,7 @@ export interface ProviderMap { host: HostProvider; ip: IpProvider; komorebi: KomorebiProvider; + media: MediaProvider; memory: MemoryProvider; network: NetworkProvider; weather: WeatherProvider; @@ -115,6 +121,8 @@ export function createProvider( return createIpProvider(config) as any; case 'komorebi': return createKomorebiProvider(config) as any; + case 'media': + return createMediaProvider(config) as any; case 'memory': return createMemoryProvider(config) as any; case 'network': diff --git a/packages/client-api/src/providers/index.ts b/packages/client-api/src/providers/index.ts index 1fe7adbb..e9be9e5a 100644 --- a/packages/client-api/src/providers/index.ts +++ b/packages/client-api/src/providers/index.ts @@ -6,6 +6,7 @@ export * from './host/host-provider-types'; export * from './ip/ip-provider-types'; export * from './keyboard/keyboard-provider-types'; export * from './komorebi/komorebi-provider-types'; +export * from './media/media-provider-types'; export * from './memory/memory-provider-types'; export * from './network/network-provider-types'; export * from './weather/weather-provider-types'; diff --git a/packages/client-api/src/providers/media/create-media-provider.ts b/packages/client-api/src/providers/media/create-media-provider.ts index e69de29b..ea889f14 100644 --- a/packages/client-api/src/providers/media/create-media-provider.ts +++ b/packages/client-api/src/providers/media/create-media-provider.ts @@ -0,0 +1,29 @@ +import {z} from 'zod'; +import {createBaseProvider} from '../create-base-provider'; +import {onProviderEmit} from '~/desktop'; +import type { + MediaOutput, + MediaProvider, + MediaProviderConfig, +} from './media-provider-types'; + +const mediaProviderConfigSchema = z.object({ + type: z.literal('media'), + refreshInterval: z.coerce.number().default(5 * 1000), +}); + +export function createMediaProvider( + config: MediaProviderConfig, +): MediaProvider { + const mergedConfig = mediaProviderConfigSchema.parse(config); + + return createBaseProvider(mergedConfig, async queue => { + return onProviderEmit(mergedConfig, ({result}) => { + if ('error' in result) { + queue.error(result.error); + } else { + queue.output(result.output); + } + }); + }); +} diff --git a/packages/client-api/src/providers/media/media-provider-types.ts b/packages/client-api/src/providers/media/media-provider-types.ts index e69de29b..5a0448c1 100644 --- a/packages/client-api/src/providers/media/media-provider-types.ts +++ b/packages/client-api/src/providers/media/media-provider-types.ts @@ -0,0 +1,21 @@ +import type {Provider} from '../create-base-provider'; + +export interface MediaProviderConfig { + type: 'media'; + /** + * How often this provider refreshes in milliseconds. + */ + refreshInterval?: number; +} + +export interface MediaOutput { + title: string; + subTitle: string; + trackNumber: number; + artist: string; + albumTitle: string; + isPlaying: boolean; + isSpotify: boolean; +} + +export type MediaProvider = Provider; diff --git a/packages/desktop/Cargo.toml b/packages/desktop/Cargo.toml index b8326a8f..029edff6 100644 --- a/packages/desktop/Cargo.toml +++ b/packages/desktop/Cargo.toml @@ -36,6 +36,7 @@ tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } netdev = "0.24" regex = "1" +lazy_static = "1.5.0" [target.'cfg(target_os = "windows")'.dependencies] komorebi-client = { git = "https://github.com/LGUG2Z/komorebi", tag = "v0.1.28" } diff --git a/packages/desktop/src/providers/media/media_provider.rs b/packages/desktop/src/providers/media/media_provider.rs index c101c19b..519d8393 100644 --- a/packages/desktop/src/providers/media/media_provider.rs +++ b/packages/desktop/src/providers/media/media_provider.rs @@ -1,7 +1,12 @@ +use std::sync::Arc; + use anyhow::{Context, Ok, Result}; use async_trait::async_trait; use serde::{Deserialize, Serialize}; -use tokio::{sync::mpsc::Sender, time}; +use tokio::{ + sync::{mpsc::Sender, Mutex}, + time, +}; use windows::{ Foundation::{EventRegistrationToken, TypedEventHandler}, Media::Control::{ @@ -12,7 +17,7 @@ use windows::{ SessionsChangedEventArgs, }, }; - +use lazy_static::lazy_static; use crate::{ impl_interval_provider, providers::{Provider, ProviderOutput, ProviderResult}, @@ -20,9 +25,7 @@ use crate::{ #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] -pub struct MediaProviderConfig { - pub refresh_interval: u64, -} +pub struct MediaProviderConfig {} #[derive(Debug, Clone, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] @@ -38,31 +41,51 @@ pub struct MediaOutput { pub struct MediaProvider { _config: MediaProviderConfig, - current_session: Option, + current_session: + Arc>>, session_changed_event_handler: TypedEventHandler< GlobalSystemMediaTransportControlsSessionManager, SessionsChangedEventArgs, >, - media_properties_changed_event_handler: TypedEventHandler< + media_properties_event_handler: TypedEventHandler< GlobalSystemMediaTransportControlsSession, MediaPropertiesChangedEventArgs, >, + playback_info_event_handler: TypedEventHandler< + GlobalSystemMediaTransportControlsSession, + PlaybackInfoChangedEventArgs, + >, } impl MediaProvider { + // lazy_static! { + // static ref CURRENT_SESSION: Arc>> = + // Arc::new(Mutex::new(None)); + // } + pub fn new(config: MediaProviderConfig) -> MediaProvider { MediaProvider { _config: config, - current_session: None, + current_session: Arc::new(Mutex::new(None)), session_changed_event_handler: TypedEventHandler::new( MediaProvider::current_session_changed, ), - media_properties_changed_event_handler: TypedEventHandler::new( + media_properties_event_handler: TypedEventHandler::new( MediaProvider::media_properties_changed, ), + playback_info_event_handler: TypedEventHandler::new( + MediaProvider::playback_info_changed, + ), } } + fn playback_info_changed( + session: &Option, + _args: &Option, + ) -> windows::core::Result<()> { + windows::core::Result::Ok(()) + } + fn media_properties_changed( session: &Option, _args: &Option, @@ -78,14 +101,19 @@ impl MediaProvider { ) -> windows::core::Result<()> { if let Some(session_manager) = session_manager { let session = session_manager.GetCurrentSession()?; - // self.current_session = Some(session); + let mut current_session = self.current_session.lock().unwrap(); + *current_session = Some(session); } windows::core::Result::Ok(()) } fn print_current_media_info(&self) -> anyhow::Result<()> { - let media_properties = - &self.current_session?.TryGetMediaPropertiesAsync()?.get()?; + let media_properties = &self + .current_session + .lock() + .unwrap() + .TryGetMediaPropertiesAsync()? + .get()?; println!("Title: {}", media_properties.Title()?); println!("Artist: {}", media_properties.Artist()?); println!("Album: {}", media_properties.AlbumTitle()?); @@ -107,108 +135,11 @@ impl MediaProvider { .context("Failed to aquire initial media session")?; println!("Initial current session obtained."); - MediaProvider::print_current_media_info(¤t_session); - - // ------------------------------- - - let media_properties_changed_handler = TypedEventHandler::new( - move |session: &Option< - GlobalSystemMediaTransportControlsSession, - >, - _| { - println!("Media properties changed event triggered."); - let session = session - .as_ref() - .expect("No session available on media properties change."); - MediaProvider::print_current_media_info(session); - windows::core::Result::Ok(()) - }, - ); - - current_session.MediaPropertiesChanged( - &self.media_properties_changed_event_handler, - )?; - - // current_session.MediaPropertiesChanged(& - // media_properties_changed_handler)?; - - // if let Err(e) = current_session - // .MediaPropertiesChanged(&media_properties_changed_handler) - // { - // eprintln!( - // "Failed to attach media properties changed handler: {:?}", - // e - // ); - // } else { - // println!("Media properties changed handler attached."); - // } - - let session_changed_handler = TypedEventHandler::new( - |session_manager: &Option< - GlobalSystemMediaTransportControlsSessionManager, - >, - _| { - println!("Session changed event triggered."); - if let Some(session_manager) = session_manager { - if let Ok(current_session) = session_manager.GetCurrentSession() - { - println!("Current session obtained."); - if let Err(e) = - MediaProvider::print_current_media_info(¤t_session) - { - eprintln!("Failed to get media properties: {:?}", e); - } - - // Attach an event listener to the current session for media - // property changes - let media_properties_changed_handler = TypedEventHandler::new( - move |session: &Option< - GlobalSystemMediaTransportControlsSession, - >, - _| { - println!("Media properties changed event triggered."); - if let Some(session) = session { - if let Err(e) = - MediaProvider::print_current_media_info(session) - { - eprintln!("Failed to get media properties: {:?}", e); - } - } else { - println!( - "No session available on media properties change." - ); - } - Ok(()) - }, - ); - - if let Err(e) = current_session - .MediaPropertiesChanged(&media_properties_changed_handler) - { - eprintln!( - "Failed to attach media properties changed handler: {:?}", - e - ); - } else { - println!("Media properties changed handler attached."); - } - } else { - println!("No current session available."); - } - } else { - println!("No session manager available."); - } - Ok(()) - }, - ); - - if let Err(e) = - session_manager.CurrentSessionChanged(&session_changed_handler) - { - eprintln!("Failed to attach session changed handler: {:?}", e); - } else { - println!("Event handler for session changes attached."); - } + self.print_current_media_info()?; + + current_session + .MediaPropertiesChanged(&self.media_properties_event_handler)?; + Ok(()) } } @@ -219,9 +150,6 @@ impl Provider for MediaProvider { if let Err(err) = self.create_session_manager() { emit_result_tx.send(Err(err).into()).await; } - // if let Err(err) = self.bind_media_events() { - // emit_result_tx.send(Err(err).into()).await; - // } } } diff --git a/packages/desktop/src/providers/provider_ref.rs b/packages/desktop/src/providers/provider_ref.rs index 76d29278..8a774ef5 100644 --- a/packages/desktop/src/providers/provider_ref.rs +++ b/packages/desktop/src/providers/provider_ref.rs @@ -12,9 +12,9 @@ use tracing::{info, warn}; use super::{ battery::BatteryProvider, cpu::CpuProvider, host::HostProvider, - ip::IpProvider, media::MediaProvider, memory::MemoryProvider, network::NetworkProvider, - weather::WeatherProvider, Provider, ProviderConfig, ProviderOutput, - SharedProviderState, + ip::IpProvider, media::MediaProvider, memory::MemoryProvider, + network::NetworkProvider, weather::WeatherProvider, Provider, + ProviderConfig, ProviderOutput, SharedProviderState, }; #[cfg(windows)] use super::{keyboard::KeyboardProvider, komorebi::KomorebiProvider}; @@ -177,7 +177,9 @@ impl ProviderRef { Box::new(MediaProvider::new(config)) } ProviderConfig::Memory(config) => { - Box::new(MediaProvider::new(super::media::MediaProviderConfig { refresh_interval: 0 })); + Box::new(MediaProvider::new(super::media::MediaProviderConfig { + refresh_interval: 0, + })); Box::new(MemoryProvider::new(config, shared_state.sysinfo.clone())) } ProviderConfig::Network(config) => Box::new(NetworkProvider::new(