mirror of
https://github.com/HenkKalkwater/harbour-sailfin.git
synced 2025-09-04 01:42:44 +00:00
core: remote playback send commands and update state
This commit is contained in:
parent
77cb5d5957
commit
7a7ddc7717
18 changed files with 371 additions and 91 deletions
|
@ -26,6 +26,7 @@ namespace Jellyfin {
|
|||
namespace DTO {
|
||||
class UserItemDataDto;
|
||||
class PlaystateRequest;
|
||||
class SessionInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,6 +45,13 @@ signals:
|
|||
*/
|
||||
void itemUserDataUpdated(const QString &itemId, const DTO::UserItemDataDto &userData);
|
||||
|
||||
/**
|
||||
* @brief The information about a session has been updated
|
||||
* @param sessionId The id of the session
|
||||
* @param sessionInfo The associated information
|
||||
*/
|
||||
void sessionInfoUpdated(const QString &sessionId, const DTO::SessionInfo &sessionInfo);
|
||||
|
||||
/**
|
||||
* @brief The server has requested to display an message to the user
|
||||
* @param header The header of the message.
|
||||
|
|
|
@ -105,7 +105,7 @@ private:
|
|||
class ControllableJellyfinSession : public ControllableSession {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ControllableJellyfinSession(QSharedPointer<DTO::SessionInfo> info, QObject *parent = nullptr);
|
||||
ControllableJellyfinSession(QSharedPointer<DTO::SessionInfo> info, ApiClient &apiClient, QObject *parent = nullptr);
|
||||
QString id() const override;
|
||||
QString name() const override;
|
||||
QString appName() const override;
|
||||
|
@ -114,6 +114,7 @@ public:
|
|||
PlaybackManager *createPlaybackManager() const override;
|
||||
private:
|
||||
QSharedPointer<DTO::SessionInfo> m_data;
|
||||
ApiClient &m_apiClient;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -84,12 +84,11 @@ class PlaybackManager : public QObject {
|
|||
Q_PROPERTY(bool hasVideo READ hasVideo NOTIFY hasVideoChanged)
|
||||
Q_PROPERTY(Jellyfin::Model::PlayerStateClass::Value playbackState READ playbackState NOTIFY playbackStateChanged)
|
||||
Q_PROPERTY(Jellyfin::Model::MediaStatusClass::Value mediaStatus READ mediaStatus NOTIFY mediaStatusChanged)
|
||||
Q_PROPERTY(Jellyfin::Model::Playlist *queue READ queue NOTIFY queueChanged)
|
||||
Q_PROPERTY(int queueIndex READ queueIndex NOTIFY queueIndexChanged)
|
||||
public:
|
||||
explicit PlaybackManager(QObject *parent = nullptr);
|
||||
virtual ~PlaybackManager();
|
||||
virtual void swap(PlaybackManager& other) = 0;
|
||||
void swap(PlaybackManager& other);
|
||||
|
||||
ApiClient * apiClient() const;
|
||||
void setApiClient(ApiClient *apiClient);
|
||||
|
@ -129,6 +128,9 @@ public:
|
|||
* @param index Index of the item to play
|
||||
*/
|
||||
virtual void playItemInList(const QList<QSharedPointer<Model::Item>> &items, int index) = 0;
|
||||
static const qint64 MS_TICK_FACTOR = 10000;
|
||||
protected:
|
||||
void setItem(QSharedPointer<Item> item);
|
||||
|
||||
signals:
|
||||
void playbackStateChanged(Jellyfin::Model::PlayerStateClass::Value newPlaybackState);
|
||||
|
@ -190,8 +192,6 @@ class LocalPlaybackManager : public PlaybackManager {
|
|||
public:
|
||||
explicit LocalPlaybackManager(QObject *parent = nullptr);
|
||||
|
||||
void swap(PlaybackManager& other) override;
|
||||
|
||||
Player *player() const;
|
||||
QString sessionId() const;
|
||||
DTO::PlayMethod playMethod() const;
|
||||
|
|
|
@ -72,6 +72,11 @@ public:
|
|||
*/
|
||||
void next();
|
||||
|
||||
/**
|
||||
* @brief Returns all items in the queue
|
||||
*/
|
||||
QList<QSharedPointer<Item>> queueAndList() const;
|
||||
|
||||
int queueSize() { return m_queue.size(); };
|
||||
int listSize() const { return m_list.size(); };
|
||||
int totalSize() const { return m_queue.size() + m_list.size(); }
|
||||
|
|
|
@ -20,10 +20,17 @@
|
|||
#define JELLYFIN_MODEL_REMOTEJELLYFINPLAYBACK_H
|
||||
|
||||
#include <JellyfinQt/dto/generalcommandtype.h>
|
||||
#include <JellyfinQt/dto/playcommand.h>
|
||||
#include <JellyfinQt/dto/playstatecommand.h>
|
||||
#include <JellyfinQt/dto/sessioninfo.h>
|
||||
#include <JellyfinQt/model/playbackmanager.h>
|
||||
#include <JellyfinQt/support/loader.h>
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QTimer>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace Jellyfin {
|
||||
|
||||
|
@ -33,11 +40,10 @@ namespace Model {
|
|||
|
||||
class RemoteJellyfinPlayback : public PlaybackManager {
|
||||
public:
|
||||
RemoteJellyfinPlayback(ApiClient &apiClient, QObject *parent = nullptr);
|
||||
|
||||
RemoteJellyfinPlayback(ApiClient &apiClient, QString sessionId, QObject *parent = nullptr);
|
||||
virtual ~RemoteJellyfinPlayback();
|
||||
|
||||
// PlaybackManager
|
||||
void swap(PlaybackManager &other) override;
|
||||
PlayerState playbackState() const override;
|
||||
MediaStatus mediaStatus() const override;
|
||||
bool hasNext() const override;
|
||||
|
@ -61,9 +67,19 @@ public slots:
|
|||
void goTo(int index) override;
|
||||
void stop() override;
|
||||
void seek(qint64 pos) override;
|
||||
private slots:
|
||||
void onPositionTimerFired();
|
||||
void onSessionInfoUpdated(const QString &sessionId, const DTO::SessionInfo &sessionInfo);
|
||||
private:
|
||||
void sendPlaystateCommand(DTO::PlaystateCommand command, qint64 seekTicks = -1);
|
||||
void sendGeneralCommand(DTO::GeneralCommandType command, QJsonObject arguments = QJsonObject());
|
||||
void sendCommand(Support::LoaderBase *loader);
|
||||
void playItemInList(const QStringList &items, int index, qint64 resumeTicks = -1);
|
||||
ApiClient &m_apiClient;
|
||||
QString m_sessionId;
|
||||
std::optional<DTO::SessionInfo> m_lastSessionInfo;
|
||||
QTimer *m_positionTimer;
|
||||
qint64 m_position = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -155,6 +155,8 @@ QString toString(const T &source, convertType<T>) {
|
|||
return QJsonDocument(val.toArray()).toJson(format);
|
||||
case QJsonValue::Object:
|
||||
return QJsonDocument(val.toObject()).toJson(format);
|
||||
case QJsonValue::String:
|
||||
return val.toString();
|
||||
case QJsonValue::Null:
|
||||
default:
|
||||
return QString();
|
||||
|
|
|
@ -334,9 +334,6 @@ private:
|
|||
int statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
m_reply->deleteLater();
|
||||
m_reply = nullptr;
|
||||
/*m_parsedWatcher.setFuture(QtConcurrent::run([this, statusCode, array]() {
|
||||
return this->parseResponse(statusCode, array);
|
||||
}));*/
|
||||
m_parsedWatcher.setFuture(
|
||||
QtConcurrent::run<typename HttpLoader<R, P>::ResultType, // Result
|
||||
HttpLoader<R, P>, // class
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
QVariant data(const QModelIndex &parent, int role = Qt::DisplayRole) const override;
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
void setPlaylistModel(Model::Playlist *data);
|
||||
|
||||
|
||||
private slots:
|
||||
|
|
|
@ -60,9 +60,30 @@ public:
|
|||
*/
|
||||
explicit WebSocket(ApiClient *client);
|
||||
enum MessageType {
|
||||
/**
|
||||
* @brief Server to client: instruct client to send periodical KeepAlive messages
|
||||
*/
|
||||
ForceKeepAlive,
|
||||
/**
|
||||
* @brief Client to server: keep the connection alive
|
||||
*/
|
||||
KeepAlive,
|
||||
UserDataChanged
|
||||
/**
|
||||
* @brief Server to client: user data for an item has changed.
|
||||
*/
|
||||
UserDataChanged,
|
||||
/**
|
||||
* @brief Client to server: Subscribe to playback update sessions.
|
||||
*/
|
||||
SessionsStart,
|
||||
/**
|
||||
* @brief Client to server: unsubscribe from playback session updates
|
||||
*/
|
||||
SessionsStop,
|
||||
/**
|
||||
* @brief Server to client: session information has changed
|
||||
*/
|
||||
Sessions
|
||||
};
|
||||
Q_PROPERTY(QAbstractSocket::SocketState state READ state NOTIFY stateChanged)
|
||||
Q_ENUM(MessageType)
|
||||
|
@ -72,6 +93,8 @@ public:
|
|||
}
|
||||
public slots:
|
||||
void open();
|
||||
void subscribeToSessionInfo();
|
||||
void unsubscribeToSessionInfo();
|
||||
private slots:
|
||||
void textMessageReceived(const QString &message);
|
||||
void onConnected();
|
||||
|
@ -80,7 +103,7 @@ private slots:
|
|||
void sendKeepAlive();
|
||||
void onWebsocketStateChanged(QAbstractSocket::SocketState newState) { emit stateChanged(newState); }
|
||||
signals:
|
||||
void commandReceived(QString arts, QVariantMap args);
|
||||
void commandReceived(QString command, QVariantMap args);
|
||||
void stateChanged(QAbstractSocket::SocketState newState);
|
||||
|
||||
protected:
|
||||
|
@ -90,6 +113,7 @@ protected:
|
|||
QTimer m_keepAliveTimer;
|
||||
QTimer m_retryTimer;
|
||||
int m_reconnectAttempt = 0;
|
||||
int m_sessionInfoSubscribeCount = 0;
|
||||
|
||||
|
||||
void setupKeepAlive(int data);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue