aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-08-08 07:26:04 +0200
committerdec05eba <dec05eba@protonmail.com>2019-08-08 07:26:08 +0200
commitc9c2621accb68634685a14703491cacdd7ed2bb1 (patch)
tree51b55692a6010c533dfd98087e12f555a54772e8
parent0943801f321216dabe9f45593f608a222c0d4310 (diff)
Retain fullscreen video when changing to next video
-rw-r--r--include/Body.hpp6
-rw-r--r--include/Program.h2
-rw-r--r--include/VideoPlayer.hpp9
-rw-r--r--src/Body.cpp22
-rw-r--r--src/Program.c3
-rw-r--r--src/QuickMedia.cpp105
-rw-r--r--src/VideoPlayer.cpp31
7 files changed, 99 insertions, 79 deletions
diff --git a/include/Body.hpp b/include/Body.hpp
index 65aae8d..5d16898 100644
--- a/include/Body.hpp
+++ b/include/Body.hpp
@@ -47,11 +47,15 @@ namespace QuickMedia {
sf::Text progress_text;
int selected_item;
std::vector<std::unique_ptr<BodyItem>> items;
- std::vector<std::shared_ptr<sf::Texture>> item_thumbnail_textures;
std::thread thumbnail_load_thread;
bool draw_thumbnails;
private:
+ struct ThumbnailData {
+ std::string url;
+ std::shared_ptr<sf::Texture> texture;
+ };
std::shared_ptr<sf::Texture> load_thumbnail_from_url(const std::string &url);
+ std::vector<ThumbnailData> item_thumbnail_textures;
bool loading_thumbnail;
};
} \ No newline at end of file
diff --git a/include/Program.h b/include/Program.h
index f891d8e..ba7e523 100644
--- a/include/Program.h
+++ b/include/Program.h
@@ -5,7 +5,7 @@
extern "C" {
#endif
-/* Return 0 if you want to continue reading */
+/* Return 0 if you want to continue reading. @data is null-terminated */
typedef int (*ProgramOutputCallback)(char *data, int size, void *userdata);
/*
diff --git a/include/VideoPlayer.hpp b/include/VideoPlayer.hpp
index 4f60883..a9b177c 100644
--- a/include/VideoPlayer.hpp
+++ b/include/VideoPlayer.hpp
@@ -28,6 +28,9 @@ namespace QuickMedia {
// Throws VideoInitializationException on error
VideoPlayer(sf::RenderWindow *window, unsigned int width, unsigned int height, const char *file, bool loop = false);
~VideoPlayer();
+
+ VideoPlayer(const VideoPlayer&) = delete;
+ VideoPlayer& operator=(const VideoPlayer&) = delete;
void handle_event(sf::Event &event);
void setPosition(float x, float y);
@@ -40,9 +43,9 @@ namespace QuickMedia {
// This is updated when mpv wants to render
std::atomic_bool redraw;
std::atomic_bool event_update;
+ // Important: Do not destroy the video player in this callback
PlaybackEndedCallback onPlaybackEndedCallback;
private:
- void on_doubleclick();
void handle_mpv_events();
private:
mpv_handle *mpv;
@@ -56,9 +59,5 @@ namespace QuickMedia {
sf::RectangleShape seekbar;
sf::RectangleShape seekbar_background;
sf::Clock cursor_last_active_timer;
- sf::Clock time_since_last_left_click;
- int left_click_counter;
- sf::RenderWindow *window;
- bool video_is_fullscreen;
};
}
diff --git a/src/Body.cpp b/src/Body.cpp
index c9fbc89..6051e02 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -54,7 +54,7 @@ namespace QuickMedia {
void Body::clear_items() {
items.clear();
- item_thumbnail_textures.clear();
+ //item_thumbnail_textures.clear();
}
BodyItem* Body::get_selected() const {
@@ -137,11 +137,8 @@ namespace QuickMedia {
if(num_items == 0)
return;
- if((int)item_thumbnail_textures.size() != num_items) {
- // First unload all textures, then prepare to load new textures
- item_thumbnail_textures.resize(0);
+ if((int)item_thumbnail_textures.size() != num_items)
item_thumbnail_textures.resize(num_items);
- }
float row_height = font_height;
if(draw_thumbnails)
@@ -173,8 +170,15 @@ namespace QuickMedia {
float row_height = font_height;
if(draw_thumbnails) {
row_height = image_height;
- if(!item->thumbnail_url.empty() && !item_thumbnail && !loading_thumbnail)
- item_thumbnail = load_thumbnail_from_url(item->thumbnail_url);
+ // TODO: Should this be optimized by instead of checking if url changes based on index,
+ // put thumbnails in hash map based on url?
+ if(item->thumbnail_url.empty() && item_thumbnail.texture) {
+ item_thumbnail.texture = nullptr;
+ item_thumbnail.url = "";
+ } else if(!item->thumbnail_url.empty() && !loading_thumbnail && (!item_thumbnail.texture || item_thumbnail.url != item->url)) {
+ item_thumbnail.url = item->url;
+ item_thumbnail.texture = load_thumbnail_from_url(item->thumbnail_url);
+ }
}
sf::Vector2f item_pos = pos;
@@ -198,8 +202,8 @@ namespace QuickMedia {
if(draw_thumbnails) {
// TODO: Verify if this is safe. The thumbnail is being modified in another thread
// and it might not be fully finished before the native handle is set?
- if(item_thumbnail && item_thumbnail->getNativeHandle() != 0) {
- image.setTexture(*item_thumbnail, true);
+ if(item_thumbnail.texture && item_thumbnail.texture->getNativeHandle() != 0) {
+ image.setTexture(*item_thumbnail.texture, true);
auto image_size = image.getTexture()->getSize();
auto height_ratio = image_height / image_size.y;
auto scale = image.getScale();
diff --git a/src/Program.c b/src/Program.c
index 480f403..731a20e 100644
--- a/src/Program.c
+++ b/src/Program.c
@@ -39,7 +39,7 @@ int exec_program(const char **args, ProgramOutputCallback output_callback, void
char buffer[2048];
for(;;) {
- ssize_t bytes_read = read(fd[READ_END], buffer, sizeof(buffer));
+ ssize_t bytes_read = read(fd[READ_END], buffer, sizeof(buffer) - 1);
if(bytes_read == 0) {
break;
} else if(bytes_read == -1) {
@@ -49,6 +49,7 @@ int exec_program(const char **args, ProgramOutputCallback output_callback, void
goto cleanup;
}
+ buffer[bytes_read] = '\0';
if(output_callback && output_callback(buffer, bytes_read, userdata) != 0)
break;
}
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 4fa5f35..0a34508 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -17,6 +17,7 @@
const sf::Color front_color(43, 45, 47);
const sf::Color back_color(33, 35, 37);
+const int DOUBLE_CLICK_TIME = 500;
namespace QuickMedia {
Program::Program() :
@@ -319,49 +320,80 @@ namespace QuickMedia {
search_bar->onTextUpdateCallback = nullptr;
search_bar->onTextSubmitCallback = nullptr;
- watched_videos.insert(content_url);
- std::unique_ptr<VideoPlayer> video_player = nullptr;
- try {
- printf("Play video: %s\n", content_url.c_str());
- video_player.reset(new VideoPlayer(&window, window_size.x, window_size.y, content_url.c_str()));
- } catch(VideoInitializationException &e) {
- show_notification("Video player", "Failed to create video player", Urgency::CRITICAL);
- video_player = nullptr;
- }
+ // This variable is needed because calling play_video is not possible in onPlaybackEndedCallback
+ bool play_next_video = false;
- std::vector<std::unique_ptr<BodyItem>> related_media = current_plugin->get_related_media(content_url);
- bool reload = false;
-
- if(video_player) {
- video_player->onPlaybackEndedCallback = [this, &related_media, &video_player, &reload]() {
- std::string new_video_url;
- // Find video that hasn't been played before in this video session
- for(auto it = related_media.begin(), end = related_media.end(); it != end; ++it) {
- if(watched_videos.find((*it)->url) == watched_videos.end()) {
- new_video_url = (*it)->url;
- related_media.erase(it);
- break;
- }
+ auto onPlaybackEndedCallback = [this, &play_next_video]() {
+ std::string new_video_url;
+ std::vector<std::unique_ptr<BodyItem>> related_media = current_plugin->get_related_media(content_url);
+ // Find video that hasn't been played before in this video session
+ for(auto it = related_media.begin(), end = related_media.end(); it != end; ++it) {
+ if(watched_videos.find((*it)->url) == watched_videos.end()) {
+ new_video_url = (*it)->url;
+ break;
}
+ }
- // If there are no videos to play, then dont play any...
- if(new_video_url.empty())
- return;
+ // If there are no videos to play, then dont play any...
+ if(new_video_url.empty()) {
+ show_notification("Video player", "No more related videos to play");
+ return;
+ }
- content_url = std::move(new_video_url);
- related_media = current_plugin->get_related_media(content_url);
- // TODO: This doesn't seem to work correctly right now, it causes video to become black when changing video (context reset bug).
- //video_player->load_file(video_url);
- reload = true;
- };
- }
+ content_url = std::move(new_video_url);
+ play_next_video = true;
+ // TODO: This doesn't seem to work correctly right now, it causes video to become black when changing video (context reset bug).
+ //video_player->load_file(video_url);
+ };
+
+ std::unique_ptr<VideoPlayer> video_player = nullptr;
+ auto play_video = [this, &video_player, &onPlaybackEndedCallback]() {
+ watched_videos.insert(content_url);
+ try {
+ printf("Play video: %s\n", content_url.c_str());
+ video_player.reset(new VideoPlayer(&window, window_size.x, window_size.y, content_url.c_str()));
+ video_player->onPlaybackEndedCallback = onPlaybackEndedCallback;
+ } catch(VideoInitializationException &e) {
+ show_notification("Video player", "Failed to create video player", Urgency::CRITICAL);
+ video_player = nullptr;
+ }
+ };
+ play_video();
- sf::Clock resize_timer;
+ sf::Clock time_since_last_left_click;
+ int left_click_counter;
+ bool video_is_fullscreen = false;
sf::Event event;
- while (current_page == Page::VIDEO_CONTENT && !reload) {
+ auto on_doubleclick = [this, &video_is_fullscreen]() {
+ if(video_is_fullscreen) {
+ window.create(sf::VideoMode::getDesktopMode(), "QuickMedia", sf::Style::Default);
+ } else {
+ window.create(sf::VideoMode::getDesktopMode(), "QuickMedia", sf::Style::Fullscreen);
+ }
+ window.setVerticalSyncEnabled(true);
+ video_is_fullscreen = !video_is_fullscreen;
+ };
+
+ 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::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
+ if(time_since_last_left_click.restart().asMilliseconds() <= DOUBLE_CLICK_TIME) {
+ if(++left_click_counter == 2) {
+ on_doubleclick();
+ left_click_counter = 0;
+ }
+ } else {
+ left_click_counter = 1;
+ }
+ }
+
if(video_player) {
if(event.type == sf::Event::Resized)
video_player->resize(window_size);
@@ -374,6 +406,11 @@ namespace QuickMedia {
video_player->draw(window);
window.display();
}
+
+ if(video_is_fullscreen) {
+ window.create(sf::VideoMode::getDesktopMode(), "QuickMedia", sf::Style::Default);
+ window.setVerticalSyncEnabled(true);
+ }
}
enum class TrackMediaType {
diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp
index 62fc7d2..4c19c61 100644
--- a/src/VideoPlayer.cpp
+++ b/src/VideoPlayer.cpp
@@ -8,7 +8,6 @@
#include <cmath>
const int UI_VISIBLE_TIMEOUT_MS = 2500;
-const int DOUBLE_CLICK_TIME = 500;
const auto pause_key = sf::Keyboard::Space;
namespace QuickMedia {
@@ -61,10 +60,7 @@ namespace QuickMedia {
mpvGl(nullptr),
context(nullptr),
textureBuffer(nullptr),
- desired_size(width, height),
- left_click_counter(0),
- window(_window),
- video_is_fullscreen(false)
+ desired_size(width, height)
{
//ContextScope context_scope(context.get());
texture.setSmooth(true);
@@ -135,12 +131,9 @@ namespace QuickMedia {
if(mpv) {
//mpv_set_wakeup_callback(mpv, nullptr, nullptr);
- //mpv_detach_destroy(mpv);
- mpv_terminate_destroy(mpv);
+ mpv_destroy(mpv);
+ //mpv_terminate_destroy(mpv);
}
-
- if(video_is_fullscreen)
- window->create(sf::VideoMode::getDesktopMode(), "QuickMedia", sf::Style::Default);
}
void VideoPlayer::handle_event(sf::Event &event) {
@@ -150,25 +143,7 @@ namespace QuickMedia {
if(event.key.code == pause_key) {
mpv_command_string(mpv, "cycle pause");
}
- } else if(event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
- if(time_since_last_left_click.restart().asMilliseconds() <= DOUBLE_CLICK_TIME) {
- if(++left_click_counter == 2) {
- on_doubleclick();
- left_click_counter = 0;
- }
- } else {
- left_click_counter = 1;
- }
- }
- }
-
- void VideoPlayer::on_doubleclick() {
- if(video_is_fullscreen) {
- window->create(sf::VideoMode::getDesktopMode(), "QuickMedia", sf::Style::Default);
- } else {
- window->create(sf::VideoMode::getDesktopMode(), "QuickMedia", sf::Style::Fullscreen);
}
- video_is_fullscreen = !video_is_fullscreen;
}
void VideoPlayer::setPosition(float x, float y) {