diff --git a/.clang-format b/.clang-format index 9055edd..6d77dfa 100644 --- a/.clang-format +++ b/.clang-format @@ -2,12 +2,12 @@ Language: Cpp # BasedOnStyle: LLVM AccessModifierOffset: -2 -AlignAfterOpenBracket: Align -AlignConsecutiveMacros: false +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveMacros: true AlignConsecutiveAssignments: false AlignConsecutiveBitFields: false AlignConsecutiveDeclarations: false -AlignEscapedNewlines: Right +AlignEscapedNewlines: Left AlignOperands: Align AlignTrailingComments: true AllowAllArgumentsOnNextLine: true @@ -29,7 +29,7 @@ BinPackParameters: true BraceWrapping: AfterCaseLabel: false AfterClass: false - AfterControlStatement: Never + AfterControlStatement: false AfterEnum: false AfterFunction: false AfterNamespace: false @@ -48,10 +48,10 @@ BraceWrapping: BreakBeforeBinaryOperators: None BreakBeforeBraces: Attach BreakBeforeInheritanceComma: false -BreakInheritanceList: BeforeColon -BreakBeforeTernaryOperators: true +BreakInheritanceList: AfterColon +BreakBeforeTernaryOperators: false BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeColon +BreakConstructorInitializers: AfterColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true ColumnLimit: 80 @@ -60,7 +60,7 @@ CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true +Cpp11BracedListStyle: false DeriveLineEnding: true DerivePointerAlignment: false DisableFormat: false @@ -70,7 +70,7 @@ ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH -IncludeBlocks: Preserve +IncludeBlocks: Regroup IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3b0653a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = false +insert_final_newline = false \ No newline at end of file diff --git a/src/ipc.hpp b/src/ipc.hpp index ea0fced..2fc233f 100644 --- a/src/ipc.hpp +++ b/src/ipc.hpp @@ -24,7 +24,7 @@ class ipc { int socklen_; public: - ipc() : ipc(DEFAULT_SOCK) {}; + ipc() : ipc(DEFAULT_SOCK){}; /* * Constructor for oim::ipc diff --git a/src/main.cpp b/src/main.cpp index 7ad1eb3..ecfe8be 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,7 +11,8 @@ using std::string; const char *help[2] = { "This program is not supposed to be called from the command line!", "Call with 'install-protocol' to instal the xdg-compatible protocol file " - "in ~/.local/share/applications/"}; + "in ~/.local/share/applications/" +}; bool install_protocol() { const char *protocol_file = R"([Desktop Entry] @@ -27,8 +28,8 @@ MimeType=x-scheme-handler/mpv if (!homedir) return false; - std::ofstream protfile(string(homedir) + - "/.local/share/applications/open-in-mpv.desktop"); + std::ofstream protfile( + string(homedir) + "/.local/share/applications/open-in-mpv.desktop"); protfile << protocol_file; protfile.flush(); protfile.close(); diff --git a/src/options.hpp b/src/options.hpp index 47634d8..7c6e506 100644 --- a/src/options.hpp +++ b/src/options.hpp @@ -1,5 +1,6 @@ #pragma once +#include "players.hpp" #include "url.hpp" #include @@ -17,6 +18,7 @@ namespace oim { */ class options { private: + player *player_info_; string url_; string flags_; string player_; @@ -60,23 +62,23 @@ options::options() { fullscreen_ = false; pip_ = false; enqueue_ = false; + new_window_ = false; } string options::build_cmd() { std::ostringstream ret; - // TODO: some of these options work only in mpv and not other players - // This can be solved by adding a list of some sorts (json/toml/whatever) - // containing the flags to use for each functionality and each player - ret << player_ << " "; + if (player_info_ == nullptr) { + return ""; + } + + ret << player_info_->executable << " "; if (fullscreen_) - ret << "--fs "; + ret << player_info_->fullscreen << " "; if (pip_) - ret << "--ontop --no-border --autofit=384x216 --geometry=98\%:98\% "; + ret << player_info_->pip << " "; if (!flags_.empty()) ret << flags_ << " "; - // NOTE: this is not needed for mpv (it always opens a new window), maybe - // for other players? if (this->new_window_) ret << "--new-window"; ret << url_; return ret.str(); @@ -109,10 +111,14 @@ void options::parse(const char *url_s) { if (u.query().empty()) throw string("Empty query"); - url_ = oim::percent_decode(u.query_value("url")); - flags_ = oim::percent_decode(u.query_value("flags")); + url_ = percent_decode(u.query_value("url")); + flags_ = percent_decode(u.query_value("flags")); player_ = u.query_value("player", "mpv"); + player_info_ = get_player_info(player_); + if (player_info_ == nullptr) + throw string("Unsupported player: ") + player_; + fullscreen_ = u.query_value("fullscreen") == "1"; pip_ = u.query_value("pip") == "1"; enqueue_ = u.query_value("enqueue") == "1"; diff --git a/src/players.hpp b/src/players.hpp new file mode 100644 index 0000000..dc37bd5 --- /dev/null +++ b/src/players.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include + +using std::string; +using std::unordered_map; + +namespace oim { + +/* + * Struct `oim::player` contains useful informations for an mpv-based player, + * such as binary name and fullscreen/pip/enqueue/new_window flags overrides for + * use in `options::build_ipc()`. A way to override any generic flags is also + * provided through the map `flag_overrides`. + */ +struct player { + string name; + string executable; + + string fullscreen; + string pip; + string enqueue; + string new_window; + + bool needs_ipc; + + /* + * Override syntax: + * `"*"`: matches anything and will take precedence over any other + * override e.g. the pair `{"*", ""}` will void all flags + * `"flag"`: matches the flag `--flag` + * e.g. the pair `{"foo", "bar"}` will replace `--foo` with + * `--bar` + * `"%s"`: is replaced with the original flag without the leading `--` + * e.g. the pair `{"foo", "--%s-bar"}` will replace `--foo` with + * `--foo-bar` + * + * Note: command line options with parameters such as --foo=bar are + * considered a flags as a whole + */ + unordered_map flag_overrides; +}; + +unordered_map player_info = { + { "mpv", + { .name = "mpv", + .executable = "mpv", + .fullscreen = "--fs", + .pip = "--ontop --no-border --autofit=384x216 --geometry=98\%:98\%", + .enqueue = "", + .new_window = "", + .needs_ipc = true, + .flag_overrides = {} } }, + { "celluloid", + { .name = "Celluloid", + .executable = "celluloid", + .fullscreen = "", + .pip = "", + .enqueue = "--enqueue", + .new_window = "--new-window", + .needs_ipc = false, + .flag_overrides = { { "*", "--mpv-options=%s" } } } } +}; + +player *get_player_info(string name) { + if (name.empty()) + return &player_info["mpv"]; + + string lower_name(name); + std::transform(name.begin(), name.end(), lower_name.begin(), ::tolower); + + auto info = player_info.find(lower_name); + if (info == player_info.end()) { + return nullptr; + } + + return &(*info).second; +} + +} // namespace oim diff --git a/src/url.hpp b/src/url.hpp index ffc849e..bc89ca2 100644 --- a/src/url.hpp +++ b/src/url.hpp @@ -83,8 +83,8 @@ url::url(const string &url_s) { url_s.begin(), url_s.end(), prot_end.begin(), prot_end.end()); protocol_.reserve(std::distance(url_s.begin(), prot_i)); // The protocol is case insensitive - std::transform(url_s.begin(), prot_i, std::back_inserter(protocol_), - std::ptr_fun(tolower)); + std::transform( + url_s.begin(), prot_i, std::back_inserter(protocol_), ::tolower); if (prot_i == url_s.end()) return; std::advance(prot_i, prot_end.length()); @@ -93,8 +93,7 @@ url::url(const string &url_s) { string::const_iterator path_i = std::find(prot_i, url_s.end(), '/'); host_.reserve(std::distance(prot_i, path_i)); // The host is also case insensitive - std::transform(prot_i, path_i, std::back_inserter(host_), - std::ptr_fun(tolower)); + std::transform(prot_i, path_i, std::back_inserter(host_), ::tolower); // Everything else is query string::const_iterator query_i = std::find(path_i, url_s.end(), '?'); @@ -146,9 +145,9 @@ string percent_decode(const string encoded) { std::byte b1 = ::alnum_to_hex(*++i); std::byte b2 = ::alnum_to_hex(*++i); - char parsed = - static_cast((0x10u * std::to_integer(b1)) + - std::to_integer(b2)); + char parsed = static_cast( + (0x10u * std::to_integer(b1)) + + std::to_integer(b2)); ret += parsed; } else { ret += *i;