Added list of supported players with flag overrides and checks for support, reformatted code, added .editorconfig

This commit is contained in:
Baldomo
2021-01-20 20:36:44 +01:00
parent 132a258a82
commit 93f7bc29f3
7 changed files with 127 additions and 30 deletions

View File

@@ -2,12 +2,12 @@
Language: Cpp Language: Cpp
# BasedOnStyle: LLVM # BasedOnStyle: LLVM
AccessModifierOffset: -2 AccessModifierOffset: -2
AlignAfterOpenBracket: Align AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveMacros: false AlignConsecutiveMacros: true
AlignConsecutiveAssignments: false AlignConsecutiveAssignments: false
AlignConsecutiveBitFields: false AlignConsecutiveBitFields: false
AlignConsecutiveDeclarations: false AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right AlignEscapedNewlines: Left
AlignOperands: Align AlignOperands: Align
AlignTrailingComments: true AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true AllowAllArgumentsOnNextLine: true
@@ -29,7 +29,7 @@ BinPackParameters: true
BraceWrapping: BraceWrapping:
AfterCaseLabel: false AfterCaseLabel: false
AfterClass: false AfterClass: false
AfterControlStatement: Never AfterControlStatement: false
AfterEnum: false AfterEnum: false
AfterFunction: false AfterFunction: false
AfterNamespace: false AfterNamespace: false
@@ -48,10 +48,10 @@ BraceWrapping:
BreakBeforeBinaryOperators: None BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon BreakInheritanceList: AfterColon
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon BreakConstructorInitializers: AfterColon
BreakAfterJavaFieldAnnotations: false BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true BreakStringLiterals: true
ColumnLimit: 80 ColumnLimit: 80
@@ -60,7 +60,7 @@ CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4 ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4
Cpp11BracedListStyle: true Cpp11BracedListStyle: false
DeriveLineEnding: true DeriveLineEnding: true
DerivePointerAlignment: false DerivePointerAlignment: false
DisableFormat: false DisableFormat: false
@@ -70,7 +70,7 @@ ForEachMacros:
- foreach - foreach
- Q_FOREACH - Q_FOREACH
- BOOST_FOREACH - BOOST_FOREACH
IncludeBlocks: Preserve IncludeBlocks: Regroup
IncludeCategories: IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2 Priority: 2

9
.editorconfig Normal file
View File

@@ -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

View File

