From 34fef69fd468f695b3b5817da6a9980ac7b5860d Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 31 May 2020 18:03:57 +0200 Subject: Add dmenu option --- README.md | 3 ++- include/Notification.hpp | 2 +- include/QuickMedia.hpp | 4 ++++ plugins/Dmenu.hpp | 20 ++++++++++++++++++++ plugins/Plugin.hpp | 2 ++ src/QuickMedia.cpp | 42 +++++++++++++++++------------------------- src/VideoPlayer.cpp | 2 +- src/plugins/Dmenu.cpp | 23 +++++++++++++++++++++++ src/plugins/Pornhub.cpp | 13 ------------- 9 files changed, 70 insertions(+), 41 deletions(-) create mode 100644 plugins/Dmenu.hpp create mode 100644 src/plugins/Dmenu.cpp diff --git a/README.md b/README.md index 941b70b..1b9b9c3 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,12 @@ Config data, including manga progress is stored under `$HOME/.config/quickmedia` ``` usage: QuickMedia [--tor] OPTIONS: -plugin The plugin to use. Should be either 4chan, manganelo, mangadex or youtube +plugin The plugin to use. Should be either 4chan, manganelo, mangadex, youtube or dmenu --tor Use tor. Disabled by default EXAMPLES: QuickMedia manganelo QuickMedia youtube --tor +echo "hello\nworld" | QuickMedia dmenu ``` ## Controls Press `arrow up` and `arrow down` to navigate the menu and also to go to the previous/next image when viewing manga.\ diff --git a/include/Notification.hpp b/include/Notification.hpp index 22f2f77..4f7fcc2 100644 --- a/include/Notification.hpp +++ b/include/Notification.hpp @@ -27,6 +27,6 @@ namespace QuickMedia { static void show_notification(const std::string &title, const std::string &description, Urgency urgency = Urgency::NORMAL) { const char *args[] = { "notify-send", "-u", urgency_string(urgency), "--", title.c_str(), description.c_str(), nullptr }; exec_program_async(args, nullptr); - printf("Notification: title: %s, description: %s\n", title.c_str(), description.c_str()); + fprintf(stderr, "Notification: title: %s, description: %s\n", title.c_str(), description.c_str()); } } \ No newline at end of file diff --git a/include/QuickMedia.hpp b/include/QuickMedia.hpp index 19d84a8..cd410c3 100644 --- a/include/QuickMedia.hpp +++ b/include/QuickMedia.hpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include namespace QuickMedia { class Plugin; @@ -49,6 +51,7 @@ namespace QuickMedia { // Returns Page::EXIT if empty Page pop_page_stack(); private: + Display *disp; sf::RenderWindow window; sf::Vector2f window_size; sf::Font font; @@ -77,5 +80,6 @@ namespace QuickMedia { std::future image_download_future; std::string downloading_chapter_url; bool image_download_cancel = false; + int exit_code = 0; }; } \ No newline at end of file diff --git a/plugins/Dmenu.hpp b/plugins/Dmenu.hpp new file mode 100644 index 0000000..84614cc --- /dev/null +++ b/plugins/Dmenu.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "Plugin.hpp" + +namespace QuickMedia { + class Dmenu : public Plugin { + public: + Dmenu(); + bool search_is_filter() override { return true; } + bool search_suggestions_has_thumbnails() const override { return false; } + bool search_results_has_thumbnails() const override { return false; } + int get_search_delay() const override { return 0; } + bool search_suggestion_is_search() const override { return true; } + Page get_page_after_search() const override { return Page::EXIT; } + PluginResult get_front_page(BodyItems &result_items) override; + SearchResult search(const std::string &text, BodyItems &result_items) override; + private: + std::vector stdin_data; + }; +} \ No newline at end of file diff --git a/plugins/Plugin.hpp b/plugins/Plugin.hpp index b430d57..be70684 100644 --- a/plugins/Plugin.hpp +++ b/plugins/Plugin.hpp @@ -43,6 +43,8 @@ namespace QuickMedia { virtual bool is_image_board() { return false; } virtual bool is_manga() { return false; } + // Return true if searching should update the search result (which could be a remote server search) or filter the existing list locally + virtual bool search_is_filter() { return false; } virtual PluginResult get_front_page(BodyItems &result_items) { (void)result_items; return PluginResult::OK; diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 5a13179..8fdedb3 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -4,6 +4,7 @@ #include "../plugins/Youtube.hpp" #include "../plugins/Pornhub.hpp" #include "../plugins/Fourchan.hpp" +#include "../plugins/Dmenu.hpp" #include "../include/Scale.hpp" #include "../include/Program.h" #include "../include/VideoPlayer.hpp" @@ -21,8 +22,6 @@ #include #include #include -#include -#include #include static const sf::Color back_color(30, 32, 34); @@ -44,6 +43,7 @@ static int x_io_error_handler(Display *display) { namespace QuickMedia { Program::Program() : + disp(nullptr), window(sf::VideoMode(800, 600), "QuickMedia"), window_size(800, 600), body(nullptr), @@ -51,6 +51,10 @@ namespace QuickMedia { current_page(Page::SEARCH_SUGGESTION), image_index(0) { + disp = XOpenDisplay(NULL); + if (!disp) + throw std::runtime_error("Failed to open display to X11 server"); + window.setVerticalSyncEnabled(true); if(!font.loadFromFile("../../../fonts/Lato-Regular.ttf")) { fprintf(stderr, "Failed to load font: Lato-Regular.ttf\n"); @@ -75,6 +79,8 @@ namespace QuickMedia { Program::~Program() { delete body; delete current_plugin; + if(disp) + XCloseDisplay(disp); } static SearchResult search_selected_suggestion(Body *input_body, Body *output_body, Plugin *plugin, std::string &selected_title, std::string &selected_url) { @@ -93,11 +99,12 @@ namespace QuickMedia { static void usage() { fprintf(stderr, "usage: QuickMedia [--tor]\n"); fprintf(stderr, "OPTIONS:\n"); - fprintf(stderr, "plugin The plugin to use. Should be either 4chan, manganelo, mangadex, pornhub or youtube\n"); + fprintf(stderr, "plugin The plugin to use. Should be either 4chan, manganelo, mangadex, pornhub, youtube or dmenu\n"); fprintf(stderr, "--tor Use tor. Disabled by default\n"); fprintf(stderr, "EXAMPLES:\n"); fprintf(stderr, "QuickMedia manganelo\n"); fprintf(stderr, "QuickMedia youtube --tor\n"); + fprintf(stderr, "echo \"hello\nworld\" | QuickMedia dmenu\n"); } static bool is_program_executable_by_name(const char *name) { @@ -146,6 +153,8 @@ namespace QuickMedia { } else if(strcmp(argv[i], "4chan") == 0) { current_plugin = new Fourchan(); plugin_logo_path = "../../../images/4chan_logo.png"; + } else if(strcmp(argv[i], "dmenu") == 0) { + current_plugin = new Dmenu(); } } @@ -237,7 +246,7 @@ namespace QuickMedia { } } - return 0; + return exit_code; } void Program::base_event_handler(sf::Event &event, Page previous_page, bool handle_keypress, bool clear_on_escape, bool handle_searchbar) { @@ -357,7 +366,7 @@ namespace QuickMedia { } search_bar->onTextUpdateCallback = [&update_search_text, this, &tabs, &selected_tab](const std::string &text) { - if(tabs[selected_tab].body == body) + if(tabs[selected_tab].body == body && !current_plugin->search_is_filter()) update_search_text = text; else { tabs[selected_tab].body->filter_search_fuzzy(text); @@ -438,6 +447,7 @@ namespace QuickMedia { tabs[selected_tab].body->select_next_item(); } else if(event.key.code == sf::Keyboard::Escape) { current_page = Page::EXIT; + exit_code = 1; } else if(event.key.code == sf::Keyboard::Left) { selected_tab = std::max(0, selected_tab - 1); search_bar->clear(); @@ -578,19 +588,6 @@ namespace QuickMedia { #endif } - struct XDisplayScope { - XDisplayScope(Display *_display) : display(_display) { - - } - - ~XDisplayScope() { - if(display) - XCloseDisplay(display); - } - - Display *display; - }; - enum class WindowFullscreenState { UNSET, SET, @@ -631,13 +628,8 @@ namespace QuickMedia { Page previous_page = pop_page_stack(); - Display* disp = XOpenDisplay(NULL); - if (!disp) - throw std::runtime_error("Failed to open display to X11 server"); - XDisplayScope display_scope(disp); - std::unique_ptr video_player_ui_window; - auto on_window_create = [disp, &video_player_ui_window](sf::WindowHandle video_player_window) { + auto on_window_create = [this, &video_player_ui_window](sf::WindowHandle video_player_window) { int screen = DefaultScreen(disp); Window ui_window = XCreateWindow(disp, RootWindow(disp, screen), 0, 0, 1, 1, 0, @@ -705,7 +697,7 @@ namespace QuickMedia { }, on_window_create); load_video_error_check(); - auto on_doubleclick = [this, disp]() { + auto on_doubleclick = [this]() { window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::TOGGLE); }; diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp index 165e6e7..08ecc7e 100644 --- a/src/VideoPlayer.cpp +++ b/src/VideoPlayer.cpp @@ -84,7 +84,7 @@ namespace QuickMedia { if(exec_program_async(args.data(), &video_process_id) != 0) return Error::FAIL_TO_LAUNCH_PROCESS; - printf("mpv input ipc server: %s\n", ipc_server_path); + fprintf(stderr, "mpv input ipc server: %s\n", ipc_server_path); if((ipc_socket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { perror("Failed to create socket for video player"); diff --git a/src/plugins/Dmenu.cpp b/src/plugins/Dmenu.cpp new file mode 100644 index 0000000..a3b354b --- /dev/null +++ b/src/plugins/Dmenu.cpp @@ -0,0 +1,23 @@ +#include "../../plugins/Dmenu.hpp" +#include + +namespace QuickMedia { + Dmenu::Dmenu() : Plugin("dmenu") { + std::string line; + while(std::getline(std::cin, line)) { + stdin_data.push_back(std::move(line)); + } + } + + PluginResult Dmenu::get_front_page(BodyItems &result_items) { + for(const std::string &line_data : stdin_data) { + result_items.push_back(std::make_unique(line_data)); + } + return PluginResult::OK; + } + + SearchResult Dmenu::search(const std::string &text, BodyItems &result_items) { + std::cout << text << std::endl; + return SearchResult::OK; + } +} \ No newline at end of file diff --git a/src/plugins/Pornhub.cpp b/src/plugins/Pornhub.cpp index c94532b..9a7242a 100644 --- a/src/plugins/Pornhub.cpp +++ b/src/plugins/Pornhub.cpp @@ -12,19 +12,6 @@ namespace QuickMedia { return strstr(str, substr); } - static void iterate_suggestion_result(const Json::Value &value, BodyItems &result_items, int &iterate_count) { - ++iterate_count; - if(value.isArray()) { - for(const Json::Value &child : value) { - iterate_suggestion_result(child, result_items, iterate_count); - } - } else if(value.isString() && iterate_count > 2) { - std::string title = value.asString(); - auto item = std::make_unique(title); - result_items.push_back(std::move(item)); - } - } - // TODO: Speed this up by using string.find instead of parsing html SuggestionResult Pornhub::update_search_suggestions(const std::string &text, BodyItems &result_items) { std::string url = "https://www.pornhub.com/video/search?search="; -- cgit v1.2.3