diff --git a/core/include/JellyfinQt/apiclient.h b/core/include/JellyfinQt/apiclient.h index d5cbbe6..00175df 100644 --- a/core/include/JellyfinQt/apiclient.h +++ b/core/include/JellyfinQt/apiclient.h @@ -41,6 +41,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "dto/generalcommandtype.h" #include "credentialmanager.h" +#include "model/controllablesession.h" #include "model/deviceprofile.h" #include "eventbus.h" @@ -97,6 +98,7 @@ public: virtual ~ApiClient(); Q_PROPERTY(QString baseUrl READ baseUrl WRITE setBaseUrl NOTIFY baseUrlChanged) Q_PROPERTY(QString appName READ appName WRITE setAppName NOTIFY appNameChanged) + Q_PROPERTY(Jellyfin::Model::DeviceTypeClass::Value deviceType READ deviceType WRITE setDeviceType NOTIFY deviceTypeChanged) Q_PROPERTY(bool authenticated READ authenticated WRITE setAuthenticated NOTIFY authenticatedChanged) Q_PROPERTY(QString userId READ userId NOTIFY userIdChanged) Q_PROPERTY(QJsonObject deviceProfile READ deviceProfileJson NOTIFY deviceProfileChanged) @@ -116,6 +118,8 @@ public: bool authenticated() const; void setBaseUrl(const QString &url); void setAppName(const QString &appName); + void setDeviceType(Model::DeviceType deviceType); + QNetworkReply *get(const QString &path, const QUrlQuery ¶ms = QUrlQuery()); QNetworkReply *post(const QString &path, const QJsonDocument &data, const QUrlQuery ¶ms = QUrlQuery()); QNetworkReply *post(const QString &path, const QByteArray &data = QByteArray(), const QUrlQuery ¶ms = QUrlQuery()); @@ -132,6 +136,7 @@ public: const QString &appName() const; const QString &userId() const; const QString &deviceId() const; + Model::DeviceType deviceType() const; /** * @brief QML applications can set this type to indicate which commands they support. * @@ -200,6 +205,7 @@ signals: void userIdChanged(QString userId); void deviceProfileChanged(); + void deviceTypeChanged(); void supportedCommandsChanged(); void onlineChanged(); diff --git a/core/src/apiclient.cpp b/core/src/apiclient.cpp index b607a0a..b69f3b5 100644 --- a/core/src/apiclient.cpp +++ b/core/src/apiclient.cpp @@ -47,6 +47,7 @@ public: QString appName; QString deviceName; QString deviceId; + Model::DeviceType deviceType = Model::DeviceType::Unknown; QString userId; bool online = true; @@ -135,6 +136,17 @@ const QString &ApiClient::deviceId() const { return d->deviceId; } +Model::DeviceType ApiClient::deviceType() const { + Q_D(const ApiClient); + return d->deviceType; +} + +void ApiClient::setDeviceType(Model::DeviceType newDeviceType) { + Q_D(ApiClient); + d->deviceType =newDeviceType; + emit deviceTypeChanged(); +} + EventBus *ApiClient::eventbus() const { Q_D(const ApiClient); return d->eventbus; diff --git a/core/src/model/controllablesession.cpp b/core/src/model/controllablesession.cpp index 275fcd0..a1b3b70 100644 --- a/core/src/model/controllablesession.cpp +++ b/core/src/model/controllablesession.cpp @@ -32,11 +32,11 @@ QString LocalSession::name() const { } DeviceType LocalSession::deviceType() const { - return DeviceType::Unknown; + return m_apiClient.deviceType(); } QString LocalSession::userName() const { - return m_apiClient.userId(); + return QString(); //m_apiClient.userId(); } PlaybackManager *LocalSession::createPlaybackManager() const { @@ -64,7 +64,42 @@ QString ControllableJellyfinSession::name() const { } DeviceType ControllableJellyfinSession::deviceType() const { - return DeviceType::Unknown; + // This is surely not the best way + // I based this of https://github.com/jellyfin/jellyfin-web/blob/45793052fa7c854ec97133878c75937065ae4650/src/utils/image.ts + const QStringList tvDevices = { + "Samsung Smart TV", + "Xbox One", + "Sony PS4", + "Kodi", + "Kodi JellyCon", + "AndroidTV", + "Android TV", + "Infuse", + "Jellyfin Roku", + "DLNA" + }; + + const QStringList pcDevices = { + "Jellyfin Web", + }; + + const QStringList phoneDevices = { + "FinAmp", + "Jellyfin Mobile (iOS)", + "Jellyfin Mobile (iPadOS)", + "Jellyfin Android", + "Sailfin" + }; + + if (tvDevices.contains(m_data->client())) { + return DeviceType::Tv; + } else if (pcDevices.contains(m_data->client())) { + return DeviceType::Computer; + } else if (phoneDevices.contains(m_data->client())) { + return DeviceType::Phone; + } else { + return DeviceType::Unknown; + } } QString ControllableJellyfinSession::userName() const { @@ -101,21 +136,23 @@ void RemoteJellyfinSessionScanner::startScanning() { Q_D(RemoteJellyfinSessionScanner); if (d->loader != nullptr) return; + LocalSession *localSession = new LocalSession(*d->apiClient); + emit resetSessions(); - emit sessionFound(new LocalSession(*d->apiClient)); + emit sessionFound(localSession); Loader::GetSessionsParams params; params.setControllableByUserId(d->apiClient->userId()); d->loader = new GetSessionsLoader(d->apiClient); d->loader->setParameters(params); - connect(d->loader, &Loader::HTTP::GetSessionsLoader::ready, this, [this, d]() { + connect(d->loader, &Loader::HTTP::GetSessionsLoader::ready, this, [this, d, localSession]() { if (d->loader == nullptr) return; QList sessions = d->loader->result(); for(auto it = sessions.begin(); it != sessions.end(); it++) { // Skip this device - if (it->jellyfinId() == d->apiClient->deviceId()) continue; + if (it->deviceId() == localSession->id()) continue; emit sessionFound(new ControllableJellyfinSession(QSharedPointer::create(*it), *d->apiClient)); } diff --git a/core/src/model/playbackmanager.cpp b/core/src/model/playbackmanager.cpp index 50a7e4c..5bd254c 100644 --- a/core/src/model/playbackmanager.cpp +++ b/core/src/model/playbackmanager.cpp @@ -155,11 +155,13 @@ int PlaybackManager::queueIndex() const { void PlaybackManager::swap(PlaybackManager &other) { other.queue()->clearList(); - other.queue()->appendToList(this->queue()->queueAndList()); - other.playItemInList(this->queue()->queueAndList(), this->queue()->currentItemIndexInList() >= 0 - ? this->queue()->currentItemIndexInList() - : 0); - other.seek(position()); + if (other.queue()->listSize() > 0) { + other.queue()->appendToList(this->queue()->queueAndList()); + other.playItemInList(this->queue()->queueAndList(), this->queue()->currentItemIndexInList() >= 0 + ? this->queue()->currentItemIndexInList() + : 0); + other.seek(position()); + } } void PlaybackManager::playItemId(const QString &id) {} diff --git a/core/src/viewmodel/playbackmanager.cpp b/core/src/viewmodel/playbackmanager.cpp index d8e4303..eb14dce 100644 --- a/core/src/viewmodel/playbackmanager.cpp +++ b/core/src/viewmodel/playbackmanager.cpp @@ -182,8 +182,12 @@ void PlaybackManager::setControllingSession(QSharedPointerm_impl->stop(); + if (other != nullptr) { + d->m_impl->swap(*other); + } } } + d->m_displayQueue->setPlaylistModel(other->queue()); d->m_impl.reset(other); d->m_session.swap(session); diff --git a/sailfish/qml/harbour-sailfin.qml b/sailfish/qml/harbour-sailfin.qml index d02a233..e11fc55 100644 --- a/sailfish/qml/harbour-sailfin.qml +++ b/sailfish/qml/harbour-sailfin.qml @@ -51,6 +51,7 @@ ApplicationWindow { id: _apiClient objectName: "Test" appName: "Sailfin" + deviceType: DeviceType.Phone supportedCommands: [GeneralCommandType.Play, GeneralCommandType.DisplayMessage] } diff --git a/sailfish/qml/pages/ControllableDevicesPage.qml b/sailfish/qml/pages/ControllableDevicesPage.qml index a6ec9cf..082c3ef 100644 --- a/sailfish/qml/pages/ControllableDevicesPage.qml +++ b/sailfish/qml/pages/ControllableDevicesPage.qml @@ -34,7 +34,19 @@ Page { } height: parent.contentHeight - 2 * Theme.paddingMedium width: height - source: "image://theme/icon-m-computer" + source: { + if (model.deviceType == J.DeviceType.Phone) { + return "image://theme/icon-m-device" + } else if (model.deviceType == J.DeviceType.Tv) { + // For the lack of a better icon + return "image://theme/icon-m-device-landscape" + } else if (model.deviceType == J.DeviceType.Computer) { + return "image://theme/icon-m-computer" + } else { + //case J.DeviceType.Unknown: + return "image://theme/icon-m-question" + } + } highlighted: parent.down || isConnected } Column {