aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/QuickMedia.cpp162
-rw-r--r--src/plugins/Info.cpp15
2 files changed, 121 insertions, 56 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index a61b836..595ae7b 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -289,6 +289,38 @@ namespace QuickMedia {
HistoryType history_type;
};
+ using OptionsPageHandler = std::function<void()>;
+
+ class OptionsPage : public Page {
+ public:
+ OptionsPage(Program *program, std::string title) : Page(program), title(std::move(title)) {}
+ const char* get_title() const override { return title.c_str(); }
+
+ PluginResult submit(const std::string&, const std::string &url, std::vector<Tab>&) override {
+ const int handlers_index = atoi(url.c_str());
+ handlers[handlers_index]();
+ program->set_go_to_previous_page();
+ return PluginResult::OK;
+ }
+
+ bool submit_is_async() override { return false; }
+
+ void add_option(BodyItems &items, std::string title, std::string description, OptionsPageHandler handler) {
+ assert(handler);
+ auto body_item = BodyItem::create(std::move(title));
+ if(!description.empty()) {
+ body_item->set_description(std::move(description));
+ body_item->set_description_color(sf::Color(179, 179, 179));
+ }
+ body_item->url = std::to_string(handlers.size());
+ handlers.push_back(std::move(handler));
+ items.push_back(std::move(body_item));
+ }
+ private:
+ std::string title;
+ std::vector<OptionsPageHandler> handlers;
+ };
+
Program::Program() :
disp(nullptr),
window_size(1280, 720),
@@ -1528,10 +1560,10 @@ namespace QuickMedia {
}
}
- void Program::page_loop(std::vector<Tab> &tabs, int start_tab_index, PageLoopSubmitHandler after_submit_handler) {
+ bool Program::page_loop(std::vector<Tab> &tabs, int start_tab_index, PageLoopSubmitHandler after_submit_handler) {
if(tabs.empty()) {
show_notification("QuickMedia", "No tabs provided!", Urgency::CRITICAL);
- return;
+ return false;
}
malloc_trim(0);
@@ -1845,7 +1877,7 @@ namespace QuickMedia {
redraw = true;
else if(event.type == sf::Event::KeyPressed) {
if(event.key.code == sf::Keyboard::Escape) {
- goto page_end;
+ return false;
} else if(event.key.code == sf::Keyboard::Tab) {
if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->set_to_autocomplete();
} else if(event.key.code == sf::Keyboard::Enter) {
@@ -2085,12 +2117,11 @@ namespace QuickMedia {
if(go_to_previous_page) {
go_to_previous_page = false;
- goto page_end;
+ return true;
}
}
- page_end:
- {}
+ return false;
}
static bool youtube_url_extract_id(const std::string &youtube_url, std::string &youtube_video_id) {
@@ -2279,20 +2310,58 @@ namespace QuickMedia {
return false;
}
+ void Program::video_page_download_video(const std::string &url, bool use_youtube_dl, sf::WindowHandle video_player_window) {
+ if(!use_youtube_dl) {
+ download_async_gui(url, FileManagerPage::get_last_accessed_directory(file_manager_start_dir).string(), use_youtube_dl, no_video);
+ return;
+ }
+
+ bool audio_only = false;
+ auto body = create_body();
+
+ auto options_page = std::make_unique<OptionsPage>(this, "Select download option");
+ options_page->add_option(body->items, "Download video and audio", "", [&audio_only](){
+ audio_only = false;
+ });
+ options_page->add_option(body->items, "Download only audio", "", [&audio_only](){
+ audio_only = true;
+ });
+
+ if(video_player_window) {
+ XUnmapWindow(disp, video_player_window);
+ XSync(disp, False);
+ }
+
+ std::vector<Tab> tabs;
+ tabs.push_back(Tab{ std::move(body), std::move(options_page), nullptr });
+ bool selected = page_loop(tabs);
+
+ if(video_player_window) {
+ XMapWindow(disp, video_player_window);
+ XSync(disp, False);
+ }
+
+ if(!selected)
+ return;
+
+ download_async_gui(url, FileManagerPage::get_last_accessed_directory(file_manager_start_dir).string(), true, audio_only);
+ }
+
#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) {
- sf::Clock time_watched_timer;
- bool video_loaded = false;
- const bool is_youtube = strcmp(plugin_name, "youtube") == 0;
- const bool is_matrix = strcmp(plugin_name, "matrix") == 0;
-
PageType previous_page = pop_page_stack();
std::string video_url = video_page->get_url();
std::string original_video_url = video_url;
+ sf::Clock time_watched_timer;
+ bool video_loaded = false;
+ std::string youtube_video_id;
+ const bool is_youtube = youtube_url_extract_id(video_url, youtube_video_id);
+ const bool is_matrix = strcmp(plugin_name, "matrix") == 0;
+
bool video_url_is_local = false;
- if(download_if_streaming_fails) {
+ if(!is_youtube && download_if_streaming_fails) {
Path video_cache_dir = get_cache_dir().join("media");
Path video_path = video_cache_dir;
SHA256 sha256;
@@ -2361,13 +2430,13 @@ namespace QuickMedia {
std::function<void(const char*)> video_event_callback;
- auto load_video_error_check = [this, &related_videos, &channel_url, &video_url, &video_title, &video_player, previous_page, &time_watched_timer, &video_loaded, video_page, &video_event_callback, &on_window_create, &video_player_window, is_matrix](bool resume_video) mutable {
+ auto load_video_error_check = [this, &related_videos, &channel_url, &video_url, &video_title, &video_player, previous_page, &time_watched_timer, &video_loaded, video_page, &video_event_callback, &on_window_create, &video_player_window, is_youtube, is_matrix](bool resume_video) mutable {
time_watched_timer.restart();
video_loaded = false;
video_player_window = None;
watched_videos.insert(video_url);
- video_player = std::make_unique<VideoPlayer>(no_video, use_system_mpv_config, resume_video, is_matrix, video_event_callback, on_window_create, resources_root, get_largest_monitor_height(disp));
+ video_player = std::make_unique<VideoPlayer>(no_video, use_system_mpv_config, resume_video, is_matrix && !is_youtube, video_event_callback, on_window_create, resources_root, get_largest_monitor_height(disp));
VideoPlayer::Error err = video_player->load_video(video_url.c_str(), window.getSystemHandle(), plugin_name, video_title);
if(err != VideoPlayer::Error::OK) {
std::string err_msg = "Failed to play url: ";
@@ -2490,8 +2559,6 @@ namespace QuickMedia {
window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::TOGGLE);
} else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::C && event.key.control) {
save_video_url_to_clipboard();
- } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::S && event.key.control) {
- download_async_gui(original_video_url, FileManagerPage::get_last_accessed_directory(file_manager_start_dir).string(), !is_matrix, no_video);
}
}
handle_window_close();
@@ -2512,7 +2579,7 @@ namespace QuickMedia {
} else if(pressed_keysym == XK_f && pressing_ctrl) {
window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::TOGGLE);
} else if(pressed_keysym == XK_s && pressing_ctrl) {
- download_async_gui(original_video_url, FileManagerPage::get_last_accessed_directory(file_manager_start_dir).string(), !is_matrix, no_video);
+ video_page_download_video(original_video_url, !is_matrix || is_youtube, video_player_window);
} else if(pressed_keysym == XK_r && pressing_ctrl) {
if(!cursor_visible)
window.setMouseCursorVisible(true);
@@ -2540,7 +2607,7 @@ namespace QuickMedia {
tabs.push_back(Tab{std::move(related_videos_body), std::move(related_videos_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
}
if(channels_page) {
- tabs.push_back(Tab{create_body(), std::move(channels_page), create_search_bar("Search...", is_youtube ? 350 : SEARCH_DELAY_FILTER)});
+ tabs.push_back(Tab{create_body(), std::move(channels_page), create_search_bar("Search...", 350)});
}
bool page_changed = false;
@@ -2591,7 +2658,7 @@ namespace QuickMedia {
show_notification("QuickMedia", "Failed to connect to mpv ipc after 10 seconds", Urgency::CRITICAL);
current_page = previous_page;
break;
- } else if(update_err == VideoPlayer::Error::EXITED && video_player->exit_status == 0 && !is_matrix) {
+ } else if(update_err == VideoPlayer::Error::EXITED && video_player->exit_status == 0 && (!is_matrix || is_youtube)) {
std::string new_video_url;
std::string new_video_title;
@@ -2608,7 +2675,7 @@ namespace QuickMedia {
};
find_next_video();
- if(new_video_url.empty() && parent_page && parent_body_page) {
+ if(new_video_url.empty() && parent_page && parent_body_page && video_page->autoplay_next_item()) {
BodyItems new_body_items;
const int fetch_page = (*parent_body_page) + 1;
TaskResult load_next_page_result = run_task_with_loading_screen([parent_page, parent_page_search, fetch_page, &new_body_items] {
@@ -4890,19 +4957,18 @@ namespace QuickMedia {
bool avatar_applied = false;
- auto launch_url = [this, matrix_chat_page, &video_page, &redraw, &avatar_applied](const std::string &url) mutable {
+ auto launch_url = [this, matrix_chat_page, &tabs, MESSAGES_TAB_INDEX, &redraw, &avatar_applied](const std::string &url) mutable {
if(url.empty())
return;
std::string video_id;
if(youtube_url_extract_id(url, video_id)) {
- page_stack.push(PageType::CHAT);
watched_videos.clear();
+ page_stack.push(PageType::CHAT);
current_page = PageType::VIDEO_CONTENT;
- video_page->url = url;
- BodyItems next_items;
- // TODO: Add title
- video_content_page(matrix_chat_page, video_page.get(), "", false, next_items, 0);
+ auto youtube_video_page = std::make_unique<YoutubeVideoPage>(this, url);
+ // TODO: Use real title
+ video_content_page(matrix_chat_page, youtube_video_page.get(), "", false, tabs[MESSAGES_TAB_INDEX].body->items, tabs[MESSAGES_TAB_INDEX].body->get_selected_item());
redraw = true;
avatar_applied = false;
} else {
@@ -6489,7 +6555,7 @@ namespace QuickMedia {
}
loading_bar.set_size(sf::Vector2f(
- std::floor((loading_bar_background.get_size().x - loading_bar_padding_x) * ui_progress),
+ std::floor((loading_bar_background.get_size().x - loading_bar_padding_x * 2.0f) * ui_progress),
loading_bar_height - loading_bar_padding_y * 2.0f));
window.clear(sf::Color(33, 37, 44));
@@ -6516,29 +6582,6 @@ namespace QuickMedia {
exit(exit_code);
}
- class ConfirmationPage : public Page {
- public:
- ConfirmationPage(Program *program, bool *file_overwrite, const std::string &title) : Page(program), file_overwrite(file_overwrite), title(title) {}
- const char* get_title() const override { return title.c_str(); }
- PluginResult submit(const std::string &title, const std::string&, std::vector<Tab>&) override {
- if(title == "Yes")
- *file_overwrite = true;
- else
- *file_overwrite = false;
-
- program->set_go_to_previous_page();
- return PluginResult::OK;
- }
-
- static void add_items(BodyItems &items) {
- items.push_back(BodyItem::create("No"));
- items.push_back(BodyItem::create("Yes"));
- }
- private:
- bool *file_overwrite;
- std::string title;
- };
-
std::string Program::file_save_page(const std::string &filename) {
sf::Vector2f body_pos;
sf::Vector2f body_size;
@@ -6590,10 +6633,10 @@ namespace QuickMedia {
const float bottom_panel_spacing = 10.0f;
Button cancel_button("Cancel", FontLoader::get_font(FontLoader::FontType::LATIN), 16, 100.0f, &rounded_rectangle_shader, get_ui_scale());
- cancel_button.set_background_color(sf::Color(104, 2, 2));
+ cancel_button.set_background_color(sf::Color(41, 45, 50));
Button save_button("Save", FontLoader::get_font(FontLoader::FontType::LATIN), 16, 100.0f, &rounded_rectangle_shader, get_ui_scale());
- save_button.set_background_color(sf::Color(35, 35, 236));
+ save_button.set_background_color(sf::Color(71, 75, 180));
sf::Text file_name_label("File name:", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(16.0f * get_ui_scale()));
@@ -6621,11 +6664,20 @@ namespace QuickMedia {
} else {
if(std::filesystem::exists(filename_full_path.data)) {
bool overwrite = false;
- std::vector<Tab> tabs;
auto body = create_body();
- ConfirmationPage::add_items(body->items);
- tabs.push_back(Tab{ std::move(body), std::make_unique<ConfirmationPage>(this, &overwrite, "Are you sure you want to overwrite " + filename_full_path.data + "?"), nullptr });
+
+ auto options_page = std::make_unique<OptionsPage>(this, "Are you sure you want to overwrite " + filename_full_path.data + "?");
+ options_page->add_option(body->items, "No", "", [&overwrite](){
+ overwrite = false;
+ });
+ options_page->add_option(body->items, "Yes", "", [&overwrite](){
+ overwrite = true;
+ });
+
+ std::vector<Tab> tabs;
+ tabs.push_back(Tab{ std::move(body), std::move(options_page), nullptr });
page_loop(tabs);
+
if(overwrite)
return std::move(filename_full_path.data);
} else {
diff --git a/src/plugins/Info.cpp b/src/plugins/Info.cpp
index b1943b3..a68033f 100644
--- a/src/plugins/Info.cpp
+++ b/src/plugins/Info.cpp
@@ -1,5 +1,6 @@
#include "../../plugins/Info.hpp"
#include "../../plugins/Saucenao.hpp"
+#include "../../plugins/Youtube.hpp"
#include "../../include/StringUtils.hpp"
#include "../../include/Program.hpp"
#include "../../include/Notification.hpp"
@@ -7,11 +8,18 @@
namespace QuickMedia {
static const char *REVERSE_IMAGE_SEARCH_URL = "reverse-image-search://";
+ static bool is_youtube_url(const std::string &url) {
+ return url.find("youtube.com/") != std::string::npos || url.find("youtu.be/") != std::string::npos;
+ }
+
PluginResult InfoPage::submit(const std::string&, const std::string &url, std::vector<Tab> &result_tabs) {
if(string_starts_with(url, REVERSE_IMAGE_SEARCH_URL)) {
std::string image_url = url.substr(strlen(REVERSE_IMAGE_SEARCH_URL));
result_tabs.push_back(Tab{create_body(), std::make_unique<SaucenaoPage>(program, image_url, false), nullptr});
return PluginResult::OK;
+ } else if(is_youtube_url(url)) {
+ result_tabs.push_back(Tab{nullptr, std::make_unique<YoutubeVideoPage>(program, url), nullptr});
+ return PluginResult::OK;
} else {
const char *launch_program = "xdg-open";
if(!is_program_executable_by_name("xdg-open")) {
@@ -33,7 +41,12 @@ namespace QuickMedia {
// static
std::shared_ptr<BodyItem> InfoPage::add_url(const std::string &url) {
- auto body_item = BodyItem::create("Open " + url + " in a browser");
+ std::string title;
+ if(is_youtube_url(url))
+ title = "Play " + url;
+ else
+ title = "Open " + url + " in a browser";
+ auto body_item = BodyItem::create(std::move(title));
body_item->url = url;
return body_item;
}