Fully implemented flag overriding and player specification in players.hpp, fixed bugs and updated README
This commit is contained in:
5
Makefile
5
Makefile
@@ -27,4 +27,7 @@ firefox:
|
||||
clean:
|
||||
@rm -f open-in-mpv Firefox.zip Chrome.crx
|
||||
|
||||
.PHONY: all release debug install uninstall firefox clean
|
||||
fmt:
|
||||
clang-format -i src/*.{hpp,cpp}
|
||||
|
||||
.PHONY: all release debug install uninstall firefox clean fmt
|
23
README.md
23
README.md
@@ -1,8 +1,14 @@
|
||||
# open-in-mpv
|
||||
<h1 align="center">open-in-mpv</h1>
|
||||
|
||||
This is a simple web extension (for Chrome and Firefox) which helps open any video in the currently open tab in the [mpv player](https://mpv.io).
|
||||
|
||||
The extension itself shares a lot of code with the one from the awesome [iina](https://github.com/iina/iina), while the (bare) backend is written in C++20 (this is a rewrite from Rust).
|
||||
|
||||
- [Installation](#installation)
|
||||
- [The `mpv://` protocol](#the-mpv-protocol)
|
||||
- [Playlist and `enqueue` functionality](#playlist-and-enqueue-functionality)
|
||||
- [Player support](#player-support)
|
||||
|
||||
## Installation
|
||||
> Compiled binaries and packed extensions can be found in the [releases page](https://github.com/Baldomo/open-in-mpv/releases).
|
||||
|
||||
@@ -15,7 +21,13 @@ sudo make install
|
||||
### The `mpv://` protocol
|
||||
`open-in-mpv install-protocol` will create a custom `xdg-open` desktop file with a scheme handler for the `mpv://` protocol. This lets `xdg-open` call `open-in-mpv` with an encoded URI, so that it can be parsed and the information can be relayed to `mpv` - this logic follows how `iina` parses and opens custom URIs with the `iina://` protocol on Mac. `install-protocol.sh` has the same functionality.
|
||||
|
||||
The table below is a simple documentation of the URL query keys and values used to let the `open-in-mpv` executable what to do:
|
||||
Please note that this specification is enforced quite strictly, as the program will error out when:
|
||||
|
||||
- The protocol is not `mpv://`
|
||||
- The method/path is not `/open`
|
||||
- The query is empty
|
||||
|
||||
The table below is a simple documentation of the URL query keys and values used to let the `open-in-mpv` executable what to do.
|
||||
|
||||
| Key | Example value | Description |
|
||||
|---------------|----------------------------------------|---------------|
|
||||
@@ -24,7 +36,7 @@ The table below is a simple documentation of the URL query keys and values used
|
||||
| `pip` | `1` | Simulates a picture-in-picture mode (only works with mpv for now) |
|
||||
| `enqueue` | `1` | Adds a video to the queue (see below) |
|
||||
| `new_window` | `1` | Forcibly starts a video in a new window even if one is already open |
|
||||
| `player` | `celluloid` | Starts any arbitrary video player (only mpv-based ones are recommended, such as [Celluloid](https://celluloid-player.github.io/)) |
|
||||
| `player` | `celluloid` | Starts any supported video player (see [Player support](#player-support)) |
|
||||
| `flags` | `--vo%3Dgpu` | Custom command options and flags to be passed to the video player, URL-encoded |
|
||||
|
||||
### Playlist and `enqueue` functionality
|
||||
@@ -32,4 +44,7 @@ For `enqueue` to work properly with any mpv-based player (provided it supports m
|
||||
|
||||
```conf
|
||||
input-ipc-server=/tmp/mpvsocket
|
||||
```
|
||||
```
|
||||
|
||||
### Player support
|
||||
Supported players are defined in `src/players.hpp`, where the struct `player` defines supported functionality and command line flag overrides. To request support for a player you're welcome to open a new issue or a pull request.
|
@@ -61,7 +61,7 @@ int main(int argc, char const *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cout << "Error writing to socket, opening new instance"
|
||||
std::cerr << "Error writing to socket, opening new instance"
|
||||
<< std::endl;
|
||||
}
|
||||
std::system(mo->build_cmd().c_str());
|
||||
|
@@ -3,12 +3,35 @@
|
||||
#include "players.hpp"
|
||||
#include "url.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace {
|
||||
// Replace all occurrences of `from` with `to` in `str`
|
||||
string replace_all(string str, const string &from, const string &to) {
|
||||
size_t start_pos = 0;
|
||||
while ((start_pos = str.find(from, start_pos)) != string::npos) {
|
||||
str.replace(start_pos, from.length(), to);
|
||||
// Handles case where 'to' is a substring of 'from'
|
||||
start_pos += to.length();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// Remove all characters equals to `c` at the beginning of the string
|
||||
string lstrip(string str, char c) {
|
||||
while (str.at(0) == c)
|
||||
str.replace(0, 1, "");
|
||||
return str;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace oim {
|
||||
|
||||
/*
|
||||
@@ -27,6 +50,11 @@ class options {
|
||||
bool enqueue_;
|
||||
bool new_window_;
|
||||
|
||||
/*
|
||||
* Parses flag overrides and returns the final flags
|
||||
*/
|
||||
string override_flags();
|
||||
|
||||
public:
|
||||
/*
|
||||
* Constructor for oim::options
|
||||
@@ -73,12 +101,16 @@ string options::build_cmd() {
|
||||
}
|
||||
|
||||
ret << player_info_->executable << " ";
|
||||
if (fullscreen_)
|
||||
if (fullscreen_ && !player_info_->fullscreen.empty())
|
||||
ret << player_info_->fullscreen << " ";
|
||||
if (pip_)
|
||||
if (pip_ && !player_info_->pip.empty())
|
||||
ret << player_info_->pip << " ";
|
||||
if (!flags_.empty())
|
||||
ret << flags_ << " ";
|
||||
if (!flags_.empty()) {
|
||||
if (!player_info_->flag_overrides.empty())
|
||||
ret << override_flags() << " ";
|
||||
else
|
||||
ret << flags_ << " ";
|
||||
}
|
||||
ret << url_;
|
||||
|
||||
return ret.str();
|
||||
@@ -99,6 +131,41 @@ string options::build_ipc() {
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
string options::override_flags() {
|
||||
// Return immediatly in case there are no overrides
|
||||
if (player_info_->flag_overrides.empty())
|
||||
return flags_;
|
||||
|
||||
bool star = false;
|
||||
std::ostringstream ret;
|
||||
|
||||
// Check whether there's a global override
|
||||
auto star_pair = player_info_->flag_overrides.find("*");
|
||||
if (star_pair != player_info_->flag_overrides.end())
|
||||
star = true;
|
||||
|
||||
// Turn flags_ into a stream to tokenize somewhat idiomatically
|
||||
auto flagstream = std::istringstream{ flags_ };
|
||||
string tmp;
|
||||
|
||||
while (flagstream >> tmp) {
|
||||
if (star) {
|
||||
// Remove all dashes at the beginning of the flag
|
||||
string stripped = ::lstrip(tmp, '-');
|
||||
ret << ::replace_all((*star_pair).second, "%s", stripped);
|
||||
} else {
|
||||
// Search for the flag currently being processed
|
||||
auto fo = player_info_->flag_overrides.find(tmp);
|
||||
if (fo == player_info_->flag_overrides.end())
|
||||
continue;
|
||||
|
||||
ret << ::replace_all((*fo).second, "%s", tmp);
|
||||
}
|
||||
}
|
||||
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
void options::parse(const char *url_s) {
|
||||
oim::url u(url_s);
|
||||
|
||||
@@ -119,15 +186,12 @@ void options::parse(const char *url_s) {
|
||||
if (player_info_ == nullptr)
|
||||
throw string("Unsupported player: ") + player_;
|
||||
|
||||
fullscreen_ = u.query_value("fullscreen") == "1";
|
||||
fullscreen_ = u.query_value("full_screen") == "1";
|
||||
pip_ = u.query_value("pip") == "1";
|
||||
enqueue_ = u.query_value("enqueue") == "1";
|
||||
new_window_ = u.query_value("new_window") == "1";
|
||||
}
|
||||
|
||||
bool options::needs_ipc() {
|
||||
// For now this is needed only when queuing videos
|
||||
return enqueue_;
|
||||
}
|
||||
bool options::needs_ipc() { return player_info_->needs_ipc; }
|
||||
|
||||
} // namespace oim
|
@@ -27,17 +27,20 @@ struct player {
|
||||
bool needs_ipc;
|
||||
|
||||
/*
|
||||
* Overrides for any extra command line flag
|
||||
*
|
||||
* Override syntax:
|
||||
* `"*"`: matches anything and will take precedence over any other
|
||||
* override e.g. the pair `{"*", ""}` will void all flags
|
||||
* 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`
|
||||
* 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`
|
||||
* e.g. the pair `{"--foo", "--%s-bar"}` will replace `--foo` with
|
||||
* `--foo-bar`
|
||||
*
|
||||
* Note: command line options with parameters such as --foo=bar are
|
||||
* Note: command line options with parameters such as `--foo=bar` are
|
||||
* considered a flags as a whole
|
||||
*/
|
||||
unordered_map<string, string> flag_overrides;
|
||||
@@ -61,7 +64,7 @@ unordered_map<string, player> player_info = {
|
||||
.enqueue = "--enqueue",
|
||||
.new_window = "--new-window",
|
||||
.needs_ipc = false,
|
||||
.flag_overrides = { { "*", "--mpv-options=%s" } } } }
|
||||
.flag_overrides = { { "*", "--mpv-options=%s" } } } },
|
||||
};
|
||||
|
||||
player *get_player_info(string name) {
|
||||
|
Reference in New Issue
Block a user