mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 11:47:25 +01:00
Add player details screen
This commit is contained in:
parent
8e952fb6e2
commit
eb77c97f9b
24 changed files with 792 additions and 43 deletions
|
|
@ -13,6 +13,7 @@
|
|||
<file preprocess="xml-stripblanks">ui/person_screen.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/person_selector.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/player_bar.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/player_screen.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/poe_list.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/preferences.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/recording_editor.ui</file>
|
||||
|
|
|
|||
305
res/ui/player_screen.ui
Normal file
305
res/ui/player_screen.ui
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<requires lib="libhandy" version="1.0"/>
|
||||
<object class="GtkImage" id="play_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">media-playback-start-symbolic</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="position">
|
||||
<property name="upper">1</property>
|
||||
<property name="step-increment">0.01</property>
|
||||
<property name="page-increment">0.05</property>
|
||||
</object>
|
||||
<object class="GtkBox" id="widget">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="HdyHeaderBar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="title" translatable="yes">Player</property>
|
||||
<property name="show-close-button">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="back_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">go-previous-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="shadow-type">none</property>
|
||||
<child>
|
||||
<object class="HdyClamp">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-left">12</property>
|
||||
<property name="margin-right">12</property>
|
||||
<property name="margin-start">12</property>
|
||||
<property name="margin-end">12</property>
|
||||
<property name="margin-top">18</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
<property name="maximum-size">800</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="previous_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">media-skip-backward-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="play_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="pause_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">media-playback-pause-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="next_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">media-skip-forward-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="title_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Title</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="subtitle_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Subtitle</property>
|
||||
<property name="ellipsize">end</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="stop_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">media-playback-stop-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="position_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">0:00</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScale" id="position_scale">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="adjustment">position</property>
|
||||
<property name="upper-stepper-sensitivity">off</property>
|
||||
<property name="round-digits">1</property>
|
||||
<property name="draw-value">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="duration_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">0:00</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label-xalign">0</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child type="label_item">
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
|
|
@ -49,6 +49,11 @@ where
|
|||
for (index, ensemble) in ensembles.iter().enumerate() {
|
||||
let label = gtk::Label::new(Some(&ensemble.name));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
|
||||
let row = SelectorRow::new(index.try_into().unwrap(), &label);
|
||||
row.show_all();
|
||||
clone.list.insert(&row, -1);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,11 @@ where
|
|||
for (index, instrument) in instruments.iter().enumerate() {
|
||||
let label = gtk::Label::new(Some(&instrument.name));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
|
||||
let row = SelectorRow::new(index.try_into().unwrap(), &label);
|
||||
row.show_all();
|
||||
clone.list.insert(&row, -1);
|
||||
|
|
|
|||
|
|
@ -140,6 +140,11 @@ impl PartEditor {
|
|||
for (index, instrument) in self.instruments.borrow().iter().enumerate() {
|
||||
let label = gtk::Label::new(Some(&instrument.name));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
|
||||
let row = SelectorRow::new(index.try_into().unwrap(), &label);
|
||||
row.show_all();
|
||||
self.instrument_list.insert(&row, -1);
|
||||
|
|
|
|||
|
|
@ -163,6 +163,11 @@ where
|
|||
for (index, performer) in self.performers.borrow().iter().enumerate() {
|
||||
let label = gtk::Label::new(Some(&performer.get_title()));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
|
||||
let row = SelectorRow::new(index.try_into().unwrap(), &label);
|
||||
row.show_all();
|
||||
self.performer_list.insert(&row, -1);
|
||||
|
|
|
|||
|
|
@ -110,6 +110,10 @@ impl RecordingSelectorPersonScreen {
|
|||
|work: &WorkDescription| {
|
||||
let label = gtk::Label::new(Some(&work.title));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
label.upcast()
|
||||
},
|
||||
|_| true,
|
||||
|
|
@ -213,6 +217,7 @@ impl RecordingSelectorWorkScreen {
|
|||
performers_label.set_halign(gtk::Align::Start);
|
||||
|
||||
let vbox = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
||||
vbox.set_border_width(6);
|
||||
vbox.add(&work_label);
|
||||
vbox.add(&performers_label);
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ impl TracksEditor {
|
|||
file_name_label.set_halign(gtk::Align::Start);
|
||||
|
||||
let vbox = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
||||
vbox.set_border_width(6);
|
||||
vbox.add(&title_label);
|
||||
vbox.add(&file_name_label);
|
||||
|
||||
|
|
|
|||
|
|
@ -341,6 +341,11 @@ where
|
|||
for (index, instrument) in self.instruments.borrow().iter().enumerate() {
|
||||
let label = gtk::Label::new(Some(&instrument.name));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
|
||||
let row = SelectorRow::new(index.try_into().unwrap(), &label);
|
||||
row.show_all();
|
||||
self.instrument_list.insert(&row, -1);
|
||||
|
|
@ -365,6 +370,10 @@ where
|
|||
for (index, part) in self.structure.borrow().iter().enumerate() {
|
||||
let label = gtk::Label::new(Some(&part.get_title()));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
|
||||
if part.is_part() {
|
||||
label.set_margin_start(6);
|
||||
|
|
|
|||
|
|
@ -142,6 +142,11 @@ where
|
|||
for (index, person) in persons.iter().enumerate() {
|
||||
let label = gtk::Label::new(Some(&person.name_lf()));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
|
||||
let row = SelectorRow::new(index.try_into().unwrap(), &label);
|
||||
row.show_all();
|
||||
self.person_list.insert(&row, -1);
|
||||
|
|
@ -207,6 +212,11 @@ where
|
|||
for (index, work) in works.iter().enumerate() {
|
||||
let label = gtk::Label::new(Some(&work.title));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
|
||||
let row = SelectorRow::new(index.try_into().unwrap(), &label);
|
||||
row.show_all();
|
||||
self.work_list.insert(&row, -1);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ sources = files(
|
|||
'screens/ensemble_screen.rs',
|
||||
'screens/mod.rs',
|
||||
'screens/person_screen.rs',
|
||||
'screens/player_screen.rs',
|
||||
'screens/recording_screen.rs',
|
||||
'screens/work_screen.rs',
|
||||
'widgets/list.rs',
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ pub struct Player {
|
|||
current_item: Cell<Option<usize>>,
|
||||
current_track: Cell<Option<usize>>,
|
||||
playing: Cell<bool>,
|
||||
playlist_cb: RefCell<Option<Box<dyn Fn(Vec<PlaylistItem>) -> ()>>>,
|
||||
track_cb: RefCell<Option<Box<dyn Fn(usize, usize) -> ()>>>,
|
||||
duration_cb: RefCell<Option<Box<dyn Fn(u64) -> ()>>>,
|
||||
playing_cb: RefCell<Option<Box<dyn Fn(bool) -> ()>>>,
|
||||
position_cb: RefCell<Option<Box<dyn Fn(u64) -> ()>>>,
|
||||
playlist_cbs: RefCell<Vec<Box<dyn Fn(Vec<PlaylistItem>) -> ()>>>,
|
||||
track_cbs: RefCell<Vec<Box<dyn Fn(usize, usize) -> ()>>>,
|
||||
duration_cbs: RefCell<Vec<Box<dyn Fn(u64) -> ()>>>,
|
||||
playing_cbs: RefCell<Vec<Box<dyn Fn(bool) -> ()>>>,
|
||||
position_cbs: RefCell<Vec<Box<dyn Fn(u64) -> ()>>>,
|
||||
}
|
||||
|
||||
impl Player {
|
||||
|
|
@ -42,11 +42,11 @@ impl Player {
|
|||
current_item: Cell::new(None),
|
||||
current_track: Cell::new(None),
|
||||
playing: Cell::new(false),
|
||||
playlist_cb: RefCell::new(None),
|
||||
track_cb: RefCell::new(None),
|
||||
duration_cb: RefCell::new(None),
|
||||
playing_cb: RefCell::new(None),
|
||||
position_cb: RefCell::new(None),
|
||||
playlist_cbs: RefCell::new(Vec::new()),
|
||||
track_cbs: RefCell::new(Vec::new()),
|
||||
duration_cbs: RefCell::new(Vec::new()),
|
||||
playing_cbs: RefCell::new(Vec::new()),
|
||||
position_cbs: RefCell::new(Vec::new()),
|
||||
});
|
||||
|
||||
let clone = fragile::Fragile::new(result.clone());
|
||||
|
|
@ -56,8 +56,8 @@ impl Player {
|
|||
clone.next().unwrap();
|
||||
} else {
|
||||
clone.player.stop();
|
||||
|
||||
if let Some(cb) = &*clone.playing_cb.borrow() {
|
||||
clone.playing.replace(false);
|
||||
for cb in &*clone.playing_cbs.borrow() {
|
||||
cb(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -65,14 +65,14 @@ impl Player {
|
|||
|
||||
let clone = fragile::Fragile::new(result.clone());
|
||||
player.connect_position_updated(move |_, position| {
|
||||
if let Some(cb) = &*clone.get().position_cb.borrow() {
|
||||
for cb in &*clone.get().position_cbs.borrow() {
|
||||
cb(position.mseconds().unwrap());
|
||||
}
|
||||
});
|
||||
|
||||
let clone = fragile::Fragile::new(result.clone());
|
||||
player.connect_duration_changed(move |_, duration| {
|
||||
if let Some(cb) = &*clone.get().duration_cb.borrow() {
|
||||
for cb in &*clone.get().duration_cbs.borrow() {
|
||||
cb(duration.mseconds().unwrap());
|
||||
}
|
||||
});
|
||||
|
|
@ -80,24 +80,24 @@ impl Player {
|
|||
result
|
||||
}
|
||||
|
||||
pub fn set_playlist_cb<F: Fn(Vec<PlaylistItem>) -> () + 'static>(&self, cb: F) {
|
||||
self.playlist_cb.replace(Some(Box::new(cb)));
|
||||
pub fn add_playlist_cb<F: Fn(Vec<PlaylistItem>) -> () + 'static>(&self, cb: F) {
|
||||
self.playlist_cbs.borrow_mut().push(Box::new(cb));
|
||||
}
|
||||
|
||||
pub fn set_track_cb<F: Fn(usize, usize) -> () + 'static>(&self, cb: F) {
|
||||
self.track_cb.replace(Some(Box::new(cb)));
|
||||
pub fn add_track_cb<F: Fn(usize, usize) -> () + 'static>(&self, cb: F) {
|
||||
self.track_cbs.borrow_mut().push(Box::new(cb));
|
||||
}
|
||||
|
||||
pub fn set_duration_cb<F: Fn(u64) -> () + 'static>(&self, cb: F) {
|
||||
self.duration_cb.replace(Some(Box::new(cb)));
|
||||
pub fn add_duration_cb<F: Fn(u64) -> () + 'static>(&self, cb: F) {
|
||||
self.duration_cbs.borrow_mut().push(Box::new(cb));
|
||||
}
|
||||
|
||||
pub fn set_playing_cb<F: Fn(bool) -> () + 'static>(&self, cb: F) {
|
||||
self.playing_cb.replace(Some(Box::new(cb)));
|
||||
pub fn add_playing_cb<F: Fn(bool) -> () + 'static>(&self, cb: F) {
|
||||
self.playing_cbs.borrow_mut().push(Box::new(cb));
|
||||
}
|
||||
|
||||
pub fn set_position_cb<F: Fn(u64) -> () + 'static>(&self, cb: F) {
|
||||
self.position_cb.replace(Some(Box::new(cb)));
|
||||
pub fn add_position_cb<F: Fn(u64) -> () + 'static>(&self, cb: F) {
|
||||
self.position_cbs.borrow_mut().push(Box::new(cb));
|
||||
}
|
||||
|
||||
pub fn get_playlist(&self) -> Vec<PlaylistItem> {
|
||||
|
|
@ -135,7 +135,7 @@ impl Player {
|
|||
was_empty
|
||||
};
|
||||
|
||||
if let Some(cb) = &*self.playlist_cb.borrow() {
|
||||
for cb in &*self.playlist_cbs.borrow() {
|
||||
cb(self.playlist.borrow().clone());
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ impl Player {
|
|||
self.player.play();
|
||||
self.playing.set(true);
|
||||
|
||||
if let Some(cb) = &*self.playing_cb.borrow() {
|
||||
for cb in &*self.playing_cbs.borrow() {
|
||||
cb(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -158,19 +158,23 @@ impl Player {
|
|||
self.player.pause();
|
||||
self.playing.set(false);
|
||||
|
||||
if let Some(cb) = &*self.playing_cb.borrow() {
|
||||
for cb in &*self.playing_cbs.borrow() {
|
||||
cb(false);
|
||||
}
|
||||
} else {
|
||||
self.player.play();
|
||||
self.playing.set(true);
|
||||
|
||||
if let Some(cb) = &*self.playing_cb.borrow() {
|
||||
for cb in &*self.playing_cbs.borrow() {
|
||||
cb(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn seek(&self, ms: u64) {
|
||||
self.player.seek(gstreamer::ClockTime::from_mseconds(ms));
|
||||
}
|
||||
|
||||
pub fn has_previous(&self) -> bool {
|
||||
if let Some(current_item) = self.current_item.get() {
|
||||
if let Some(current_track) = self.current_track.get() {
|
||||
|
|
@ -266,7 +270,7 @@ impl Player {
|
|||
self.current_item.set(Some(current_item));
|
||||
self.current_track.set(Some(current_track));
|
||||
|
||||
if let Some(cb) = &*self.track_cb.borrow() {
|
||||
for cb in &*self.track_cbs.borrow() {
|
||||
cb(current_item, current_track);
|
||||
}
|
||||
|
||||
|
|
@ -280,11 +284,11 @@ impl Player {
|
|||
self.current_track.set(None);
|
||||
self.playlist.replace(Vec::new());
|
||||
|
||||
if let Some(cb) = &*self.playing_cb.borrow() {
|
||||
for cb in &*self.playing_cbs.borrow() {
|
||||
cb(false);
|
||||
}
|
||||
|
||||
if let Some(cb) = &*self.playlist_cb.borrow() {
|
||||
for cb in &*self.playlist_cbs.borrow() {
|
||||
cb(Vec::new());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ impl EnsembleScreen {
|
|||
performers_label.set_halign(gtk::Align::Start);
|
||||
|
||||
let vbox = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
||||
vbox.set_border_width(6);
|
||||
vbox.add(&work_label);
|
||||
vbox.add(&performers_label);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ pub use ensemble_screen::*;
|
|||
pub mod person_screen;
|
||||
pub use person_screen::*;
|
||||
|
||||
pub mod player_screen;
|
||||
pub use player_screen::*;
|
||||
|
||||
pub mod work_screen;
|
||||
pub use work_screen::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@ impl PersonScreen {
|
|||
|work: &WorkDescription| {
|
||||
let label = gtk::Label::new(Some(&work.title));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
label.upcast()
|
||||
},
|
||||
clone!(@strong search_entry => move |work: &WorkDescription| {
|
||||
|
|
@ -81,6 +85,7 @@ impl PersonScreen {
|
|||
performers_label.set_halign(gtk::Align::Start);
|
||||
|
||||
let vbox = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
||||
vbox.set_border_width(6);
|
||||
vbox.add(&work_label);
|
||||
vbox.add(&performers_label);
|
||||
|
||||
|
|
|
|||
336
src/screens/player_screen.rs
Normal file
336
src/screens/player_screen.rs
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
use crate::player::*;
|
||||
use crate::widgets::*;
|
||||
use gettextrs::gettext;
|
||||
use glib::clone;
|
||||
use gtk::prelude::*;
|
||||
use gtk_macros::get_widget;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::rc::Rc;
|
||||
|
||||
struct PlaylistElement {
|
||||
pub item: usize,
|
||||
pub track: usize,
|
||||
pub title: String,
|
||||
pub subtitle: Option<String>,
|
||||
pub playable: bool,
|
||||
}
|
||||
|
||||
pub struct PlayerScreen {
|
||||
pub widget: gtk::Box,
|
||||
title_label: gtk::Label,
|
||||
subtitle_label: gtk::Label,
|
||||
previous_button: gtk::Button,
|
||||
play_button: gtk::Button,
|
||||
next_button: gtk::Button,
|
||||
position_label: gtk::Label,
|
||||
position: gtk::Adjustment,
|
||||
duration_label: gtk::Label,
|
||||
play_image: gtk::Image,
|
||||
pause_image: gtk::Image,
|
||||
list: Rc<List<PlaylistElement>>,
|
||||
player: Rc<RefCell<Option<Rc<Player>>>>,
|
||||
seeking: Rc<Cell<bool>>,
|
||||
current_item: Rc<Cell<usize>>,
|
||||
current_track: Rc<Cell<usize>>,
|
||||
back_cb: Rc<RefCell<Option<Box<dyn Fn() -> ()>>>>,
|
||||
}
|
||||
|
||||
impl PlayerScreen {
|
||||
pub fn new() -> Self {
|
||||
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/player_screen.ui");
|
||||
|
||||
get_widget!(builder, gtk::Box, widget);
|
||||
get_widget!(builder, gtk::Button, back_button);
|
||||
get_widget!(builder, gtk::Label, title_label);
|
||||
get_widget!(builder, gtk::Label, subtitle_label);
|
||||
get_widget!(builder, gtk::Button, previous_button);
|
||||
get_widget!(builder, gtk::Button, play_button);
|
||||
get_widget!(builder, gtk::Button, next_button);
|
||||
get_widget!(builder, gtk::Button, stop_button);
|
||||
get_widget!(builder, gtk::Label, position_label);
|
||||
get_widget!(builder, gtk::Scale, position_scale);
|
||||
get_widget!(builder, gtk::Adjustment, position);
|
||||
get_widget!(builder, gtk::Label, duration_label);
|
||||
get_widget!(builder, gtk::Image, play_image);
|
||||
get_widget!(builder, gtk::Image, pause_image);
|
||||
get_widget!(builder, gtk::Frame, frame);
|
||||
|
||||
let back_cb = Rc::new(RefCell::new(None::<Box<dyn Fn() -> ()>>));
|
||||
|
||||
back_button.connect_clicked(clone!(@strong back_cb => move |_| {
|
||||
if let Some(cb) = &*back_cb.borrow() {
|
||||
cb();
|
||||
}
|
||||
}));
|
||||
|
||||
let player = Rc::new(RefCell::new(None::<Rc<Player>>));
|
||||
let seeking = Rc::new(Cell::new(false));
|
||||
|
||||
previous_button.connect_clicked(clone!(@strong player => move |_| {
|
||||
if let Some(player) = &*player.borrow() {
|
||||
player.previous().unwrap();
|
||||
}
|
||||
}));
|
||||
|
||||
play_button.connect_clicked(clone!(@strong player => move |_| {
|
||||
if let Some(player) = &*player.borrow() {
|
||||
player.play_pause();
|
||||
}
|
||||
}));
|
||||
|
||||
next_button.connect_clicked(clone!(@strong player => move |_| {
|
||||
if let Some(player) = &*player.borrow() {
|
||||
player.next().unwrap();
|
||||
}
|
||||
}));
|
||||
|
||||
stop_button.connect_clicked(clone!(@strong player, @strong back_cb => move |_| {
|
||||
if let Some(player) = &*player.borrow() {
|
||||
if let Some(cb) = &*back_cb.borrow() {
|
||||
cb();
|
||||
}
|
||||
|
||||
player.clear();
|
||||
}
|
||||
}));
|
||||
|
||||
position_scale.connect_button_press_event(clone!(@strong seeking => move |_, _| {
|
||||
seeking.replace(true);
|
||||
Inhibit(false)
|
||||
}));
|
||||
|
||||
position_scale.connect_button_release_event(
|
||||
clone!(@strong seeking, @strong position, @strong player => move |_, _| {
|
||||
if let Some(player) = &*player.borrow() {
|
||||
player.seek(position.get_value() as u64);
|
||||
}
|
||||
|
||||
seeking.replace(false);
|
||||
Inhibit(false)
|
||||
}),
|
||||
);
|
||||
|
||||
position_scale.connect_value_changed(
|
||||
clone!(@strong seeking, @strong position, @strong position_label => move |_| {
|
||||
if seeking.get() {
|
||||
let ms = position.get_value() as u64;
|
||||
let min = ms / 60000;
|
||||
let sec = (ms % 60000) / 1000;
|
||||
position_label.set_text(&format!("{}:{:02}", min, sec));
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
let current_item = Rc::new(Cell::<usize>::new(0));
|
||||
let current_track = Rc::new(Cell::<usize>::new(0));
|
||||
let list = List::new(
|
||||
clone!(
|
||||
@strong current_item,
|
||||
@strong current_track
|
||||
=> move |element: &PlaylistElement| {
|
||||
let title_label = gtk::Label::new(Some(&element.title));
|
||||
title_label.set_ellipsize(pango::EllipsizeMode::End);
|
||||
title_label.set_halign(gtk::Align::Start);
|
||||
let vbox = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
||||
vbox.add(&title_label);
|
||||
if let Some(subtitle) = &element.subtitle {
|
||||
let subtitle_label = gtk::Label::new(Some(&subtitle));
|
||||
subtitle_label.set_ellipsize(pango::EllipsizeMode::End);
|
||||
subtitle_label.set_halign(gtk::Align::Start);
|
||||
subtitle_label.set_opacity(0.5);
|
||||
vbox.add(&subtitle_label);
|
||||
}
|
||||
|
||||
let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 6);
|
||||
hbox.set_border_width(6);
|
||||
|
||||
if element.playable {
|
||||
let image = gtk::Image::new();
|
||||
|
||||
if element.item == current_item.get() && element.track == current_track.get() {
|
||||
image.set_from_icon_name(
|
||||
Some("media-playback-start-symbolic"),
|
||||
gtk::IconSize::Button,
|
||||
);
|
||||
}
|
||||
|
||||
hbox.add(&image);
|
||||
} else if element.item > 0 {
|
||||
hbox.set_margin_top(18);
|
||||
}
|
||||
hbox.add(&vbox);
|
||||
hbox.upcast()
|
||||
}
|
||||
),
|
||||
|_| true,
|
||||
"",
|
||||
);
|
||||
|
||||
list.set_selected(clone!(@strong player => move |element| {
|
||||
if let Some(player) = &*player.borrow() {
|
||||
player.set_track(element.item, element.track).unwrap();
|
||||
}
|
||||
}));
|
||||
|
||||
frame.add(&list.widget);
|
||||
|
||||
Self {
|
||||
widget,
|
||||
title_label,
|
||||
subtitle_label,
|
||||
previous_button,
|
||||
play_button,
|
||||
next_button,
|
||||
position_label,
|
||||
position,
|
||||
duration_label,
|
||||
play_image,
|
||||
pause_image,
|
||||
list,
|
||||
player,
|
||||
seeking,
|
||||
current_item,
|
||||
current_track,
|
||||
back_cb,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_player(&self, player: Option<Rc<Player>>) {
|
||||
self.player.replace(player.clone());
|
||||
|
||||
if let Some(player) = player {
|
||||
let playlist = Rc::new(RefCell::new(Vec::<PlaylistItem>::new()));
|
||||
|
||||
player.add_playlist_cb(clone!(
|
||||
@strong player,
|
||||
@strong self.previous_button as previous_button,
|
||||
@strong self.next_button as next_button,
|
||||
@strong self.list as list,
|
||||
@strong playlist
|
||||
=> move |new_playlist| {
|
||||
playlist.replace(new_playlist);
|
||||
previous_button.set_sensitive(player.has_previous());
|
||||
next_button.set_sensitive(player.has_next());
|
||||
|
||||
let mut elements = Vec::new();
|
||||
for (item_index, item) in playlist.borrow().iter().enumerate() {
|
||||
elements.push(PlaylistElement {
|
||||
item: item_index,
|
||||
track: 0,
|
||||
title: item.recording.work.get_title(),
|
||||
subtitle: Some(item.recording.get_performers()),
|
||||
playable: false,
|
||||
});
|
||||
|
||||
for (track_index, track) in item.tracks.iter().enumerate() {
|
||||
let mut parts = Vec::<String>::new();
|
||||
for part in &track.work_parts {
|
||||
parts.push(item.recording.work.parts[*part].title.clone());
|
||||
}
|
||||
|
||||
let title = if parts.is_empty() {
|
||||
gettext("Unknown")
|
||||
} else {
|
||||
parts.join(", ")
|
||||
};
|
||||
|
||||
elements.push(PlaylistElement {
|
||||
item: item_index,
|
||||
track: track_index,
|
||||
title: title,
|
||||
subtitle: None,
|
||||
playable: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
list.show_items(elements);
|
||||
}
|
||||
));
|
||||
|
||||
player.add_track_cb(clone!(
|
||||
@strong player,
|
||||
@strong playlist,
|
||||
@strong self.previous_button as previous_button,
|
||||
@strong self.next_button as next_button,
|
||||
@strong self.title_label as title_label,
|
||||
@strong self.subtitle_label as subtitle_label,
|
||||
@strong self.position_label as position_label,
|
||||
@strong self.current_item as self_item,
|
||||
@strong self.current_track as self_track,
|
||||
@strong self.list as list
|
||||
=> move |current_item, current_track| {
|
||||
previous_button.set_sensitive(player.has_previous());
|
||||
next_button.set_sensitive(player.has_next());
|
||||
|
||||
let item = &playlist.borrow()[current_item];
|
||||
let track = &item.tracks[current_track];
|
||||
|
||||
let mut parts = Vec::<String>::new();
|
||||
for part in &track.work_parts {
|
||||
parts.push(item.recording.work.parts[*part].title.clone());
|
||||
}
|
||||
|
||||
let mut title = item.recording.work.get_title();
|
||||
if !parts.is_empty() {
|
||||
title = format!("{}: {}", title, parts.join(", "));
|
||||
}
|
||||
|
||||
title_label.set_text(&title);
|
||||
subtitle_label.set_text(&item.recording.get_performers());
|
||||
position_label.set_text("0:00");
|
||||
|
||||
self_item.replace(current_item);
|
||||
self_track.replace(current_track);
|
||||
list.update();
|
||||
}
|
||||
));
|
||||
|
||||
player.add_duration_cb(clone!(
|
||||
@strong self.duration_label as duration_label,
|
||||
@strong self.position as position
|
||||
=> move |ms| {
|
||||
let min = ms / 60000;
|
||||
let sec = (ms % 60000) / 1000;
|
||||
duration_label.set_text(&format!("{}:{:02}", min, sec));
|
||||
position.set_upper(ms as f64);
|
||||
}
|
||||
));
|
||||
|
||||
player.add_playing_cb(clone!(
|
||||
@strong self.play_button as play_button,
|
||||
@strong self.play_image as play_image,
|
||||
@strong self.pause_image as pause_image
|
||||
=> move |playing| {
|
||||
if let Some(child) = play_button.get_child() {
|
||||
play_button.remove( &child);
|
||||
}
|
||||
|
||||
play_button.add(if playing {
|
||||
&pause_image
|
||||
} else {
|
||||
&play_image
|
||||
});
|
||||
}
|
||||
));
|
||||
|
||||
player.add_position_cb(clone!(
|
||||
@strong self.position_label as position_label,
|
||||
@strong self.position as position,
|
||||
@strong self.seeking as seeking
|
||||
=> move |ms| {
|
||||
if !seeking.get() {
|
||||
let min = ms / 60000;
|
||||
let sec = (ms % 60000) / 1000;
|
||||
position_label.set_text(&format!("{}:{:02}", min, sec));
|
||||
position.set_value(ms as f64);
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_back_cb<F: Fn() -> () + 'static>(&self, cb: F) {
|
||||
self.back_cb.replace(Some(Box::new(cb)));
|
||||
}
|
||||
}
|
||||
|
|
@ -75,6 +75,7 @@ impl RecordingScreen {
|
|||
file_name_label.set_halign(gtk::Align::Start);
|
||||
|
||||
let vbox = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
||||
vbox.set_border_width(6);
|
||||
vbox.add(&title_label);
|
||||
vbox.add(&file_name_label);
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ impl WorkScreen {
|
|||
performers_label.set_halign(gtk::Align::Start);
|
||||
|
||||
let vbox = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
||||
vbox.set_border_width(6);
|
||||
vbox.add(&work_label);
|
||||
vbox.add(&performers_label);
|
||||
|
||||
|
|
|
|||
|
|
@ -88,12 +88,23 @@ where
|
|||
}
|
||||
|
||||
pub fn select_index(&self, index: usize) {
|
||||
self.widget.select_row(self.widget.get_row_at_index(index.try_into().unwrap()).as_ref());
|
||||
self.widget.select_row(
|
||||
self.widget
|
||||
.get_row_at_index(index.try_into().unwrap())
|
||||
.as_ref(),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn show_items(&self, items: Vec<T>) {
|
||||
self.items.replace(items);
|
||||
self.update();
|
||||
}
|
||||
|
||||
pub fn invalidate_filter(&self) {
|
||||
self.widget.invalidate_filter();
|
||||
}
|
||||
|
||||
pub fn update(&self) {
|
||||
for child in self.widget.get_children() {
|
||||
self.widget.remove(&child);
|
||||
}
|
||||
|
|
@ -105,10 +116,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn invalidate_filter(&self) {
|
||||
self.widget.invalidate_filter();
|
||||
}
|
||||
|
||||
pub fn clear_selection(&self) {
|
||||
self.widget.unselect_all();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ impl PersonList {
|
|||
|person: &Person| {
|
||||
let label = gtk::Label::new(Some(&person.name_lf()));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
label.upcast()
|
||||
},
|
||||
clone!(@strong search_entry => move |person: &Person| {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ pub struct PlayerBar {
|
|||
play_image: gtk::Image,
|
||||
pause_image: gtk::Image,
|
||||
player: Rc<RefCell<Option<Rc<Player>>>>,
|
||||
playlist_cb: Rc<RefCell<Option<Box<dyn Fn() -> ()>>>>,
|
||||
}
|
||||
|
||||
impl PlayerBar {
|
||||
|
|
@ -31,10 +32,12 @@ impl PlayerBar {
|
|||
get_widget!(builder, gtk::Button, next_button);
|
||||
get_widget!(builder, gtk::Label, position_label);
|
||||
get_widget!(builder, gtk::Label, duration_label);
|
||||
get_widget!(builder, gtk::Button, playlist_button);
|
||||
get_widget!(builder, gtk::Image, play_image);
|
||||
get_widget!(builder, gtk::Image, pause_image);
|
||||
|
||||
let player = Rc::new(RefCell::new(None::<Rc<Player>>));
|
||||
let playlist_cb = Rc::new(RefCell::new(None::<Box<dyn Fn() -> ()>>));
|
||||
|
||||
previous_button.connect_clicked(clone!(@strong player => move |_| {
|
||||
if let Some(player) = &*player.borrow() {
|
||||
|
|
@ -54,6 +57,12 @@ impl PlayerBar {
|
|||
}
|
||||
}));
|
||||
|
||||
playlist_button.connect_clicked(clone!(@strong playlist_cb => move |_| {
|
||||
if let Some(cb) = &*playlist_cb.borrow() {
|
||||
cb();
|
||||
}
|
||||
}));
|
||||
|
||||
Self {
|
||||
widget,
|
||||
title_label,
|
||||
|
|
@ -66,6 +75,7 @@ impl PlayerBar {
|
|||
play_image,
|
||||
pause_image,
|
||||
player: player,
|
||||
playlist_cb: playlist_cb,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +85,7 @@ impl PlayerBar {
|
|||
if let Some(player) = player {
|
||||
let playlist = Rc::new(RefCell::new(Vec::<PlaylistItem>::new()));
|
||||
|
||||
player.set_playlist_cb(clone!(
|
||||
player.add_playlist_cb(clone!(
|
||||
@strong player,
|
||||
@strong self.widget as widget,
|
||||
@strong self.previous_button as previous_button,
|
||||
|
|
@ -89,7 +99,7 @@ impl PlayerBar {
|
|||
}
|
||||
));
|
||||
|
||||
player.set_track_cb(clone!(
|
||||
player.add_track_cb(clone!(
|
||||
@strong player,
|
||||
@strong playlist,
|
||||
@strong self.previous_button as previous_button,
|
||||
|
|
@ -120,7 +130,7 @@ impl PlayerBar {
|
|||
}
|
||||
));
|
||||
|
||||
player.set_duration_cb(clone!(
|
||||
player.add_duration_cb(clone!(
|
||||
@strong self.duration_label as duration_label
|
||||
=> move |ms| {
|
||||
let min = ms / 60000;
|
||||
|
|
@ -129,7 +139,7 @@ impl PlayerBar {
|
|||
}
|
||||
));
|
||||
|
||||
player.set_playing_cb(clone!(
|
||||
player.add_playing_cb(clone!(
|
||||
@strong self.play_button as play_button,
|
||||
@strong self.play_image as play_image,
|
||||
@strong self.pause_image as pause_image
|
||||
|
|
@ -146,7 +156,7 @@ impl PlayerBar {
|
|||
}
|
||||
));
|
||||
|
||||
player.set_position_cb(clone!(
|
||||
player.add_position_cb(clone!(
|
||||
@strong self.position_label as position_label
|
||||
=> move |ms| {
|
||||
let min = ms / 60000;
|
||||
|
|
@ -158,4 +168,8 @@ impl PlayerBar {
|
|||
self.widget.set_reveal_child(false);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_playlist_cb<F: Fn() -> () + 'static>(&self, cb: F) {
|
||||
self.playlist_cb.replace(Some(Box::new(cb)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ impl PoeList {
|
|||
|poe: &PersonOrEnsemble| {
|
||||
let label = gtk::Label::new(Some(&poe.get_title()));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
label.set_margin_start(6);
|
||||
label.set_margin_end(6);
|
||||
label.set_margin_top(6);
|
||||
label.set_margin_bottom(6);
|
||||
label.upcast()
|
||||
},
|
||||
clone!(@strong search_entry => move |poe: &PersonOrEnsemble| {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,6 @@ impl ObjectImpl for SelectorRowPriv {
|
|||
self.parent_constructed(object);
|
||||
|
||||
let row = object.downcast_ref::<SelectorRow>().unwrap();
|
||||
row.set_border_width(6);
|
||||
|
||||
let child = self.child.borrow();
|
||||
match child.as_ref() {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ pub struct Window {
|
|||
poe_list: Rc<PoeList>,
|
||||
navigator: Rc<Navigator>,
|
||||
player_bar: PlayerBar,
|
||||
player_screen: PlayerScreen,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
|
|
@ -38,6 +39,9 @@ impl Window {
|
|||
let backend = Rc::new(Backend::new());
|
||||
backend.clone().init();
|
||||
|
||||
let player_screen = PlayerScreen::new();
|
||||
stack.add_named(&player_screen.widget, "player_screen");
|
||||
|
||||
let poe_list = PoeList::new(backend.clone());
|
||||
let navigator = Navigator::new(&empty_screen);
|
||||
navigator.set_back_cb(clone!(@strong leaflet, @strong sidebar_box => move || {
|
||||
|
|
@ -56,6 +60,7 @@ impl Window {
|
|||
poe_list,
|
||||
navigator,
|
||||
player_bar,
|
||||
player_screen,
|
||||
});
|
||||
|
||||
result.window.set_application(Some(app));
|
||||
|
|
@ -85,6 +90,18 @@ impl Window {
|
|||
})).show();
|
||||
}));
|
||||
|
||||
result
|
||||
.player_bar
|
||||
.set_playlist_cb(clone!(@strong result => move || {
|
||||
result.stack.set_visible_child_name("player_screen");
|
||||
}));
|
||||
|
||||
result
|
||||
.player_screen
|
||||
.set_back_cb(clone!(@strong result => move || {
|
||||
result.stack.set_visible_child_name("content");
|
||||
}));
|
||||
|
||||
action!(
|
||||
result.window,
|
||||
"preferences",
|
||||
|
|
@ -298,7 +315,8 @@ impl Window {
|
|||
clone.poe_list.clone().reload();
|
||||
|
||||
let player = clone.backend.get_player().unwrap();
|
||||
clone.player_bar.set_player(Some(player));
|
||||
clone.player_bar.set_player(Some(player.clone()));
|
||||
clone.player_screen.set_player(Some(player));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue