Compare commits

...

2 commits

Author SHA1 Message Date
0320e12206 kill ffi 2024-10-31 12:02:58 +01:00
efbe32ed22 translate play queue widget 2024-10-31 12:02:00 +01:00
10 changed files with 100 additions and 160 deletions

View file

@ -28,16 +28,16 @@ template $AudreyUiPlayQueue: Adw.Bin {
show-separators: true; show-separators: true;
single-click-activate: true; single-click-activate: true;
activate => $on_row_activated (); activate => $on_row_activated () swapped;
model: NoSelection { model: NoSelection {
model: bind template.playbin as <$AudreyPlaybin>.play_queue; model: bind template.playbin as <$AudreyPlaybin>.play_queue;
}; };
factory: SignalListItemFactory { factory: SignalListItemFactory {
setup => $on_song_list_setup (); setup => $on_song_list_setup () swapped;
bind => $on_song_list_bind (); bind => $on_song_list_bind () swapped;
unbind => $on_song_list_unbind (); unbind => $on_song_list_unbind () swapped;
}; };
} }
}; };

6
src/ffi.rs Normal file
View file

@ -0,0 +1,6 @@
#![allow(dead_code)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
include!(concat!(env!("OUT_DIR"), "/audrey_ffi.rs"));

View file

@ -29,6 +29,7 @@ fn main() -> glib::ExitCode {
gio::resources_register_include!("audrey.gresource").expect("could not register resources"); gio::resources_register_include!("audrey.gresource").expect("could not register resources");
ui::Playbar::ensure_type(); ui::Playbar::ensure_type();
ui::PlayQueue::ensure_type();
gtk::disable_setlocale(); gtk::disable_setlocale();
bindtextdomain("audrey", meson_config::LOCALEDIR).expect("failed to bind text domain"); bindtextdomain("audrey", meson_config::LOCALEDIR).expect("failed to bind text domain");

View file

@ -5,7 +5,6 @@ audrey_sources = [
'playbin.vala', 'playbin.vala',
'rust.vapi', 'rust.vapi',
'subsonic.vala', 'subsonic.vala',
'ui/play_queue.vala',
'ui/setup.vala', 'ui/setup.vala',
'ui/window.vala', 'ui/window.vala',
] ]

View file

@ -40,6 +40,7 @@ pub mod ffi {
to: std::ffi::c_uint, to: std::ffi::c_uint,
); );
pub fn audrey_playbin_remove_track(self_: *mut AudreyPlaybin, position: std::ffi::c_uint); pub fn audrey_playbin_remove_track(self_: *mut AudreyPlaybin, position: std::ffi::c_uint);
pub fn audrey_playbin_select_track(self_: *mut AudreyPlaybin, position: std::ffi::c_uint);
} }
} }
@ -116,4 +117,8 @@ impl Playbin {
pub fn remove_track(&self, position: u32) { pub fn remove_track(&self, position: u32) {
unsafe { ffi::audrey_playbin_remove_track(self.to_glib_none().0, position) } unsafe { ffi::audrey_playbin_remove_track(self.to_glib_none().0, position) }
} }
pub fn select_track(&self, position: u32) {
unsafe { ffi::audrey_playbin_select_track(self.to_glib_none().0, position) }
}
} }

View file

@ -15,3 +15,6 @@ void audrey_ui_play_queue_song_set_show_artist(AudreyUiPlayQueueSong *self, gboo
void audrey_ui_play_queue_song_set_show_cover(AudreyUiPlayQueueSong *self, gboolean show_cover); void audrey_ui_play_queue_song_set_show_cover(AudreyUiPlayQueueSong *self, gboolean show_cover);
void audrey_ui_play_queue_song_bind(AudreyUiPlayQueueSong *self, guint position, void *song); void audrey_ui_play_queue_song_bind(AudreyUiPlayQueueSong *self, guint position, void *song);
void audrey_ui_play_queue_song_unbind(AudreyUiPlayQueueSong *self); void audrey_ui_play_queue_song_unbind(AudreyUiPlayQueueSong *self);
// ui::PlayQueue
typedef void AudreyUiPlayQueue;

View file

@ -23,4 +23,9 @@ namespace Audrey {
public void unbind (); public void unbind ();
} }
public class Ui.PlayQueue : Adw.Bin {
public Playbin playbin { get; set; }
public bool can_clear_all { get; }
}
} }

View file

