died once

This commit is contained in:
Erica Z 2024-11-03 20:00:46 +01:00
parent 301c934567
commit 616aefc1c4
4 changed files with 63 additions and 109 deletions

View file

@ -1,21 +0,0 @@
public class Audrey.PlaybinSong : Object {
private static int64 next_counter = 0;
public int64 counter { get; private set; }
public string id { get; set; }
public string title { get; set; }
public string artist { get; set; }
public string album { get; set; }
public string? genre { get; set; }
public int64 duration { get; set; }
public int64 track { get; set; }
public int64 play_count { get; set; }
public string cover_art_url { get; set; }
public string stream_url { get; set; }
construct {
this.counter = next_counter;
next_counter += 1;
}
}

View file

@ -1,106 +1,81 @@
pub mod ffi { mod imp {
use adw::prelude::*;
use gtk::glib; use gtk::glib;
use std::ffi::c_char; use gtk::subclass::prelude::*;
use std::cell::{Cell, RefCell};
#[repr(C)] static NEXT_COUNTER: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
pub struct AudreyPlaybinSong {
_data: [u8; 0], #[derive(glib::Properties, Default)]
#[properties(wrapper_type = super::Song)]
pub struct Song {
#[property(get, set)]
counter: Cell<u64>,
#[property(get, set)]
id: RefCell<String>,
#[property(get, set)]
title: RefCell<String>,
#[property(get, set)]
artist: RefCell<String>,
#[property(get, set)]
album: RefCell<String>,
#[property(get, set)]
genre: RefCell<Option<String>>,
#[property(get, set)]
duration: Cell<i64>,
#[property(get, set)]
track: Cell<i64>,
#[property(get, set)]
cover_art_url: RefCell<String>,
#[property(get, set)]
stream_url: RefCell<String>,
} }
#[repr(C)] #[glib::object_subclass]
pub struct AudreyPlaybinSongClass { impl ObjectSubclass for Song {
_data: [u8; 0], const NAME: &'static str = "AudreyPlaybinSong";
type Type = super::Song;
} }
extern "C" { #[glib::derived_properties]
pub fn audrey_playbin_song_get_type() -> glib::ffi::GType; impl ObjectImpl for Song {
pub fn audrey_playbin_song_get_counter(self_: *mut AudreyPlaybinSong) -> i64; fn constructed(&self) {
pub fn audrey_playbin_song_get_id(self_: *mut AudreyPlaybinSong) -> *const c_char; self.parent_constructed();
pub fn audrey_playbin_song_get_title(self_: *mut AudreyPlaybinSong) -> *const c_char;
pub fn audrey_playbin_song_get_artist(self_: *mut AudreyPlaybinSong) -> *const c_char;
pub fn audrey_playbin_song_get_album(self_: *mut AudreyPlaybinSong) -> *const c_char;
pub fn audrey_playbin_song_get_duration(self_: *mut AudreyPlaybinSong) -> i64;
pub fn audrey_playbin_song_get_cover_art_url( self.obj()
self_: *mut AudreyPlaybinSong, .set_counter(NEXT_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed));
) -> *const c_char; }
pub fn audrey_playbin_song_get_stream_url(self_: *mut AudreyPlaybinSong) -> *const c_char;
} }
} }
use glib::translate::{from_glib_none, ToGlibPtr}; use crate::subsonic;
use glib::GString; use glib::Object;
use gtk::glib; use gtk::glib;
glib::wrapper! { glib::wrapper! {
pub struct Song(Object<ffi::AudreyPlaybinSong, ffi::AudreyPlaybinSongClass>); pub struct Song(ObjectSubclass<imp::Song>);
match fn {
type_ => || ffi::audrey_playbin_song_get_type(),
}
} }
impl Song { impl Song {
pub fn counter(&self) -> i64 { pub fn from_child(api: &subsonic::Client, song: &subsonic::schema::Child) -> Self {
unsafe { ffi::audrey_playbin_song_get_counter(self.to_glib_none().0) } Object::builder()
} .property("id", &song.id)
.property("title", &song.title)
pub fn id(&self) -> GString { .property("artist", &song.artist)
unsafe { from_glib_none(ffi::audrey_playbin_song_get_id(self.to_glib_none().0)) } .property("album", &song.album)
} .property("genre", &song.genre)
.property("duration", song.duration as i64)
pub fn title(&self) -> GString { //.property("track", song.track)
unsafe { from_glib_none(ffi::audrey_playbin_song_get_title(self.to_glib_none().0)) } .property("cover-art-url", api.cover_art_url(&song.id).as_str())
} .property("stream-url", api.stream_url(&song.id).as_str())
pub fn artist(&self) -> GString {
unsafe { from_glib_none(ffi::audrey_playbin_song_get_artist(self.to_glib_none().0)) }
}
pub fn album(&self) -> GString {
unsafe { from_glib_none(ffi::audrey_playbin_song_get_album(self.to_glib_none().0)) }
}
pub fn duration(&self) -> i64 {
unsafe { ffi::audrey_playbin_song_get_duration(self.to_glib_none().0) }
}
pub fn cover_art_url(&self) -> url::Url {
let url: String = unsafe {
from_glib_none(ffi::audrey_playbin_song_get_cover_art_url(
self.to_glib_none().0,
))
};
url::Url::parse(&url).expect("invalid url from vala side")
}
pub fn stream_url(&self) -> url::Url {
let url: String = unsafe {
from_glib_none(ffi::audrey_playbin_song_get_stream_url(
self.to_glib_none().0,
))
};
url::Url::parse(&url).expect("invalid url from vala side")
}
pub fn from_child(
api: &crate::subsonic::Client,
child: &crate::subsonic::schema::Child,
) -> Self {
glib::Object::builder()
.property("id", &child.id)
.property("title", &child.title)
.property("artist", &child.artist)
.property("album", &child.album)
.property("duration", child.duration as i64)
.property("cover-art-url", api.cover_art_url(&child.id).as_str())
.property("stream-url", api.stream_url(&child.id).as_str())
.build() .build()
} }
} }
impl crate::playbin::PlaybinEntry for Song { impl crate::playbin::PlaybinEntry for Song {
fn url(&self) -> url::Url { fn url(&self) -> url::Url {
self.stream_url() url::Url::parse(&self.stream_url()).unwrap()
} }
} }

