Added list of supported players with flag overrides and checks for support, reformatted code, added .editorconfig
This commit is contained in:
@@ -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
9
.editorconfig
Normal 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
|
@@ -24,7 +24,7 @@ class ipc {
|
||||
int socklen_;
|
||||
|
||||
public:
|
||||
ipc() : ipc(DEFAULT_SOCK) {};
|
||||
ipc() : ipc(DEFAULT_SOCK){};
|
||||
|
||||
/*
|
||||
* Constructor for oim::ipc
|
||||
|
@@ -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();
|
||||
|
@@ -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
82
src/players.hpp
Normal 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
|
13
src/url.hpp
13
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<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;
|
||||
|
Reference in New Issue
Block a user