@@ -24,7 +24,7 @@ class ipc {
int socklen_; int socklen_;
public: public:
ipc() : ipc(DEFAULT_SOCK) {}; ipc() : ipc(DEFAULT_SOCK){};
/* /*
* Constructor for oim::ipc * Constructor for oim::ipc

View File

@@ -11,7 +11,8 @@ using std::string;
const char *help[2] = { const char *help[2] = {
"This program is not supposed to be called from the command line!", "This program is not supposed to be called from the command line!",
"Call with 'install-protocol' to instal the xdg-compatible protocol file " "Call with 'install-protocol' to instal the xdg-compatible protocol file "
"in ~/.local/share/applications/"}; "in ~/.local/share/applications/"
};
bool install_protocol() { bool install_protocol() {
const char *protocol_file = R"([Desktop Entry] const char *protocol_file = R"([Desktop Entry]
@@ -27,8 +28,8 @@ MimeType=x-scheme-handler/mpv
if (!homedir) if (!homedir)
return false; return false;
std::ofstream protfile(string(homedir) + std::ofstream protfile(
"/.local/share/applications/open-in-mpv.desktop"); string(homedir) + "/.local/share/applications/open-in-mpv.desktop");
protfile << protocol_file; protfile << protocol_file;
protfile.flush(); protfile.flush();
protfile.close(); protfile.close();

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "players.hpp"
#include "url.hpp" #include "url.hpp"
#include <cstring> #include <cstring>
@@ -17,6 +18,7 @@ namespace oim {
*/ */
class options { class options {
private: private:
player *player_info_;
string url_; string url_;
string flags_; string flags_;
string player_; string player_;
@@ -60,23 +62,23 @@ options::options() {
fullscreen_ = false; fullscreen_ = false;
pip_ = false; pip_ = false;
enqueue_ = false; enqueue_ = false;
new_window_ = false;
} }
string options::build_cmd() { string options::build_cmd() {
std::ostringstream ret; std::ostringstream ret;
// TODO: some of these options work only in mpv and not other players if (player_info_ == nullptr) {
// This can be solved by adding a list of some sorts (json/toml/whatever) return "";
// containing the flags to use for each functionality and each player }
ret << player_ << " ";
ret << player_info_->executable << " ";
if (fullscreen_) if (fullscreen_)
ret << "--fs "; ret << player_info_->fullscreen << " ";
if (pip_) if (pip_)
ret << "--ontop --no-border --autofit=384x216 --geometry=98\%:98\% "; ret << player_info_->pip << " ";
if (!flags_.empty()) if (!flags_.empty())
ret << flags_ << " "; 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_; ret << url_;
return ret.str(); return ret.str();
@@ -109,10 +111,14 @@ void options::parse(const char *url_s) {
if (u.query().empty()) if (u.query().empty())
throw string("Empty query"); throw string("Empty query");
url_ = oim::percent_decode(u.query_value("url")); url_ = percent_decode(u.query_value("url"));
flags_ = oim::percent_decode(u.query_value("flags")); flags_ = percent_decode(u.query_value("flags"));
player_ = u.query_value("player", "mpv"); 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"; fullscreen_ = u.query_value("fullscreen") == "1";
pip_ = u.query_value("pip") == "1"; pip_ = u.query_value("pip") == "1";
enqueue_ = u.query_value("enqueue") == "1"; enqueue_ = u.query_value("enqueue") == "1";

82
src/players.hpp Normal file
View File

@@ -0,0 +1,82 @@
#pragma once
#include <algorithm>
#include <string>
#include <unordered_map>
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<string, string> flag_overrides;
};
unordered_map<string, player> 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

View File

@@ -83,8 +83,8 @@ url::url(const string &url_s) {
url_s.begin(), url_s.end(), prot_end.begin(), prot_end.end()); url_s.begin(), url_s.end(), prot_end.begin(), prot_end.end());
protocol_.reserve(std::distance(url_s.begin(), prot_i)); protocol_.reserve(std::distance(url_s.begin(), prot_i));
// The protocol is case insensitive // The protocol is case insensitive
std::transform(url_s.begin(), prot_i, std::back_inserter(protocol_), std::transform(
std::ptr_fun<int, int>(tolower)); url_s.begin(), prot_i, std::back_inserter(protocol_), ::tolower);
if (prot_i == url_s.end()) if (prot_i == url_s.end())
return; return;
std::advance(prot_i, prot_end.length()); 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(), '/'); string::const_iterator path_i = std::find(prot_i, url_s.end(), '/');
host_.reserve(std::distance(prot_i, path_i)); host_.reserve(std::distance(prot_i, path_i));
// The host is also case insensitive // The host is also case insensitive
std::transform(prot_i, path_i, std::back_inserter(host_), std::transform(prot_i, path_i, std::back_inserter(host_), ::tolower);
std::ptr_fun<int, int>(tolower));
// Everything else is query // Everything else is query
string::const_iterator query_i = std::find(path_i, url_s.end(), '?'); string::const_iterator query_i = std::find(path_i, url_s.end(), '?');
@@ -146,8 +145,8 @@ string percent_decode(const string encoded) {
std::byte b1 = ::alnum_to_hex(*++i); std::byte b1 = ::alnum_to_hex(*++i);
std::byte b2 = ::alnum_to_hex(*++i); std::byte b2 = ::alnum_to_hex(*++i);
char parsed = char parsed = static_cast<char>(
static_cast<char>((0x10u * std::to_integer<unsigned int>(b1)) + (0x10u * std::to_integer<unsigned int>(b1)) +
std::to_integer<unsigned int>(b2)); std::to_integer<unsigned int>(b2));
ret += parsed; ret += parsed;
} else { } else {