diff --git a/ID.cpp b/ID.cpp index 195c0d8..55f915f 100644 --- a/ID.cpp +++ b/ID.cpp @@ -72,7 +72,7 @@ refPlaylist ID::toPlaylist() const if (client == ckYandex) { if (YClient::instance == nullptr) return nullptr; if (id == -1) return YClient::instance->userDailyPlaylist()->toPlaylist(); - return refPlaylist(YClient::instance->playlist(id)); + return nullptr; } if (client == ckNone) { if (YClient::instance == nullptr) return nullptr; diff --git a/main.cpp b/main.cpp index 13ea556..d957404 100644 --- a/main.cpp +++ b/main.cpp @@ -67,6 +67,7 @@ int main(int argc, char *argv[]) qmlRegisterType("DMusic", 1, 0, "DFileDialog"); qmlRegisterType("DMusic", 1, 0, "YPlaylist"); qmlRegisterType("DMusic", 1, 0, "YLikedTracks"); + qmlRegisterType("DMusic", 1, 0, "YPlaylistsModel"); qmlRegisterSingletonType("DMusic", 1, 0, "Messages", &Messages::qmlInstance); qmlRegisterSingletonType("DMusic", 1, 0, "YClient", &YClient::qmlInstance); diff --git a/main.qml b/main.qml index 4728344..f891077 100644 --- a/main.qml +++ b/main.qml @@ -53,8 +53,7 @@ Window { } function afterLogin() { - _userDailyPlaylist.playlist = YClient.userDailyPlaylist() - _userLikedPlaylist.playlist = YClient.userLikedTracks() + _yandexHomePlaylistsRepeater.model = YClient.homePlaylistsModel() } function autologin() { @@ -235,24 +234,22 @@ Window { else if (event.key == Qt.Key_A) _player.prev() } - PlaylistEntry { - id: _userLikedPlaylist + Row { + id: _yandexHomePlaylists + spacing: 25 anchors.left: root.left anchors.top: _title.bottom anchors.leftMargin: 25 anchors.topMargin: 25 - onPlay: YClient.playPlaylist(playlist) - } - - PlaylistEntry { - id: _userDailyPlaylist - anchors.left: _userLikedPlaylist.right - anchors.top: _title.bottom - anchors.leftMargin: 25 - anchors.topMargin: 25 + Repeater { + id: _yandexHomePlaylistsRepeater + PlaylistEntry { + playlist: element - onPlay: YClient.playPlaylist(playlist) + onPlay: YClient.playPlaylist(playlist) + } + } } ListModel { diff --git a/translations/russian.ts b/translations/russian.ts index 06f6e37..a4e70e3 100644 --- a/translations/russian.ts +++ b/translations/russian.ts @@ -119,26 +119,34 @@ usage: %1 [options] YClient - + Failed to initialize yandex music client Не удалось инициализировать клиент Яндекс.Музыки + + + Failed to load one of Yandex.Music smart playlists + Не удалось загрузить один из умных плейлистов Яндекс.Музыки + + + + Failed to load Yandex.Music smart playlists + Не удалось загрузить умные плейлисты Яндекс.Музыки + Failed to load Yandex.Music user liked tracks (playlist with id 3) Не удалось загрузить понравившиеся треки пользователя Яндекс.Музыки - Failed to load Yandex.Music user liked tracks - Не удалось загрузить понравившиеся треки пользователя Яндекс.Музыки + Не удалось загрузить понравившиеся треки пользователя Яндекс.Музыки - Failed to load Yandex.Music playlist (id: %1) - Не удалось загрузить плейлист Яндекс.Музыки (id: %1) + Не удалось загрузить плейлист Яндекс.Музыки (id: %1) - + Failed to load Yandex.Music daily playlist Не удалось загрузить плейлист дня Яндекс.Музыки @@ -146,17 +154,17 @@ usage: %1 [options] YLikedTracks - + Favorites Мне нравится - + Failed to load Yandex.Music user liked tracks Не удалось загрузить понравившиеся треки пользователя Яндекс.Музыки - + Yandex music api is not initialized Api Яндекс.Музыки не инициализировано @@ -168,12 +176,12 @@ usage: %1 [options] YTrack - + Failed to get Yandex.Music track media (id: %1) Не удалось загрузить медиа для трека Яндекс.Музыки (id: %1) - + Failed to load Yandex.Music track (id: %1) Не удалось загрузить трек Яндекс.Музыки (id: %1) @@ -181,72 +189,72 @@ usage: %1 [options] main - + Play Play button Прослушать - + Play playlist Прослушать плейлист - + ID - + Play downloaded Прослушать скачанное - + Play custom Прослушать добавленный - + Title Заголовок - + Artists Авторы - + Extra Дополнительная информация - - + + Chose media Выберите медиафайл - - + + Audio (*.mp3 *.wav *.ogg *.m4a) Звук (*.mp3 *.wav *.ogg *.m4a) - - + + Chose cover Выберите обложку - - + + Image (*.jpg *.png *.svg) Изображение (*.jpg *.png *.svg) - + Add custom track Добавить трек diff --git a/yapi.cpp b/yapi.cpp index 83190bc..a757653 100644 --- a/yapi.cpp +++ b/yapi.cpp @@ -81,16 +81,15 @@ void repeat_if_error_async(std::function f, std::function(); - _client = client; + _fetchYandex(obj); } YTrack::~YTrack() @@ -335,7 +334,7 @@ void YTrack::_fetchYandex() { QMutexLocker lock(&_mtx); if (_py != py::none) return; - auto _pys = _client->fetchTracks(_id); + auto _pys = YClient::instance->fetchTracks(_id); if (_pys.empty()) { _fetchYandex(none); } else { @@ -736,44 +735,16 @@ QVector YClient::fetchTracks(qint64 id) return tracks; } -Playlist* YClient::likedTracks() -{ - DPlaylist* res = new DPlaylist(this); - if (!initialized()) return res; - - try { - auto a = me.call("users_likes_tracks").get("tracks_ids"); - for (auto&& p : a) { - if (!p.contains(":")) continue; - res->add(track(p.call("split", ":")[0].to())); - } - } catch (py::error& e) { - Messages::error(tr("Failed to load Yandex.Music user liked tracks"), e.what()); - } - return res; -} - -YLikedTracks* YClient::userLikedTracks() +YLikedTracks* YClient::likedTracks() { return YLikedTracks::instance; } -Playlist* YClient::playlist(int id) +YPlaylist* YClient::playlist(int id) { if (id == 3) return likedTracks(); - DPlaylist* res = new DPlaylist(this); - if (!initialized()) return res; - - try { - auto a = me.call("playlists_list", me.get("me").get("account").get("uid").to() + ":" + QString::number(id))[0].call("fetch_tracks"); - for (auto&& p : a) { - if (!p.has("id")) continue; - res->add(track(p.get("id").to())); - } - } catch (py::error& e) { - Messages::error(tr("Failed to load Yandex.Music playlist (id: %1)").arg(id), e.what()); - } - return res; + if (!initialized()) return nullptr; + return new YPlaylist(me.call("playlists_list", me.get("me").get("account").get("uid").to() + ":" + QString::number(id))[0]); } Playlist* YClient::oneTrack(qint64 id) @@ -824,6 +795,25 @@ Playlist* YClient::downloadsPlaylist() return res; } +YPlaylistsModel* YClient::homePlaylistsModel() +{ + auto res = new YPlaylistsModel(this); + if (!initialized()) return res; + res->playlists.append(likedTracks()); + try { + for (auto&& p : me.call("landing", std::vector{"personalplaylists"}).get("blocks")[0].get("entities")) { + try { + res->playlists.append(new YPlaylist(p.get("data").get("data"))); + } catch (py::error& e) { + Messages::error(tr("Failed to load one of Yandex.Music smart playlists"), e.what()); + } + } + } catch (py::error& e) { + Messages::error(tr("Failed to load Yandex.Music smart playlists"), e.what()); + } + return res; +} + void YClient::playPlaylist(YPlaylist* playlist) { if (playlist == nullptr) return; @@ -834,3 +824,32 @@ void YClient::addUserTrack(QString media, QString cover, QString title, QString { UserTrack().setup(media, cover, title, artists, extra); } + +YPlaylistsModel::YPlaylistsModel(QObject* parent) : QAbstractListModel(parent) +{ + +} + +int YPlaylistsModel::rowCount(const QModelIndex&) const +{ + return playlists.length(); +} + +QVariant YPlaylistsModel::data(const QModelIndex& index, int) const +{ + if (index.row() >= playlists.length()) return QVariant::Invalid; + QVariant res; + res.setValue(playlists[index.row()]); + return res; +} + + +QHash YPlaylistsModel::roleNames() const +{ + static QHash* pHash = nullptr; + if (!pHash) { + pHash = new QHash; + (*pHash)[Qt::UserRole + 1] = "element"; + } + return *pHash; +} diff --git a/yapi.hpp b/yapi.hpp index b39ffa8..087f095 100644 --- a/yapi.hpp +++ b/yapi.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "python.hpp" #include "api.hpp" @@ -14,8 +15,8 @@ struct YTrack : Track { Q_OBJECT public: - YTrack(qint64 id, YClient* client); - YTrack(py::object obj, YClient* client); + YTrack(qint64 id, QObject* parent = nullptr); + YTrack(py::object obj, QObject* parent = nullptr); ~YTrack(); YTrack(QObject* parent = nullptr); @@ -41,8 +42,6 @@ struct YTrack : Track QString stringMetadata(); void saveMetadata(); - YClient* _client; - public slots: void setLiked(bool liked) override; @@ -143,6 +142,18 @@ struct YLikedTracks : YPlaylist refPlaylist toPlaylist() override; }; +struct YPlaylistsModel : QAbstractListModel +{ + Q_OBJECT +public: + YPlaylistsModel(QObject* parent = nullptr); + int rowCount(const QModelIndex& parent) const override; + QVariant data(const QModelIndex& index, int role) const override; + QHash roleNames() const override; + + QVector playlists; +}; + struct YClient : QObject { Q_OBJECT @@ -172,13 +183,13 @@ public slots: QVector fetchTracks(qint64 id); - Playlist* likedTracks(); - YLikedTracks* userLikedTracks(); - Playlist* playlist(int id); + YLikedTracks* likedTracks(); + YPlaylist* playlist(int id); Playlist* oneTrack(qint64 id); YPlaylist* userDailyPlaylist(); Playlist* userTrack(int id); Playlist* downloadsPlaylist(); + YPlaylistsModel* homePlaylistsModel(); void playPlaylist(YPlaylist* playlist);