diff --git a/moe.tsuna.tsukimi.gschema.xml b/moe.tsuna.tsukimi.gschema.xml
index be81cf10..7a8f56ad 100644
--- a/moe.tsuna.tsukimi.gschema.xml
+++ b/moe.tsuna.tsukimi.gschema.xml
@@ -29,6 +29,10 @@
true
Default switch state
+
+ true
+ Default switch state
+
700
Default background height
diff --git a/resources/ui/settings.ui b/resources/ui/settings.ui
index f93969c2..f679b2a4 100644
--- a/resources/ui/settings.ui
+++ b/resources/ui/settings.ui
@@ -57,6 +57,11 @@
Show Playing Window Immediately
+
+
+
diff --git a/src/ui/moviedrop.rs b/src/ui/moviedrop.rs
index 3f468f8d..96d5bbbf 100644
--- a/src/ui/moviedrop.rs
+++ b/src/ui/moviedrop.rs
@@ -76,6 +76,16 @@ pub fn newmediadropsel(playbackinfo: network::Media, info: SearchResult) -> gtk:
vbox.append(&subdropdown);
let info = info.clone();
let playbutton = gtk::Button::with_label("Play");
+ let settings = gtk::gio::Settings::new(crate::APP_ID);
+ if settings.boolean("is-resume") {
+ if let Some(userdata) = &info.user_data {
+ if let Some(percentage) = userdata.played_percentage {
+ if percentage > 0. {
+ playbutton.set_label("Resume");
+ }
+ }
+ }
+ }
playbutton.connect_clicked(move |button| {
button.set_label("Playing...");
let nameselected = namedropdown.selected_item();
@@ -94,7 +104,11 @@ pub fn newmediadropsel(playbackinfo: network::Media, info: SearchResult) -> gtk:
playsessionid: playback_info.play_session_id.clone(),
tick: 0.,
};
- play_event(button.clone(),directurl,None,media.name,back);
+ if let Some(userdata) = &info.user_data {
+ play_event(button.clone(),directurl,None,media.name,back,userdata.played_percentage);
+ return;
+ }
+ play_event(button.clone(),directurl,None,media.name,back,None);
return;
}
}
@@ -117,11 +131,16 @@ pub fn newmediadropsel(playbackinfo: network::Media, info: SearchResult) -> gtk:
playsessionid: playback_info.play_session_id.clone(),
tick: 0.,
};
- play_event(button.clone(),Some(directurl),Some(suburl),media.name,back);
+ if let Some(userdata) = &info.user_data {
+ play_event(button.clone(),Some(directurl),Some(suburl),media.name,back,userdata.played_percentage);
+ return;
+ }
+ play_event(button.clone(),Some(directurl),Some(suburl),media.name,back,None);
return;
} else {
- super::new_dropsel::set_sub(info.id.clone(),media.id.clone(),nameselected.to_string(),subselected.to_string(),button.clone());
- return;
+ let userdata = info.user_data.clone();
+ super::new_dropsel::set_sub(info.id.clone(),media.id.clone(),nameselected.to_string(),subselected.to_string(),button.clone(),userdata);
+ return;
}
} else {
let back = Back {
@@ -130,7 +149,11 @@ pub fn newmediadropsel(playbackinfo: network::Media, info: SearchResult) -> gtk:
playsessionid: playback_info.play_session_id.clone(),
tick: 0.,
};
- play_event(button.clone(),Some(directurl),None,media.name,back);
+ if let Some(userdata) = &info.user_data {
+ play_event(button.clone(),Some(directurl),None,media.name,back,userdata.played_percentage);
+ return;
+ }
+ play_event(button.clone(),Some(directurl),None,media.name,back,None);
return;
}
}
diff --git a/src/ui/mpv/event.rs b/src/ui/mpv/event.rs
index 0b987a6d..5333d59c 100644
--- a/src/ui/mpv/event.rs
+++ b/src/ui/mpv/event.rs
@@ -4,7 +4,7 @@ use libmpv::{events::*, *};
use std::{collections::HashMap, env, thread, time::{Duration, Instant}};
use crate::{config::set_config, ui::network::{runtime, Back}, APP_ID};
-pub fn play(url:String,suburl:Option,name:Option,back:&Back) -> Result<()> {
+pub fn play(url:String,suburl:Option,name:Option,back:&Back,percentage:Option) -> Result<()> {
unsafe {
use libc::setlocale;
@@ -21,17 +21,26 @@ pub fn play(url:String,suburl:Option,name:Option,back:&Back) ->
init.set_property("config", true)?;
init.set_property("input-vo-keyboard", true)?;
init.set_property("input-default-bindings", true)?;
+
if let Some(name) = name {
init.set_property("force-media-title", name)?;
}
+
let settings = gtk::gio::Settings::new(APP_ID);
+
if settings.boolean("is-fullscreen") {
init.set_property("fullscreen", true)?;
}
+
if settings.boolean("is-force-window") {
init.set_property("force-window", "immediate")?;
}
+ if settings.boolean("is-resume") {
+ if let Some(percentage) = percentage {
+ init.set_property("start", format!("{}%",percentage as u32))?;
+ }
+ }
Ok(())
}).unwrap();
@@ -42,12 +51,15 @@ pub fn play(url:String,suburl:Option,name:Option,back:&Back) ->
ev_ctx.observe_property("volume", Format::Int64, 0)?;
ev_ctx.observe_property("time-pos", Format::Double, 0)?;
- let backc = back.clone();
-
+ let mut backc = back.clone();
+ if let Some(percentage) = percentage {
+ backc.tick = percentage * 10000000.0;
+ }
runtime().spawn(async move {
crate::ui::network::playstart(backc).await;
- });
+ });
+
crossbeam::scope(|scope| {
scope.spawn(|_| {
mpv.playlist_load_files(&[(&url, FileState::AppendPlay, None)])
diff --git a/src/ui/new_dropsel.rs b/src/ui/new_dropsel.rs
index 84b040fc..ef04032a 100644
--- a/src/ui/new_dropsel.rs
+++ b/src/ui/new_dropsel.rs
@@ -86,6 +86,16 @@ pub fn newmediadropsel(playbackinfo: network::Media, info: SeriesInfo) -> gtk::B
vbox.append(&subdropdown);
let info = info.clone();
let playbutton = gtk::Button::with_label("Play");
+ let settings = gtk::gio::Settings::new(crate::APP_ID);
+ if settings.boolean("is-resume") {
+ if let Some(userdata) = &info.user_data {
+ if let Some(percentage) = userdata.played_percentage {
+ if percentage > 0. {
+ playbutton.set_label("Resume");
+ }
+ }
+ }
+ }
playbutton.connect_clicked(move |button| {
button.set_label("Playing...");
button.set_sensitive(false);
@@ -105,7 +115,11 @@ pub fn newmediadropsel(playbackinfo: network::Media, info: SeriesInfo) -> gtk::B
playsessionid: playback_info.play_session_id.clone(),
tick: 0.,
};
- play_event(button.clone(),directurl,None,media.name,back);
+ if let Some(userdata) = &info.user_data {
+ play_event(button.clone(),directurl,None,media.name,back,userdata.played_percentage);
+ return;
+ }
+ play_event(button.clone(),directurl,None,media.name,back,None);
return;
}
}
@@ -128,11 +142,16 @@ pub fn newmediadropsel(playbackinfo: network::Media, info: SeriesInfo) -> gtk::B
playsessionid: playback_info.play_session_id.clone(),
tick: 0.,
};
- play_event(button.clone(),Some(directurl),Some(suburl),media.name,back);
+ if let Some(userdata) = &info.user_data {
+ play_event(button.clone(),Some(directurl),Some(suburl),media.name,back,userdata.played_percentage);
+ return;
+ }
+ play_event(button.clone(),Some(directurl),Some(suburl),media.name,back,None);
return;
} else {
// Ask Luke
- set_sub(info.id.clone(),media.id.clone(),nameselected.to_string(),subselected.to_string(),button.clone());
+ let userdata = info.user_data.clone();
+ set_sub(info.id.clone(),media.id.clone(),nameselected.to_string(),subselected.to_string(),button.clone(),userdata);
return;
}
} else {
@@ -142,7 +161,11 @@ pub fn newmediadropsel(playbackinfo: network::Media, info: SeriesInfo) -> gtk::B
playsessionid: playback_info.play_session_id.clone(),
tick: 0.,
};
- play_event(button.clone(),Some(directurl),None,media.name,back);
+ if let Some(userdata) = &info.user_data {
+ play_event(button.clone(),Some(directurl),None,media.name,back,userdata.played_percentage);
+ return;
+ }
+ play_event(button.clone(),Some(directurl),None,media.name,back,None);
return;
}
}
@@ -158,13 +181,13 @@ pub fn newmediadropsel(playbackinfo: network::Media, info: SeriesInfo) -> gtk::B
hbox
}
-pub fn play_event(button: gtk::Button, directurl: Option, suburl:Option, name: String, back: Back) {
+pub fn play_event(button: gtk::Button, directurl: Option, suburl:Option, name: String, back: Back,percentage:Option) {
let (sender, receiver) = async_channel::bounded(1);
gtk::gio::spawn_blocking(move || {
sender
.send_blocking(false)
.expect("The channel needs to be open.");
- match mpv::event::play(directurl.expect("no url"),suburl,Some(name),&back) {
+ match mpv::event::play(directurl.expect("no url"),suburl,Some(name),&back,percentage) {
Ok(_) => {
sender
.send_blocking(true)
@@ -178,7 +201,12 @@ pub fn play_event(button: gtk::Button, directurl: Option, suburl:Option<
glib::spawn_future_local(glib::clone!(@weak button =>async move {
while let Ok(enable_button) = receiver.recv().await {
if enable_button {
- button.set_label("Play");
+ let settings = gtk::gio::Settings::new(crate::APP_ID);
+ if settings.boolean("is-resume") {
+ button.set_label("Resume");
+ } else {
+ button.set_label("Play");
+ }
}
button.set_sensitive(enable_button);
}
@@ -190,7 +218,8 @@ pub fn set_sub(
sourceid:String,
nameselected: String,
subselected: String,
- button: gtk::Button
+ button: gtk::Button,
+ userdata: Option
) {
let (sender, receiver) = async_channel::bounded::(1);
let idc = id.clone();
@@ -222,7 +251,11 @@ pub fn set_sub(
playsessionid: media.play_session_id.clone(),
tick: 0.,
};
- play_event(button.clone(),Some(directurl),Some(suburl),mediasource.name,back);
+ if let Some(userdata) = userdata {
+ play_event(button.clone(),Some(directurl),Some(suburl),nameselected,back,userdata.played_percentage);
+ return;
+ }
+ play_event(button.clone(),Some(directurl),Some(suburl),nameselected,back,None);
return;
}
}
diff --git a/src/ui/widgets/settings.rs b/src/ui/widgets/settings.rs
index a57db346..c3c3dff2 100644
--- a/src/ui/widgets/settings.rs
+++ b/src/ui/widgets/settings.rs
@@ -28,6 +28,8 @@ mod imp {
pub spinrow: TemplateChild,
#[template_child]
pub forcewindowcontrol: TemplateChild,
+ #[template_child]
+ pub resumecontrol: TemplateChild,
}
// The central trait for subclassing a GObject
@@ -57,6 +59,7 @@ mod imp {
obj.set_spin();
obj.set_fullscreen();
obj.set_forcewindow();
+ obj.set_resume();
}
}
@@ -136,5 +139,14 @@ impl SettingsPage {
settings.set_boolean("is-force-window", control.is_active()).unwrap();
}));
}
+
+ pub fn set_resume(&self) {
+ let imp = imp::SettingsPage::from_obj(self);
+ let settings = gio::Settings::new(APP_ID);
+ imp.resumecontrol.set_active(settings.boolean("is-resume"));
+ imp.resumecontrol.connect_active_notify(glib::clone!(@weak self as obj =>move |control| {
+ settings.set_boolean("is-resume", control.is_active()).unwrap();
+ }));
+ }
}