rip off amberol

This commit is contained in:
Erica Z 2024-11-13 22:28:49 +01:00
parent a25333ec79
commit 641161c059
4 changed files with 76 additions and 22 deletions

25
Cargo.lock generated
View file

@ -221,6 +221,7 @@ dependencies = [
"bindgen", "bindgen",
"bytes", "bytes",
"chrono", "chrono",
"color-thief",
"event-listener", "event-listener",
"futures", "futures",
"gettext-rs", "gettext-rs",
@ -334,6 +335,12 @@ version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytemuck"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.5.0" version = "1.5.0"
@ -455,6 +462,15 @@ dependencies = [
"libloading", "libloading",
] ]
[[package]]
name = "color-thief"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6460d760cf38ce67c9e0318f896538820acc54f2d0a3bfc5b2c557211066c98"
dependencies = [
"rgb",
]
[[package]] [[package]]
name = "concurrent-queue" name = "concurrent-queue"
version = "2.5.0" version = "2.5.0"
@ -2081,6 +2097,15 @@ dependencies = [
"windows-registry", "windows-registry",
] ]
[[package]]
name = "rgb"
version = "0.8.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a"
dependencies = [
"bytemuck",
]
[[package]] [[package]]
name = "ring" name = "ring"
version = "0.17.8" version = "0.17.8"

View file

@ -8,6 +8,7 @@ adw = { version = "0.7.0", package = "libadwaita", features = ["v1_6"] }
async-channel = "2.3.1" async-channel = "2.3.1"
bytes = "1.8.0" bytes = "1.8.0"
chrono = { version = "0.4.38", features = ["serde"] } chrono = { version = "0.4.38", features = ["serde"] }
color-thief = "0.2.2"
event-listener = "5.3.1" event-listener = "5.3.1"
futures = "0.3.31" futures = "0.3.31"
gettext-rs = { version = "0.7.2", features = ["gettext-system"] } gettext-rs = { version = "0.7.2", features = ["gettext-system"] }

View file

@ -1,3 +1,13 @@
window.background > * {
/* from amberol */
background: linear-gradient(127deg, color-mix(in srgb, var(--background-color-0) 55%, transparent), color-mix(in srgb, var(--background-color-0) 0%, transparent) 70.71%),
linear-gradient(217deg, color-mix(in srgb, var(--background-color-1) 55%, transparent), color-mix(in srgb, var(--background-color-1) 0%, transparent) 70.71%),
linear-gradient(336deg, color-mix(in srgb, var(--background-color-2) 55%, transparent), color-mix(in srgb, var(--background-color-2) 0%, transparent) 70.71%);
transition-property: background;
transition-duration: 250ms;
transition-timing-function: ease;
}
#seek-scale slider { #seek-scale slider {
margin: 0px; margin: 0px;
opacity: 0%; opacity: 0%;

View file

@ -87,6 +87,8 @@ mod imp {
#[property(get, set)] #[property(get, set)]
refreshing_albums: Cell<bool>, refreshing_albums: Cell<bool>,
css_provider: gtk::CssProvider,
} }
impl Default for Window { impl Default for Window {
@ -146,6 +148,8 @@ mod imp {
mpris_player: Default::default(), mpris_player: Default::default(),
refreshing_albums: Cell::new(true), refreshing_albums: Cell::new(true),
css_provider: gtk::CssProvider::new(),
} }
} }
} }
@ -171,6 +175,10 @@ mod imp {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
if let Some(display) = gdk::Display::default() {
gtk::style_context_add_provider_for_display(&display, &self.css_provider, 420);
}
use gio::ActionEntry; use gio::ActionEntry;
let action_seek_backward = ActionEntry::builder("seek-backward") let action_seek_backward = ActionEntry::builder("seek-backward")
@ -671,32 +679,41 @@ mod imp {
match window.song() { match window.song() {
Some(song) if song.id() == song_id => { Some(song) if song.id() == song_id => {
let texture = gdk::Texture::from_bytes(&glib::Bytes::from_owned(bytes)) let loader = gtk::gdk_pixbuf::PixbufLoader::new(); // TODO: pass mime type?
.expect("could not create texture from cover art for {song_id}"); loader.write(&bytes).unwrap();
loader.close().unwrap();
let pixbuf = loader.pixbuf().unwrap();
let texture = gdk::Texture::for_pixbuf(&pixbuf);
window.set_playing_cover_art(Some(&texture.clone().into())); window.set_playing_cover_art(Some(&texture.clone().into()));
// from g4music // from amberol
let snapshot = gtk::Snapshot::new(); let palette = color_thief::get_palette(
snapshot.push_blur(512.0 * 0.1); pixbuf.pixel_bytes().unwrap().as_ref(),
snapshot.push_opacity(0.5); if pixbuf.has_alpha() {
texture.snapshot(&snapshot, 512.0, 512.0); color_thief::ColorFormat::Rgba
snapshot.pop(); } else {
snapshot.pop(); color_thief::ColorFormat::Rgb
},
5,
4,
)
.unwrap();
use gtk::graphene; let mut css = String::new();
let rect = graphene::Rect::new(0.0, 0.0, 512.0, 512.0); css.push_str(":root {");
if let Some(node) = snapshot.clone().to_node() { let n_colors = palette.len();
window.set_background(Some( for (i, color) in palette.into_iter().enumerate() {
window css.push_str(&format!("--background-color-{i}: {color}; "));
.native()
.unwrap()
.renderer()
.unwrap()
.render_texture(node, Some(&rect)),
));
} else {
todo!();
} }
for i in n_colors..3 {
css.push_str(&format!(
"--background-color-{i}: var(--window-bg-color); "
));
}
css.push_str("}");
window.imp().css_provider.load_from_string(&css);
} }
_ => { _ => {
event!( event!(
@ -762,6 +779,7 @@ mod imp {
match self.state.get() { match self.state.get() {
State::Active => {} State::Active => {}
State::FileLoading => {} State::FileLoading => {}
State::FileLoaded => {}
State::Seeking => {} State::Seeking => {}
other => panic!("invalid state transition: EndFile from {other:?}"), other => panic!("invalid state transition: EndFile from {other:?}"),