File indexing completed on 2024-05-12 16:21:17
0001 // SPDX-FileCopyrightText: 2021 Jonah Brüchert <jbb@kaidan.im> 0002 // 0003 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 0005 #include <QApplication> 0006 #include <QQmlApplicationEngine> 0007 #include <QtQml> 0008 #include <QSortFilterProxyModel> 0009 #include <QUrl> 0010 #include <QQuickWindow> 0011 #include <QQuickStyle> 0012 #include <QStyle> 0013 #include <QStyleFactory> 0014 0015 #include <KLocalizedContext> 0016 #include <KLocalizedString> 0017 #include <KCrash> 0018 #include <KAboutData> 0019 0020 #include <mprisplugin.h> 0021 0022 #include "clipboard.h" 0023 #include "searchmodel.h" 0024 #include "albummodel.h" 0025 #include "videoinfoextractor.h" 0026 #include "artistmodel.h" 0027 #include "userplaylistmodel.h" 0028 #include "errorhandler.h" 0029 #include "playlistmodel.h" 0030 #include "playerutils.h" 0031 #include "library.h" 0032 #include "thumbnailsource.h" 0033 #include "blur.h" 0034 #include "localplaylistmodel.h" 0035 #include "localplaylistsmodel.h" 0036 #include "playlistimporter.h" 0037 0038 #include <ThreadedDatabase> 0039 0040 constexpr auto URI = "org.kde.ytmusic"; 0041 0042 Q_DECL_EXPORT int main(int argc, char *argv[]) 0043 { 0044 QApplication app(argc, argv); 0045 0046 // set default style and icon theme 0047 QIcon::setFallbackThemeName(QStringLiteral("breeze")); 0048 if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE") && QQuickStyle::name().isEmpty()) { 0049 QQuickStyle::setStyle(QStringLiteral("org.kde.desktop")); 0050 QApplication::setStyle(QStyleFactory::create(QStringLiteral("Breeze"))); 0051 } 0052 0053 // WORKAROUND: Force QtMultimedia gstreamer backend 0054 /* 0055 ffmpeg unfortunately loses the connection to youtube's servers with the following error message after ~2 minutes 0056 at the time of writing (2023-10-29 with ffmpeg 6.0 and Qt 6.6.1) 0057 [tls @ 0x561f31d3d500] Error in the pull function. 0058 [tls @ 0x561f31d3d500] IO error: Connection reset by peer 0059 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x561f3225e000] Packet corrupt (stream = 0, dts = 4590016). 0060 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x561f3225e000] stream 0, offset 0x19c06c: partial file 0061 [aac @ 0x561f3244bc00] Input buffer exhausted before END element found 0062 */ 0063 qputenv("QT_MEDIA_BACKEND", "gstreamer"); 0064 0065 QCoreApplication::setOrganizationName(QStringLiteral("KDE")); 0066 QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org")); 0067 QCoreApplication::setApplicationName(QStringLiteral("audiotube")); 0068 0069 KLocalizedString::setApplicationDomain("audiotube"); 0070 0071 KAboutData about(QStringLiteral("audiotube"), 0072 i18n("AudioTube"), 0073 QStringLiteral(AUDIOTUBE_VERSION_STRING), 0074 i18nc("YouTube Music is a music streaming service by Google", "Stream music from YouTube Music"), 0075 KAboutLicense::GPL_V3, 0076 i18n("© 2021-2023 Jonah Brüchert, 2021-2023 KDE Community")); 0077 about.addAuthor(i18n("Jonah Brüchert"), i18n("Maintainer"), QStringLiteral("jbb@kaidan.im")); 0078 about.addAuthor(i18n("Mathis Brüchert"), i18n("Designer"), QStringLiteral("mbb@kaidan.im")); 0079 about.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails")); 0080 about.setOrganizationDomain("kde.org"); 0081 about.setBugAddress("https://bugs.kde.org/describecomponents.cgi?product=audiotube"); 0082 auto future = YTMusicThread::instance()->version(); 0083 QCoro::connect(std::move(future), &app, [&about](const auto &version) { 0084 about.addComponent(QStringLiteral("ytmusicapi"), 0085 i18nc("YouTube Music is a music streaming service by Google", 0086 "Unofficial API for YouTube Music"), 0087 version); 0088 KAboutData::setApplicationData(about); 0089 }); 0090 0091 QGuiApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("org.kde.audiotube"))); 0092 0093 KCrash::initialize(); 0094 0095 QQmlApplicationEngine engine; 0096 0097 MprisPlugin(&engine).registerTypes("org.nemomobile.qtmpris"); 0098 0099 qmlRegisterType<SearchModel>(URI, 1, 0, "SearchModel"); 0100 qmlRegisterType<AlbumModel>(URI, 1, 0, "AlbumModel"); 0101 qmlRegisterType<VideoInfoExtractor>(URI, 1, 0, "VideoInfoExtractor"); 0102 qmlRegisterType<ArtistModel>(URI, 1, 0, "ArtistModel"); 0103 qmlRegisterType<PlaylistModel>(URI, 1, 0, "PlaylistModel"); 0104 qmlRegisterUncreatableType<PlaybackHistoryModel>(URI, 1, 0, "PlaybackHistoryModel",""); 0105 qmlRegisterType<QSortFilterProxyModel>(URI, 1, 0, "SortFilterModel"); 0106 qmlRegisterType<Blur>(URI, 1, 0, "Blur"); 0107 qmlRegisterType<LocalSearchModel>(URI, 1, 0, "LocalSearchModel"); 0108 qmlRegisterType<LocalPlaylistModel>(URI, 1, 0, "LocalPlaylistModel"); 0109 qmlRegisterType<LocalPlaylistsModel>(URI, 1, 0, "LocalPlaylistsModel"); 0110 qmlRegisterType<PlaylistImporter>(URI, 1, 0, "PlaylistImporter"); 0111 qmlRegisterSingletonType(URI, 1, 0, "About", [](QQmlEngine *engine, QJSEngine *) -> QJSValue { 0112 return engine->toScriptValue(KAboutData::applicationData()); 0113 }); 0114 0115 qmlRegisterSingletonType<UserPlaylistModel>(URI, 1, 0, "UserPlaylistModel", [](QQmlEngine *, QJSEngine *) { 0116 return new UserPlaylistModel(); 0117 }); 0118 qmlRegisterSingletonType<ErrorHandler>(URI, 1, 0, "ErrorHandler", [](QQmlEngine *, QJSEngine *) { 0119 return new ErrorHandler(); 0120 }); 0121 0122 qmlRegisterSingletonType<PlayerUtils>(URI, 1, 0, "PlayerUtils", [](QQmlEngine *, QJSEngine *) { 0123 return new PlayerUtils(); 0124 }); 0125 qmlRegisterSingletonType<Clipboard>(URI, 1, 0, "Clipboard", [](QQmlEngine *, QJSEngine *) { 0126 return new Clipboard(); 0127 }); 0128 0129 qmlRegisterSingletonInstance<Library>(URI, 1, 0, "Library", &Library::instance()); 0130 qmlRegisterType<ThumbnailSource>(URI, 1, 0, "ThumbnailSource"); 0131 qmlRegisterAnonymousType<FavouriteWatcher>(URI, 1); 0132 qmlRegisterAnonymousType<WasPlayedWatcher>(URI, 1); 0133 0134 engine.rootContext()->setContextObject(new KLocalizedContext(&engine)); 0135 engine.load(QUrl(QStringLiteral("qrc:///main.qml"))); 0136 0137 if (engine.rootObjects().isEmpty()) { 0138 return -1; 0139 } 0140 0141 return app.exec(); 0142 }