feat: queue videos in running player
This commit is contained in:
@@ -120,6 +120,7 @@ actions! {
|
||||
ViewTabPrevious, "view.tab.previous", "Select the previous view tab", VIEW, ["shift+tab"];
|
||||
ViewRefresh, "view.refresh", "Refresh the current view and configuration", VIEW, ["r"];
|
||||
VideoPlay, "video.play", "Play checked videos in displayed order, or the selected video", VIEW, ["enter"];
|
||||
VideoEnqueue, "video.enqueue", "Append checked videos in displayed order, or the selected video, to Terebi's queue", VIEW, ["super+enter", "ctrl+enter"];
|
||||
VideoOpen, "video.open", "Open the selected YouTube video in the default browser", VIEW, ["o"];
|
||||
VideoCopyUrl, "video.copy_url", "Copy the selected video's URL to the terminal clipboard", VIEW, ["y"];
|
||||
VideoNext, "video.select.next", "Select the next video", VIEW, ["j", "down", "ctrl+j"];
|
||||
@@ -487,6 +488,10 @@ impl Bindings {
|
||||
&[VideoPlay],
|
||||
"Play checked videos in displayed order, or the selected video",
|
||||
),
|
||||
(
|
||||
&[VideoEnqueue],
|
||||
"Append checked videos, or the selected video, to Terebi's queue",
|
||||
),
|
||||
(
|
||||
&[VideoToggle],
|
||||
"Check / uncheck the selected video for playback",
|
||||
|
||||
+17
-5
File diff suppressed because one or more lines are too long
+19
-3
@@ -578,6 +578,11 @@ impl Browser {
|
||||
self.push(Screen::new(Content::Series { media, data: None }));
|
||||
self.load_series();
|
||||
} else {
|
||||
self.play(false);
|
||||
}
|
||||
}
|
||||
fn play(&mut self, enqueue: bool) {
|
||||
if self.screen().playable() {
|
||||
let videos = self.screen().playback_videos();
|
||||
if videos.is_empty() {
|
||||
return;
|
||||
@@ -586,15 +591,16 @@ impl Browser {
|
||||
self.screen_mut().error = None;
|
||||
// Dropping the launcher cancels only its CLI child, not the native player.
|
||||
self.player = None;
|
||||
let result = PlayerLaunch::start(&videos, &self.options.player, &mut self.state);
|
||||
let result =
|
||||
PlayerLaunch::start(&videos, &self.options.player, &mut self.state, enqueue);
|
||||
match result {
|
||||
Ok(player) => {
|
||||
self.player = Some(player);
|
||||
self.screen_mut().checked.clear();
|
||||
self.status = if videos.len() == 1 {
|
||||
format!("Opening {} in Terebi…", safe(&videos[0].title))
|
||||
format!("Handing {} to Terebi…", safe(&videos[0].title))
|
||||
} else {
|
||||
format!("Opening {} episodes in Terebi…", videos.len())
|
||||
format!("Handing {} episodes to Terebi…", videos.len())
|
||||
};
|
||||
}
|
||||
Err(error) => self.fail(error),
|
||||
@@ -1210,6 +1216,7 @@ impl Browser {
|
||||
Some(Action::ViewNext) => self.history(true),
|
||||
Some(Action::ViewRefresh) => self.refresh(),
|
||||
Some(Action::VideoPlay) => self.open(),
|
||||
Some(Action::VideoEnqueue) => self.play(true),
|
||||
Some(Action::VideoToggle) => self.screen_mut().toggle_checked(),
|
||||
Some(Action::VideoClear) => self.screen_mut().checked.clear(),
|
||||
Some(Action::VideoCopyUrl) if self.screen().playable() => {
|
||||
@@ -1375,6 +1382,10 @@ impl Browser {
|
||||
Content::Series { .. } | Content::Collection { .. }
|
||||
) {
|
||||
bindings.extend([
|
||||
(
|
||||
Action::VideoEnqueue,
|
||||
"Append checked or selected episodes to Terebi's queue",
|
||||
),
|
||||
(Action::VideoToggle, "Toggle checked episode"),
|
||||
(Action::VideoClear, "Clear checked episodes"),
|
||||
(Action::VideoCopyUrl, "Copy selected episode URL"),
|
||||
@@ -1445,6 +1456,7 @@ impl Browser {
|
||||
];
|
||||
if self.screen().playable() {
|
||||
actions.extend([
|
||||
(Action::VideoEnqueue, "enqueue"),
|
||||
(Action::VideoToggle, "check"),
|
||||
(Action::VideoClear, "clear checks"),
|
||||
]);
|
||||
@@ -1498,6 +1510,7 @@ impl Browser {
|
||||
&[
|
||||
(Action::InfoDescription, "description"),
|
||||
(Action::VideoPlay, "play"),
|
||||
(Action::VideoEnqueue, "enqueue"),
|
||||
(Action::VideoToggle, "check"),
|
||||
(Action::VideoClear, "clear checks"),
|
||||
(Action::InfoHide, "close"),
|
||||
@@ -1510,6 +1523,7 @@ impl Browser {
|
||||
&[
|
||||
(Action::InfoOverview, "info"),
|
||||
(Action::VideoPlay, "play"),
|
||||
(Action::VideoEnqueue, "enqueue"),
|
||||
(Action::VideoToggle, "check"),
|
||||
(Action::VideoClear, "clear checks"),
|
||||
(Action::InfoHide, "close"),
|
||||
@@ -1528,6 +1542,7 @@ impl Browser {
|
||||
(Action::Help, "help"),
|
||||
(Action::ProviderChoose, "provider"),
|
||||
(Action::VideoPlay, "play"),
|
||||
(Action::VideoEnqueue, "enqueue"),
|
||||
(Action::InfoOverview, "info"),
|
||||
(Action::WatchStatusWatching, "mark watching"),
|
||||
(Action::WatchStatusWatched, "mark watched"),
|
||||
@@ -1553,6 +1568,7 @@ impl Browser {
|
||||
"play"
|
||||
},
|
||||
),
|
||||
(Action::VideoEnqueue, "enqueue"),
|
||||
(Action::InfoOverview, "info"),
|
||||
(Action::WatchStatusWatching, "mark watching"),
|
||||
(Action::WatchStatusWatched, "mark watched"),
|
||||
|
||||
+9
-2
@@ -929,6 +929,7 @@ impl PlayerLaunch {
|
||||
videos: &[Video],
|
||||
player: &OsStr,
|
||||
state: &mut crate::video_state::State,
|
||||
enqueue: bool,
|
||||
) -> io::Result<Self> {
|
||||
if videos.is_empty() {
|
||||
return Err(io::Error::new(
|
||||
@@ -937,8 +938,14 @@ impl PlayerLaunch {
|
||||
));
|
||||
}
|
||||
let mut command = isolated_command(player);
|
||||
command.arg("--new-instance");
|
||||
if let [video] = videos {
|
||||
command.arg(if enqueue {
|
||||
"--enqueue"
|
||||
} else {
|
||||
"--new-instance"
|
||||
});
|
||||
if let [video] = videos
|
||||
&& !enqueue
|
||||
{
|
||||
let url = video_url(&video.id)?;
|
||||
let report = state.progress_file(video)?;
|
||||
crate::video_state::register_identity(&report, &video.id)?;
|
||||
|
||||
Reference in New Issue
Block a user