View file

@ -47,7 +47,7 @@ pub struct Child {
pub starred: Option<chrono::DateTime<chrono::offset::Utc>>, // TODO: check which is best pub starred: Option<chrono::DateTime<chrono::offset::Utc>>, // TODO: check which is best
// applicable // applicable
pub duration: u64, pub duration: u64,
pub play_count: Option<u32>, //pub play_count: Option<u32>,
pub genre: Option<String>, pub genre: Option<String>,
pub cover_art: String, pub cover_art: String,
} }

View file

@ -54,23 +54,23 @@ mod imp {
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl Playbar { impl Playbar {
#[template_callback] #[template_callback]
fn song_title(&self, song: Option<&PlaybinSong>) -> Option<GString> { fn song_title(&self, song: Option<&PlaybinSong>) -> Option<String> {
song.map(|song| song.title()) song.map(|song| song.title())
} }
#[template_callback] #[template_callback]
fn song_artist(&self, song: Option<&PlaybinSong>) -> Option<GString> { fn song_artist(&self, song: Option<&PlaybinSong>) -> Option<String> {
song.map(|song| song.artist()) song.map(|song| song.artist())
} }
#[template_callback] #[template_callback]
fn song_album(&self, song: Option<&PlaybinSong>) -> Option<GString> { fn song_album(&self, song: Option<&PlaybinSong>) -> Option<String> {
song.map(|song| song.album()) song.map(|song| song.album())
} }
#[template_callback] #[template_callback]
fn format_timestamp(&self, s: f64) -> GString { fn format_timestamp(&self, s: f64) -> String {
gformat!("{:02}:{:02}", (s as i64) / 64, (s as i64) % 60) format!("{:02}:{:02}", (s as i64) / 64, (s as i64) % 60)
} }
#[template_callback] #[template_callback]