Skip to content

Commit

Permalink
Merge pull request #160 from open-dynaMIX/loadfile
Browse files Browse the repository at this point in the history
feat(api): add `loadfile` endpoint
  • Loading branch information
open-dynaMIX committed Dec 6, 2020
2 parents c84e20e + 0bfda78 commit aeb68f6
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 39 deletions.
74 changes: 38 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,42 +229,44 @@ In order to have the notification work properly you need to at least once trigge
## Endpoints
You can also directly talk to the endpoints:

| URI | Method | Parameter | Description |
| ---------------------------------- | ------ | ---------------------------------- | ----------------------------------------------------------------------- |
| /api/status | GET | | Returns JSON data about playing media --> see below |
| /api/play | POST | | Play media |
| /api/pause | POST | | Pause media |
| /api/toggle_pause | POST | | Toggle play/pause |
| /api/fullscreen | POST | | Toggle fullscreen |
| /api/quit | POST | | Quit the program |
| /api/add/:name/:value | POST | `string` and `int` or `float` | Add `:value` (default of `1`) to the `:name` property |
| /api/cycle/:name/:value | POST | `string` and `up` or `down` | Cycle `:name` by `:value` (default of `up`) |
| /api/multiply/:name/:value | POST | `string` and `int` or `float` | Multiply `:name` by `:value` |
| /api/set/:name/:value | POST | `string` and anything | Set `:name` to `:value` |
| /api/toggle/:name | POST | `string` | Toggle the boolean property |
| /api/seek/:seconds | POST | `int` or `float` (can be negative) | Seek |
| /api/set_position/:seconds | POST | | Go to position :seconds |
| /api/playlist_prev | POST | | Go to previous media in playlist |
| /api/playlist_next | POST | | Go to next media in playlist |
| /api/playlist_jump/:index | POST | `int` | Jump to playlist item at position `:index` |
| /api/playlist_move/:source/:target | POST | `int` and `int` | Move playlist item from position `:source` to position `:target` |
| /api/playlist_move_up/:index | POST | `int` | Move playlist item at position `:index` one position up |
| /api/playlist_remove/:index | POST | `int` | Remove playlist item at position `:index` |
| /api/playlist_shuffle | POST | | Shuffle the playlist |
| /api/loop_file/:mode | POST | `string` or `int` | Loop the current file. `:mode` accepts the same loop modes as mpv |
| /api/loop_playlist/:mode | POST | `string` or `int` | Loop the whole playlist `:mode` accepts the same loop modes as mpv |
| /api/add_chapter/:amount | POST | `int` (can be negative) | Jump `:amount` chapters in current media |
| /api/add_volume/:percent | POST | `int` or `float` (can be negative) | Add :percent% volume |
| /api/set_volume/:percent | POST | `int` or `float` | Set volume to :percent% |
| /api/add_sub_delay/:ms | POST | `int` or `float` (can be negative) | Add :seconds seconds subtitles delay |
| /api/set_sub_delay/:ms | POST | `int` or `float` (can be negative) | Set subtitles delay to :ms milliseconds |
| /api/add_audio_delay/:seconds | POST | `int` or `float` (can be negative) | Add :seconds seconds audio delay |
| /api/set_audio_delay/:seconds | POST | `int` or `float` (can be negative) | Set audio delay to :seconds milliseconds |
| /api/cycle_sub | POST | | Cycle trough available subtitles |
| /api/cycle_audio | POST | | Cycle trough available audio tracks |
| /api/cycle_audio_device | POST | | Cycle trough audio devices. [More information.](#audio-devices-string) |
| /api/speed_set/:speed | POST | `int` or `float` | Set playback speed to `:speed` (defaults to `1` for quick reset) |
| /api/speed_adjust/:amount | POST | `int` or `float` | Multiply playback speed by `:amount` (where `1.0` is no change) |
| URI | Method | Parameter | Description |
| ---------------------------------- | ------ | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| /api/status | GET | | Returns JSON data about playing media --> see below |
| /api/play | POST | | Play media |
| /api/pause | POST | | Pause media |
| /api/toggle_pause | POST | | Toggle play/pause |
| /api/fullscreen | POST | | Toggle fullscreen |
| /api/quit | POST | | Quit the program |
| /api/add/:name/:value | POST | `string` and `int` or `float` | Add `:value` (default of `1`) to the `:name` property |
| /api/cycle/:name/:value | POST | `string` and `up` or `down` | Cycle `:name` by `:value` (default of `up`) |
| /api/multiply/:name/:value | POST | `string` and `int` or `float` | Multiply `:name` by `:value` |
| /api/set/:name/:value | POST | `string` and anything | Set `:name` to `:value` |
| /api/toggle/:name | POST | `string` | Toggle the boolean property |
| /api/seek/:seconds | POST | `int` or `float` (can be negative) | Seek |
| /api/set_position/:seconds | POST | | Go to position :seconds |
| /api/playlist_prev | POST | | Go to previous media in playlist |
| /api/playlist_next | POST | | Go to next media in playlist |
| /api/playlist_jump/:index | POST | `int` | Jump to playlist item at position `:index` |
| /api/playlist_move/:source/:target | POST | `int` and `int` | Move playlist item from position `:source` to position `:target` |
| /api/playlist_move_up/:index | POST | `int` | Move playlist item at position `:index` one position up |
| /api/playlist_remove/:index | POST | `int` | Remove playlist item at position `:index` |
| /api/playlist_shuffle | POST | | Shuffle the playlist |
| /api/loop_file/:mode | POST | `string` or `int` | Loop the current file. `:mode` accepts the same loop modes as mpv |
| /api/loop_playlist/:mode | POST | `string` or `int` | Loop the whole playlist `:mode` accepts the same loop modes as mpv |
| /api/add_chapter/:amount | POST | `int` (can be negative) | Jump `:amount` chapters in current media |
| /api/add_volume/:percent | POST | `int` or `float` (can be negative) | Add :percent% volume |
| /api/set_volume/:percent | POST | `int` or `float` | Set volume to :percent% |
| /api/add_sub_delay/:ms | POST | `int` or `float` (can be negative) | Add :seconds seconds subtitles delay |
| /api/set_sub_delay/:ms | POST | `int` or `float` (can be negative) | Set subtitles delay to :ms milliseconds |
| /api/add_audio_delay/:seconds | POST | `int` or `float` (can be negative) | Add :seconds seconds audio delay |
| /api/set_audio_delay/:seconds | POST | `int` or `float` (can be negative) | Set audio delay to :seconds milliseconds |
| /api/cycle_sub | POST | | Cycle trough available subtitles |
| /api/cycle_audio | POST | | Cycle trough available audio tracks |
| /api/cycle_audio_device | POST | | Cycle trough audio devices. [More information.](#audio-devices-string) |
| /api/speed_set/:speed | POST | `int` or `float` | Set playback speed to `:speed` (defaults to `1` for quick reset) |
| /api/speed_adjust/:amount | POST | `int` or `float` | Multiply playback speed by `:amount` (where `1.0` is no change) |
| /api/loadfile /:url/:mode | POST | :url `string` <br />:mode `string` options: `replace` (default), `append`, `append-play` | Load file to playlist. Together with youtube-dl, this also works for URLs |


All POST endpoints return a JSON message. If successful: `{"message": "success"}`, otherwise, the message will contain
information about the error.
Expand Down
48 changes: 45 additions & 3 deletions tests/tests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-

import urllib

import pytest
import requests
from requests.auth import HTTPBasicAuth
Expand Down Expand Up @@ -36,10 +38,11 @@ def get_script_opts(options):
return {"options": [f"--script-opts={','.join(option_strings)}"]}


def send(command, arg=None, expect=200, status=None):
def send(command, arg=None, arg2=None, expect=200, status=None):
api = f"api/{command}"
if arg is not None:
api += f"/{arg}"
for a in [arg, arg2]:
if a is not None:
api += f"/{a}"
resp = requests.post(get_uri(api))
assert resp.status_code == expect
if status is not None:
Expand Down Expand Up @@ -266,6 +269,45 @@ def shuffle():
assert get_order(status) == order[:2]


def test_loadfile(mpv_instance):
def send_loadfile(url, mode=None, expect=200):
return send(
"loadfile",
urllib.parse.quote(url, safe=""),
mode,
status="playlist",
expect=expect,
)

send("pause")
status = get_status()
assert status["playlist"][0]["current"] is True
assert len(status["playlist"]) == 3

playlist = send_loadfile("./environment/test_media/01 - dummy.mp3", "append-play")

assert len(playlist) == 4
assert playlist[-1]["filename"] == "./environment/test_media/01 - dummy.mp3"

playlist = send_loadfile("./environment/test_media/01 - dummy.mp3", "append")

assert len(playlist) == 5
assert playlist[-2]["filename"] == "./environment/test_media/01 - dummy.mp3"
assert playlist[-1]["filename"] == "./environment/test_media/01 - dummy.mp3"

playlist = send_loadfile("./environment/test_media/01 - dummy.mp3", "replace")

assert len(playlist) == 1
assert playlist[0]["filename"] == "./environment/test_media/01 - dummy.mp3"

playlist = send_loadfile("./environment/test_media/01 - dummy.mp3")

assert len(playlist) == 1
assert playlist[0]["filename"] == "./environment/test_media/01 - dummy.mp3"

send_loadfile("./environment/test_media/01 - dummy.mp3", "not a valid mode", 400)


@pytest.mark.parametrize(
"mpv_instance,status_code",
[
Expand Down
22 changes: 22 additions & 0 deletions webui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,25 @@ local commands = {

quit = function()
return pcall(mp.commandv, 'osd-msg', 'quit')
end,

loadfile = function(uri, mode)
if uri == nil or type(uri) ~= "string" then
return true, false, "No url provided!"
end
if mode ~= nil and
mode ~= "" and
mode ~= "replace" and
mode ~= "append" and
mode ~= "append-play"
then
print('Invalid mode: "' .. mode .. '"')
return true, false, "Invalid mode: '" .. mode .. "'"
end
if mode == nil or mode == "" then
mode = "replace"
end
return pcall(mp.commandv, "loadfile", uri, mode)
end
}

Expand Down Expand Up @@ -547,6 +566,9 @@ local function handle_post(path)
local param1 = components() or ""
local param2 = components() or ""

param1 = url.unescape(param1)
param2 = url.unescape(param2)

local f = commands[command]
if f ~= nil then
local _, success, ret = f(param1, param2)
Expand Down

0 comments on commit aeb68f6

Please sign in to comment.