diff --git a/PlaylistEntry.qml b/PlaylistEntry.qml index 82f8b43..01b7374 100644 --- a/PlaylistEntry.qml +++ b/PlaylistEntry.qml @@ -11,7 +11,7 @@ Item { property real _anim_n: 0 property real _anim2_n: 0 - property YPlaylist playlist + property var playlist signal play() signal pause() @@ -132,7 +132,7 @@ Item { horizontalAlignment: Text.AlignHCenter wrapMode: Text.WordWrap - text: playlist == null? qsTr("some playlist") : playlist.name + text: playlist == null? qsTr("Some playlist") : playlist.name MouseArea { id: _textMouse diff --git a/main.cpp b/main.cpp index d5fb3db..13ea556 100644 --- a/main.cpp +++ b/main.cpp @@ -66,6 +66,7 @@ int main(int argc, char *argv[]) qmlRegisterType("DMusic", 1, 0, "Clipboard"); qmlRegisterType("DMusic", 1, 0, "DFileDialog"); qmlRegisterType("DMusic", 1, 0, "YPlaylist"); + qmlRegisterType("DMusic", 1, 0, "YLikedTracks"); qmlRegisterSingletonType("DMusic", 1, 0, "Messages", &Messages::qmlInstance); qmlRegisterSingletonType("DMusic", 1, 0, "YClient", &YClient::qmlInstance); diff --git a/main.qml b/main.qml index ec294f4..4728344 100644 --- a/main.qml +++ b/main.qml @@ -54,7 +54,7 @@ Window { function afterLogin() { _userDailyPlaylist.playlist = YClient.userDailyPlaylist() - _userLikedPlaylist.playlist = YClient.userLikedTracksPlaylist() + _userLikedPlaylist.playlist = YClient.userLikedTracks() } function autologin() { @@ -242,7 +242,6 @@ Window { anchors.leftMargin: 25 anchors.topMargin: 25 -// onPlay: _player.player.play(YClient.playlist(3)) onPlay: YClient.playPlaylist(playlist) } diff --git a/qml.qrc b/qml.qrc index e7a781a..5aa0dc6 100644 --- a/qml.qrc +++ b/qml.qrc @@ -63,5 +63,6 @@ resources/player/like.svg resources/player/liked.svg Message.qml + resources/covers/like.png diff --git a/resources/covers/like.png b/resources/covers/like.png new file mode 100644 index 0000000..fcdc7f1 Binary files /dev/null and b/resources/covers/like.png differ diff --git a/translations/russian.ts b/translations/russian.ts index c2686a3..06f6e37 100644 --- a/translations/russian.ts +++ b/translations/russian.ts @@ -4,7 +4,7 @@ AudioPlayer - + Failed to load track Не удалось загрузить трек @@ -52,6 +52,14 @@ Не удалось инициализировать discord pressence + + PlaylistEntry + + + Some playlist + Какой-то плейлист + + QObject @@ -65,7 +73,7 @@ Ошибка автоматической установки модуля python '%1' - + DMusic - music player usage: %1 [options] @@ -111,30 +119,61 @@ usage: %1 [options] YClient - + Failed to initialize yandex music client Не удалось инициализировать клиент Яндекс.Музыки - + 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) - + Failed to load Yandex.Music daily playlist Не удалось загрузить плейлист дня Яндекс.Музыки + + YLikedTracks + + + Favorites + Мне нравится + + + + Failed to load Yandex.Music user liked tracks + Не удалось загрузить понравившиеся треки пользователя Яндекс.Музыки + + + + Yandex music api is not initialized + Api Яндекс.Музыки не инициализировано + + + Failed to load Yandex.Music user liked tracks (playlist with id 3) + Не удалось загрузить понравившиеся треки пользователя Яндекс.Музыки + + YTrack - + Failed to get Yandex.Music track media (id: %1) Не удалось загрузить медиа для трека Яндекс.Музыки (id: %1) - + Failed to load Yandex.Music track (id: %1) Не удалось загрузить трек Яндекс.Музыки (id: %1) @@ -142,72 +181,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 46d127d..83190bc 100644 --- a/yapi.cpp +++ b/yapi.cpp @@ -545,6 +545,95 @@ bool YArtist::saveCover(int quality) } +YPlaylist::YPlaylist(py::object impl, QObject* parent) : QObject(parent), impl(impl) +{ + +} + +YPlaylist::YPlaylist() +{ + +} + +QString YPlaylist::name() +{ + return impl.get("title").to(); +} + +QUrl YPlaylist::cover() +{ + try { + auto a = "http://" + impl.get("cover").get("uri").to(); + return QUrl(a.replace("%%", "m" + Settings::ym_coverQuality())); + } catch (py::error& e) { + return QUrl("qrc:resources/player/no-cover.svg"); + } +} + +refPlaylist YPlaylist::toPlaylist() +{ + DPlaylist* res = new DPlaylist(this); + auto a = impl.call("fetch_tracks"); + for (auto&& p : a) { + if (!p.has("id")) continue; + res->add(refTrack(new YTrack(p.get("id").to(), YClient::instance))); + } + return refPlaylist(res); +} + +bool YPlaylist::setName(QString name) +{ + Q_UNUSED(name) + // TODO + return false; +} + +bool YPlaylist::setCover(QUrl cover) +{ + Q_UNUSED(cover) + // TODO + return false; +} + +YLikedTracks::YLikedTracks(QObject* parent) : YPlaylist(py::none, parent) +{ + +} + +YLikedTracks* YLikedTracks::instance = new YLikedTracks; + +YLikedTracks* YLikedTracks::qmlInstance(QQmlEngine*, QJSEngine*) +{ + return instance; +} + +QString YLikedTracks::name() +{ + return tr("Favorites"); +} + +QUrl YLikedTracks::cover() +{ + return QUrl("qrc:/resources/covers/like.png"); +} + +refPlaylist YLikedTracks::toPlaylist() +{ + DPlaylist* res = new DPlaylist(this); + try { + if (!YClient::instance->initialized()) throw std::runtime_error(tr("Yandex music api is not initialized").toStdString()); + auto a = YClient::instance->me.call("users_likes_tracks").get("tracks_ids"); + for (auto&& p : a) { + if (!p.contains(":")) continue; + res->add(refTrack(new YTrack(p.call("split", ":")[0].to(), YClient::instance))); + } + } catch (std::exception& e) { + Messages::error(tr("Failed to load Yandex.Music user liked tracks"), e.what()); + } + return refPlaylist(res); +} + + YClient::~YClient() { if (instance == this) instance = nullptr; @@ -659,20 +748,14 @@ Playlist* YClient::likedTracks() res->add(track(p.call("split", ":")[0].to())); } } catch (py::error& e) { - Messages::error(tr("Failed to load Yandex.Music user liked tracks (playlist with id 3)"), e.what()); + Messages::error(tr("Failed to load Yandex.Music user liked tracks"), e.what()); } return res; } -YPlaylist* YClient::userLikedTracksPlaylist() +YLikedTracks* YClient::userLikedTracks() { - if (!initialized()) return nullptr; - try { - return new YPlaylist(me.call("playlists_list", me.get("me").get("account").get("uid").to() + ":" + QString::number(3))[0]); - } catch (py::error& e) { - Messages::error(tr("Failed to load Yandex.Music user liked tracks (playlist with id 3)"), e.what()); - } - return nullptr; + return YLikedTracks::instance; } Playlist* YClient::playlist(int id) @@ -751,53 +834,3 @@ void YClient::addUserTrack(QString media, QString cover, QString title, QString { UserTrack().setup(media, cover, title, artists, extra); } - -YPlaylist::YPlaylist(py::object impl, QObject* parent) : QObject(parent), impl(impl) -{ - -} - -YPlaylist::YPlaylist() -{ - -} - -QString YPlaylist::name() -{ - return impl.get("title").to(); -} - -QUrl YPlaylist::cover() -{ - try { - auto a = "http://" + impl.get("cover").get("uri").to(); - return QUrl(a.replace("%%", "m" + Settings::ym_coverQuality())); - } catch (py::error& e) { - return QUrl("qrc:resources/player/no-cover.svg"); - } -} - -refPlaylist YPlaylist::toPlaylist() -{ - DPlaylist* res = new DPlaylist(this); - auto a = impl.call("fetch_tracks"); - for (auto&& p : a) { - if (!p.has("id")) continue; - res->add(refTrack(new YTrack(p.get("id").to(), YClient::instance))); - } - return refPlaylist(res); -} - -bool YPlaylist::setName(QString name) -{ - Q_UNUSED(name) - // TODO - return false; -} - -bool YPlaylist::setCover(QUrl cover) -{ - Q_UNUSED(cover) - // TODO - return false; -} diff --git a/yapi.hpp b/yapi.hpp index a26c71b..b39ffa8 100644 --- a/yapi.hpp +++ b/yapi.hpp @@ -111,9 +111,9 @@ struct YPlaylist : QObject Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QUrl cover READ cover WRITE setCover NOTIFY coverChanged) - QString name(); - QUrl cover(); - refPlaylist toPlaylist(); + virtual QString name(); + virtual QUrl cover(); + virtual refPlaylist toPlaylist(); public slots: bool setName(QString name); @@ -129,6 +129,20 @@ public slots: inline PyObject* toPyObject(YPlaylist const& a) { Py_INCREF(a.raw()); return a.raw(); } inline void fromPyObject(py::object const& o, YPlaylist*& res) { res = new YPlaylist(o.raw); } +struct YLikedTracks : YPlaylist +{ + Q_OBJECT +public: + YLikedTracks(QObject* parent = nullptr); + + static YLikedTracks* instance; + static YLikedTracks* qmlInstance(QQmlEngine*, QJSEngine*); + + QString name() override; + QUrl cover() override; + refPlaylist toPlaylist() override; +}; + struct YClient : QObject { Q_OBJECT @@ -159,7 +173,7 @@ public slots: QVector fetchTracks(qint64 id); Playlist* likedTracks(); - YPlaylist* userLikedTracksPlaylist(); + YLikedTracks* userLikedTracks(); Playlist* playlist(int id); Playlist* oneTrack(qint64 id); YPlaylist* userDailyPlaylist(); @@ -173,12 +187,13 @@ public slots: signals: void initializedChanged(bool initialized); -private: +public: py::module ym; // yandex_music module py::module ym_request; py::object me; // client +private: bool _initialized = false; std::atomic_bool loggined = false; };