aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-06-12 04:05:03 +0200
committerdec05eba <dec05eba@protonmail.com>2021-06-12 04:05:03 +0200
commitf903b027871a989c1956e6bf16b47e302a01c763 (patch)
tree4dcf30a392b0442c8e02bc0f5f68ea245775a52d
parentb83e18c475fa68806accf5d5b23aafcc2234e5dc (diff)
Start from youtube url timestamp
-rw-r--r--TODO3
-rw-r--r--include/VideoPlayer.hpp7
-rw-r--r--shaders/rounded_rectangle.glsl8
-rw-r--r--src/QuickMedia.cpp19
-rw-r--r--src/VideoPlayer.cpp53
5 files changed, 43 insertions, 47 deletions
diff --git a/TODO b/TODO
index c1b56b8..8a2485d 100644
--- a/TODO
+++ b/TODO
@@ -164,4 +164,5 @@ Reload youtube video url if the video is idle for too long. The video url is onl
Improve live stream startup time by downloading the video formats in parts instead of the hls manifest?
Add youtube chapters.
Faster seeking for long youtube videos.
-Disable drop shadow on pinephone. \ No newline at end of file
+Disable drop shadow on pinephone.
+--resume-playback doesn't seem to work with the new youtube code. Or maybe --save-position-on-quit fails? \ No newline at end of file
diff --git a/include/VideoPlayer.hpp b/include/VideoPlayer.hpp
index 341c686..1e40de1 100644
--- a/include/VideoPlayer.hpp
+++ b/include/VideoPlayer.hpp
@@ -40,8 +40,9 @@ namespace QuickMedia {
VideoPlayer(const VideoPlayer&) = delete;
VideoPlayer& operator=(const VideoPlayer&) = delete;
- // |audio_path| is only set when video and audio are separate files/urls
- Error load_video(const char *path, const char *audio_path, sf::WindowHandle parent_window, const std::string &plugin_name, const std::string &title);
+ // |audio_path| is only set when video and audio are separate files/urls.
+ // |start_time| is ignored if |resume_playback| is true.
+ Error load_video(const char *path, const char *audio_path, sf::WindowHandle parent_window, const std::string &plugin_name, const std::string &title, const std::string &start_time = "");
// Should be called every update frame
Error update();
@@ -56,7 +57,7 @@ namespace QuickMedia {
int exit_status;
private:
Error send_command(const char *cmd, size_t size);
- Error launch_video_process(const char *path, const char *audio_path, sf::WindowHandle parent_window, const std::string &plugin_name, const std::string &title);
+ Error launch_video_process(const char *path, const char *audio_path, sf::WindowHandle parent_window, const std::string &plugin_name, const std::string &title, const std::string &start_time);
VideoPlayer::Error read_ipc_func();
private:
bool no_video;
diff --git a/shaders/rounded_rectangle.glsl b/shaders/rounded_rectangle.glsl
index 8ba138f..88a057a 100644
--- a/shaders/rounded_rectangle.glsl
+++ b/shaders/rounded_rectangle.glsl
@@ -12,14 +12,10 @@ void main() {
vec2 uv = gl_TexCoord[0].xy * resolution;
vec2 center = resolution * 0.5;
vec2 size = resolution * 0.5;
-
+ vec4 background_color = vec4(0.0, 0.0, 0.0, 0.0);
float a = clamp(rounded_rect(uv - center, size - radius, radius), 0.0, 1.0);
- // same as: if(uv.x >= band_pos.x && uv.x <= band_pos.x + band_size.x && uv.y >= band_pos.y && uv.y <= band_pos.y + band_size.y)
- //vec2 band_blend = step(band_pos, uv) - step(band_pos + band_size, uv);
- //vec4 front_color = mix(gl_Color, band_color, band_blend.x*band_blend.y);
vec4 front_color = gl_Color;
if(uv.x >= band_pos.x && uv.x <= band_pos.x + band_size.x && uv.y >= band_pos.y && uv.y <= band_pos.y + band_size.y)
front_color = band_color;
- front_color.a *= (1.0 - a);
- gl_FragColor = front_color;
+ gl_FragColor = mix(front_color, background_color, a);
} \ No newline at end of file
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 65a5387..5dd1ebb 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -2363,6 +2363,19 @@ namespace QuickMedia {
download_async_gui(url, file_manager_start_dir.string(), true, audio_only);
}
+ static std::string youtube_url_extract_timestamp(const std::string &url) {
+ size_t timestamp_start = url.find("t=");
+ if(timestamp_start == std::string::npos)
+ return "";
+
+ timestamp_start += 2;
+ size_t timestamp_end = url.find('&');
+ if(timestamp_end == std::string::npos)
+ timestamp_end = url.size();
+
+ return url.substr(timestamp_start, timestamp_end - timestamp_start);
+ }
+
#define CLEANMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask|Mod4Mask|Mod5Mask))
void Program::video_content_page(Page *parent_page, VideoPage *video_page, std::string video_title, bool download_if_streaming_fails, BodyItems &next_play_items, int play_index, int *parent_body_page, const std::string &parent_page_search) {
@@ -2497,12 +2510,16 @@ namespace QuickMedia {
}
}
}
+
+ std::string start_time;
+ if(is_youtube)
+ start_time = youtube_url_extract_timestamp(video_page->get_url());
time_watched_timer.restart();
watched_videos.insert(video_page->get_url());
video_player = std::make_unique<VideoPlayer>(is_audio_only, use_system_mpv_config, resume_video, is_matrix && !is_youtube, video_event_callback, on_window_create, resources_root, largest_monitor_height);
- VideoPlayer::Error err = video_player->load_video(video_url.c_str(), audio_url.c_str(), window.getSystemHandle(), plugin_name, video_title);
+ VideoPlayer::Error err = video_player->load_video(video_url.c_str(), audio_url.c_str(), window.getSystemHandle(), plugin_name, video_title, start_time);
if(err != VideoPlayer::Error::OK) {
std::string err_msg = "Failed to play url: ";
err_msg += video_page->get_url();
diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp
index adc7eb8..490ce82 100644
--- a/src/VideoPlayer.cpp
+++ b/src/VideoPlayer.cpp
@@ -67,20 +67,7 @@ namespace QuickMedia {
XCloseDisplay(display);
}
- static std::string escape_quotes(const std::string &str) {
- std::string result;
- for(char c : str) {
- if(c == '"')
- result += "\\\"";
- else if(c == '\\')
- result += "\\\\";
- else
- result += c;
- }
- return result;
- }
-
- VideoPlayer::Error VideoPlayer::launch_video_process(const char *path, const char *audio_path, sf::WindowHandle _parent_window, const std::string &plugin_name, const std::string &title) {
+ VideoPlayer::Error VideoPlayer::launch_video_process(const char *path, const char *audio_path, sf::WindowHandle _parent_window, const std::string &plugin_name, const std::string &title, const std::string &start_time) {
parent_window = _parent_window;
if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
@@ -103,9 +90,6 @@ namespace QuickMedia {
wid_arg += parent_window_str;
std::string input_conf = "--input-conf=" + resource_root + "input.conf";
- //Path video_cache_dir = get_cache_dir().join("video");
- //create_directory_recursive(video_cache_dir);
- //std::string cache_dir = "--cache-dir=" + video_cache_dir.data;
Path mpv_watch_later_dir = get_storage_dir().join("mpv").join("watch_later");
if(create_directory_recursive(mpv_watch_later_dir) != 0)
@@ -128,9 +112,7 @@ namespace QuickMedia {
"--no-terminal",
"--save-position-on-quit=yes",
"--profile=pseudo-gui", // For gui when playing audio, requires a version of mpv that isn't ancient
- //cache_dir.c_str(),
watch_later_dir.c_str(),
- //"--cache-on-disk=yes",
ytdl_format.c_str(),
// TODO: Disable hr seek on low power devices?
"--hr-seek=yes",
@@ -149,7 +131,9 @@ namespace QuickMedia {
if(keep_open)
args.push_back("--keep-open=yes");
- if(!resume_playback)
+ if(resume_playback)
+ args.push_back("--resume-playback");
+ else
args.push_back("--no-resume-playback");
if(!use_system_mpv_config) {
@@ -161,31 +145,27 @@ namespace QuickMedia {
});
}
- //std::string ytdl_options_arg;
- //if(plugin_name.empty()) {
- // ytdl_options_arg = "--ytdl-raw-options=sub-lang=\"en,eng,enUS,en-US\",write-sub=";
- // args.push_back(ytdl_options_arg.c_str());
- //} else {
- // ytdl_options_arg = "--ytdl-raw-options=sub-lang=\"en,eng,enUS,en-US\",write-sub=,mark-watched=,cookies=\"" + escape_quotes(cookies_filepath.data) + "\"";
- // args.push_back(ytdl_options_arg.c_str());
- //}
-
std::string force_media_title_arg;
- if(!title.empty())
+ if(!title.empty()) {
force_media_title_arg = "--force-media-title=" + title;
-
- if(!force_media_title_arg.empty())
args.push_back(force_media_title_arg.c_str());
+ }
if(no_video)
args.push_back("--no-video");
- std::string audio_file_arg = "--audio-file=";
+ std::string audio_file_arg;
if(audio_path && audio_path[0] != '\0') {
- audio_file_arg += audio_path;
+ audio_file_arg = std::string("--audio-file=") + audio_path;
args.push_back(audio_file_arg.c_str());
}
+ std::string start_time_arg;
+ if(!resume_playback && !start_time.empty()) {
+ start_time_arg = "--start=" + start_time;
+ args.push_back(start_time_arg.c_str());
+ }
+
args.insert(args.end(), { "--", path, nullptr });
if(exec_program_async(args.data(), &video_process_id) != 0) {
@@ -204,15 +184,16 @@ namespace QuickMedia {
return Error::OK;
}
- VideoPlayer::Error VideoPlayer::load_video(const char *path, const char *audio_path, sf::WindowHandle _parent_window, const std::string &plugin_name, const std::string &title) {
+ VideoPlayer::Error VideoPlayer::load_video(const char *path, const char *audio_path, sf::WindowHandle _parent_window, const std::string &plugin_name, const std::string &title, const std::string &start_time) {
// This check is to make sure we dont change window that the video belongs to. This is not a usecase we will have so
// no need to support it for now at least.
assert(parent_window == 0 || parent_window == _parent_window);
assert(path);
fprintf(stderr, "Playing video: %s, audio: %s\n", path ? path : "", audio_path ? audio_path : "");
if(video_process_id == -1)
- return launch_video_process(path, audio_path, _parent_window, plugin_name, title);
+ return launch_video_process(path, audio_path, _parent_window, plugin_name, title, start_time);
+ // TODO: When these are used, add audio_path, title and start_time. Also handle plugin_name
Json::Value command_data(Json::arrayValue);
command_data.append("loadfile");
command_data.append(path);