Formatted code and added .clang-format, small refactors
This commit is contained in:
144
.clang-format
Normal file
144
.clang-format
Normal file
@@ -0,0 +1,144 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveBitFields: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentCaseLabels: false
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
...
|
||||
|
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
||||
INCLUDES = -Isrc/
|
||||
CXXFLAGS_debug = -Wall -DDEBUG -g -rdynamic
|
||||
CXXFLAGS_debug = -Wall -DDEBUG -g -rdynamic -std=c++2a $(INCLUDES)
|
||||
CXXFLAGS_release = -Wall -fvisibility=hidden -fvisibility-inlines-hidden -std=c++2a -march=x86-64 -mtune=generic -O3 -pipe -fno-plt $(INCLUDES)
|
||||
SRCS = src/curl.hpp \
|
||||
src/mpvopts.hpp \
|
||||
|
40
src/ipc.hpp
40
src/ipc.hpp
@@ -1,11 +1,12 @@
|
||||
#ifndef MPVIPC_HPP_
|
||||
#define MPVIPC_HPP_
|
||||
#ifndef OIM_IPC_HPP_
|
||||
#define OIM_IPC_HPP_
|
||||
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
const char *DEFAULT_SOCK = "/tmp/mpvsocket";
|
||||
@@ -14,16 +15,17 @@ namespace oim {
|
||||
|
||||
/*
|
||||
* The class oim::ipc provides easy communication and basic socket management
|
||||
* for any running mpv instance configured to receive commands over a JSON-IPC server/socket.
|
||||
* for any running mpv instance configured to receive commands over a JSON-IPC
|
||||
* server/socket.
|
||||
*/
|
||||
class ipc {
|
||||
private:
|
||||
sockaddr_un sockaddress;
|
||||
int sockfd;
|
||||
int socklen;
|
||||
private:
|
||||
sockaddr_un sockaddress_;
|
||||
int sockfd_;
|
||||
int socklen_;
|
||||
|
||||
public:
|
||||
ipc() : ipc(DEFAULT_SOCK) {};
|
||||
public:
|
||||
ipc() : ipc(DEFAULT_SOCK){};
|
||||
ipc(const char *sockpath);
|
||||
~ipc();
|
||||
|
||||
@@ -34,28 +36,26 @@ public:
|
||||
* Constructor for oim::ipc
|
||||
*/
|
||||
ipc::ipc(const char *sockpath) {
|
||||
this->sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
this->sockaddress.sun_family = AF_UNIX;
|
||||
std::strcpy(this->sockaddress.sun_path, sockpath);
|
||||
this->socklen = sizeof(this->sockaddress);
|
||||
sockfd_ = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
sockaddress_.sun_family = AF_UNIX;
|
||||
std::strcpy(sockaddress_.sun_path, sockpath);
|
||||
socklen_ = sizeof(sockaddress_);
|
||||
|
||||
connect(this->sockfd, (const sockaddr*)&this->sockaddress, this->socklen);
|
||||
connect(sockfd_, (const sockaddr *)&sockaddress_, socklen_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destructor for oim::ipc
|
||||
*/
|
||||
ipc::~ipc() {
|
||||
close(this->sockfd);
|
||||
}
|
||||
ipc::~ipc() { close(sockfd_); }
|
||||
|
||||
/*
|
||||
* Sends a raw command string to the internal socket at DEFAULT_SOCK
|
||||
*/
|
||||
bool ipc::send(string cmd) {
|
||||
return write(this->sockfd, cmd.c_str(), cmd.length()) != -1;
|
||||
return write(sockfd_, cmd.c_str(), cmd.length()) != -1;
|
||||
}
|
||||
|
||||
} // namespace name
|
||||
} // namespace oim
|
||||
|
||||
#endif
|
20
src/main.cpp
20
src/main.cpp
@@ -1,5 +1,5 @@
|
||||
#include "options.hpp"
|
||||
#include "ipc.hpp"
|
||||
#include "options.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
@@ -10,8 +10,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/"
|
||||
};
|
||||
"Call with 'install-protocol' to instal the xdg-compatible protocol file "
|
||||
"in ~/.local/share/applications/"};
|
||||
|
||||
bool install_protocol() {
|
||||
const char *protocol_file = R"([Desktop Entry]
|
||||
@@ -24,9 +24,11 @@ MimeType=x-scheme-handler/mpv
|
||||
)";
|
||||
|
||||
const char *homedir = std::getenv("HOME");
|
||||
if (!homedir) return false;
|
||||
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();
|
||||
@@ -40,9 +42,8 @@ int main(int argc, char const *argv[]) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
if (string(argv[1]) == "install-protocol") {
|
||||
return install_protocol();
|
||||
}
|
||||
if (string(argv[1]) == "install-protocol")
|
||||
return install_protocol() ? 0 : 1;
|
||||
|
||||
oim::options *mo = new oim::options();
|
||||
try {
|
||||
@@ -59,7 +60,8 @@ int main(int argc, char const *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cout << "Error writing to socket, opening new instance" << std::endl;
|
||||
std::cout << "Error writing to socket, opening new instance"
|
||||
<< std::endl;
|
||||
}
|
||||
std::system(mo->build_cmd().c_str());
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#ifndef MPVOPTS_HPP_
|
||||
#define MPVOPTS_HPP_
|
||||
#ifndef OIM_OPTS_HPP_
|
||||
#define OIM_OPTS_HPP_
|
||||
|
||||
#include "url.hpp"
|
||||
|
||||
@@ -17,16 +17,16 @@ namespace oim {
|
||||
* communicate with an mpv player window.
|
||||
*/
|
||||
class options {
|
||||
private:
|
||||
string url;
|
||||
string flags;
|
||||
string player;
|
||||
bool fullscreen;
|
||||
bool pip;
|
||||
bool enqueue;
|
||||
bool new_window;
|
||||
private:
|
||||
string url_;
|
||||
string flags_;
|
||||
string player_;
|
||||
bool fullscreen_;
|
||||
bool pip_;
|
||||
bool enqueue_;
|
||||
bool new_window_;
|
||||
|
||||
public:
|
||||
public:
|
||||
options();
|
||||
|
||||
string build_cmd();
|
||||
@@ -40,12 +40,12 @@ public:
|
||||
* Constructor for oim::options
|
||||
*/
|
||||
options::options() {
|
||||
this->url = "";
|
||||
this->flags = "";
|
||||
this->player = "mpv";
|
||||
this->fullscreen = false;
|
||||
this->pip = false;
|
||||
this->enqueue = false;
|
||||
url_ = "";
|
||||
flags_ = "";
|
||||
player_ = "mpv";
|
||||
fullscreen_ = false;
|
||||
pip_ = false;
|
||||
enqueue_ = false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -57,14 +57,16 @@ string options::build_cmd() {
|
||||
// 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 << this->player << " ";
|
||||
if (this->fullscreen) ret << "--fs ";
|
||||
if (this->pip) ret << "--ontop --no-border --autofit=384x216 --geometry=98\%:98\% ";
|
||||
if (!this->flags.empty())
|
||||
ret << this->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 << this->url;
|
||||
ret << player_ << " ";
|
||||
if (fullscreen_)
|
||||
ret << "--fs ";
|
||||
if (pip_)
|
||||
ret << "--ontop --no-border --autofit=384x216 --geometry=98\%:98\% ";
|
||||
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();
|
||||
}
|
||||
@@ -75,20 +77,20 @@ string options::build_cmd() {
|
||||
string options::build_ipc() {
|
||||
std::ostringstream ret;
|
||||
|
||||
if (!this->needs_ipc()) return "";
|
||||
if (!needs_ipc())
|
||||
return "";
|
||||
|
||||
// TODO: in the future this may need a more serious json serializer for
|
||||
// In the future this may need a more serious json serializer for
|
||||
// more complicated commands
|
||||
// Syntax: {"command": ["loadfile", "%s", "append-play"]}\n
|
||||
ret << R"({"command": ["loadfile", ")"
|
||||
<< this->url
|
||||
<< R"(", "append-play"]})" << std::endl;
|
||||
ret << R"({"command": ["loadfile", ")" << url_ << R"(", "append-play"]})"
|
||||
<< std::endl;
|
||||
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a URL and populate the current MpvOptions (uses libcurl for parsing)
|
||||
* Parse a URL and populate the current oim::options
|
||||
*/
|
||||
void options::parse(const char *url_s) {
|
||||
oim::url u(url_s);
|
||||
@@ -102,13 +104,14 @@ void options::parse(const char *url_s) {
|
||||
if (u.query().empty())
|
||||
throw string("Empty query");
|
||||
|
||||
this->url = oim::url_decode(u.query_value("url"));
|
||||
this->flags = oim::url_decode(u.query_value("flags"));
|
||||
this->player = u.query_value("player", "mpv");
|
||||
this->fullscreen = u.query_value("fullscreen") == "1";
|
||||
this->pip = u.query_value("pip") == "1";
|
||||
this->enqueue = u.query_value("enqueue") == "1";
|
||||
this->new_window = u.query_value("new_window") == "1";
|
||||
url_ = oim::url_decode(u.query_value("url"));
|
||||
flags_ = oim::url_decode(u.query_value("flags"));
|
||||
player_ = u.query_value("player", "mpv");
|
||||
|
||||
fullscreen_ = u.query_value("fullscreen") == "1";
|
||||
pip_ = u.query_value("pip") == "1";
|
||||
enqueue_ = u.query_value("enqueue") == "1";
|
||||
new_window_ = u.query_value("new_window") == "1";
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -117,7 +120,7 @@ void options::parse(const char *url_s) {
|
||||
*/
|
||||
bool options::needs_ipc() {
|
||||
// For now this is needed only when queuing videos
|
||||
return this->enqueue;
|
||||
return enqueue_;
|
||||
}
|
||||
|
||||
} // namespace oim
|
||||
|
39
src/url.hpp
39
src/url.hpp
@@ -1,5 +1,5 @@
|
||||
#ifndef MPVURL_HPP_
|
||||
#define MPVURL_HPP_
|
||||
#ifndef OIM_URL_HPP_
|
||||
#define OIM_URL_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
@@ -11,7 +11,8 @@ using std::string;
|
||||
|
||||
/*
|
||||
* Converts a single character to a percent-decodable byte representation
|
||||
* Taken from https://github.com/cpp-netlib/url/blob/main/include/skyr/v1/percent_encoding/percent_decode_range.hpp
|
||||
* Taken from
|
||||
* https://github.com/cpp-netlib/url/blob/main/include/skyr/v1/percent_encoding/percent_decode_range.hpp
|
||||
*/
|
||||
inline std::byte alnum_to_hex(char value) {
|
||||
if ((value >= '0') && (value <= '9')) {
|
||||
@@ -37,21 +38,20 @@ namespace oim {
|
||||
* query value searching by key is also provided by url::query_value(string).
|
||||
*/
|
||||
class url {
|
||||
private:
|
||||
private:
|
||||
string protocol_, host_, path_, query_;
|
||||
|
||||
public:
|
||||
public:
|
||||
/* Constructor with C-style string URL */
|
||||
url(const char *url_s) : url(string(url_s)) {};
|
||||
url(const char *url_s) : url(string(url_s)){};
|
||||
|
||||
/* Constructor with C++ std::string URL */
|
||||
url(const string &url_s) {
|
||||
const string prot_end("://");
|
||||
string::const_iterator prot_i = std::search(url_s.begin(), url_s.end(),
|
||||
prot_end.begin(), prot_end.end());
|
||||
string::const_iterator prot_i = std::search(
|
||||
url_s.begin(), url_s.end(), prot_end.begin(), prot_end.end());
|
||||
protocol_.reserve(std::distance(url_s.begin(), prot_i));
|
||||
std::transform(url_s.begin(), prot_i,
|
||||
std::back_inserter(protocol_),
|
||||
std::transform(url_s.begin(), prot_i, std::back_inserter(protocol_),
|
||||
std::ptr_fun<int, int>(tolower)); // protocol is icase
|
||||
if (prot_i == url_s.end())
|
||||
return;
|
||||
@@ -59,8 +59,7 @@ public:
|
||||
|
||||
string::const_iterator path_i = std::find(prot_i, url_s.end(), '/');
|
||||
host_.reserve(std::distance(prot_i, path_i));
|
||||
std::transform(prot_i, path_i,
|
||||
std::back_inserter(host_),
|
||||
std::transform(prot_i, path_i, std::back_inserter(host_),
|
||||
std::ptr_fun<int, int>(tolower)); // host is icase
|
||||
|
||||
string::const_iterator query_i = std::find(path_i, url_s.end(), '?');
|
||||
@@ -96,7 +95,8 @@ public:
|
||||
string query_value(string key) {
|
||||
// Find the beginning of the last occurrence of `key` in `query`
|
||||
auto pos = query_.rfind(key + "=");
|
||||
if (pos == string::npos) return "";
|
||||
if (pos == string::npos)
|
||||
return "";
|
||||
|
||||
// Offset calculation (beginning of the value string associated with
|
||||
// `key`):
|
||||
@@ -111,12 +111,13 @@ public:
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets a value from a query string given a key (overload with optional fallback if
|
||||
* value isn't found)
|
||||
* Gets a value from a query string given a key (overload with optional
|
||||
* fallback if value isn't found)
|
||||
*/
|
||||
string query_value(string key, string fallback) {
|
||||
string ret = query_value(key);
|
||||
if (ret.empty()) return fallback;
|
||||
if (ret.empty())
|
||||
return fallback;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
@@ -131,9 +132,9 @@ string url_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