Change control parameters to lower case

This commit is contained in:
badaix 2021-12-17 18:43:10 +01:00
parent 96b55c9b24
commit 8d8061a946
7 changed files with 93 additions and 96 deletions

View file

@ -40,7 +40,6 @@ import time
import json import json
import musicbrainzngs import musicbrainzngs
import fcntl import fcntl
import threading
__version__ = "@version@" __version__ = "@version@"
__git_version__ = "@gitversion@" __git_version__ = "@gitversion@"
@ -378,31 +377,27 @@ class MPDWrapper(object):
params = request['params'].get('params', {}) params = request['params'].get('params', {})
logger.debug( logger.debug(
f'Control command: {command}, params: {params}') f'Control command: {command}, params: {params}')
if command == 'Next': if command == 'next':
self.next() self.next()
elif command == 'Previous': elif command == 'previous':
self.previous() self.previous()
elif command == 'Play': elif command == 'play':
self.play() self.play()
elif command == 'Pause': elif command == 'pause':
self.pause(1) self.pause(1)
elif command == 'PlayPause': elif command == 'playPause':
if self.status()['state'] == 'play': if self.status()['state'] == 'play':
self.pause(1) self.pause(1)
else: else:
self.play() self.play()
elif command == 'Stop': elif command == 'stop':
self.stop() self.stop()
elif command == 'SetPosition': elif command == 'setPosition':
position = float(params['Position']) position = float(params['position'])
logger.info(f'SetPosition {position}') logger.info(f'setPosition {position}')
if 'TrackId' in params: self.seekcur(position)
trackid = params['TrackId'].rsplit('/', 1)[1] elif command == 'seek':
self.seekid(int(trackid), position) offset = float(params['offset'])
else:
self.seekcur(position)
elif command == 'Seek':
offset = float(params['Offset'])
strOffset = str(offset) strOffset = str(offset)
if offset >= 0: if offset >= 0:
strOffset = "+" + strOffset strOffset = "+" + strOffset

View file

@ -888,38 +888,38 @@ class MPRISInterface(dbus.service.Object):
# Player methods # Player methods
@ dbus.service.method(__player_interface, in_signature='', out_signature='') @ dbus.service.method(__player_interface, in_signature='', out_signature='')
def Next(self): def Next(self):
snapcast_wrapper.control("Next") snapcast_wrapper.control("next")
return return
@ dbus.service.method(__player_interface, in_signature='', out_signature='') @ dbus.service.method(__player_interface, in_signature='', out_signature='')
def Previous(self): def Previous(self):
snapcast_wrapper.control("Previous") snapcast_wrapper.control("previous")
return return
@ dbus.service.method(__player_interface, in_signature='', out_signature='') @ dbus.service.method(__player_interface, in_signature='', out_signature='')
def Pause(self): def Pause(self):
snapcast_wrapper.control("Pause") snapcast_wrapper.control("pause")
return return
@ dbus.service.method(__player_interface, in_signature='', out_signature='') @ dbus.service.method(__player_interface, in_signature='', out_signature='')
def PlayPause(self): def PlayPause(self):
snapcast_wrapper.control("PlayPause") snapcast_wrapper.control("playPause")
return return
@ dbus.service.method(__player_interface, in_signature='', out_signature='') @ dbus.service.method(__player_interface, in_signature='', out_signature='')
def Stop(self): def Stop(self):
snapcast_wrapper.control("Stop") snapcast_wrapper.control("stop")
return return
@ dbus.service.method(__player_interface, in_signature='', out_signature='') @ dbus.service.method(__player_interface, in_signature='', out_signature='')
def Play(self): def Play(self):
snapcast_wrapper.control("Play") snapcast_wrapper.control("play")
return return
@ dbus.service.method(__player_interface, in_signature='x', out_signature='') @ dbus.service.method(__player_interface, in_signature='x', out_signature='')
def Seek(self, offset): def Seek(self, offset):
logger.debug(f'Seek {offset}') logger.debug(f'Seek {offset}')
snapcast_wrapper.control("Seek", {"Offset": float(offset) / 1000000}) snapcast_wrapper.control("seek", {"offset": float(offset) / 1000000})
# status = mpd_wrapper.status() # status = mpd_wrapper.status()
# current, end = status['time'].split(':') # current, end = status['time'].split(':')
# current = int(current) # current = int(current)
@ -935,9 +935,9 @@ class MPRISInterface(dbus.service.Object):
@ dbus.service.method(__player_interface, in_signature='ox', out_signature='') @ dbus.service.method(__player_interface, in_signature='ox', out_signature='')
def SetPosition(self, trackid, position): def SetPosition(self, trackid, position):
logger.debug(f'SetPosition TrackId: {trackid}, Position: {position}') logger.debug(f'setPosition trackId: {trackid}, position: {position}')
snapcast_wrapper.control( snapcast_wrapper.control(
"SetPosition", {"TrackId": trackid, "Position": float(position) / 1000000}) "setPosition", {"position": float(position) / 1000000})
self.Seeked(position) self.Seeked(position)
# song = mpd_wrapper.last_currentsong() # song = mpd_wrapper.last_currentsong()