@ -1,32 +1,92 @@
pub mod song; pub mod song;
pub use song::Song; pub use song::Song;
mod ffi { mod imp {
use gtk::glib; use adw::{glib, prelude::*, subclass::prelude::*};
use glib::{subclass::InitializingObject, WeakRef};
#[repr(C)] #[derive(gtk::CompositeTemplate, glib::Properties, Default)]
pub struct AudreyUiPlayQueue { #[template(resource = "/eu/callcc/audrey/play_queue.ui")]
_data: [u8; 0], #[properties(wrapper_type = super::PlayQueue)]
pub struct PlayQueue {
#[property(get, set)]
playbin: WeakRef<crate::Playbin>,
} }
#[repr(C)] #[glib::object_subclass]
pub struct AudreyUiPlayQueueClass { impl ObjectSubclass for PlayQueue {
_data: [u8; 0], const NAME: &'static str = "AudreyUiPlayQueue";
type Type = super::PlayQueue;
type ParentType = adw::Bin;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
klass.bind_template_callbacks();
} }
extern "C" { fn instance_init(obj: &InitializingObject<Self>) {
pub fn audrey_ui_play_queue_get_type() -> glib::ffi::GType; obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for PlayQueue {}
impl WidgetImpl for PlayQueue {}
impl BinImpl for PlayQueue {}
#[gtk::template_callbacks]
impl PlayQueue {
#[template_callback]
fn visible_child_name(&self, n_items: u32) -> &'static str {
if n_items > 0 {
"not-empty"
} else {
"empty"
}
}
#[template_callback]
fn on_song_list_setup(&self, item: &gtk::ListItem, _factory: &gtk::SignalListItemFactory) {
let child = super::Song::new(&self.playbin.upgrade().unwrap());
child.set_draggable(true);
child.set_show_position(true);
child.set_show_artist(true);
child.set_show_cover(true);
item.set_child(Some(&child));
}
#[template_callback]
fn on_song_list_bind(&self, item: &gtk::ListItem, _factory: &gtk::SignalListItemFactory) {
let child = item.child().and_downcast::<super::Song>().unwrap();
child.bind(
item.position(),
item.item().unwrap().downcast_ref::<crate::playbin::Song>().unwrap(),
);
}
#[template_callback]
fn on_song_list_unbind(&self, item: &gtk::ListItem, _factory: &gtk::SignalListItemFactory) {
let child = item.child().and_downcast::<super::Song>().unwrap();
child.unbind();
}
#[template_callback]
fn on_row_activated(&self, position: u32) {
self.obj().playbin().unwrap().select_track(position);
}
} }
} }
use gtk::glib; use gtk::glib;
glib::wrapper! { glib::wrapper! {
pub struct PlayQueue(Object<ffi::AudreyUiPlayQueue, ffi::AudreyUiPlayQueueClass>) pub struct PlayQueue(ObjectSubclass<imp::PlayQueue>)
@extends adw::Bin, gtk::Widget, @extends adw::Bin, gtk::Widget,
@implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget; @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
match fn {
type_ => || ffi::audrey_ui_play_queue_get_type(),
}
} }

View file

@ -1,63 +0,0 @@
/*
[GtkTemplate (ui = "/eu/callcc/audrey/play_queue.ui")]
public class Audrey.Ui.PlayQueue : Adw.Bin {
private weak Playbin _playbin;
public Playbin playbin {
get { return _playbin; }
set {
assert (_playbin == null); // only set once
_playbin = value;
_playbin.play_queue.items_changed.connect (this.on_store_items_changed);
this.can_clear_all = _playbin.play_queue.get_n_items () > 0;
}
}
public bool can_clear_all { get; private set; }
/*[GtkCallback] private void on_clear () {
this.playbin.clear ();
}*/
private void on_store_items_changed (GLib.ListModel store, uint position, uint removed, uint added) {
this.can_clear_all = store.get_n_items () > 0;
}
[GtkCallback] private void on_song_list_setup (Gtk.SignalListItemFactory factory, Object object) {
var item = object as Gtk.ListItem;
var child = new PlayQueueSong (this.playbin);
child.draggable = true;
child.show_position = true;
child.show_artist = true;
child.show_cover = true;
item.child = child;
}
[GtkCallback] private void on_song_list_bind (Gtk.SignalListItemFactory factory, Object object) {
var item = object as Gtk.ListItem;
var child = item.child as PlayQueueSong;
child.bind (item.position, item.item as PlaybinSong);
}
[GtkCallback] private void on_song_list_unbind (Gtk.SignalListItemFactory factory, Object object) {
var item = object as Gtk.ListItem;
var child = item.child as PlayQueueSong;
child.unbind ();
}
[GtkCallback] private void on_row_activated (uint position) {
playbin.select_track (position);
}
[GtkCallback] private string visible_child_name (uint n_items) {
return n_items > 0 ? "not-empty" : "empty";
}
~PlayQueue () {
debug ("destroying play queue widget");
}
}

