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

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_;
public:
ipc() : ipc(DEFAULT_SOCK) {};
ipc() : ipc(DEFAULT_SOCK){};
/*
* Constructor for oim::ipc

View File

@@ -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();

View File

@@ -1,5 +1,6 @@
#pragma once
#include "players.hpp"
#include "url.hpp"
#include <cstring>
@@ -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";

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());
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<int, int>(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<int, int>(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<char>((0x10u * std::to_integer<unsigned int>(b1)) +
std::to_integer<unsigned int>(b2));
char parsed = static_cast<char>(
(0x10u * std::to_integer<unsigned int>(b1)) +
std::to_integer<unsigned int>(b2));
ret += parsed;
} else {
ret += *i;