diff --git a/core/include/JellyfinQt/apimodel.h b/core/include/JellyfinQt/apimodel.h
index a0bff30..9b85df2 100644
--- a/core/include/JellyfinQt/apimodel.h
+++ b/core/include/JellyfinQt/apimodel.h
@@ -248,8 +248,8 @@ extern template int extractTotalRecordCount(const QList &resul
extern template void setRequestLimit(Loader::GetLatestMediaParams ¶ms, int limit);
extern template bool setRequestStartIndex(Loader::GetLatestMediaParams ¶ms, int offset);
-extern template void setRequestLimit(Loader::GetItemsByUserIdParams ¶ms, int limit);
-extern template bool setRequestStartIndex(Loader::GetItemsByUserIdParams ¶ms, int offset);
+extern template void setRequestLimit(Loader::GetItemsParams ¶ms, int limit);
+extern template bool setRequestStartIndex(Loader::GetItemsParams ¶ms, int offset);
extern template void setRequestLimit(Loader::GetResumeItemsParams ¶ms, int limit);
extern template bool setRequestStartIndex(Loader::GetResumeItemsParams ¶ms, int offset);
@@ -332,7 +332,6 @@ protected:
R result = m_loader->result();
QList records = extractRecords(result);
int totalRecordCount = extractTotalRecordCount(result);
- qDebug() << "Total record count: " << totalRecordCount << ", records in request: " << records.size();
// If totalRecordCount < 0, it is not supported for this endpoint
if (totalRecordCount < 0) {
totalRecordCount = records.size();
@@ -549,7 +548,6 @@ protected:
void loadingFinished() override {
Q_ASSERT(m_loader != nullptr);
std::pair, int> result = m_loader->result();
- qDebug() << "Results loaded: index: " << result.second << ", count: " << result.first.size();
if (result.second == -1) {
clear();
} else if (result.second == m_array.size()) {
diff --git a/core/include/JellyfinQt/eventbus.h b/core/include/JellyfinQt/eventbus.h
index 3b94ac3..755ac32 100644
--- a/core/include/JellyfinQt/eventbus.h
+++ b/core/include/JellyfinQt/eventbus.h
@@ -26,7 +26,7 @@ namespace Jellyfin {
namespace DTO {
class UserItemDataDto;
class PlaystateRequest;
- class SessionInfo;
+ class SessionInfoDto;
}
/**
@@ -43,14 +43,14 @@ signals:
* @param itemId The id of the item which was updated.
* @param userData The new userData
*/
- void itemUserDataUpdated(const QString &itemId, const DTO::UserItemDataDto &userData);
+ void itemUserDataUpdated(const QString &itemId, const Jellyfin::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);
+ void sessionInfoUpdated(const QString &sessionId, const Jellyfin::DTO::SessionInfoDto &sessionInfo);
/**
* @brief The server has requested to display an message to the user
diff --git a/core/include/JellyfinQt/model/controllablesession.h b/core/include/JellyfinQt/model/controllablesession.h
index a41c40a..5d3aa6a 100644
--- a/core/include/JellyfinQt/model/controllablesession.h
+++ b/core/include/JellyfinQt/model/controllablesession.h
@@ -5,7 +5,7 @@
#include
#include
-#include "JellyfinQt/dto/sessioninfo.h"
+#include "JellyfinQt/dto/sessioninfodto.h"
namespace Jellyfin {
@@ -105,7 +105,7 @@ private:
class ControllableJellyfinSession : public ControllableSession {
Q_OBJECT
public:
- ControllableJellyfinSession(QSharedPointer info, ApiClient &apiClient, QObject *parent = nullptr);
+ ControllableJellyfinSession(QSharedPointer info, ApiClient &apiClient, QObject *parent = nullptr);
QString id() const override;
QString name() const override;
QString appName() const override;
@@ -113,7 +113,7 @@ public:
QString userName() const override;
PlaybackManager *createPlaybackManager() const override;
private:
- QSharedPointer m_data;
+ QSharedPointer m_data;
ApiClient &m_apiClient;
};
diff --git a/core/include/JellyfinQt/model/remotejellyfinplayback.h b/core/include/JellyfinQt/model/remotejellyfinplayback.h
index 835856c..15068ce 100644
--- a/core/include/JellyfinQt/model/remotejellyfinplayback.h
+++ b/core/include/JellyfinQt/model/remotejellyfinplayback.h
@@ -22,7 +22,7 @@
#include
#include
#include
-#include
+#include
#include
#include
@@ -69,7 +69,7 @@ public slots:
void seek(qint64 pos) override;
private slots:
void onPositionTimerFired();
- void onSessionInfoUpdated(const QString &sessionId, const DTO::SessionInfo &sessionInfo);
+ void onSessionInfoUpdated(const QString &sessionId, const DTO::SessionInfoDto &sessionInfo);
private:
void sendPlaystateCommand(DTO::PlaystateCommand command, qint64 seekTicks = -1);
void sendGeneralCommand(DTO::GeneralCommandType command, QJsonObject arguments = QJsonObject());
@@ -88,7 +88,7 @@ private:
void updateQueue(QList itemIds);
ApiClient &m_apiClient;
QString m_sessionId;
- std::optional m_lastSessionInfo;
+ std::optional m_lastSessionInfo;
QTimer *m_positionTimer;
qint64 m_position = 0;
};
diff --git a/core/include/JellyfinQt/viewmodel/item.h b/core/include/JellyfinQt/viewmodel/item.h
index 2cff478..1ae23bc 100644
--- a/core/include/JellyfinQt/viewmodel/item.h
+++ b/core/include/JellyfinQt/viewmodel/item.h
@@ -116,7 +116,7 @@ public:
Q_PROPERTY(QString playlistItemId READ playlistItemId NOTIFY playlistItemIdChanged)
Q_PROPERTY(QDateTime dateCreated READ dateCreated NOTIFY dateCreatedChanged)
Q_PROPERTY(QDateTime dateLastMediaAdded READ dateLastMediaAdded NOTIFY dateLastMediaAddedChanged)
- Q_PROPERTY(QString extraType READ extraType NOTIFY extraTypeChanged)
+ Q_PROPERTY(Jellyfin::DTO::ExtraTypeClass::Value extraType READ extraType NOTIFY extraTypeChanged)
Q_PROPERTY(int airsBeforeSeasonNumber READ airsBeforeSeasonNumber NOTIFY airsBeforeSeasonNumberChanged)
Q_PROPERTY(int airsAfterSeasonNumber READ airsAfterSeasonNumber NOTIFY airsAfterSeasonNumberChanged)
Q_PROPERTY(int airsBeforeEpisodeNumber READ airsBeforeEpisodeNumber NOTIFY airsBeforeEpisodeNumberChanged)
@@ -143,7 +143,7 @@ public:
Q_PROPERTY(int indexNumber READ indexNumber NOTIFY indexNumberChanged)
Q_PROPERTY(int indexNumberEnd READ indexNumberEnd NOTIFY indexNumberEndChanged)
Q_PROPERTY(bool isFolder READ isFolder NOTIFY isFolderChanged)
- Q_PROPERTY(QString type READ type NOTIFY typeChanged)
+ Q_PROPERTY(Jellyfin::DTO::BaseItemKindClass::Value type READ type NOTIFY typeChanged)
Q_PROPERTY(QString parentBackdropItemId READ parentBackdropItemId NOTIFY parentBackdropItemIdChanged)
Q_PROPERTY(QStringList parentBackdropImageTags READ parentBackdropImageTags NOTIFY parentBackdropImageTagsChanged)
Q_PROPERTY(Jellyfin::ViewModel::UserData *userData READ userData NOTIFY userDataChanged)
@@ -163,7 +163,7 @@ public:
Q_PROPERTY(double primaryImageAspectRatio READ primaryImageAspectRatio NOTIFY primaryImageAspectRatioChanged)
Q_PROPERTY(QStringList artists READ artists NOTIFY artistsChanged)
Q_PROPERTY(QList artistItems READ artistItems NOTIFY artistItemsChanged);
- Q_PROPERTY(QString collectionType READ collectionType NOTIFY collectionTypeChanged)
+ Q_PROPERTY(Jellyfin::DTO::CollectionTypeClass::Value collectionType READ collectionType NOTIFY collectionTypeChanged)
// Why is this a QJsonObject? Well, because I couldn't be bothered to implement the deserialisations of
// a QHash at the moment.
Q_PROPERTY(QJsonObject imageTags READ imageTags NOTIFY imageTagsChanged)
@@ -178,7 +178,7 @@ public:
Q_PROPERTY(int albumCount READ albumCount NOTIFY albumCountChanged)
Q_PROPERTY(int artistCount READ artistCount NOTIFY artistCountChanged)
Q_PROPERTY(int musicVideoCount READ musicVideoCount NOTIFY musicVideoCountChanged)
- Q_PROPERTY(QString mediaType READ mediaType NOTIFY mediaTypeChanged)
+ Q_PROPERTY(Jellyfin::DTO::MediaTypeClass::Value mediaType READ mediaType NOTIFY mediaTypeChanged)
Q_PROPERTY(QDateTime endDate READ endDate NOTIFY endDateChanged)
Q_PROPERTY(QDateTime startDate READ startDate NOTIFY startDateChanged)
Q_PROPERTY(int width READ width NOTIFY widthChanged)
@@ -194,7 +194,7 @@ public:
QString playlistItemId() const { return m_data->playlistItemId(); }
QDateTime dateCreated() const { return m_data->dateCreated(); }
QDateTime dateLastMediaAdded() const { return m_data->dateLastMediaAdded(); }
- QString extraType() const { return m_data->extraType(); }
+ ExtraType extraType() const { return m_data->extraType(); }
int airsBeforeSeasonNumber() const { return m_data->airsBeforeSeasonNumber().value_or(0); }
int airsAfterSeasonNumber() const { return m_data->airsAfterSeasonNumber().value_or(999); }
int airsBeforeEpisodeNumber() const { return m_data->airsBeforeEpisodeNumber().value_or(0); }
@@ -204,7 +204,7 @@ public:
int indexNumber() const { return m_data->indexNumber().value_or(-1); }
int indexNumberEnd() const { return m_data->indexNumberEnd().value_or(-1); }
bool isFolder() const { return m_data->isFolder().value_or(false); }
- QString type() const { return m_data->type(); }
+ BaseItemKind type() const { return m_data->type(); }
QString parentBackdropItemId() const { return m_data->parentBackdropItemId(); }
QStringList parentBackdropImageTags() const { return m_data->parentBackdropImageTags(); }
UserData *userData() const { return m_userData; }
@@ -223,11 +223,11 @@ public:
double primaryImageAspectRatio() const { return m_data->primaryImageAspectRatio().value_or(1.0); }
QStringList artists() const { return m_data->artists(); }
QList artistItems() const{ return this->m_artistItems; }
- QString collectionType() const { return this->m_data->collectionType(); }
+ CollectionType collectionType() const { return this->m_data->collectionType(); }
QJsonObject imageTags() const { return m_data->imageTags(); }
QStringList backdropImageTags() const { return m_data->backdropImageTags(); }
QJsonObject imageBlurHashes() const { return m_data->imageBlurHashes(); }
- QString mediaType() const { return m_data->mediaType(); }
+ MediaType mediaType() const { return m_data->mediaType(); }
QDateTime endDate() const { return m_data->endDate(); }
QDateTime startDate() const { return m_data->startDate(); }
Item *currentProgram() const { return m_currentProgram; }
@@ -281,7 +281,7 @@ signals:
void indexNumberChanged(int newIndexNumber);
void indexNumberEndChanged(int newIndexNumberEnd);
void isFolderChanged(bool newIsFolder);
- void typeChanged(const QString &newType);
+ void typeChanged(const BaseItemKind &newType);
void parentBackdropItemIdChanged();
void parentBackdropImageTagsChanged();
void userDataChanged(UserData *newUserData);
@@ -313,7 +313,7 @@ signals:
void albumCountChanged(int newAlbumCount);
void artistCountChanged(int newArtistCount);
void musicVideoCountChanged(int newMusicVideoCount);
- void mediaTypeChanged(const QString &newMediaType);
+ void mediaTypeChanged(const MediaType &newMediaType);
void endDateChanged();
void startDateChanged();
void widthChanged(int newWidth);
diff --git a/core/include/JellyfinQt/viewmodel/itemmodel.h b/core/include/JellyfinQt/viewmodel/itemmodel.h
index 5c9e9c3..30792c6 100644
--- a/core/include/JellyfinQt/viewmodel/itemmodel.h
+++ b/core/include/JellyfinQt/viewmodel/itemmodel.h
@@ -38,7 +38,7 @@
public: \
Q_PROPERTY(type propName READ propName WRITE set##propSetName NOTIFY propName##Changed) \
type propName() const { return this->m_parameters.propName(); } \
- void set##propSetName(type newValue) { \
+ void set##propSetName(const type &newValue) { \
this->m_parameters.set##propSetName( newValue ); \
emit propName##Changed(); \
autoReloadIfNeeded(); \
@@ -92,7 +92,7 @@ public:
this->connect(this, &BaseModelLoader::apiClientChanged, this, &AbstractUserParameterLoader::apiClientChanged);
}
protected:
- virtual bool canReload() const override {
+ bool canReload() const override {
return BaseModelLoader::canReload() && !this->m_parameters.userId().isNull();
}
private:
@@ -125,7 +125,7 @@ public:
FWDPROP(bool, includeExternalContent, IncludeExternalContent)
FWDPROP(bool, includeHidden, IncludeHidden)
- FWDPROP(QStringList, presetViews, PresetViews)
+ FWDLISTPROP(Jellyfin::DTO::CollectionType, presetViews, PresetViews)
};
using LatestMediaBase = AbstractUserParameterLoader, Jellyfin::Loader::GetLatestMediaParams>;
@@ -141,12 +141,12 @@ public:
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
FWDPROP(bool, groupItems, GroupItems)
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
- FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
+ FWDLISTPROP(Jellyfin::DTO::BaseItemKindClass::Value, includeItemTypes, IncludeItemTypes)
FWDPROP(bool, isPlayed, IsPlayed)
FWDPROP(QString, parentId, ParentId)
};
-using UserItemsLoaderBase = AbstractUserParameterLoader;
+using UserItemsLoaderBase = AbstractUserParameterLoader;
class UserItemsLoader : public UserItemsLoaderBase {
Q_OBJECT
public:
@@ -166,7 +166,7 @@ public:
FWDPROP(bool, enableUserData, EnableUserData)
FWDPROP(QStringList, excludeArtistIds, ExcludeArtistIds)
FWDPROP(QStringList, excludeItemIds, ExcludeItemIds)
- FWDPROP(QStringList, excludeItemTypes, ExcludeItemTypes)
+ FWDLISTPROP(Jellyfin::DTO::BaseItemKindClass::Value, excludeItemTypes, ExcludeItemTypes)
FWDPROP(QList, excludeLocationTypes, ExcludeLocationTypes)
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
FWDLISTPROP(Jellyfin::DTO::ItemFilterClass::Value, filters, Filters)
@@ -186,7 +186,7 @@ public:
FWDPROP(QStringList, ids, Ids)
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
FWDLISTPROP(Jellyfin::DTO::ImageTypeClass::Value, imageTypes, ImageTypes)
- FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
+ FWDLISTPROP(Jellyfin::DTO::BaseItemKindClass::Value, includeItemTypes, IncludeItemTypes)
FWDPROP(bool, is3D, Is3D)
FWDPROP(bool, is4K, Is4K)
FWDPROP(bool, isFavorite, IsFavorite)
@@ -201,13 +201,13 @@ public:
FWDPROP(QString, maxOfficialRating, MaxOfficialRating)
FWDPROP(QDateTime, maxPremiereDate, MaxPremiereDate)
FWDPROP(qint32, maxWidth, MaxWidth)
- FWDPROP(QStringList, mediaTypes, MediaTypes)
+ FWDLISTPROP(Jellyfin::DTO::MediaTypeClass::Value, mediaTypes, MediaTypes)
FWDPROP(qint32, minHeight, MinHeight)
FWDPROP(QString, minOfficialRating, MinOfficialRating)
FWDPROP(QDateTime, minPremiereDate, MinPremiereDate)
FWDPROP(qint32, minWidth, MinWidth)
- FWDPROP(QString, sortBy, SortBy)
- FWDPROP(QString, sortOrder, SortOrder)
+ FWDLISTPROP(Jellyfin::DTO::ItemSortByClass::Value, sortBy, SortBy)
+ FWDLISTPROP(Jellyfin::DTO::SortOrderClass::Value, sortOrder, SortOrder)
FWDPROP(QStringList, tags, Tags)
FWDPROP(QList, years, Years)
@@ -227,11 +227,11 @@ public:
FWDPROP(bool, enableImages, EnableImages)
FWDPROP(bool, enableTotalRecordCount, EnableTotalRecordCount)
FWDPROP(bool, enableUserData, EnableUserData)
- FWDPROP(QStringList, excludeItemTypes, ExcludeItemTypes)
+ FWDLISTPROP(Jellyfin::DTO::BaseItemKindClass::Value, excludeItemTypes, ExcludeItemTypes)
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
- FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
- FWDPROP(QStringList, mediaTypes, MediaTypes)
+ FWDLISTPROP(Jellyfin::DTO::BaseItemKindClass::Value, includeItemTypes, IncludeItemTypes)
+ FWDLISTPROP(Jellyfin::DTO::MediaTypeClass::Value, mediaTypes, MediaTypes)
FWDPROP(QString, parentId, ParentId)
FWDPROP(QString, searchTerm, SearchTerm)
};
@@ -269,7 +269,7 @@ public:
FWDPROP(bool, isMissing, IsMissing)
FWDPROP(qint32, season, Season)
FWDPROP(QString, seasonId, SeasonId)
- FWDPROP(QString, sortBy, SortBy)
+ FWDPROP(Jellyfin::DTO::ItemSortByClass::Value, sortBy, SortBy)
FWDPROP(QString, startItemId, StartItemId)
};
@@ -281,7 +281,7 @@ public:
FWDPROP(bool, disableFirstEpisode, DisableFirstEpisode)
FWDLISTPROP(Jellyfin::DTO::ImageTypeClass::Value, enableImageTypes, EnableImageTypes);
- FWDPROP(bool, enableImges, EnableImges)
+ FWDPROP(bool, enableImages, EnableImages)
FWDPROP(bool, enableTotalRecordCount, EnableTotalRecordCount)
FWDPROP(bool, enableUserData, EnableUserData)
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
@@ -300,16 +300,16 @@ public:
FWDPROP(bool, enableImages, EnableImages)
FWDPROP(bool, enableTotalRecordCount, EnableTotalRecordCount)
FWDPROP(bool, enableUserData, EnableUserData)
- FWDPROP(QStringList, excludeItemTypes, ExcludeItemTypes)
+ FWDLISTPROP(Jellyfin::DTO::BaseItemKindClass::Value, excludeItemTypes, ExcludeItemTypes)
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
FWDLISTPROP(Jellyfin::DTO::ItemFilterClass::Value, filters, Filters)
FWDPROP(QStringList, genreIds, GenreIds)
FWDPROP(QStringList, genres, Genres)
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
- FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
+ FWDLISTPROP(Jellyfin::DTO::BaseItemKindClass::Value, includeItemTypes, IncludeItemTypes)
FWDPROP(bool, isFavorite, IsFavorite)
FWDPROP(int, limit, Limit)
- FWDPROP(QStringList, mediaTypes, MediaTypes)
+ FWDLISTPROP(Jellyfin::DTO::MediaTypeClass::Value, mediaTypes, MediaTypes)
FWDPROP(double, minCommunityRating, MinCommunityRating)
FWDPROP(QString, nameLessThan, NameLessThan)
FWDPROP(QString, nameStartsWith, NameStartsWith)
@@ -347,7 +347,7 @@ public:
FWDLISTPROP(Jellyfin::DTO::ImageTypeClass::Value, enableImageTypes, EnableImageTypes)
FWDLISTPROP(Jellyfin::DTO::ItemFieldsClass::Value, fields, Fields)
FWDPROP(bool, enableUserData, EnableUserData)
- FWDPROP(QStringList, sortBy, SortBy)
+ FWDLISTPROP(Jellyfin::DTO::ItemSortByClass::Value, sortBy, SortBy)
FWDPROP(Jellyfin::DTO::SortOrderClass::Value, sortOrder, SortOrder)
FWDPROP(bool, enableFavoriteSorting, EnableFavoriteSorting)
FWDPROP(bool, addCurrentProgram, AddCurrentProgram)
@@ -405,7 +405,7 @@ public:
explicit ItemModel (QObject *parent = nullptr);
- virtual QHash roleNames() const override {
+ QHash roleNames() const override {
return {
JFRN(jellyfinId),
JFRN(name),
@@ -450,7 +450,7 @@ public:
QSharedPointer itemAt(int index);
private slots:
void onInsertItems(const QModelIndex &parent, int start, int end);
- void onUserDataUpdated(const DTO::UserItemDataDto &newUserData);
+ void onUserDataUpdated(const Jellyfin::DTO::UserItemDataDto &newUserData);
};
#undef JFRN
diff --git a/core/include/JellyfinQt/viewmodel/mediastream.h b/core/include/JellyfinQt/viewmodel/mediastream.h
index 0728fdf..6a4b706 100644
--- a/core/include/JellyfinQt/viewmodel/mediastream.h
+++ b/core/include/JellyfinQt/viewmodel/mediastream.h
@@ -41,7 +41,7 @@ public:
Q_PROPERTY(QString comment READ comment NOTIFY commentChanged);
Q_PROPERTY(QString timeBase READ timeBase NOTIFY timeBaseChanged);
Q_PROPERTY(QString title READ title NOTIFY titleChanged);
- Q_PROPERTY(QString videoRange READ videoRange NOTIFY videoRangeChanged);
+ Q_PROPERTY(Jellyfin::DTO::VideoRangeClass::Value videoRange READ videoRange NOTIFY videoRangeChanged);
Q_PROPERTY(QString localizedUndefined READ localizedUndefined NOTIFY localizedUndefinedChanged);
Q_PROPERTY(QString localizedDefault READ localizedDefault NOTIFY localizedDefaultChanged);
Q_PROPERTY(QString localizedForced READ localizedForced NOTIFY localizedForcedChanged);
@@ -78,7 +78,7 @@ public:
QString comment() const { return m_data->comment(); }
QString timeBase() const { return m_data->timeBase(); }
QString title() const { return m_data->title(); }
- QString videoRange() const { return m_data->videoRange(); }
+ DTO::VideoRange videoRange() const { return m_data->videoRange(); }
QString localizedUndefined() const { return m_data->localizedUndefined(); }
QString localizedDefault() const { return m_data->localizedDefault(); }
QString localizedForced() const { return m_data->localizedForced(); }
@@ -116,7 +116,7 @@ signals:
void commentChanged(const QString &newComment);
void timeBaseChanged(const QString &newTimeBase);
void titleChanged(const QString &newTitle);
- void videoRangeChanged(const QString &newVideoRanged);
+ void videoRangeChanged(const DTO::VideoRange &newVideoRanged);
void localizedUndefinedChanged(const QString &newLocalizedUndefined);
void localizedDefaultChanged(const QString &newLocalizedDefault);
void localizedForcedChanged(const QString &newLocalizedForced);
diff --git a/core/src/apiclient.cpp b/core/src/apiclient.cpp
index 6ccb740..d510559 100644
--- a/core/src/apiclient.cpp
+++ b/core/src/apiclient.cpp
@@ -430,15 +430,15 @@ void ApiClient::authenticate(QString username, QString password, bool storeCrede
}
void ApiClient::submitQuickConnectCode(const QString &code) {
- using QQAuthorizeLoader = Loader::HTTP::AuthorizeLoader;
- Loader::AuthorizeParams params;
+ using QQAuthorizeLoader = Loader::HTTP::AuthorizeQuickConnectLoader;
+ Loader::AuthorizeQuickConnectParams params;
params.setCode(code);
QQAuthorizeLoader *loader = new QQAuthorizeLoader(this);
loader->setParameters(params);
loader->load();
- loader->connect(loader, &QQAuthorizeLoader::error, this, [this, loader](QString message) {
+ loader->connect(loader, &QQAuthorizeLoader::error, this, [this, loader](const QString &message) {
qDebug() << "QQ error: " << message;
emit this->quickConnectRejected();
loader->deleteLater();
@@ -475,17 +475,18 @@ void ApiClient::generateDeviceProfile() {
Q_D(ApiClient);
QSharedPointer deviceProfile = QSharedPointer::create(Model::DeviceProfile::generateProfile());
deviceProfile->setJellyfinId(d->deviceId);
- deviceProfile->setFriendlyName(QSysInfo::prettyProductName());
+ deviceProfile->setName(QSysInfo::prettyProductName());
deviceProfile->setMaxStreamingBitrate(d->settings->maxStreamingBitRate());
d->deviceProfile = deviceProfile;
- QSharedPointer clientCapabilities = QSharedPointer::create(true, // supports mediaControl
- false, // supports content uploading
- true, // supports persistent identifier
- false, // supports sync
- deviceProfile);
- clientCapabilities->setPlayableMediaTypes({"Audio", "Video", "Photo"});
- clientCapabilities->setSupportedCommands(d->supportedCommands);
+ QSharedPointer clientCapabilities = QSharedPointer::create(
+ QList({ MediaType::Audio, MediaType::Video, MediaType::Photo }),
+ d->supportedCommands,
+ true, // supports mediaControl
+ true, // supports persistent identifier
+ deviceProfile
+ );
+
clientCapabilities->setAppStoreUrl("https://chris.netsoj.nl/projects/harbour-sailfin");
clientCapabilities->setIconUrl("https://chris.netsoj.nl/static/img/logo.png");
diff --git a/core/src/apimodel.cpp b/core/src/apimodel.cpp
index 20113d9..36b43d9 100644
--- a/core/src/apimodel.cpp
+++ b/core/src/apimodel.cpp
@@ -64,7 +64,6 @@ void BaseModelLoader::setApiClient(ApiClient *newApiClient) {
void BaseModelLoader::setLimit(int newLimit) {
m_explicitLimitSet = newLimit >= 0;
- qCDebug(jellyfinApiModel) << "Limit explicitly set to " << newLimit;
this->m_limit = newLimit;
emit limitChanged(newLimit);
}
@@ -144,12 +143,12 @@ bool setRequestStartIndex(Loader::GetLatestMediaParams ¶ms, int offset) {
}
template<>
-void setRequestLimit(Loader::GetItemsByUserIdParams ¶ms, int limit) {
+void setRequestLimit(Loader::GetItemsParams ¶ms, int limit) {
params.setLimit(limit);
}
template<>
-bool setRequestStartIndex(Loader::GetItemsByUserIdParams ¶ms, int index) {
+bool setRequestStartIndex(Loader::GetItemsParams ¶ms, int index) {
params.setStartIndex(index);
return true;
}
diff --git a/core/src/jellyfin.cpp b/core/src/jellyfin.cpp
index 8efcca3..c15d13f 100644
--- a/core/src/jellyfin.cpp
+++ b/core/src/jellyfin.cpp
@@ -18,7 +18,9 @@
*/
#include "JellyfinQt/jellyfin.h"
+#include "JellyfinQt/dto/collectiontype.h"
#include "JellyfinQt/model/item.h"
+#include "JellyfinQt/dto/itemsortby.h"
#include "JellyfinQt/dto/itemfields.h"
#include "JellyfinQt/dto/mediastream.h"
#include "JellyfinQt/dto/nameguidpair.h"
@@ -92,11 +94,16 @@ void JellyfinPlugin::registerTypes(const char *uri) {
qmlRegisterType(uri, 1, 0, "LiveTvChannelsLoader");
// Enumerations
+ qmlRegisterUncreatableType(uri, 1, 0, "CollectionType", "Is an enum");
qmlRegisterUncreatableType(uri, 1, 0, "GeneralCommandType", "Is an enum");
- qmlRegisterUncreatableType(uri, 1, 0, "ModelStatus", "Is an enum");
- qmlRegisterUncreatableType(uri, 1, 0, "PlayMethod", "Is an enum");
qmlRegisterUncreatableType(uri, 1, 0, "ItemFields", "Is an enum");
qmlRegisterUncreatableType(uri, 1, 0, "ImageType", "Is an enum");
+ qmlRegisterUncreatableType(uri, 1, 0, "MediaType", "Is an enum");
+ qmlRegisterUncreatableType(uri, 1, 0, "ItemType", "Is an enum");
+ qmlRegisterUncreatableType(uri, 1, 0, "PlayMethod", "Is an enum");
+ qmlRegisterUncreatableType(uri, 1, 0, "SortBy", "Is an enum");
+ qmlRegisterUncreatableType(uri, 1, 0, "SortOrder", "Is an enum");
+ qmlRegisterUncreatableType(uri, 1, 0, "ModelStatus", "Is an enum");
qmlRegisterUncreatableType(uri, 1, 0, "NowPlayingSection", "Is an enum");
qmlRegisterUncreatableType(uri, 1, 0, "PlayerState", "Is an enum");
qmlRegisterUncreatableType(uri, 1, 0, "MediaStatus", "Is an enum");
diff --git a/core/src/model/controllablesession.cpp b/core/src/model/controllablesession.cpp
index a1b3b70..c499575 100644
--- a/core/src/model/controllablesession.cpp
+++ b/core/src/model/controllablesession.cpp
@@ -46,7 +46,7 @@ PlaybackManager *LocalSession::createPlaybackManager() const {
}
// ControllableJellyfinSession
-ControllableJellyfinSession::ControllableJellyfinSession(const QSharedPointer info, ApiClient &apiClient, QObject *parent)
+ControllableJellyfinSession::ControllableJellyfinSession(const QSharedPointer info, ApiClient &apiClient, QObject *parent)
: ControllableSession(parent),
m_data(info),
m_apiClient(apiClient){}
@@ -147,14 +147,15 @@ void RemoteJellyfinSessionScanner::startScanning() {
d->loader->setParameters(params);
connect(d->loader, &Loader::HTTP::GetSessionsLoader::ready, this, [this, d, localSession]() {
if (d->loader == nullptr) return;
- QList sessions = d->loader->result();
+ QList sessions = d->loader->result();
+ qDebug() << "Found " << sessions.count() << " sessions";
for(auto it = sessions.begin(); it != sessions.end(); it++) {
// Skip this device
if (it->deviceId() == localSession->id()) continue;
- emit sessionFound(new ControllableJellyfinSession(QSharedPointer::create(*it), *d->apiClient));
+ emit sessionFound(new ControllableJellyfinSession(QSharedPointer::create(*it), *d->apiClient));
}
});
d->loader->load();
diff --git a/core/src/model/deviceprofile.cpp b/core/src/model/deviceprofile.cpp
index ba5363a..8c6fdf1 100644
--- a/core/src/model/deviceprofile.cpp
+++ b/core/src/model/deviceprofile.cpp
@@ -53,8 +53,6 @@ int DeviceProfile::maxStreamingBitrate() {
}
DTO::DeviceProfile DeviceProfile::generateProfile() {
- using JsonPair = QPair;
-
QStringList audioCodes = {
"aac",
"flac",
@@ -94,130 +92,138 @@ DTO::DeviceProfile DeviceProfile::generateProfile() {
// AAC
- DTO::CodecProfile codecProfile1(DTO::CodecType::VideoAudio);
+ DTO::CodecProfile codecProfile1(
+ DTO::CodecType::VideoAudio,
+ {
+ createCondition(CondVal::IsSecondaryAudio,
+ Condition::Equals,
+ "false",
+ false)
+ },
+ {}
+ );
codecProfile1.setCodec("aac");
- QList codecProfile1Conditions;
- codecProfile1Conditions.append(createCondition(CondVal::IsSecondaryAudio,
- Condition::Equals,
- "false",
- false));
- codecProfile1.setConditions(codecProfile1Conditions);
-
- DTO::CodecProfile codecProfile2(DTO::CodecType::Video);
- codecProfile2.setCodec("h264");
- codecProfile2.setConditions({
- createCondition(CondVal::IsAnamorphic,
+ DTO::CodecProfile codecProfile2(
+ DTO::CodecType::Video,
+ {
+ createCondition(CondVal::IsAnamorphic,
Condition::NotEquals,
"true", false),
- createCondition(CondVal::VideoProfile,
- Condition::EqualsAny,
- "baseline|constrained baseline", false), //"high|main|baseline|constrained baseline"
- createCondition(CondVal::VideoLevel,
- Condition::LessThanEqual,
- "51", false),
- createCondition(CondVal::IsInterlaced,
- Condition::NotEquals,
- "true", false)
- });
+ createCondition(CondVal::VideoProfile,
+ Condition::EqualsAny,
+ "baseline|constrained baseline", false), //"high|main|baseline|constrained baseline"
+ createCondition(CondVal::VideoLevel,
+ Condition::LessThanEqual,
+ "51", false),
+ createCondition(CondVal::IsInterlaced,
+ Condition::NotEquals,
+ "true", false)
+ },
+ {}
+ );
+ codecProfile2.setCodec("h264");
QList codecProfiles = {
codecProfile1,
codecProfile2
};
// Hard coded nr 1:
- DTO::TranscodingProfile transcoding1(DTO::DlnaProfileType::Audio,
- false, // estimeateContentLength
- false, // enable MPEG2 TS M2 mode
- DTO::TranscodeSeekInfo::Auto,
- false, // copyTimestamps
- DTO::EncodingContext::Streaming,
- false, // enable subtitles in manifest
- 0, // minSegments
- 0, // minSegmentLength
- true // set break on nonkeyframes
- );
- transcoding1.setAudioCodec("aac");
- transcoding1.setContainer("ts");
+ DTO::TranscodingProfile transcoding1(
+ QStringLiteral("ts"),
+ DTO::DlnaProfileType::Audio,
+ QStringLiteral("h264"),
+ QStringLiteral("aac"),
+ DTO::MediaStreamProtocol::Hls,
+ false, // estimeateContentLength
+ false, // enable MPEG2 TS M2 mode
+ DTO::TranscodeSeekInfo::Auto,
+ false, // copyTimestamps
+ DTO::EncodingContext::Streaming,
+ false, // enable subtitles in manifest
+ 0, // minSegments
+ 0, // minSegmentLength
+ true, // set break on nonkeyframes,
+ {}, // conditions
+ true // Enable audio VBR encoding
+ );
transcoding1.setMaxAudioChannels("2");
- transcoding1.setProtocol("hls");
// Hard code nr 2
- DTO::TranscodingProfile transcoding2(DTO::DlnaProfileType::Video,
- false, // estimate content length
- false, // enable MPEG2 ts M2 mode
- DTO::TranscodeSeekInfo::Auto,
- false, // copy timestamps
- DTO::EncodingContext::Streaming,
- false, // enable subtitles in manifest
- 0, // minSegments
- 0, // minSegmentLength
- true // set break on non-keyframes
- );
- transcoding2.setAudioCodec("mp3,aac");
- transcoding2.setContainer("ts");
+ DTO::TranscodingProfile transcoding2(
+ QStringLiteral("ts"),
+ DTO::DlnaProfileType::Video,
+ QStringLiteral("h264"),
+ QStringLiteral("mp3,aac"),
+ DTO::MediaStreamProtocol::Hls,
+ false, // estimate content length
+ false, // enable MPEG2 ts M2 mode
+ DTO::TranscodeSeekInfo::Auto,
+ false, // copy timestamps
+ DTO::EncodingContext::Streaming,
+ false, // enable subtitles in manifest
+ 0, // minSegments
+ 0, // minSegmentLength
+ true, // set break on non-keyframes
+ {}, // conditions
+ true// enableAudioVbrEncoding
+ );
transcoding2.setMaxAudioChannels("2");
- transcoding2.setProtocol("hls");
- transcoding2.setVideoCodec("h264");
// Fallback
- DTO::TranscodingProfile transcoding3(DTO::DlnaProfileType::Video,
- false, // estimate content length
- false, // enable MPEG2 ts M2 mode
- DTO::TranscodeSeekInfo::Auto,
- false, // copy timestamps
- DTO::EncodingContext::Static,
- false, // enable subtitles in manifest
- 0, // minSegments
- 0, // minSegmentLength
- true // set break on non-keyframes
- );
- transcoding3.setContainer("mp4");
- transcoding3.setAudioCodec(videoAudioCodecs.join(','));
- transcoding3.setVideoCodec("h264");
- transcoding3.setProtocol("http");
+ DTO::TranscodingProfile transcoding3(
+ QStringLiteral("mp4"),
+ DTO::DlnaProfileType::Video,
+ QStringLiteral("h264"),
+ videoAudioCodecs.join(","),
+ DTO::MediaStreamProtocol::Http,
+ false, // estimate content length
+ false, // enable MPEG2 ts M2 mode
+ DTO::TranscodeSeekInfo::Auto,
+ false, // copy timestamps
+ DTO::EncodingContext::Static,
+ false, // enable subtitles in manifest
+ 0, // minSegments
+ 0, // minSegmentLength
+ true, // set break on non-keyframes
+ {},
+ true
+ );
QList transcodingProfiles = {
transcoding1, transcoding2, transcoding3
};
if (supportsHls() && !hlsVideoAudioCodecs.isEmpty()) {
- DTO::TranscodingProfile transcoding4(DTO::DlnaProfileType::Video,
- false, // estimate content length
- false, // enable MPEG2 ts M2 mode
- DTO::TranscodeSeekInfo::Auto,
- false, // copy timestamps
- DTO::EncodingContext::Streaming,
- false, // enable subtitles in manifest
- 1, // minSegments
- 0, // minSegmentLength
- true // set break on non-keyframes
- );
- transcoding4.setContainer("ts");
- transcoding4.setAudioCodec(hlsVideoAudioCodecs.join(','));
- transcoding4.setVideoCodec(hlsVideoCodecs.join(','));
- transcoding4.setProtocol("hls");
+ DTO::TranscodingProfile transcoding4(
+ QStringLiteral("ts"),
+ DTO::DlnaProfileType::Video,
+ hlsVideoAudioCodecs.join(","),
+ hlsVideoAudioCodecs.join(","),
+ DTO::MediaStreamProtocol::Hls,
+ false, // estimate content length
+ false, // enable MPEG2 ts M2 mode
+ DTO::TranscodeSeekInfo::Auto,
+ false, // copy timestamps
+ DTO::EncodingContext::Streaming,
+ false, // enable subtitles in manifest
+ 1, // minSegments
+ 0, // minSegmentLength
+ true, // set break on non-keyframes
+ {},
+ true
+ );
transcoding4.setMaxAudioChannels("2");
transcodingProfiles.append(transcoding4);
}
- // Response profiles (or whatever it actually does?)
- DTO::ResponseProfile responseProfile1(DTO::DlnaProfileType::Video);
- responseProfile1.setContainer("m4v");
- responseProfile1.setMimeType("video/mp4");
- QList responseProfiles = {
- responseProfile1
- };
-
// Direct play profiles
// Video
- DTO::DirectPlayProfile directPlayProfile1(DTO::DlnaProfileType::Video);
- directPlayProfile1.setContainer("mp4,m4v");
+ DTO::DirectPlayProfile directPlayProfile1("mp4,m4v", DTO::DlnaProfileType::Video);
directPlayProfile1.setVideoCodec(mp4VideoCodecs.join(','));
directPlayProfile1.setAudioCodec(videoAudioCodecs.join(','));
- DTO::DirectPlayProfile directPlayProfile2(DTO::DlnaProfileType::Video);
- directPlayProfile2.setContainer("mkv");
+ DTO::DirectPlayProfile directPlayProfile2("mkv", DTO::DlnaProfileType::Video);
directPlayProfile2.setVideoCodec(mp4VideoCodecs.join(','));
directPlayProfile2.setAudioCodec(videoAudioCodecs.join(','));
@@ -227,43 +233,36 @@ DTO::DeviceProfile DeviceProfile::generateProfile() {
// Audio
for (auto it = audioCodes.begin(); it != audioCodes.end(); it++) {
if (*it == "mp2") {
- DTO::DirectPlayProfile profile(DTO::DlnaProfileType::Audio);
- profile.setContainer("mp2,mp3");
+ DTO::DirectPlayProfile profile("mp2,mp3", DTO::DlnaProfileType::Audio);
profile.setAudioCodec("mp2");
directPlayProfiles.append(profile);
} else if(*it == "mp3") {
- DTO::DirectPlayProfile profile(DTO::DlnaProfileType::Audio);
- profile.setContainer("mp3");
+ DTO::DirectPlayProfile profile("mp3", DTO::DlnaProfileType::Audio);
profile.setAudioCodec("mp3");
directPlayProfiles.append(profile);
} else if (*it == "webma") {
- DTO::DirectPlayProfile profile(DTO::DlnaProfileType::Audio);
- profile.setContainer("webma,webm");
+ DTO::DirectPlayProfile profile("webma,webm", DTO::DlnaProfileType::Audio);
directPlayProfiles.append(profile);
} else {
- DTO::DirectPlayProfile profile(DTO::DlnaProfileType::Audio);
- profile.setContainer(*it);
+ DTO::DirectPlayProfile profile(*it, DTO::DlnaProfileType::Audio);
directPlayProfiles.append(profile);
}
}
+ QList containerProfiles = { };
+
+ QList subtitleProfiles = {
+ DTO::SubtitleProfile(DTO::SubtitleDeliveryMethodClass::Hls),
+ DTO::SubtitleProfile(DTO::SubtitleDeliveryMethodClass::Encode)
+ };
+
DTO::DeviceProfile profile(
- QSharedPointer::create(),
- false, // enableAlbumArtInDidl
- false, // enableSingleAlbumArtLimit
- false, // enableSingleSubtitleLimit
- std::numeric_limits().max(), // max album art width
- std::numeric_limits().max(), // max album art height
- 0, // timeline offset seconds
- false, // request plain video items
- false, // request plain folders
- false, // enableMSMediaReceiverRegistrar,
- false //ignoreTranscodeByteRangeRequests
+ directPlayProfiles,
+ transcodingProfiles,
+ containerProfiles,
+ codecProfiles,
+ subtitleProfiles
);
- profile.setCodecProfiles(codecProfiles);
- profile.setDirectPlayProfiles(directPlayProfiles);
- profile.setResponseProfiles(responseProfiles);
- profile.setTranscodingProfiles(transcodingProfiles);
profile.setMaxStreamingBitrate(std::make_optional(maxStreamingBitrate()));
return profile;
}
diff --git a/core/src/model/item.cpp b/core/src/model/item.cpp
index 4687e68..496dcc7 100644
--- a/core/src/model/item.cpp
+++ b/core/src/model/item.cpp
@@ -26,12 +26,16 @@ namespace Model {
Item::Item(ApiClient *apiClient, QObject *parent)
: Item(DTO::BaseItemDto(
QString(), // id
+ ExtraType::Unknown,
Video3DFormat::EnumNotSet,
PlayAccess::Full,
- QSharedPointer::create(0, 0, false, false),
+ BaseItemKind::EnumNotSet,
+ QSharedPointer::create(0, 0, false, false, QString(), QString()),
+ CollectionType::EnumNotSet,
VideoType::EnumNotSet,
LocationType::Virtual,
IsoType::EnumNotSet,
+ MediaType::EnumNotSet,
ImageOrientation::EnumNotSet,
ChannelType::EnumNotSet,
ProgramAudio::EnumNotSet,
diff --git a/core/src/model/playbackmanager.cpp b/core/src/model/playbackmanager.cpp
index 5bd254c..2cb65b7 100644
--- a/core/src/model/playbackmanager.cpp
+++ b/core/src/model/playbackmanager.cpp
@@ -232,7 +232,7 @@ public:
void requestItemUrl(QSharedPointer item);
// slots
- void handlePlaybackInfoResponse(QString itemId, QString mediaType, DTO::PlaybackInfoResponse &response);
+ void handlePlaybackInfoResponse(QString itemId, MediaType mediaType, DTO::PlaybackInfoResponse &response);
/// Called when we have fetched the playback URL and playSession
void onItemUrlReceived(const QString &itemId, const QUrl &url, const QString &playSession,
// Fully specify class to please MOC
@@ -352,7 +352,7 @@ void LocalPlaybackManagerPrivate::setItem(QSharedPointer newItem) {
}
}
-void LocalPlaybackManagerPrivate::handlePlaybackInfoResponse(QString itemId, QString mediaType, DTO::PlaybackInfoResponse &response) {
+void LocalPlaybackManagerPrivate::handlePlaybackInfoResponse(QString itemId, MediaType mediaType, DTO::PlaybackInfoResponse &response) {
Q_Q(LocalPlaybackManager);
//TODO: move the item URL fetching logic out of this function, into MediaSourceInfo?
QList mediaSources = response.mediaSources();
@@ -394,15 +394,16 @@ void LocalPlaybackManagerPrivate::handlePlaybackInfoResponse(QString itemId, QSt
resultingUrl = QUrl::fromLocalFile(source.path());
playMethod = PlayMethod::DirectPlay;
} else if (source.supportsDirectStream() && !transcodePreferred) {
- if (mediaType == "Video") {
- mediaType.append('s');
+ QString mediaTypeUrl = Support::toString(mediaType);
+ if (mediaType == MediaType::Video) {
+ mediaTypeUrl.append('s');
}
QUrlQuery query;
query.addQueryItem("mediaSourceId", source.jellyfinId());
query.addQueryItem("deviceId", m_apiClient->deviceId());
query.addQueryItem("api_key", m_apiClient->token());
query.addQueryItem("Static", "True");
- resultingUrl = QUrl(m_apiClient->baseUrl() + "/" + mediaType + "/" + itemId
+ resultingUrl = QUrl(m_apiClient->baseUrl() + "/" + mediaTypeUrl + "/" + itemId
+ "/stream." + source.container() + "?" + query.toString(QUrl::EncodeReserved));
playMethod = PlayMethod::DirectStream;
} else if (source.supportsTranscoding() && !source.transcodingUrlNull() && transcodingAllowed) {
diff --git a/core/src/model/playbackreporter.cpp b/core/src/model/playbackreporter.cpp
index 8d26b10..1b27fb3 100644
--- a/core/src/model/playbackreporter.cpp
+++ b/core/src/model/playbackreporter.cpp
@@ -149,7 +149,9 @@ void PlaybackReporterPrivate::postPlaybackInfo(PlaybackInfoType type) {
m_playbackManager->player()->state() == PlayerState::Paused,
false, // is muted?
m_playbackManager->playMethod(),
- DTO::RepeatMode::RepeatNone);
+ DTO::RepeatMode::RepeatNone,
+ DTO::PlaybackOrder::Default
+ );
progress.setSessionId(m_playbackManager->sessionId());
diff --git a/core/src/model/remotejellyfinplayback.cpp b/core/src/model/remotejellyfinplayback.cpp
index 213cc12..76d6e6b 100644
--- a/core/src/model/remotejellyfinplayback.cpp
+++ b/core/src/model/remotejellyfinplayback.cpp
@@ -20,7 +20,7 @@
#include
#include
-#include
+#include
#include
#include
#include
@@ -174,7 +174,7 @@ void RemoteJellyfinPlayback::onPositionTimerFired() {
emit positionChanged(position());
}
-void RemoteJellyfinPlayback::onSessionInfoUpdated(const QString &sessionId, const SessionInfo &sessionInfo) {
+void RemoteJellyfinPlayback::onSessionInfoUpdated(const QString &sessionId, const SessionInfoDto &sessionInfo) {
if (sessionId != m_sessionId) return;
m_lastSessionInfo = sessionInfo;
@@ -245,8 +245,7 @@ void RemoteJellyfinPlayback::sendGeneralCommand(DTO::GeneralCommandType command,
using CommandLoader = Loader::HTTP::SendFullGeneralCommandLoader;
Params params;
- QSharedPointer fullCommand = QSharedPointer::create(command, m_apiClient.userId());
- fullCommand->setArguments(arguments);
+ QSharedPointer fullCommand = QSharedPointer::create(command, m_apiClient.userId(), arguments);
params.setBody(fullCommand);
params.setSessionId(m_sessionId);
diff --git a/core/src/viewmodel/item.cpp b/core/src/viewmodel/item.cpp
index 85a452f..cfa54fa 100644
--- a/core/src/viewmodel/item.cpp
+++ b/core/src/viewmodel/item.cpp
@@ -101,7 +101,7 @@ void Item::setUserData(DTO::UserItemDataDto &newData) {
void Item::setUserData(QSharedPointer newData) {
if (m_data.isNull() || m_data->userData().isNull()) {
- m_userData->setData(QSharedPointer::create(0, 0, false, false));
+ m_userData->setData(QSharedPointer::create(0, 0, false, false, QString(), QString()));
} else {
m_userData->setData(newData);
}
diff --git a/core/src/viewmodel/itemmodel.cpp b/core/src/viewmodel/itemmodel.cpp
index 10c648b..24c2902 100644
--- a/core/src/viewmodel/itemmodel.cpp
+++ b/core/src/viewmodel/itemmodel.cpp
@@ -48,7 +48,7 @@ LatestMediaLoader::LatestMediaLoader(QObject *parent)
: LatestMediaBase(new Jellyfin::Loader::HTTP::GetLatestMediaLoader(), parent){ }
UserItemsLoader::UserItemsLoader(QObject *parent)
- : UserItemsLoaderBase(new Jellyfin::Loader::HTTP::GetItemsByUserIdLoader(), parent) {}
+ : UserItemsLoaderBase(new Jellyfin::Loader::HTTP::GetItemsLoader(), parent) {}
ResumeItemsLoader::ResumeItemsLoader(QObject *parent)
: ResumeItemsLoaderBase(new Jellyfin::Loader::HTTP::GetResumeItemsLoader(), parent) {}
diff --git a/core/src/viewmodel/userdata.cpp b/core/src/viewmodel/userdata.cpp
index a4dda54..184b428 100644
--- a/core/src/viewmodel/userdata.cpp
+++ b/core/src/viewmodel/userdata.cpp
@@ -22,7 +22,7 @@ namespace Jellyfin {
namespace ViewModel {
UserData::UserData(QObject *parent)
- : UserData(QSharedPointer::create(0, 0, false, false), parent) {
+ : UserData(QSharedPointer::create(0, 0, false, false, QString(), QString()), parent) {
}
@@ -30,13 +30,13 @@ UserData::UserData(QSharedPointer data, QObject *parent)
: QObject(parent),
m_data(data) {
if (m_data.isNull()) {
- m_data = QSharedPointer::create(0, 0, false, false);
+ m_data = QSharedPointer::create(0, 0, false, false, QString(), QString());
}
}
void UserData::setData(QSharedPointer data) {
if (data.isNull()) {
- m_data = QSharedPointer::create(0, 0, false, false);
+ m_data = QSharedPointer::create(0, 0, false, false, QString(), QString());
} else {
m_data = data;
}
diff --git a/core/src/websocket.cpp b/core/src/websocket.cpp
index bc7a99f..16e3eac 100644
--- a/core/src/websocket.cpp
+++ b/core/src/websocket.cpp
@@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include
#include
#include
-#include
+#include
#include
Q_LOGGING_CATEGORY(jellyfinWebSocket, "jellyfin.websocket");
@@ -157,7 +157,7 @@ void WebSocket::textMessageReceived(const QString &message) {
}
} else if (messageType == QStringLiteral("Sessions")) {
try {
- QList sessionInfoList = Support::fromJsonValue>(data);
+ QList sessionInfoList = Support::fromJsonValue>(data);
for (auto it = sessionInfoList.cbegin(); it != sessionInfoList.cend(); it++) {
emit m_apiClient->eventbus()->sessionInfoUpdated(it->jellyfinId(), *it);
}
diff --git a/qtquick/qml/ApiClient.qml b/qtquick/qml/ApiClient.qml
index 643e0d3..0d3edbb 100644
--- a/qtquick/qml/ApiClient.qml
+++ b/qtquick/qml/ApiClient.qml
@@ -3,5 +3,6 @@ import QtQuick 2.12
import nl.netsoj.chris.Jellyfin 1.0 as J
J.ApiClient {
+ appName: "Sailfin QtQuick"
supportedCommands: [J.GeneralCommandType.Play, J.GeneralCommandType.DisplayContent, J.GeneralCommandType.DisplayMessage]
}
diff --git a/qtquick/qml/main.qml b/qtquick/qml/main.qml
index cec66b3..7104305 100644
--- a/qtquick/qml/main.qml
+++ b/qtquick/qml/main.qml
@@ -110,7 +110,7 @@ ApplicationWindow {
enabled: playbackManager.hasPrevious
}
Button {
- readonly property bool _playing: playbackManager.playbackState === PlayerState.Playing
+ readonly property bool _playing: playbackManager.playbackState === J.PlayerState.Playing
anchors.verticalCenter: parent.verticalCenter
text: _playing ? "Pause" : "Play"
onClicked: _playing ? playbackManager.pause() : playbackManager.play()
diff --git a/qtquick/qml/pages/MainPage.qml b/qtquick/qml/pages/MainPage.qml
index b58e33b..49d01e8 100644
--- a/qtquick/qml/pages/MainPage.qml
+++ b/qtquick/qml/pages/MainPage.qml
@@ -34,10 +34,21 @@ Page {
Column {
id: content
width: parent.width
- CheckBox {
- checked: ApiClient.settings.allowTranscoding
- text: "allow transcoding"
- onCheckedChanged: ApiClient.settings.allowTranscoding = checked
+ Row {
+ CheckBox {
+ checked: ApiClient.settings.allowTranscoding
+ text: "allow transcoding"
+ onCheckedChanged: ApiClient.settings.allowTranscoding = checked
+ }
+ ComboBox {
+ model: J.RemoteDeviceList {
+ id: deviceList
+ apiClient: ApiClient
+ scanning: _modelsLoaded == true
+ }
+ textRole: "deviceName"
+ width: 400
+ }
}
Repeater {
model: mediaLibraryModel
diff --git a/sailfish/qml/Utils.js b/sailfish/qml/Utils.js
index 3b702fa..268b003 100644
--- a/sailfish/qml/Utils.js
+++ b/sailfish/qml/Utils.js
@@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
.pragma library
+.import nl.netsoj.chris.Jellyfin 1.0 as J
/**
* Converts miliseconds to a h:mm:ss format
@@ -89,54 +90,60 @@ function itemModelImageUrl(baseUrl, itemId, tag, type, options) {
}
function usePortraitCover(itemType) {
- return ["Series", "Movie", "tvshows", "movies"].indexOf(itemType) >= 0
+ var portraitTypes = [J.ItemType.Series, J.ItemType.Movie, J.CollectionType.Tvshows, J.CollectionType.Movies]
+ console.log("UsePortraitCover itemType: ", itemType)
+ return portraitTypes.indexOf(itemType) >= 0
}
/**
* Returns the page url for a certain item type.
*/
function getPageUrl(mediaType, itemType, isFolder) {
- switch (itemType.toLowerCase()) {
- case "series":
+ switch (itemType) {
+ case J.ItemType.Series:
return Qt.resolvedUrl("pages/itemdetails/SeriesPage.qml")
- case "movie":
+ case J.ItemType.Movie:
return Qt.resolvedUrl("pages/itemdetails/FilmPage.qml")
- case "collection":
- case "photoalbum":
+ case J.ItemType.Folder:
+ case J.ItemType.PhotoAlbum:
return Qt.resolvedUrl("pages/itemdetails/CollectionPage.qml")
- case "season":
+ case J.ItemType.Season:
return Qt.resolvedUrl("pages/itemdetails/SeasonPage.qml")
- case "episode":
+ case J.ItemType.Episode:
return Qt.resolvedUrl("pages/itemdetails/EpisodePage.qml")
- case "musicartist":
+ case J.ItemType.MusicArtist:
return Qt.resolvedUrl("pages/itemdetails/MusicArtistPage.qml")
- case "musicalbum":
- case "playlist":
+ case J.ItemType.MusicAlbum:
+ case J.ItemType.Playlist:
return Qt.resolvedUrl("pages/itemdetails/MusicAlbumPage.qml")
- case "photo":
+ case J.ItemType.Photo:
return Qt.resolvedUrl("pages/itemdetails/PhotoPage.qml")
- case "tvchannel":
+ case J.ItemType.TvChannel:
return Qt.resolvedUrl("pages/itemdetails/LiveTvChannelPage.qml")
- case "collectionfolder":
+ case J.ItemType.CollectionFolder:
// TODO: support for other collection folders
- switch(mediaType.toLowerCase()) {
- case "music":
+ switch(mediaType) {
+ case J.CollectionType.Music:
return Qt.resolvedUrl("pages/itemdetails/MusicLibraryPage.qml")
}
// FALLTRHOUGH
default:
- switch (mediaType ? mediaType.toLowerCase() : isFolder ? "folder" : "") {
- case "livetv":
- return Qt.resolvedUrl("pages/itemdetails/LiveTvChannelsPage.qml")
- case "folder":
- return Qt.resolvedUrl("pages/itemdetails/CollectionPage.qml")
- case "video":
- return Qt.resolvedUrl("pages/itemdetails/VideoPage.qml")
- case "photo":
- return Qt.resolvedUrl("pages/itemdetails/PhotoPage.qml")
- default:
- if (isFolder) return Qt.resolvedUrl("pages/itemdetails/CollectionPage.qml")
- return Qt.resolvedUrl("pages/itemdetails/UnsupportedPage.qml")
+ if (isFolder) {
+ switch (mediaType) {
+ case J.CollectionType.Livetv:
+ return Qt.resolvedUrl("pages/itemdetails/LiveTvChannelsPage.qml")
+ default:
+ return Qt.resolvedUrl("pages/itemdetails/CollectionPage.qml")
+ }
+ } else {
+ switch (mediaType) {
+ case J.MediaType.Photo:
+ return Qt.resolvedUrl("pages/itemdetails/PhotoPage.qml")
+ case J.MediaType.Video:
+ return Qt.resolvedUrl("pages/itemdetails/VideoPage.qml")
+ default:
+ return Qt.resolvedUrl("pages/itemdetails/UnsupportedPage.qml")
+ }
}
}
}
diff --git a/sailfish/qml/components/ItemChildrenShowcase.qml b/sailfish/qml/components/ItemChildrenShowcase.qml
index 93084e5..cc91a68 100644
--- a/sailfish/qml/components/ItemChildrenShowcase.qml
+++ b/sailfish/qml/components/ItemChildrenShowcase.qml
@@ -10,7 +10,7 @@ MoreSection {
busy: itemModel.loader.status === J.ModelStatus.Loading || extraBusy
property bool extraBusy: false
property alias loader: itemModel.loader
- property string collectionType
+ property int collectionType
property bool collapseWhenEmpty: true
J.ItemModel {
diff --git a/sailfish/qml/components/PlaybackBar.qml b/sailfish/qml/components/PlaybackBar.qml
index dcfc2e1..c4f1f32 100644
--- a/sailfish/qml/components/PlaybackBar.qml
+++ b/sailfish/qml/components/PlaybackBar.qml
@@ -158,7 +158,7 @@ PanelBackground {
}
switch(manager.item.mediaType) {
- case "Audio":
+ case J.MediaType.Audio:
var links = [];
var items = manager.item.artistItems;
console.log(items)
@@ -181,7 +181,7 @@ PanelBackground {
color: highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor
linkColor: Theme.secondaryColor
onLinkActivated: {
- appWindow.navigateToItem(link, "Audio", "MusicArtist", true)
+ appWindow.navigateToItem(link, J.MediaType.Audio, J.ItemType.MusicArtist, true)
}
textFormat: Text.StyledText
Icon {
diff --git a/sailfish/qml/components/music/SongDelegate.qml b/sailfish/qml/components/music/SongDelegate.qml
index 3d85e61..73ce4be 100644
--- a/sailfish/qml/components/music/SongDelegate.qml
+++ b/sailfish/qml/components/music/SongDelegate.qml
@@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
import QtQuick 2.6
import Sailfish.Silica 1.0
+import nl.netsoj.chris.Jellyfin 1.0 as J
import "../.."
@@ -106,7 +107,7 @@ ListItem {
}
function goToArtist(id) {
- appWindow.navigateToItem(id, "audio", "MusicArtist", true)
+ appWindow.navigateToItem(id, J.MediaType.Audio, J.ItemType.MusicArtist, true)
}
Component {
diff --git a/sailfish/qml/cover/CollectionPage.qml b/sailfish/qml/cover/CollectionPage.qml
index b81178b..d90591d 100644
--- a/sailfish/qml/cover/CollectionPage.qml
+++ b/sailfish/qml/cover/CollectionPage.qml
@@ -41,7 +41,7 @@ CoverBackground {
apiClient: appWindow.apiClient
limit: cover.rowCount * 2 - 2
imageTypes: [J.ImageType.Primary]
- sortBy: "IsFavoriteOrLiked,Random"
+ sortBy: [J.SortBy.IsFavoriteOrLiked, J.SortBy.Random]
recursive: true
parentId: itemId
autoReload: false
diff --git a/sailfish/qml/cover/PosterCover.qml b/sailfish/qml/cover/PosterCover.qml
index 2bd769e..5972df0 100644
--- a/sailfish/qml/cover/PosterCover.qml
+++ b/sailfish/qml/cover/PosterCover.qml
@@ -38,7 +38,7 @@ CoverBackground {
Shim {
// Movies usually show their name on the poster,
// so showing it here as well is a bit double
- visible: mData.type !== "Movie"
+ visible: mData.type !== J.ItemType.Movie
anchors {
left: parent.left
right: parent.right
diff --git a/sailfish/qml/harbour-sailfin.qml b/sailfish/qml/harbour-sailfin.qml
index 7651dcf..483f995 100644
--- a/sailfish/qml/harbour-sailfin.qml
+++ b/sailfish/qml/harbour-sailfin.qml
@@ -156,7 +156,7 @@ ApplicationWindow {
}
function navigateToItem(jellyfinId, mediaType, type, isFolder) {
- if (mediaType === "Audio" && !isFolder) {
+ if (mediaType === MediaType.Audio && !isFolder) {
playbackManager.playItemId(jellyfinId)
} else {
var url = Utils.getPageUrl(mediaType, type, isFolder)
diff --git a/sailfish/qml/pages/AboutPage.qml b/sailfish/qml/pages/AboutPage.qml
index 5099792..e8b0356 100644
--- a/sailfish/qml/pages/AboutPage.qml
+++ b/sailfish/qml/pages/AboutPage.qml
@@ -56,7 +56,7 @@ Page {
"You can view its source code on GitHub. " +
"Parts of the code of Sailfin are from other libraries. View their licenses here.
")
.arg(apiClient.version)
- .arg(2024)
+ .arg(2025)
textFormat: Text.StyledText
color: Theme.secondaryHighlightColor
linkColor: Theme.primaryColor
diff --git a/sailfish/qml/pages/MainPage.qml b/sailfish/qml/pages/MainPage.qml
index 34f38a6..e619e09 100644
--- a/sailfish/qml/pages/MainPage.qml
+++ b/sailfish/qml/pages/MainPage.qml
@@ -109,13 +109,13 @@ Page {
ItemChildrenShowcase {
text: model.name
onHeaderClicked: appWindow.navigateToItem(model.jellyfinId, model.collectionType, model.type, model.isFolder);
- collectionType: model.collectionType || ""
+ collectionType: model.collectionType || 0
loader: J.LatestMediaLoader {
apiClient: appWindow.apiClient
parentId: jellyfinId
}
Binding on loader {
- when: model.collectionType == "livetv"
+ when: model.collectionType == J.CollectionType.Livetv
value: J.LiveTvChannelsLoader{
apiClient: appWindow.apiClient
}
diff --git a/sailfish/qml/pages/itemdetails/CollectionPage.qml b/sailfish/qml/pages/itemdetails/CollectionPage.qml
index afb9104..8014477 100644
--- a/sailfish/qml/pages/itemdetails/CollectionPage.qml
+++ b/sailfish/qml/pages/itemdetails/CollectionPage.qml
@@ -39,7 +39,7 @@ BaseDetailPage {
id: collectionLoader
apiClient: appWindow.apiClient
parentId: itemData.jellyfinId
- sortBy: "SortName"
+ sortBy: [ J.SortBy.SortName ]
autoReload: itemData.jellyfinId.length > 0 && (pageRoot.status == PageStatus.Active || _collectionModelLoaded)
}
}
@@ -107,7 +107,7 @@ BaseDetailPage {
id: itemImage
anchors.fill: parent
source: Utils.itemModelImageUrl(apiClient.baseUrl, model.jellyfinId, model.imageTags.Primary, "Primary", {"maxWidth": width})
- blurhash: model.imageBlurHashes.Primary[model.imageTags.Primary]
+ blurhash: model.imageBlurHashes.Primary !== undefined ? model.imageBlurHashes.Primary[model.imageTags.Primary] : undefined
fallbackColor: Utils.colorFromString(model.name)
fillMode: Image.PreserveAspectCrop
clip: true
@@ -152,8 +152,14 @@ BaseDetailPage {
Component {
id: sortPageComponent
+
Page {
id: sortPage
+ readonly property var sortMap: {
+ "SortName": [J.SortBy.SortName],
+ "PlayCount": [J.SortBy.PlayCount],
+ "DateCreated": [J.SortBy.DateCreated]
+ };
ListModel {
id: sortOptions
@@ -183,19 +189,19 @@ BaseDetailPage {
MenuItem {
//: Sort order
text: qsTr("Ascending")
- onClicked: apply(model.value, "Ascending")
+ onClicked: apply(model.value, J.SortOrder.Ascending)
}
MenuItem {
//: Sort order
text: qsTr("Descending")
- onClicked: apply(model.value, "Descending")
+ onClicked: apply(model.value, J.SortOrder.Descending)
}
}
onClicked: openMenu()
function apply(field, order) {
- collectionModel.loader.sortBy = field;
- collectionModel.loader.sortOrder = order;
+ collectionModel.loader.sortBy = sortMap[field];
+ collectionModel.loader.sortOrder = [order];
collectionModel.loader.reload()
pageStack.pop()
}
diff --git a/sailfish/qml/pages/itemdetails/MusicAlbumPage.qml b/sailfish/qml/pages/itemdetails/MusicAlbumPage.qml
index cf8f618..4cecad9 100644
--- a/sailfish/qml/pages/itemdetails/MusicAlbumPage.qml
+++ b/sailfish/qml/pages/itemdetails/MusicAlbumPage.qml
@@ -51,7 +51,7 @@ BaseDetailPage {
id: collectionModel
loader: J.UserItemsLoader {
apiClient: appWindow.apiClient
- sortBy: itemData.type === "MusicAlbum" ? "ParentIndexNumber,IndexNumber,SortName" : ""
+ sortBy: itemData.type === J.ItemType.MusicAlbum ? [J.SortBy.ParentIndexNumber, J.SortBy.IndexNumber,J.SortBy.SortName] : []
fields: [J.ItemFields.ItemCounts, J.ItemFields.PrimaryImageAspectRatio]
parentId: itemData.jellyfinId
autoReload: itemData.jellyfinId.length > 0
diff --git a/sailfish/qml/pages/itemdetails/MusicArtistPage.qml b/sailfish/qml/pages/itemdetails/MusicArtistPage.qml
index 48ce3e1..017630a 100644
--- a/sailfish/qml/pages/itemdetails/MusicArtistPage.qml
+++ b/sailfish/qml/pages/itemdetails/MusicArtistPage.qml
@@ -33,11 +33,11 @@ BaseDetailPage {
id: albumsModel
loader: J.UserItemsLoader {
apiClient: appWindow.apiClient
- sortBy: "PremiereDate,ProductionYear,SortName"
- sortOrder: "Descending"
+ sortBy: [J.SortBy.PremiereDate, J.SortBy.ProductionYear, J.SortBy.SortName]
+ sortOrder: [J.SortOrder.Descending]
fields: [J.ItemFields.ItemCounts, J.ItemFields.PrimaryImageAspectRatio]
- includeItemTypes: ["MusicAlbum"]
- albumArtistIds: itemData.jellyfinId
+ includeItemTypes: [J.ItemType.MusicAlbum]
+ albumArtistIds: [itemData.jellyfinId]
recursive: true
autoReload: itemData.jellyfinId.length > 0
limit: _maxItems
@@ -48,10 +48,10 @@ BaseDetailPage {
id: fullAlbumsModelComponent
J.UserItemsLoader {
apiClient: appWindow.apiClient
- sortBy: "PremiereDate,ProductionYear,SortName"
- sortOrder: "Descending"
+ sortBy: [J.SortBy.PremiereDate, J.SortBy.ProductionYear, J.SortBy.SortName]
+ sortOrder: [J.SortOrder.Descending]
fields: [J.ItemFields.ItemCounts, J.ItemFields.PrimaryImageAspectRatio]
- includeItemTypes: ["MusicAlbum"]
+ includeItemTypes: [J.ItemType.MusicAlbum]
albumArtistIds: itemData.jellyfinId
recursive: true
autoReload: false
@@ -62,10 +62,10 @@ BaseDetailPage {
id: appearsOnModel
loader: J.UserItemsLoader {
apiClient: appWindow.apiClient
- sortBy: "PremiereDate,ProductionYear,SortName"
- sortOrder: "Descending"
+ sortBy: [J.SortBy.PremiereDate, J.SortBy.ProductionYear, J.SortBy.SortName]
+ sortOrder: [J.SortOrder.Descending]
fields: [J.ItemFields.ItemCounts, J.ItemFields.PrimaryImageAspectRatio]
- includeItemTypes: ["MusicAlbum"]
+ includeItemTypes: [J.ItemType.MusicAlbum]
contributingArtistIds: itemData.jellyfinId
recursive: true
autoReload: itemData.jellyfinId.length > 0
@@ -76,10 +76,10 @@ BaseDetailPage {
id: fullAppearsOnModelComponent
J.UserItemsLoader {
apiClient: appWindow.apiClient
- sortBy: "PremiereDate,ProductionYear,SortName"
- sortOrder: "Descending"
+ sortBy: [J.SortBy.PremiereDate, J.SortBy.ProductionYear, J.SortBy.SortName]
+ sortOrder: [J.SortOrder.Descending]
fields: [J.ItemFields.ItemCounts, J.ItemFields.PrimaryImageAspectRatio]
- includeItemTypes: ["MusicAlbum"]
+ includeItemTypes: [J.ItemType.MusicAlbum]
contributingArtistIds: itemData.jellyfinId
recursive: true
autoReload: false
diff --git a/sailfish/qml/pages/itemdetails/MusicLibraryPage.qml b/sailfish/qml/pages/itemdetails/MusicLibraryPage.qml
index 965f488..7dbf95e 100644
--- a/sailfish/qml/pages/itemdetails/MusicLibraryPage.qml
+++ b/sailfish/qml/pages/itemdetails/MusicLibraryPage.qml
@@ -56,7 +56,7 @@ BaseDetailPage {
J.LatestMediaLoader {
apiClient: appWindow.apiClient
parentId: itemData.jellyfinId
- includeItemTypes: "Audio"
+ includeItemTypes: [J.ItemType.Audio]
autoReload: false
}
}
@@ -74,9 +74,9 @@ BaseDetailPage {
J.UserItemsLoader {
apiClient: appWindow.apiClient
parentId: itemData.jellyfinId
- includeItemTypes: "MusicAlbum"
+ includeItemTypes: [J.ItemType.MusicAlbum]
recursive: true
- sortBy: "SortName"
+ sortBy: [J.SortBy.SortName]
autoReload: false
}
}
@@ -85,9 +85,9 @@ BaseDetailPage {
J.UserItemsLoader {
apiClient: appWindow.apiClient
parentId: itemData.jellyfinId
- includeItemTypes: "Playlist"
+ includeItemTypes: [J.ItemType.Playlist]
recursive: true
- sortBy: "SortName"
+ sortBy: [J.SortBy.SortName]
autoReload: false
}
}
@@ -109,7 +109,7 @@ BaseDetailPage {
apiClient: appWindow.apiClient
parentId: itemData.jellyfinId
autoReload: _firstTimeLoaded && itemData.jellyfinId.length > 0
- includeItemTypes: "Audio"
+ includeItemTypes: [J.ItemType.Audio]
limit: 12
}
onHeaderClicked: pageStack.push(Qt.resolvedUrl("CollectionPage.qml"), {
@@ -128,9 +128,9 @@ BaseDetailPage {
loader: J.UserItemsLoader {
apiClient: appWindow.apiClient
parentId: itemData.jellyfinId
- includeItemTypes: "MusicAlbum"
+ includeItemTypes: [J.ItemType.MusicAlbum]
autoReload: _firstTimeLoaded && itemData.jellyfinId.length > 0
- sortBy: "Random"
+ sortBy: [J.SortBy.Random]
recursive: true
limit: 12
}
@@ -148,9 +148,9 @@ BaseDetailPage {
loader: J.UserItemsLoader {
apiClient: appWindow.apiClient
parentId: itemData.jellyfinId
- includeItemTypes: "Playlist"
+ includeItemTypes: [J.ItemType.Playlist]
autoReload: _firstTimeLoaded && itemData.jellyfinId.length > 0
- sortBy: "Random"
+ sortBy: [J.SortBy.Random]
recursive: true
limit: 12
}
diff --git a/sailfish/translations/harbour-sailfin-de.ts b/sailfish/translations/harbour-sailfin-de.ts
index a20e489..62255ba 100644
--- a/sailfish/translations/harbour-sailfin-de.ts
+++ b/sailfish/translations/harbour-sailfin-de.ts
@@ -110,7 +110,7 @@
-
+
Sort by
Menu item for selecting the sort order of a collection
@@ -126,28 +126,28 @@
-
+
Name
-
+
Play count
-
+
Date added
-
+
Ascending
Sort order
-
+
Descending
Sort order
@@ -268,14 +268,17 @@
LiveTvChannelPage
+
%1 | %2 - %3
+
Program info
+
No program info available
@@ -283,6 +286,7 @@
LiveTvChannelsPage
+
No program information available
Shown in the channel list when the name of the current program is unknown
@@ -362,12 +366,12 @@
-
+
Network error
-
+
Pull down to retry again
@@ -394,7 +398,7 @@
-
+
Disc %1
@@ -546,7 +550,7 @@ Page title for the list of all artists within the music library
QObject
-
+
Sailfin
Application display name
@@ -585,7 +589,7 @@ Placeholder text for textfield for entering the Quick Connect codeyy
SeasonPage
-
+
No overview available
No overview/summary text of an episode available
@@ -674,13 +678,13 @@ Placeholder text for textfield for entering the Quick Connect codeyy
SongDelegate
-
+
Go to %1
Context menu item for navigating to the artist of the selected track
-
+
Go to artists
Context menu item for navigating to one of the artists of the selected track (opens submenu)
@@ -801,7 +805,7 @@ This is still an alpha version :)
VideoPage
-
+
Run time: %2
diff --git a/sailfish/translations/harbour-sailfin-ru.ts b/sailfish/translations/harbour-sailfin-ru.ts
index a20e489..62255ba 100644
--- a/sailfish/translations/harbour-sailfin-ru.ts
+++ b/sailfish/translations/harbour-sailfin-ru.ts
@@ -110,7 +110,7 @@
-
+
Sort by
Menu item for selecting the sort order of a collection
@@ -126,28 +126,28 @@
-
+
Name
-
+
Play count
-
+
Date added
-
+
Ascending
Sort order
-
+
Descending
Sort order
@@ -268,14 +268,17 @@
LiveTvChannelPage
+
%1 | %2 - %3
+
Program info
+
No program info available
@@ -283,6 +286,7 @@
LiveTvChannelsPage
+
No program information available
Shown in the channel list when the name of the current program is unknown
@@ -362,12 +366,12 @@
-
+
Network error
-
+
Pull down to retry again
@@ -394,7 +398,7 @@
-
+
Disc %1
@@ -546,7 +550,7 @@ Page title for the list of all artists within the music library
QObject
-
+
Sailfin
Application display name
@@ -585,7 +589,7 @@ Placeholder text for textfield for entering the Quick Connect codeyy
SeasonPage
-
+
No overview available
No overview/summary text of an episode available
@@ -674,13 +678,13 @@ Placeholder text for textfield for entering the Quick Connect codeyy
SongDelegate
-
+
Go to %1
Context menu item for navigating to the artist of the selected track
-
+
Go to artists
Context menu item for navigating to one of the artists of the selected track (opens submenu)
@@ -801,7 +805,7 @@ This is still an alpha version :)
VideoPage
-
+
Run time: %2
diff --git a/sailfish/translations/harbour-sailfin.ts b/sailfish/translations/harbour-sailfin.ts
index a20e489..62255ba 100644
--- a/sailfish/translations/harbour-sailfin.ts
+++ b/sailfish/translations/harbour-sailfin.ts
@@ -110,7 +110,7 @@
-
+
Sort by
Menu item for selecting the sort order of a collection
@@ -126,28 +126,28 @@
-
+
Name
-
+
Play count
-
+
Date added
-
+
Ascending
Sort order
-
+
Descending
Sort order
@@ -268,14 +268,17 @@
LiveTvChannelPage
+
%1 | %2 - %3
+
Program info
+
No program info available
@@ -283,6 +286,7 @@
LiveTvChannelsPage
+
No program information available
Shown in the channel list when the name of the current program is unknown
@@ -362,12 +366,12 @@
-
+
Network error
-
+
Pull down to retry again
@@ -394,7 +398,7 @@
-
+
Disc %1
@@ -546,7 +550,7 @@ Page title for the list of all artists within the music library
QObject
-
+
Sailfin
Application display name
@@ -585,7 +589,7 @@ Placeholder text for textfield for entering the Quick Connect codeyy
SeasonPage
-
+
No overview available
No overview/summary text of an episode available
@@ -674,13 +678,13 @@ Placeholder text for textfield for entering the Quick Connect codeyy
SongDelegate
-
+
Go to %1
Context menu item for navigating to the artist of the selected track
-
+
Go to artists
Context menu item for navigating to one of the artists of the selected track (opens submenu)
@@ -801,7 +805,7 @@ This is still an alpha version :)
VideoPage
-
+
Run time: %2