diff options
-rw-r--r-- | include/Program.h | 3 | ||||
-rw-r--r-- | include/VideoPlayer.hpp | 3 | ||||
-rw-r--r-- | src/Program.c | 22 | ||||
-rw-r--r-- | src/QuickMedia.cpp | 61 | ||||
-rw-r--r-- | src/VideoPlayer.cpp | 12 |
5 files changed, 72 insertions, 29 deletions
diff --git a/include/Program.h b/include/Program.h index 6a6d038..bc3e91e 100644 --- a/include/Program.h +++ b/include/Program.h @@ -2,6 +2,7 @@ #define QUICKMEDIA_PROGRAM_H #include <sys/types.h> +#include <stdbool.h> #ifdef __cplusplus extern "C" { @@ -25,6 +26,8 @@ int exec_program(const char **args, ProgramOutputCallback output_callback, void // Return the exit status, or a negative value if waiting failed int wait_program(pid_t process_id); +bool wait_program_non_blocking(pid_t process_id, int *status); + /* @args need to have at least 2 arguments. The first which is the program name and the last which is NULL, which indicates end of args diff --git a/include/VideoPlayer.hpp b/include/VideoPlayer.hpp index 4dc7b53..c5d9cfe 100644 --- a/include/VideoPlayer.hpp +++ b/include/VideoPlayer.hpp @@ -31,7 +31,8 @@ namespace QuickMedia { READ_TIMEOUT, READ_RESPONSE_ERROR, READ_INCORRECT_TYPE, - INIT_FAILED + INIT_FAILED, + EXITED }; // @event_callback is called from another thread diff --git a/src/Program.c b/src/Program.c index 2c6759e..65164c4 100644 --- a/src/Program.c +++ b/src/Program.c @@ -114,6 +114,28 @@ int wait_program(pid_t process_id) { return WEXITSTATUS(status); } +bool wait_program_non_blocking(pid_t process_id, int *status) { + int s; + int wait_result = waitpid(process_id, &s, WNOHANG); + if(wait_result == -1) { + perror("waitpid failed"); + *status = -errno; + return false; + } else if(wait_result == 0) { + /* the child process is still running */ + *status = 0; + return false; + } + + if(!WIFEXITED(s)) { + *status = -4; + return false; + } + + *status = WEXITSTATUS(s); + return true; +} + int exec_program_async(const char **args, pid_t *result_process_id) { /* 1 arguments */ if(args[0] == NULL) diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 2ccb9d6..df5a1e8 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -692,54 +692,34 @@ namespace QuickMedia { return false; } - static bool youtube_dl_can_download_video(const std::string &video_url) { - const char *args[] = { "youtube-dl", "--skip-download", "--", video_url.c_str(), nullptr }; - return exec_program(args, nullptr, nullptr) == 0; - } - void Program::video_content_page() { search_bar->onTextUpdateCallback = nullptr; search_bar->onTextSubmitCallback = nullptr; Page previous_page = pop_page_stack(); - bool seekable = false; - std::unique_ptr<VideoPlayer> video_player; sf::WindowHandle video_player_window = None; - auto on_window_create = [this, &video_player, &seekable, &video_player_window](sf::WindowHandle _video_player_window) mutable { + auto on_window_create = [this, &video_player_window](sf::WindowHandle _video_player_window) mutable { video_player_window = _video_player_window; XSelectInput(disp, video_player_window, KeyPressMask); XSync(disp, False); - video_player->is_seekable(&seekable); }; auto load_video_error_check = [this, &video_player, previous_page]() mutable { watched_videos.insert(content_url); - std::string video_url = content_url; - - std::string youtube_video_id; - if(youtube_url_extract_id(video_url, youtube_video_id)) { - // This can fail for example if the video requires age vertification... - // TODO: Remove this when youtube-dl is modified to work with videos that require age verification. - if(!youtube_dl_can_download_video(video_url)) { - // Im sorry invidio.us server... this will be removed later and it only happens when youtube-dl fails! - video_url = "https://www.invidio.us/latest_version?id=" + youtube_video_id + "&itag=22"; - } - } - - VideoPlayer::Error err = video_player->load_video(video_url.c_str(), window.getSystemHandle()); + VideoPlayer::Error err = video_player->load_video(content_url.c_str(), window.getSystemHandle()); if(err != VideoPlayer::Error::OK) { std::string err_msg = "Failed to play url: "; - err_msg += video_url; + err_msg += content_url; show_notification("Video player", err_msg.c_str(), Urgency::CRITICAL); current_page = previous_page; } }; bool has_video_started = true; - video_player = std::make_unique<VideoPlayer>(current_plugin->use_tor, use_system_mpv_config, [this, &video_player, &seekable, &load_video_error_check, previous_page, &has_video_started](const char *event_name) mutable { + auto video_event_callback = [this, &video_player, &load_video_error_check, previous_page, &has_video_started](const char *event_name) mutable { bool end_of_file = false; if(strcmp(event_name, "pause") == 0) { double time_remaining = 9999.0; @@ -747,7 +727,6 @@ namespace QuickMedia { end_of_file = true; } else if(strcmp(event_name, "playback-restart") == 0) { video_player->set_paused(false); - video_player->is_seekable(&seekable); } else if(strcmp(event_name, "start-file") == 0) { has_video_started = true; } @@ -774,9 +753,10 @@ namespace QuickMedia { content_url = std::move(new_video_url); load_video_error_check(); } - }, on_window_create); - load_video_error_check(); + }; + video_player = std::make_unique<VideoPlayer>(current_plugin->use_tor, use_system_mpv_config, video_event_callback, on_window_create); + load_video_error_check(); sf::Event event; @@ -806,8 +786,33 @@ namespace QuickMedia { show_notification("Video player", "Failed to connect to mpv ipc after 5 seconds", Urgency::CRITICAL); current_page = previous_page; return; + } else if(update_err == VideoPlayer::Error::EXITED) { + std::string youtube_video_id; + if(youtube_url_extract_id(content_url, youtube_video_id)) { + fprintf(stderr, "Failed to play youtube video (maybe because of age verification?), trying with invidio.us...\n"); + // This can fail for example if the video requires age vertification... + // Im sorry invidio.us server... this will be removed later and it only happens when youtube-dl fails! + // TODO: Remove this when youtube-dl is modified to work with videos that require age verification. + video_player_window = None; + has_video_started = true; + video_player.reset(); + video_player = std::make_unique<VideoPlayer>(current_plugin->use_tor, use_system_mpv_config, video_event_callback, on_window_create); + + std::string new_video_url = "https://www.invidio.us/latest_version?id=" + youtube_video_id + "&itag=22"; + VideoPlayer::Error err = video_player->load_video(new_video_url.c_str(), window.getSystemHandle()); + if(err != VideoPlayer::Error::OK) { + std::string err_msg = "Failed to play url: "; + err_msg += content_url; + show_notification("Video player", err_msg.c_str(), Urgency::CRITICAL); + current_page = previous_page; + } + } else { + show_notification("Video player", "The video player failed to play the video", Urgency::CRITICAL); + current_page = previous_page; + return; + } } else if(update_err != VideoPlayer::Error::OK) { - show_notification("Video player", "Unexpected error while updating", Urgency::CRITICAL); + show_notification("Video player", "The video player failed to play the video", Urgency::CRITICAL); current_page = previous_page; return; } diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp index 138f269..6024ca8 100644 --- a/src/VideoPlayer.cpp +++ b/src/VideoPlayer.cpp @@ -191,6 +191,18 @@ namespace QuickMedia { } } + if(video_process_id != -1) { + int status; + if(wait_program_non_blocking(video_process_id, &status)) { + fprintf(stderr, "The video player exited!, status: %d\n", status); + close(ipc_socket); + remove(ipc_server_path); + video_process_id = -1; + ipc_socket = -1; + return Error::EXITED; + } + } + if(connected_to_ipc && event_callback) { Error err = read_ipc_func(); if(err != Error::OK) |