diff --git a/src/albummodel.cpp b/src/albummodel.cpp index 265b9f67..f66745a0 100644 --- a/src/albummodel.cpp +++ b/src/albummodel.cpp @@ -11,9 +11,9 @@ AlbumModel::AlbumModel(QObject *parent) { connect(this, &AlbumModel::browseIdChanged, this, [=] { setLoading(true); - AsyncYTMusic::instance().fetchAlbum(m_browseId); + YTMusicThread::instance()->fetchAlbum(m_browseId); }); - connect(&AsyncYTMusic::instance(), &AsyncYTMusic::fetchAlbumFinished, this, [=](const album::Album &album) { + connect(&YTMusicThread::instance().get(), &AsyncYTMusic::fetchAlbumFinished, this, [=](const album::Album &album) { setLoading(false); beginResetModel(); @@ -25,7 +25,7 @@ AlbumModel::AlbumModel(QObject *parent) Q_EMIT thumbnailUrlChanged(); Q_EMIT playlistIdChanged(); }); - connect(&AsyncYTMusic::instance(), &AsyncYTMusic::errorOccurred, this, [=] { + connect(&YTMusicThread::instance().get(), &AsyncYTMusic::errorOccurred, this, [=] { setLoading(false); }); } diff --git a/src/artistmodel.cpp b/src/artistmodel.cpp index 97bfd83a..51437831 100644 --- a/src/artistmodel.cpp +++ b/src/artistmodel.cpp @@ -18,9 +18,9 @@ ArtistModel::ArtistModel(QObject *parent) setLoading(true); - AsyncYTMusic::instance().fetchArtist(m_channelId); + YTMusicThread::instance()->fetchArtist(m_channelId); }); - connect(&AsyncYTMusic::instance(), &AsyncYTMusic::fetchArtistFinished, this, [=](const artist::Artist &artist) { + connect(&YTMusicThread::instance().get(), &AsyncYTMusic::fetchArtistFinished, this, [=](const artist::Artist &artist) { setLoading(false); beginResetModel(); @@ -31,7 +31,7 @@ ArtistModel::ArtistModel(QObject *parent) Q_EMIT titleChanged(); Q_EMIT thumbnailUrlChanged(); }); - connect(&AsyncYTMusic::instance(), &AsyncYTMusic::errorOccurred, this, [=] { + connect(&YTMusicThread::instance().get(), &AsyncYTMusic::errorOccurred, this, [=] { setLoading(false); }); } diff --git a/src/asyncytmusic.cpp b/src/asyncytmusic.cpp index 26730278..482fac5f 100644 --- a/src/asyncytmusic.cpp +++ b/src/asyncytmusic.cpp @@ -12,11 +12,6 @@ namespace py = pybind11; -static QThread *const ytmthread = []() -> QThread * { - auto *thread = new QThread(); - thread->setObjectName(QStringLiteral("YTMusicAPI")); - return thread; -}(); AsyncYTMusic::AsyncYTMusic(QObject *parent) : QObject(parent) @@ -47,25 +42,6 @@ AsyncYTMusic::AsyncYTMusic(QObject *parent) }); } -AsyncYTMusic &AsyncYTMusic::instance() -{ - static AsyncYTMusic &inst = []() -> AsyncYTMusic& { - static AsyncYTMusic ytm; - ytm.moveToThread(ytmthread); - ytmthread->start(); - - return ytm; - }(); - - return inst; -} - -void AsyncYTMusic::stopInstance() -{ - ytmthread->quit(); - ytmthread->wait(); -} - // // search // @@ -214,3 +190,32 @@ void AsyncYTMusic::internalFetchWatchPlaylist(const std::optional &vide Q_EMIT errorOccurred(QString::fromLocal8Bit(err.what())); } } + +YTMusicThread &YTMusicThread::instance() +{ + static YTMusicThread thread; + return thread; +} + +YTMusicThread::~YTMusicThread() +{ + quit(); + wait(); +} + +AsyncYTMusic *YTMusicThread::operator->() +{ + return &m_ytm; +} + +AsyncYTMusic &YTMusicThread::get() +{ + return m_ytm; +} + +YTMusicThread::YTMusicThread() +{ + setObjectName(QStringLiteral("YTMusicAPI")); + m_ytm.moveToThread(this); + start(); +} diff --git a/src/asyncytmusic.h b/src/asyncytmusic.h index 1da41680..1f46e97c 100644 --- a/src/asyncytmusic.h +++ b/src/asyncytmusic.h @@ -46,20 +46,11 @@ private: class AsyncYTMusic : public QObject { + friend class YTMusicThread; + Q_OBJECT public: - explicit AsyncYTMusic(QObject *parent = nullptr); - - /// - /// Singleton instance of AsyncYtMusic running on it's own thread. - /// - /// It is necessary t call stopInstance before the application exits, - /// so the thread can properly finish. - /// - static AsyncYTMusic &instance(); - static void stopInstance(); - // public functions need to be thread safe void search(const QString &query); Q_SIGNAL void searchFinished(std::vector); @@ -88,6 +79,9 @@ public: Q_SIGNAL void errorOccurred(const QString &error); +protected: + explicit AsyncYTMusic(QObject *parent = nullptr); + private: Q_SIGNAL void startSearch(const QString &query); Q_SLOT void internalSearch(const QString &query); @@ -115,3 +109,17 @@ private: Lazy m_ytm; }; + +class YTMusicThread : private QThread { +public: + static YTMusicThread &instance(); + ~YTMusicThread(); + + AsyncYTMusic *operator->(); + AsyncYTMusic &get(); + +private: + YTMusicThread(); + + AsyncYTMusic m_ytm; +}; diff --git a/src/errorhandler.cpp b/src/errorhandler.cpp index 75dbca61..fbd4d5b4 100644 --- a/src/errorhandler.cpp +++ b/src/errorhandler.cpp @@ -9,5 +9,5 @@ ErrorHandler::ErrorHandler(QObject *parent) : QObject(parent) { - connect(&AsyncYTMusic::instance(), &AsyncYTMusic::errorOccurred, this, &ErrorHandler::errorOccurred); + connect(&YTMusicThread::instance().get(), &AsyncYTMusic::errorOccurred, this, &ErrorHandler::errorOccurred); } diff --git a/src/main.cpp b/src/main.cpp index 63a35a07..22cf6a7f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,7 +45,5 @@ Q_DECL_EXPORT int main(int argc, char *argv[]) return -1; } - int ret = app.exec(); - AsyncYTMusic::stopInstance(); - return ret; + return app.exec(); } diff --git a/src/playlistmodel.cpp b/src/playlistmodel.cpp index 12129455..60a01372 100644 --- a/src/playlistmodel.cpp +++ b/src/playlistmodel.cpp @@ -15,7 +15,7 @@ PlaylistModel::PlaylistModel(QObject *parent) } setLoading(true); - AsyncYTMusic::instance().fetchWatchPlaylist(m_initialVideoId); + YTMusicThread::instance()->fetchWatchPlaylist(m_initialVideoId); }); connect(this, &PlaylistModel::playlistIdChanged, this, [=] { if (m_playlistId.isEmpty()) { @@ -23,9 +23,9 @@ PlaylistModel::PlaylistModel(QObject *parent) } setLoading(true); - AsyncYTMusic::instance().fetchWatchPlaylist(std::nullopt, m_playlistId); + YTMusicThread::instance()->fetchWatchPlaylist(std::nullopt, m_playlistId); }); - connect(&AsyncYTMusic::instance(), &AsyncYTMusic::fetchWatchPlaylistFinished, this, [=](const watch::Playlist &playlist) { + connect(&YTMusicThread::instance().get(), &AsyncYTMusic::fetchWatchPlaylistFinished, this, [=](const watch::Playlist &playlist) { setLoading(false); beginResetModel(); @@ -37,7 +37,7 @@ PlaylistModel::PlaylistModel(QObject *parent) Q_EMIT currentVideoIdChanged(); }); - connect(&AsyncYTMusic::instance(), &AsyncYTMusic::errorOccurred, this, [=] { + connect(&YTMusicThread::instance().get(), &AsyncYTMusic::errorOccurred, this, [=] { setLoading(false); }); } diff --git a/src/searchmodel.cpp b/src/searchmodel.cpp index e82f2962..2a2e38c5 100644 --- a/src/searchmodel.cpp +++ b/src/searchmodel.cpp @@ -18,15 +18,15 @@ SearchModel::SearchModel(QObject *parent) } setLoading(true); - AsyncYTMusic::instance().search(m_searchQuery); + YTMusicThread::instance()->search(m_searchQuery); }); - connect(&AsyncYTMusic::instance(), &AsyncYTMusic::searchFinished, this, [=](const std::vector &results) { + connect(&YTMusicThread::instance().get(), &AsyncYTMusic::searchFinished, this, [=](const std::vector &results) { beginResetModel(); setLoading(false); m_searchResults = results; endResetModel(); }); - connect(&AsyncYTMusic::instance(), &AsyncYTMusic::errorOccurred, this, [=] { + connect(&YTMusicThread::instance().get(), &AsyncYTMusic::errorOccurred, this, [=] { setLoading(false); }); } diff --git a/src/videoinfoextractor.cpp b/src/videoinfoextractor.cpp index a7f6c967..1f956273 100644 --- a/src/videoinfoextractor.cpp +++ b/src/videoinfoextractor.cpp @@ -17,10 +17,10 @@ VideoInfoExtractor::VideoInfoExtractor(QObject *parent) } setLoading(true); - AsyncYTMusic::instance().extractVideoInfo(QString::fromStdString(m_videoId.toStdString())); + YTMusicThread::instance()->extractVideoInfo(QString::fromStdString(m_videoId.toStdString())); }); - connect(&AsyncYTMusic::instance(), &AsyncYTMusic::extractVideoInfoFinished, this, [=](const video_info::VideoInfo &info) { + connect(&YTMusicThread::instance().get(), &AsyncYTMusic::extractVideoInfoFinished, this, [=](const video_info::VideoInfo &info) { m_videoInfo = info; setLoading(false); Q_EMIT audioUrlChanged();