View file

@ -484,8 +484,8 @@ See [Plugin.Stream.Player.Control](stream_plugin.md#pluginstreamplayercontrol).
{"id": 1, "jsonrpc": "2.0", "error": {"code": -32602, "message": "Command '<command>' not supported"}} {"id": 1, "jsonrpc": "2.0", "error": {"code": -32602, "message": "Command '<command>' not supported"}}
{"id": 1, "jsonrpc": "2.0", "error": {"code": -32602, "message": "Parameter 'commmand' is missing"}} {"id": 1, "jsonrpc": "2.0", "error": {"code": -32602, "message": "Parameter 'commmand' is missing"}}
{"id": 1, "jsonrpc": "2.0", "error": {"code": -32602, "message": "SetPosition requires parameters 'Position'"}} {"id": 1, "jsonrpc": "2.0", "error": {"code": -32602, "message": "setPosition requires parameter 'position'"}}
{"id": 1, "jsonrpc": "2.0", "error": {"code": -32602, "message": "Seek requires parameter 'Offset'"}} {"id": 1, "jsonrpc": "2.0", "error": {"code": -32602, "message": "seek requires parameter 'offset'"}}
``` ```
### Stream.SetProperty ### Stream.SetProperty

View file

@ -31,30 +31,29 @@ Used to control the player. The property `canControl` must be `true`.
#### Supported `command`s #### Supported `command`s
* `Play`: Start playback (if `canPlay` is `true`) * `play`: Start playback (if `canPlay` is `true`)
* `params`: none * `params`: none
* `Pause`: Stop playback (if `canPause` is `true`) * `pause`: Stop playback (if `canPause` is `true`)
* `params`: none * `params`: none
* `PlayPause`: Toggle play/pause (if `canPause` is `true`) * `playPause`: Toggle play/pause (if `canPause` is `true`)
* `params`: none * `params`: none
* `Stop`: Stop playback (if `canControl` is `true`) * `stop`: Stop playback (if `canControl` is `true`)
* `params`: none * `params`: none
* `Next`: Skip to next track (if `canGoNext` is `true`) * `next`: Skip to next track (if `canGoNext` is `true`)
* `params`: none * `params`: none
* `Previous`: Skip to previous track (if `canGoPrevious` is `true`) * `previous`: Skip to previous track (if `canGoPrevious` is `true`)
* `params`: none * `params`: none
* `Seek`: Seek forward or backward in the current track (if `canSeek` is `true`) * `seek`: Seek forward or backward in the current track (if `canSeek` is `true`)
* `params`: * `params`:
* `Offset`: [float] seek offset in seconds * `offset`: [float] seek offset in seconds
* `SetPosition`: Set the current track position in seconds (if `canSeek` is `true`) * `setPosition`: Set the current track position in seconds (if `canSeek` is `true`)
* `params`: * `params`:
* `Position`: [float] the new track position * `position`: [float] the new track position
* `TrackId`: [string] the optional currently playing track's identifier
#### Example #### Example
```json ```json
{"id": 1, "jsonrpc": "2.0", "method": "Plugin.Stream.Player.Control", "params": {"command": "SetPosition", "params": { "Position": 17.827, "TrackId": "/org/mpris/MediaPlayer2/Track/2"}}} {"id": 1, "jsonrpc": "2.0", "method": "Plugin.Stream.Player.Control", "params": {"command": "setPosition", "params": { "position": 17.827 }}}
``` ```
#### Expected response #### Expected response
@ -119,11 +118,11 @@ Any [json-rpc 2.0 conformant error](https://www.jsonrpc.org/specification#error_
* `volume`: [int] Voume in percent, valid range [0..100] * `volume`: [int] Voume in percent, valid range [0..100]
* `rate`: [float] The current playback rate, valid range (0..) * `rate`: [float] The current playback rate, valid range (0..)
* `position`: [float] Current playback position in seconds * `position`: [float] Current playback position in seconds
* `canGoNext`: [bool] Whether the client can call the `Next` method on this interface and expect the current track to change * `canGoNext`: [bool] Whether the client can call the `next` method on this interface and expect the current track to change
* `canGoPrevious`: [bool] Whether the client can call the `Previous` method on this interface and expect the current track to change * `canGoPrevious`: [bool] Whether the client can call the `previous` method on this interface and expect the current track to change
* `canPlay`: [bool] Whether playback can be started using `Play` or `PlayPause` * `canPlay`: [bool] Whether playback can be started using `play` or `playPause`
* `canPause`: [bool] Whether playback can be paused using `Pause` or `PlayPause` * `canPause`: [bool] Whether playback can be paused using `pause` or `playPause`
* `canSeek`: [bool] Whether the client can control the playback position using `Seek` and `SetPosition` * `canSeek`: [bool] Whether the client can control the playback position using `seek` and `setPosition`
* `canControl`: [bool] Whether the media player may be controlled over this interface * `canControl`: [bool] Whether the media player may be controlled over this interface
* `metadata`: [json] message with the following (optional) fields: * `metadata`: [json] message with the following (optional) fields:
* `trackId`: [string] A unique identity for this track within the context of an MPRIS object (eg: tracklist). * `trackId`: [string] A unique identity for this track within the context of an MPRIS object (eg: tracklist).

View file

@ -458,7 +458,7 @@ void Server::processRequest(const jsonrpcpp::request_ptr request, const OnRespon
if (ec) if (ec)
log_level = AixLog::Severity::error; log_level = AixLog::Severity::error;
LOG(log_level, LOG_TAG) << "Response to '" << command << "': " << ec << ", message: " << ec.detailed_message() << ", msg: " << ec.message() LOG(log_level, LOG_TAG) << "Response to '" << command << "': " << ec << ", message: " << ec.detailed_message() << ", msg: " << ec.message()
<< ", category: " << ec.category().name() << "\n"; << ", category: " << ec.category().name() << "\n";
std::shared_ptr<jsonrpcpp::Response> response; std::shared_ptr<jsonrpcpp::Response> response;
if (ec) if (ec)
response = make_shared<jsonrpcpp::Response>(request->id(), jsonrpcpp::Error(ec.detailed_message(), ec.value())); response = make_shared<jsonrpcpp::Response>(request->id(), jsonrpcpp::Error(ec.detailed_message(), ec.value()));
@ -468,43 +468,43 @@ void Server::processRequest(const jsonrpcpp::request_ptr request, const OnRespon
on_response(response, nullptr); on_response(response, nullptr);
}; };
if (command == "SetPosition") if (command == "setPosition")
{ {
if (!request->params().has("params") || !request->params().get("params").contains("Position")) if (!request->params().has("params") || !request->params().get("params").contains("position"))
throw jsonrpcpp::InvalidParamsException("SetPosition requires parameters 'Position'"); throw jsonrpcpp::InvalidParamsException("setPosition requires parameter 'position'");
auto seconds = request->params().get("params")["Position"].get<float>(); auto seconds = request->params().get("params")["position"].get<float>();
stream->setPosition(std::chrono::milliseconds(static_cast<int>(seconds * 1000)), stream->setPosition(std::chrono::milliseconds(static_cast<int>(seconds * 1000)),
[handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); }); [handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); });
} }
else if (command == "Seek") else if (command == "seek")
{ {
if (!request->params().has("params") || !request->params().get("params").contains("Offset")) if (!request->params().has("params") || !request->params().get("params").contains("offset"))
throw jsonrpcpp::InvalidParamsException("Seek requires parameter 'Offset'"); throw jsonrpcpp::InvalidParamsException("Seek requires parameter 'offset'");
auto offset = request->params().get("params")["Offset"].get<float>(); auto offset = request->params().get("params")["offset"].get<float>();
stream->seek(std::chrono::milliseconds(static_cast<int>(offset * 1000)), stream->seek(std::chrono::milliseconds(static_cast<int>(offset * 1000)),
[handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); }); [handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); });
} }
else if (command == "Next") else if (command == "next")
{ {
stream->next([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); }); stream->next([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); });
} }
else if (command == "Previous") else if (command == "previous")
{ {
stream->previous([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); }); stream->previous([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); });
} }
else if (command == "Pause") else if (command == "pause")
{ {
stream->pause([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); }); stream->pause([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); });
} }
else if (command == "PlayPause") else if (command == "playPause")
{ {
stream->playPause([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); }); stream->playPause([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); });
} }
else if (command == "Stop") else if (command == "stop")
{ {
stream->stop([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); }); stream->stop([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); });
} }
else if (command == "Play") else if (command == "play")
{ {
stream->play([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); }); stream->play([handle_response](const snapcast::ErrorCode& ec) { handle_response(ec); });
} }

