diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..9055edd --- /dev/null +++ b/.clang-format @@ -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 +... + diff --git a/Makefile b/Makefile index 8880e05..3546650 100644 --- a/Makefile +++ b/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 \ diff --git a/src/ipc.hpp b/src/ipc.hpp index 4ec14e0..57c9085 100644 --- a/src/ipc.hpp +++ b/src/ipc.hpp @@ -1,11 +1,12 @@ -#ifndef MPVIPC_HPP_ -#define MPVIPC_HPP_ +#ifndef OIM_IPC_HPP_ +#define OIM_IPC_HPP_ #include -#include #include #include #include +#include + using std::string; const char *DEFAULT_SOCK = "/tmp/mpvsocket"; @@ -13,17 +14,18 @@ const char *DEFAULT_SOCK = "/tmp/mpvsocket"; 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. + * 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. */ 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 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 146079a..7ad1eb3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,5 @@ -#include "options.hpp" #include "ipc.hpp" +#include "options.hpp" #include #include @@ -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 { @@ -51,7 +52,7 @@ int main(int argc, char const *argv[]) { std::cout << err << std::endl; return 1; } - + if (mo->needs_ipc()) { oim::ipc *mipc = new oim::ipc(); bool success = mipc->send(mo->build_ipc()); @@ -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()); diff --git a/src/options.hpp b/src/options.hpp index 31e6eed..0759aca 100644 --- a/src/options.hpp +++ b/src/options.hpp @@ -1,5 +1,5 @@ -#ifndef MPVOPTS_HPP_ -#define MPVOPTS_HPP_ +#ifndef OIM_OPTS_HPP_ +#define OIM_OPTS_HPP_ #include "url.hpp" @@ -12,21 +12,21 @@ using std::string; namespace oim { /* - * The class oim::options defines a model for the data contained in the mpv:// - * URL and acts as a command generator (both CLI and IPC) to spawn and + * The class oim::options defines a model for the data contained in the mpv:// + * URL and acts as a command generator (both CLI and IPC) to spawn and * 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(); @@ -37,15 +37,15 @@ public: }; /* - * Constructor for oim::options + * 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,25 +77,25 @@ 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); - if (u.protocol() != "mpv") + if (u.protocol() != "mpv") throw string("Unsupported protocol supplied: ") + u.protocol(); if (u.path() != "/open") @@ -102,14 +104,15 @@ 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"; +} /* * Checks wether or not oim::options needs to communicate with mpv via IPC @@ -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 diff --git a/src/url.hpp b/src/url.hpp index 72708b7..cab8474 100644 --- a/src/url.hpp +++ b/src/url.hpp @@ -1,5 +1,5 @@ -#ifndef MPVURL_HPP_ -#define MPVURL_HPP_ +#ifndef OIM_URL_HPP_ +#define OIM_URL_HPP_ #include #include @@ -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(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(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( - (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;