diff options
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | include/VideoPlayer.hpp | 7 | ||||
-rw-r--r-- | shaders/rounded_rectangle.glsl | 8 | ||||
-rw-r--r-- | src/QuickMedia.cpp | 19 | ||||
-rw-r--r-- | src/VideoPlayer.cpp | 53 |
5 files changed, 43 insertions, 47 deletions
@@ -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); |