View file

@ -359,9 +359,9 @@ void PcmStream::setPosition(std::chrono::milliseconds position, ResultHandler ha
if (!properties_.can_seek) if (!properties_.can_seek)
return handler({ControlErrc::can_seek_is_false}); return handler({ControlErrc::can_seek_is_false});
json params; json params;
params["command"] = "SetPosition"; params["command"] = "setPosition";
json j; json j;
j["Position"] = position.count() / 1000.f; j["position"] = position.count() / 1000.f;
params["params"] = j; params["params"] = j;
sendRequest("Plugin.Stream.Player.Control", params, std::move(handler)); sendRequest("Plugin.Stream.Player.Control", params, std::move(handler));
} }
@ -373,9 +373,9 @@ void PcmStream::seek(std::chrono::milliseconds offset, ResultHandler handler)
if (!properties_.can_seek) if (!properties_.can_seek)
return handler({ControlErrc::can_seek_is_false}); return handler({ControlErrc::can_seek_is_false});
json params; json params;
params["command"] = "Seek"; params["command"] = "seek";
json j; json j;
j["Offset"] = offset.count() / 1000.f; j["offset"] = offset.count() / 1000.f;
params["params"] = j; params["params"] = j;
sendRequest("Plugin.Stream.Player.Control", params, std::move(handler)); sendRequest("Plugin.Stream.Player.Control", params, std::move(handler));
} }
@ -386,7 +386,7 @@ void PcmStream::next(ResultHandler handler)
LOG(DEBUG, LOG_TAG) << "next\n"; LOG(DEBUG, LOG_TAG) << "next\n";
if (!properties_.can_go_next) if (!properties_.can_go_next)
return handler({ControlErrc::can_go_next_is_false}); return handler({ControlErrc::can_go_next_is_false});
sendRequest("Plugin.Stream.Player.Control", {"command", "Next"}, std::move(handler)); sendRequest("Plugin.Stream.Player.Control", {"command", "next"}, std::move(handler));
} }
@ -395,7 +395,7 @@ void PcmStream::previous(ResultHandler handler)
LOG(DEBUG, LOG_TAG) << "previous\n"; LOG(DEBUG, LOG_TAG) << "previous\n";
if (!properties_.can_go_previous) if (!properties_.can_go_previous)
return handler({ControlErrc::can_go_previous_is_false}); return handler({ControlErrc::can_go_previous_is_false});
sendRequest("Plugin.Stream.Player.Control", {"command", "Previous"}, std::move(handler)); sendRequest("Plugin.Stream.Player.Control", {"command", "previous"}, std::move(handler));
} }
@ -404,9 +404,37 @@ void PcmStream::pause(ResultHandler handler)
LOG(DEBUG, LOG_TAG) << "pause\n"; LOG(DEBUG, LOG_TAG) << "pause\n";
if (!properties_.can_pause) if (!properties_.can_pause)
return handler({ControlErrc::can_pause_is_false}); return handler({ControlErrc::can_pause_is_false});
sendRequest("Plugin.Stream.Player.Control", {"command", "Pause"}, std::move(handler)); sendRequest("Plugin.Stream.Player.Control", {"command", "pause"}, std::move(handler));
} }
void PcmStream::playPause(ResultHandler handler)
{
LOG(DEBUG, LOG_TAG) << "playPause\n";
if (!properties_.can_pause)
return handler({ControlErrc::can_play_is_false});
sendRequest("Plugin.Stream.Player.Control", {"command", "playPause"}, std::move(handler));
}
void PcmStream::stop(ResultHandler handler)
{
LOG(DEBUG, LOG_TAG) << "stop\n";
if (!properties_.can_control)
return handler({ControlErrc::can_control_is_false});
sendRequest("Plugin.Stream.Player.Control", {"command", "stop"}, std::move(handler));
}
void PcmStream::play(ResultHandler handler)
{
LOG(DEBUG, LOG_TAG) << "play\n";
if (!properties_.can_play)
return handler({ControlErrc::can_play_is_false});
sendRequest("Plugin.Stream.Player.Control", {"command", "play"}, std::move(handler));
}
void PcmStream::sendRequest(const std::string& method, const jsonrpcpp::Parameter& params, ResultHandler handler) void PcmStream::sendRequest(const std::string& method, const jsonrpcpp::Parameter& params, ResultHandler handler)
{ {
if (!stream_ctrl_) if (!stream_ctrl_)
@ -422,33 +450,6 @@ void PcmStream::sendRequest(const std::string& method, const jsonrpcpp::Paramete
} }
void PcmStream::playPause(ResultHandler handler)
{
LOG(DEBUG, LOG_TAG) << "playPause\n";
if (!properties_.can_pause)
return handler({ControlErrc::can_play_is_false});
sendRequest("Plugin.Stream.Player.Control", {"command", "PlayPause"}, std::move(handler));
}
void PcmStream::stop(ResultHandler handler)
{
LOG(DEBUG, LOG_TAG) << "stop\n";
if (!properties_.can_control)
return handler({ControlErrc::can_control_is_false});
sendRequest("Plugin.Stream.Player.Control", {"command", "Stop"}, std::move(handler));
}
void PcmStream::play(ResultHandler handler)
{
LOG(DEBUG, LOG_TAG) << "play\n";
if (!properties_.can_play)
return handler({ControlErrc::can_play_is_false});
sendRequest("Plugin.Stream.Player.Control", {"command", "Play"}, std::move(handler));
}
void PcmStream::setProperties(const Properties& properties) void PcmStream::setProperties(const Properties& properties)
{ {
std::lock_guard<std::recursive_mutex> lock(mutex_); std::lock_guard<std::recursive_mutex> lock(mutex_);

View file

@ -19,10 +19,12 @@
#ifndef PROPERTIES_HPP #ifndef PROPERTIES_HPP
#define PROPERTIES_HPP #define PROPERTIES_HPP
// local headers
#include "common/aixlog.hpp" #include "common/aixlog.hpp"
#include "common/json.hpp" #include "common/json.hpp"
#include "metadata.hpp" #include "metadata.hpp"
// standard headers
#include <optional> #include <optional>
#include <set> #include <set>
#include <string> #include <string>
@ -170,9 +172,9 @@ public:
std::optional<float> minimum_rate; std::optional<float> minimum_rate;
/// The maximum value which the Rate property can take. Clients should not attempt to set the Rate property above this value /// The maximum value which the Rate property can take. Clients should not attempt to set the Rate property above this value
std::optional<float> maximum_rate; std::optional<float> maximum_rate;
/// Whether the client can call the Next method on this interface and expect the current track to change /// Whether the client can call the next method on this interface and expect the current track to change
bool can_go_next = false; bool can_go_next = false;
/// Whether the client can call the Previous method on this interface and expect the current track to change /// Whether the client can call the previous method on this interface and expect the current track to change
bool can_go_previous = false; bool can_go_previous = false;
/// Whether playback can be started using "play" or "playPause" /// Whether playback can be started using "play" or "playPause"
bool can_play = false; bool can_play = false;