1
0
Fork 0
mirror of https://github.com/HenkKalkwater/harbour-sailfin.git synced 2024-05-04 05:22:42 +00:00
harbour-sailfin/core/src/jellyfinplaybackmanager.cpp

164 lines
5.3 KiB
C++

/*
Sailfin: a Jellyfin client written using Qt
Copyright (C) 2020 Chris Josten
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "JellyfinQt/jellyfinplaybackmanager.h"
namespace Jellyfin {
PlaybackManager::PlaybackManager(QObject *parent)
: QObject(parent) {
m_updateTimer.setInterval(10000); // 10 seconds
m_updateTimer.setSingleShot(false);
connect(&m_updateTimer, &QTimer::timeout, this, &PlaybackManager::updatePlaybackInfo);
}
void PlaybackManager::fetchStreamUrl() {
QUrlQuery params;
params.addQueryItem("UserId", m_apiClient->userId());
params.addQueryItem("StartTimeTicks", QString::number(m_position));
params.addQueryItem("IsPlayback", "true");
params.addQueryItem("AutoOpenLiveStream", this->m_autoOpen ? "true" : "false");
params.addQueryItem("MediaSourceId", this->m_itemId);
params.addQueryItem("SubtitleStreamIndex", QString::number(m_subtitleIndex));
params.addQueryItem("AudioStreamIndex", QString::number(m_audioIndex));
QJsonObject root;
root["DeviceProfile"] = m_apiClient->playbackDeviceProfile();
QNetworkReply *rep = m_apiClient->post("/Items/" + this->m_itemId + "/PlaybackInfo", QJsonDocument(root), params);
connect(rep, &QNetworkReply::finished, this, [this, rep]() {
QJsonObject root = QJsonDocument::fromJson(rep->readAll()).object();
this->m_playSessionId = root["PlaySessionId"].toString();
qDebug() << "Session id: " << this->m_playSessionId;
if (this->m_autoOpen) {
QJsonArray mediaSources = root["MediaSources"].toArray();
//FIXME: relies on the fact that the returned transcode url always has a query!
this->m_streamUrl = this->m_apiClient->baseUrl()
+ mediaSources[0].toObject()["TranscodingUrl"].toString();
this->m_playMethod = Transcode;
emit this->streamUrlChanged(this->m_streamUrl);
qDebug() << "Found stream url: " << this->m_streamUrl;
}
rep->deleteLater();
});
}
void PlaybackManager::setItemId(const QString &newItemId) {
if (m_apiClient == nullptr) {
qWarning() << "apiClient is not set on this MediaSource instance! Aborting.";
return;
}
this->m_itemId = newItemId;
// Deinitialize the streamUrl
setStreamUrl("");
if (!newItemId.isEmpty()) {
fetchStreamUrl();
}
}
void PlaybackManager::setStreamUrl(const QString &streamUrl) {
this->m_streamUrl = streamUrl;
emit streamUrlChanged(streamUrl);
}
void PlaybackManager::setPosition(qint64 position) {
if (position == 0 && m_position != 0) {
// Save the old position when stop gets called. The QMediaPlayer will try to set
// position to 0 when stopped, but we don't want to report that to Jellyfin. We
// want the old position.
m_stopPosition = m_position;
}
m_position = position;
emit positionChanged(position);
}
void PlaybackManager::setState(QMediaPlayer::State newState) {
if (m_state == newState) return;
if (m_state == QMediaPlayer::StoppedState) {
// We're transitioning from stopped to either playing or paused.
// Set up the recurring timer
m_updateTimer.start();
postPlaybackInfo(Started);
} else if (newState == QMediaPlayer::StoppedState) {
// We've stopped playing the media. Post a stop signal.
m_updateTimer.stop();
postPlaybackInfo(Stopped);
} else {
postPlaybackInfo(Progress);
}
m_state = newState;
emit this->stateChanged(newState);
}
void PlaybackManager::updatePlaybackInfo() {
postPlaybackInfo(Progress);
}
void PlaybackManager::postPlaybackInfo(PlaybackInfoType type) {
QJsonObject root;
root["ItemId"] = m_itemId;
root["SessionId"] = m_playSessionId;
switch(type) {
case Started: // FALLTHROUGH
case Progress:
root["IsPaused"] = m_state != QMediaPlayer::PlayingState;
root["IsMuted"] = false;
root["AudioStreamIndex"] = m_audioIndex;
root["SubtitleStreamIndex"] = m_subtitleIndex;
root["PlayMethod"] = QVariant::fromValue(m_playMethod).toString();
root["PositionTicks"] = m_position;
break;
case Stopped:
root["PositionTicks"] = m_stopPosition;
break;
}
QString path;
switch (type) {
case Started:
path = "/Sessions/Playing";
break;
case Progress:
path = "/Sessions/Playing/Progress";
break;
case Stopped:
path = "/Sessions/Playing/Stopped";
break;
}
QNetworkReply *rep = m_apiClient->post(path, QJsonDocument(root));
connect(rep, &QNetworkReply::finished, this, [rep](){
rep->deleteLater();
});
m_apiClient->setDefaultErrorHandler(rep);
}
}