View file

@ -1,7 +1,7 @@
mod imp { mod imp {
use glib::{subclass::InitializingObject, WeakRef}; use glib::{subclass::InitializingObject, WeakRef};
use gtk::{gdk, gio, glib, prelude::*, subclass::prelude::*}; use gtk::{gdk, gio, glib, prelude::*, subclass::prelude::*};
use std::cell::{RefCell, Cell}; use std::cell::{Cell, RefCell};
#[derive(gtk::CompositeTemplate, glib::Properties, Default)] #[derive(gtk::CompositeTemplate, glib::Properties, Default)]
#[template(resource = "/eu/callcc/audrey/play_queue_song.ui")] #[template(resource = "/eu/callcc/audrey/play_queue_song.ui")]
@ -208,79 +208,3 @@ impl Song {
.disconnect(self.imp().connection.take().unwrap()); .disconnect(self.imp().connection.take().unwrap());
} }
} }
pub mod ffi {
use adw::prelude::*;
use glib::ffi::{gboolean, GType};
use glib::subclass::basic::InstanceStruct;
use glib::translate::{from_glib, from_glib_none, IntoGlib, IntoGlibPtr};
use gtk::glib;
use std::ffi::c_uint;
type AudreyUiPlayQueueSong = InstanceStruct<super::imp::Song>;
#[no_mangle]
extern "C" fn audrey_ui_play_queue_song_get_type() -> GType {
super::Song::static_type().into_glib()
}
#[no_mangle]
extern "C" fn audrey_ui_play_queue_song_new(
playbin: *mut crate::playbin::ffi::AudreyPlaybin,
) -> *mut AudreyUiPlayQueueSong {
unsafe { super::Song::new(&from_glib_none(playbin)).into_glib_ptr() }
}
#[no_mangle]
extern "C" fn audrey_ui_play_queue_song_set_draggable(
self_: *mut AudreyUiPlayQueueSong,
draggable: gboolean,
) {
let self_: super::Song = unsafe { from_glib_none(self_) };
self_.set_draggable(unsafe { from_glib::<_, bool>(draggable) });
}
#[no_mangle]
extern "C" fn audrey_ui_play_queue_song_set_show_position(
self_: *mut AudreyUiPlayQueueSong,
show_position: gboolean,
) {
let self_: super::Song = unsafe { from_glib_none(self_) };
self_.set_show_position(unsafe { from_glib::<_, bool>(show_position) });
}
#[no_mangle]
extern "C" fn audrey_ui_play_queue_song_set_show_artist(
self_: *mut AudreyUiPlayQueueSong,
show_artist: gboolean,
) {
let self_: super::Song = unsafe { from_glib_none(self_) };
self_.set_show_artist(unsafe { from_glib::<_, bool>(show_artist) });
}
#[no_mangle]
extern "C" fn audrey_ui_play_queue_song_set_show_cover(
self_: *mut AudreyUiPlayQueueSong,
show_cover: gboolean,
) {
let self_: super::Song = unsafe { from_glib_none(self_) };
self_.set_show_cover(unsafe { from_glib::<_, bool>(show_cover) });
}
#[no_mangle]
extern "C" fn audrey_ui_play_queue_song_bind(
self_: *mut AudreyUiPlayQueueSong,
position: c_uint,
song: *mut crate::playbin::song::ffi::AudreyPlaybinSong,
) {
let self_: super::Song = unsafe { from_glib_none(self_) };
let song: crate::playbin::Song = unsafe { from_glib_none(song) };
self_.bind(position, &song);
}
#[no_mangle]
extern "C" fn audrey_ui_play_queue_song_unbind(self_: *mut AudreyUiPlayQueueSong) {
let self_: super::Song = unsafe { from_glib_none(self_) };
self_.unbind();
}
}