diff options
author | dec05eba <dec05eba@protonmail.com> | 2019-08-09 15:54:44 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2019-08-09 15:55:18 +0200 |
commit | 322513ac417aa7002946a3f203ae1a65f959677a (patch) | |
tree | 95144d28741e79b637159c8ddb1a11fe6accf6ef | |
parent | 10fcdec298ccef4971dc6d109222079a0f438004 (diff) |
Wait until mpv process dies (prevent zombie), fix crash that happens sometimes when quiting video
-rw-r--r-- | include/Program.h | 3 | ||||
-rw-r--r-- | src/Program.c | 13 | ||||
-rw-r--r-- | src/QuickMedia.cpp | 48 | ||||
-rw-r--r-- | src/VideoPlayer.cpp | 4 |
4 files changed, 57 insertions, 11 deletions
diff --git a/include/Program.h b/include/Program.h index 69ee564..6a6d038 100644 --- a/include/Program.h +++ b/include/Program.h @@ -22,6 +22,9 @@ typedef int (*ProgramOutputCallback)(char *data, int size, void *userdata); */ int exec_program(const char **args, ProgramOutputCallback output_callback, void *userdata); +// Return the exit status, or a negative value if waiting failed +int wait_program(pid_t process_id); + /* @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/src/Program.c b/src/Program.c index a863fcd..8d20d43 100644 --- a/src/Program.c +++ b/src/Program.c @@ -87,6 +87,19 @@ int exec_program(const char **args, ProgramOutputCallback output_callback, void } } +int wait_program(pid_t process_id) { + int status; + if(waitpid(process_id, &status, WUNTRACED) == -1) { + perror("waitpid failed"); + return -errno; + } + + if(!WIFEXITED(status)) + return -4; + + return WEXITSTATUS(status); +} + 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 db2eeb0..eb77aef 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -373,6 +373,19 @@ namespace QuickMedia { throw std::runtime_error("Failed to open display to X11 server"); XDisplayScope display_scope(disp); + int screen = DefaultScreen(disp); + Window video_player_window_id = XCreateWindow(disp, RootWindow(disp, screen), + 0, 0, window.getSize().x, window.getSize().y, 0, + DefaultDepth(disp, screen), + InputOutput, + DefaultVisual(disp, screen), + 0, NULL); + + XReparentWindow(disp, video_player_window_id, window.getSystemHandle(), 0, 0); + XMapWindow(disp, video_player_window_id); + XFlush(disp); + std::unique_ptr<sf::RenderWindow> video_player_window = std::make_unique<sf::RenderWindow>(video_player_window_id); + std::unique_ptr<sf::RenderWindow> video_player_ui_window; auto on_window_create = [disp, &video_player_ui_window](sf::WindowHandle video_player_window) { int screen = DefaultScreen(disp); @@ -396,7 +409,7 @@ namespace QuickMedia { std::unique_ptr<VideoPlayer> video_player; - auto play_video = [this, &video_player, &play_next_video, &on_window_create, &video_player_ui_window, &ui_resize]() { + auto play_video = [this, &video_player, &play_next_video, &on_window_create, &video_player_ui_window, &ui_resize, &video_player_window]() { printf("Playing video: %s\n", content_url.c_str()); watched_videos.insert(content_url); video_player = std::make_unique<VideoPlayer>([this, &play_next_video, &video_player_ui_window, &ui_resize](const char *event_name) { @@ -428,7 +441,7 @@ namespace QuickMedia { } }, on_window_create); - VideoPlayer::Error err = video_player->load_video(content_url.c_str(), window.getSystemHandle()); + VideoPlayer::Error err = video_player->load_video(content_url.c_str(), video_player_window->getSystemHandle()); if(err != VideoPlayer::Error::OK) { std::string err_msg = "Failed to play url: "; err_msg += content_url; @@ -455,20 +468,32 @@ namespace QuickMedia { sf::Clock get_progress_timer; double progress = 0.0; + // We want a black screen before video starts playing, instead of being frozen at previous UI + video_player_window->clear(); + video_player_window->display(); + while (current_page == Page::VIDEO_CONTENT) { if(play_next_video) { play_next_video = false; play_video(); } - while (window.pollEvent(event)) { - base_event_handler(event, Page::SEARCH_SUGGESTION); - if(event.type == sf::Event::Resized) { + while (video_player_window->pollEvent(event)) { + if (event.type == sf::Event::Closed) { + current_page = Page::EXIT; + } else if(event.type == sf::Event::Resized) { + window_size.x = event.size.width; + window_size.y = event.size.height; + video_player_window->setSize(sf::Vector2u(window_size.x, window_size.y)); if(video_player_ui_window) ui_resize = true; - } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space) { - if(video_player->toggle_pause() != VideoPlayer::Error::OK) { - fprintf(stderr, "Failed to toggle pause!\n"); + } else if(event.type == sf::Event::KeyPressed) { + if(event.key.code == sf::Keyboard::Escape) + current_page = Page::SEARCH_SUGGESTION; + else if(event.key.code == sf::Keyboard::Space) { + if(video_player->toggle_pause() != VideoPlayer::Error::OK) { + fprintf(stderr, "Failed to toggle pause!\n"); + } } } else if(event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) { if(time_since_last_left_click.restart().asMilliseconds() <= DOUBLE_CLICK_TIME) { @@ -509,8 +534,8 @@ namespace QuickMedia { } // TODO: Show loading video animation - //window.clear(); - //window.display(); + //video_player_window->clear(); + //video_player_window->display(); if(get_progress_timer.getElapsedTime().asMilliseconds() >= 500) { get_progress_timer.restart(); @@ -547,6 +572,9 @@ namespace QuickMedia { } } } + + video_player_ui_window.reset(); + video_player_window.reset(); } enum class TrackMediaType { diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp index 0e6735a..65bbb67 100644 --- a/src/VideoPlayer.cpp +++ b/src/VideoPlayer.cpp @@ -38,8 +38,10 @@ namespace QuickMedia { } VideoPlayer::~VideoPlayer() { - if(video_process_id != -1) + if(video_process_id != -1) { kill(video_process_id, SIGTERM); + wait_program(video_process_id); + } if(ipc_socket != -1) close(ipc_socket); |