diff --git a/CMakeLists.txt b/CMakeLists.txt index 457c4c3..6f2cfd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,97 +1,97 @@ cmake_minimum_required(VERSION 3.0) -set(VVAVE_VERSION 1.1.0) +set(VVAVE_VERSION 1.1.1) project(vvave VERSION ${VVAVE_VERSION}) find_package(ECM 1.7.0 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${ECM_MODULE_PATH}) set(CMAKE_CXX_STANDARD 17) find_package(MauiKit REQUIRED) find_package(Qt5 REQUIRED NO_MODULE COMPONENTS Qml Quick Network WebSockets Sql QuickControls2 Xml Multimedia DBus Svg WebView) find_package(KF5 ${KF5_VERSION} REQUIRED COMPONENTS I18n Notifications Config KIO Attica SyntaxHighlighting) include(KDEInstallDirs) include(KDECompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) include(ECMInstallIcons) include(ECMAddAppIcon) include(ECMSetupVersion) include(FeatureSummary) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTORCC ON) include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/services/web ${CMAKE_CURRENT_BINARY_DIR}/services/web ) add_executable(vvave qml.qrc main.cpp vvave.cpp # pulpo/services/geniusService.cpp # pulpo/services/deezerService.cpp pulpo/services/lastfmService.cpp # pulpo/services/lyricwikiaService.cpp # pulpo/services/spotifyService.cpp # pulpo/services/musicbrainzService.cpp pulpo/pulpo.cpp pulpo/htmlparser.cpp pulpo/service.cpp services/local/taginfo.cpp services/local/player.cpp services/local/youtubedl.cpp # services/local/linking.cpp # services/local/socket.cpp services/web/youtube.cpp services/web/NextCloud/nextmusic.cpp services/web/abstractmusicprovider.cpp # services/web/Spotify/spotify.cpp db/collectionDB.cpp # utils/brain.cpp models/tracks/tracksmodel.cpp models/playlists/playlistsmodel.cpp models/albums/albumsmodel.cpp models/cloud/cloud.cpp ) ecm_setup_version(${VVAVE_VERSION} VARIABLE_PREFIX VVAVE VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/vvave_version.h" ) if (ANDROID) find_package(Qt5 REQUIRED COMPONENTS AndroidExtras WebView Xml) find_package(OpenSSL REQUIRED) include(ExternalProject) externalproject_add(taglib URL http://taglib.org/releases/taglib-1.11.1.tar.gz CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} ) set(TAGLIB_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/include ${CMAKE_INSTALL_PREFIX}/include/taglib) set(TAGLIB_LIBRARIES ${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/libtag.a) target_link_libraries(vvave MauiKit Qt5::AndroidExtras Qt5::WebView Qt5::Xml OpenSSL::SSL) add_dependencies(vvave taglib) kde_source_files_enable_exceptions(vvave) else() find_package(Taglib REQUIRED) target_sources(vvave PRIVATE kde/mpris2.cpp kde/notify.cpp ) target_link_libraries(vvave Qt5::WebView KF5::ConfigCore KF5::Notifications KF5::KIOCore KF5::I18n Qt5::DBus KF5::Attica KF5::SyntaxHighlighting) endif() target_include_directories(vvave PRIVATE ${TAGLIB_INCLUDE_DIRS}) target_link_libraries(vvave MauiKit Qt5::Network Qt5::Sql Qt5::WebSockets Qt5::Qml Qt5::Xml Qt5::Multimedia Qt5::QuickControls2 ${TAGLIB_LIBRARIES}) install(TARGETS vvave ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES org.kde.vvave.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) #TODO: port to ecm_install_icons() install(FILES assets/vvave.svg DESTINATION ${KDE_INSTALL_ICONDIR}/hicolor/scalable/apps) install(FILES org.kde.vvave.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..e36f7f0 Binary files /dev/null and b/logo.png differ diff --git a/main.cpp b/main.cpp index e337c3a..1d1d88f 100644 --- a/main.cpp +++ b/main.cpp @@ -1,147 +1,159 @@ #include #include #include #include #include #ifdef STATIC_KIRIGAMI #include "3rdparty/kirigami/src/kirigamiplugin.h" #endif #ifdef STATIC_MAUIKIT #include "3rdparty/mauikit/src/mauikit.h" #include "fmstatic.h" #include "mauiapp.h" #else #include #include #endif #if defined Q_OS_ANDROID || defined Q_OS_IOS #include #include #else #include #endif #ifdef Q_OS_ANDROID #include "mauiandroid.h" #endif #ifdef Q_OS_MACOS #include "mauimacos.h" #endif +#ifdef Q_OS_WIN +#include +#else +#include +#endif + #include "vvave.h" #include "utils/bae.h" #include "services/web/youtube.h" #include "services/local/player.h" #include "models/tracks/tracksmodel.h" #include "models/albums/albumsmodel.h" #include "models/playlists/playlistsmodel.h" #include "models/cloud/cloud.h" #ifdef Q_OS_ANDROID Q_DECL_EXPORT #endif int main(int argc, char *argv[]) { - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#if defined Q_OS_LINUX || defined Q_OS_ANDROID + QtWebView::initialize(); +#else + QtWebEngine::initialize(); +#endif #ifdef Q_OS_WIN32 qputenv("QT_MULTIMEDIA_PREFERRED_PLUGINS", "w"); #endif #if defined Q_OS_ANDROID | defined Q_OS_IOS QGuiApplication app(argc, argv); #else QApplication app(argc, argv); #endif #ifdef Q_OS_ANDROID if (!MAUIAndroid::checkRunTimePermissions({"android.permission.WRITE_EXTERNAL_STORAGE"})) return -1; #endif app.setApplicationName(BAE::appName); app.setApplicationVersion(BAE::version); app.setApplicationDisplayName(BAE::displayName); app.setOrganizationName(BAE::orgName); app.setOrganizationDomain(BAE::orgDomain); app.setWindowIcon(QIcon("qrc:/assets/vvave.png")); MauiApp::instance()->setCredits ({QVariantMap({{"name", "Camilo Higuita"}, {"email", "milo.h@aol.com"}, {"year", "2019-2020"}})}); MauiApp::instance()->setIconName("qrc:/assets/vvave.svg"); MauiApp::instance()->setDescription("VVAVE will handle your whole music collection by retreaving semantic information from the web. Just relax, enjoy and discover your new music "); MauiApp::instance()->setWebPage("https://mauikit.org"); MauiApp::instance()->setReportPage("https://invent.kde.org/maui/vvave/-/issues"); QCommandLineParser parser; parser.setApplicationDescription(BAE::description); const QCommandLineOption versionOption = parser.addVersionOption(); parser.process(app); const QStringList args = parser.positionalArguments(); static auto babe = new vvave; static auto youtube = new YouTube; QFontDatabase::addApplicationFont(":/assets/materialdesignicons-webfont.ttf"); QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url, args](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); if(FMStatic::loadSettings("Settings", "ScanCollectionOnStartUp", true ).toBool()) { const auto currentSources = vvave::getSourceFolders(); babe->scanDir(currentSources.isEmpty() ? BAE::defaultSources : currentSources); } if(!args.isEmpty()) babe->openUrls(args); }, Qt::QueuedConnection); qmlRegisterSingletonType("org.maui.vvave", 1, 0, "Vvave", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject* { Q_UNUSED(engine) Q_UNUSED(scriptEngine) return babe; }); qmlRegisterSingletonType("org.maui.vvave", 1, 0, "YouTube", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject* { Q_UNUSED(engine) Q_UNUSED(scriptEngine) return youtube; }); qmlRegisterType("TracksList", 1, 0, "Tracks"); qmlRegisterType("PlaylistsList", 1, 0, "Playlists"); qmlRegisterType("AlbumsList", 1, 0, "Albums"); qmlRegisterType("CloudList", 1, 0, "Cloud"); qmlRegisterType("Player", 1, 0, "Player"); #ifdef STATIC_KIRIGAMI KirigamiPlugin::getInstance().registerTypes(); #endif #ifdef STATIC_MAUIKIT MauiKit::getInstance().registerTypes(); #endif engine.load(url); #ifdef Q_OS_MACOS // MAUIMacOS::removeTitlebarFromWindow(); #endif return app.exec(); } diff --git a/main.qml b/main.qml index ec49862..2b254cc 100644 --- a/main.qml +++ b/main.qml @@ -1,774 +1,775 @@ import QtQuick 2.10 import QtQuick.Controls 2.10 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui import org.kde.mauikit 1.1 as MauiLab import org.maui.vvave 1.0 as Vvave import Player 1.0 import AlbumsList 1.0 import TracksList 1.0 import PlaylistsList 1.0 import "utils" import "widgets" import "widgets/PlaylistsView" import "widgets/MainPlaylist" import "widgets/SettingsView" import "widgets/SearchView" import "widgets/CloudView" import "view_models" import "view_models/BabeTable" import "services/local" import "services/web" import "view_models/BabeGrid" import "widgets/InfoView" import "db/Queries.js" as Q import "utils/Help.js" as H import "utils/Player.js" as Player Maui.ApplicationWindow { id: root title: currentTrack ? currentTrack.title + " - " + currentTrack.artist + " | " + currentTrack.album : "" /***************************************************/ /******************** ALIASES ********************/ /*************************************************/ property alias mainPlaylist: mainPlaylist property alias selectionBar: _selectionBar property alias progressBar: progressBar property alias dialog : _dialogLoader.item background.opacity: translucency ? 0.5 : 1 // floatingHeader: swipeView.currentIndex === viewsIndex.albums || swipeView.currentIndex === viewsIndex.artists // autoHideHeader: true floatingFooter: false /***************************************************/ /******************** PLAYBACK ********************/ /*************************************************/ property bool isShuffle: Maui.FM.loadSettings("SHUFFLE","PLAYBACK", false) property var currentTrack: mainPlaylist.listView.itemAtIndex(currentTrackIndex) property int currentTrackIndex: -1 property int prevTrackIndex: 0 readonly property string currentArtwork: currentTrack ? currentTrack.artwork : "" property alias durationTimeLabel: player.duration property string progressTimeLabel: player.transformTime((player.duration/1000) *(player.pos/ 1000)) property alias isPlaying: player.playing property int onQueue: 0 property bool mainlistEmpty: !mainPlaylist.table.count > 0 /***************************************************/ /******************** HANDLERS ********************/ /*************************************************/ readonly property var viewsIndex: ({ tracks: 0, albums: 1, artists: 2, playlists: 3, cloud: 4, folders: 5, youtube: 6}) property string syncPlaylist: "" property bool sync: false property bool focusView : false property bool selectionMode : false /***************************************************/ /******************** UI COLORS *******************/ /*************************************************/ readonly property color babeColor: "#f84172" property bool translucency : Maui.Handy.isLinux /*SIGNALS*/ signal missingAlert(var track) // flickable: swipeView.currentItem.flickable || swipeView.currentItem.item.flickable footerPositioning: ListView.InlineFooter /*HANDLE EVENTS*/ onClosing: Player.savePlaylist() onMissingAlert: { var message = qsTr("Missing file") var messageBody = track.title + " by " + track.artist + " is missing.\nDo you want to remove it from your collection?" notify("dialog-question", message, messageBody, function () { mainPlaylist.list.remove(mainPlaylist.table.currentIndex) }) } /*COMPONENTS*/ Player { id: player volume: 100 onFinishedChanged: if (!mainlistEmpty) { if (currentTrack && currentTrack.url) mainPlaylist.list.countUp(currentTrackIndex) Player.nextTrack() } } headBar.visible: !focusView headBar.rightContent: ToolButton { visible: Maui.Handy.isTouch icon.name: "item-select" onClicked: selectionMode = !selectionMode checkable: false checked: selectionMode } Loader { id: _dialogLoader } InfoView { id: infoView maxWidth: parent.width * 0.8 maxHeight: parent.height * 0.9 } Loader { id: _focusViewLoader anchors.fill: parent active: focusView source: "widgets/FocusView.qml" } Component { id: _shareDialogComponent MauiLab.ShareDialog {} } Component { id: _fmDialogComponent Maui.FileDialog {} } Component { id: _settingsDialogComponent SettingsDialog {} } FloatingDisk { id: _floatingDisk } mainMenu: [ MenuSeparator{}, MenuItem { text: qsTr("Settings") icon.name: "settings-configure" onTriggered: { _dialogLoader.sourceComponent = _settingsDialogComponent dialog.open() } }, MenuSeparator{}, MenuItem { text: qsTr("Open") icon.name: "folder-add" onTriggered: { _dialogLoader.sourceComponent = _fmDialogComponent root.dialog.settings.onlyDirs = false root.dialog.settings.filterType = Maui.FMList.AUDIO root.dialog.show(function(paths) { Vvave.Vvave.openUrls(paths) root.dialog.close() }) } } ] Playlists { id: playlistsList } PlaylistDialog { id: playlistDialog } sideBar: Maui.AbstractSideBar { id: _drawer width: visible ? Math.min(Kirigami.Units.gridUnit * 16, root.width) : 0 collapsed: !isWide collapsible: true dragMargin: Maui.Style.space.big overlay.visible: collapsed && position > 0 && visible Connections { target: _drawer.overlay onClicked: _drawer.close() } background: Rectangle { color: Kirigami.Theme.backgroundColor opacity: translucency ? 0.5 : 1 } MainPlaylist { id: mainPlaylist anchors.fill: parent Connections { target: mainPlaylist onCoverPressed: Player.appendAll(tracks) onCoverDoubleClicked: Player.playAll(tracks) } } } // autoHideFooter: true // autoHideFooterMargins: root.height * 0.2 // autoHideFooterDelay: 5000 footer: ItemDelegate { visible: !focusView width: parent.width height: visible ? _footerLayout.implicitHeight : 0 background: Item { Image { id: artworkBg height: parent.height width: parent.width sourceSize.width: 500 sourceSize.height: height fillMode: Image.PreserveAspectCrop antialiasing: true smooth: true asynchronous: true cache: true source: currentArtwork } FastBlur { id: fastBlur anchors.fill: parent source: artworkBg radius: 100 transparentBorder: false cached: true Rectangle { anchors.fill: parent color: Kirigami.Theme.backgroundColor opacity: 0.8 } } Kirigami.Separator { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right } } ColumnLayout { id: _footerLayout anchors.fill: parent spacing: 0 Maui.ToolBar { Layout.fillWidth: true preferredHeight: Maui.Style.toolBarHeightAlt * 0.8 position: ToolBar.Footer visible: isPlaying leftContent: Label { id: _label1 visible: text.length verticalAlignment: Qt.AlignVCenter horizontalAlignment: Qt.AlignHCenter text: progressTimeLabel elide: Text.ElideMiddle wrapMode: Text.NoWrap color: Kirigami.Theme.textColor font.weight: Font.Normal font.pointSize: Maui.Style.fontSizes.default } middleContent: Item { Layout.fillHeight: true Layout.fillWidth: true Label { anchors.fill: parent visible: text.length verticalAlignment: Qt.AlignVCenter horizontalAlignment: Qt.AlignHCenter text: root.title elide: Text.ElideMiddle wrapMode: Text.NoWrap color: Kirigami.Theme.textColor font.weight: Font.Normal font.pointSize: Maui.Style.fontSizes.default } } rightContent: Label { id: _label2 visible: text.length verticalAlignment: Qt.AlignVCenter horizontalAlignment: Qt.AlignHCenter text: player.transformTime(player.duration/1000) elide: Text.ElideMiddle wrapMode: Text.NoWrap color: Kirigami.Theme.textColor font.weight: Font.Normal font.pointSize: Maui.Style.fontSizes.default opacity: 0.7 } background: Slider { id: progressBar + z: parent.z+1 padding: 0 from: 0 to: 1000 value: player.pos spacing: 0 focus: true onMoved: player.pos = value enabled: player.playing Kirigami.Separator { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right } background: Rectangle { implicitWidth: progressBar.width implicitHeight: progressBar.height width: progressBar.availableWidth height: implicitHeight color: "transparent" opacity: 0.4 Rectangle { width: progressBar.visualPosition * parent.width height: progressBar.height color: Kirigami.Theme.highlightColor } } handle: Rectangle { x: progressBar.leftPadding + progressBar.visualPosition * (progressBar.availableWidth - width) y: 0 implicitWidth: Maui.Style.iconSizes.medium implicitHeight: progressBar.height color: progressBar.pressed ? Qt.lighter(Kirigami.Theme.highlightColor, 1.2) : "transparent" } } } Maui.ToolBar { Layout.fillWidth: true Layout.preferredHeight: Maui.Style.toolBarHeight position: ToolBar.Footer background: Item {} rightContent: ToolButton { icon.name: _volumeSlider.value === 0 ? "player-volume-muted" : "player-volume" onPressAndHold : { player.volume = player.volume === 0 ? 100 : 0 } onClicked: { _sliderPopup.visible ? _sliderPopup.close() : _sliderPopup.open() } Popup { id: _sliderPopup height: 150 width: parent.width y: -150 x: 0 // closePolicy: Popup.CloseOnEscape | Popup.CloseOnPress Slider { id: _volumeSlider visible: true height: parent.height width: 20 anchors.horizontalCenter: parent.horizontalCenter from: 0 to: 100 value: player.volume orientation: Qt.Vertical onMoved: { player.volume = value } } } } middleContent: [ ToolButton { id: babeBtnIcon icon.name: "love" enabled: currentTrackIndex >= 0 checked: currentTrack ? Maui.FM.isFav(currentTrack.url) : false icon.color: checked ? babeColor : Kirigami.Theme.textColor onClicked: if (!mainlistEmpty) { mainPlaylist.list.fav(currentTrackIndex, !Maui.FM.isFav(currentTrack.url)) } }, Maui.ToolActions { expanded: true autoExclusive: false checkable: false Action { icon.name: "media-skip-backward" onTriggered: Player.previousTrack() // onPressAndHold: Player.playAt(prevTrackIndex) } //ambulatorios1@clinicaantioquia.com.co, copago martha hilda restrepo, cc 22146440 eps salud total, consulta expecialista urologo, hora 3:40 pm Action { id: playIcon text: qsTr("Play and pause") enabled: currentTrackIndex >= 0 icon.name: isPlaying ? "media-playback-pause" : "media-playback-start" onTriggered: player.playing = !player.playing } Action { text: qsTr("Next") icon.name: "media-skip-forward" onTriggered: Player.nextTrack() // onPressAndHold: Player.playAt(Player.shuffle()) } }, ToolButton { id: shuffleBtn icon.color: babeColor icon.name: isShuffle ? "media-playlist-shuffle" : "media-playlist-normal" onClicked: { isShuffle = !isShuffle Maui.FM.saveSettings("SHUFFLE", isShuffle, "PLAYBACK") } } ] } } } Maui.Page { anchors.fill: parent visible: !focusView flickable: swipeView.currentItem.item.flickable MauiLab.AppViews { id: swipeView anchors.fill: parent MauiLab.AppViewLoader { MauiLab.AppView.title: qsTr("Tracks") MauiLab.AppView.iconName: "view-media-track" TracksView { id: tracksView onRowClicked: Player.quickPlay(tracksView.listModel.get(index)) onQuickPlayTrack: Player.quickPlay(tracksView.listModel.get(index)) onAppendTrack: Player.addTrack(tracksView.listModel.get(index)) onPlayAll: Player.playAll( tracksView.listModel.getAll()) onAppendAll: Player.appendAll( tracksView.listModel.getAll()) onQueueTrack: Player.queueTracks([tracksView.listModel.get(index)], index) Connections { target: Vvave.Vvave onRefreshTables: tracksView.list.refresh() } } } MauiLab.AppViewLoader { MauiLab.AppView.title: qsTr("Albums") MauiLab.AppView.iconName: "view-media-album-cover" AlbumsView { id: albumsView holder.emoji: "qrc:/assets/dialog-information.svg" holder.isMask: false holder.title : qsTr("No Albums!") holder.body: qsTr("Add new music sources") holder.emojiSize: Maui.Style.iconSizes.huge list.query: Albums.ALBUMS list.sortBy: Albums.ALBUM onRowClicked: Player.quickPlay(track) onAppendTrack: Player.addTrack(track) onPlayTrack: Player.quickPlay(track) onAlbumCoverClicked: albumsView.populateTable(album, artist) onAlbumCoverPressedAndHold: { var query = Q.GET.albumTracks_.arg(album) query = query.arg(artist) mainPlaylist.list.clear() mainPlaylist.list.sortBy = Tracks.NONE mainPlaylist.list.query = query Player.playAt(0) } onPlayAll: Player.playAll(albumsView.listModel.getAll()) onAppendAll: Player.appendAll(albumsView.listModel.getAll()) Connections { target: Vvave.Vvave onRefreshTables: albumsView.list.refresh() } } } MauiLab.AppViewLoader { MauiLab.AppView.title: qsTr("Artists") MauiLab.AppView.iconName: "view-media-artist" AlbumsView { id: artistsView holder.emoji: "qrc:/assets/dialog-information.svg" holder.isMask: false holder.title : qsTr("No Artists!") holder.body: qsTr("Add new music sources") holder.emojiSize: Maui.Style.iconSizes.huge list.query: Albums.ARTISTS list.sortBy: Albums.ARTIST table.list.sortBy: Tracks.NONE onRowClicked: Player.quickPlay(track) onAppendTrack: Player.addTrack(track) onPlayTrack: Player.quickPlay(track) onAlbumCoverClicked: artistsView.populateTable(undefined, artist) onAlbumCoverPressedAndHold: { var query = Q.GET.artistTracks_.arg(artist) mainPlaylist.list.clear() mainPlaylist.list.sortBy = Tracks.NONE mainPlaylist.list.query = query Player.playAt(0) } onPlayAll: Player.playAll(artistsView.listModel.getAll()) onAppendAll: Player.appendAll(artistsView.listModel.getAll()) Connections { target: Vvave.Vvave onRefreshTables: artistsView.list.refresh() } } } MauiLab.AppViewLoader { MauiLab.AppView.title: qsTr("Playlists") MauiLab.AppView.iconName: "view-media-playlist" PlaylistsView { id: playlistsView onRowClicked: Player.quickPlay(track) onAppendTrack: Player.addTrack(track) onPlayTrack: Player.quickPlay(track) onAppendAll: Player.appendAll(playlistsView.listModel.getAll()) onSyncAndPlay: { Player.playAll(playlistsView.listModel.getAll()) root.sync = true root.syncPlaylist = playlist } onPlayAll: Player.playAll(playlistsView.listModel.getAll()) } } MauiLab.AppViewLoader { MauiLab.AppView.title: qsTr("Cloud") MauiLab.AppView.iconName: "folder-cloud" CloudView { id: cloudView } } MauiLab.AppViewLoader { MauiLab.AppView.title: qsTr("Folders") MauiLab.AppView.iconName: "folder" FoldersView { id: foldersView Connections { target: Vvave.Vvave onRefreshTables: foldersView.populate() } Connections { target: foldersView.list onRowClicked: Player.quickPlay(foldersView.list.model.get(index)) onQuickPlayTrack: Player.quickPlay(foldersView.list.model.get(index)) onAppendTrack: Player.addTrack(foldersView.listModel.get(index)) onPlayAll: Player.playAll(foldersView.listModel.getAll()) onAppendAll: Player.appendAll(foldersView.listModel.getAll()) onQueueTrack: Player.queueTracks([foldersView.list.model.get(index)], index) } } } MauiLab.AppViewLoader { MauiLab.AppView.title: qsTr("YouTube") MauiLab.AppView.iconName: "internet-services" YouTube { id: youtubeView } } } footer: SelectionBar { id: _selectionBar property alias listView: _selectionBar.selectionList anchors.horizontalCenter: parent.horizontalCenter width: Math.min(parent.width-(Maui.Style.space.medium*2), implicitWidth) padding: Maui.Style.space.big maxListHeight: swipeView.height - Maui.Style.space.medium onExitClicked: { root.selectionMode = false clear() } } } /*CONNECTIONS*/ Connections { target: Vvave.Vvave onRefreshTables: { if(size>0) root.notify("emblem-info", "Collection updated", size+" new tracks added...") } onOpenFiles: { Player.appendTracksAt(tracks, 0) Player.playAt(0) } } Component.onCompleted: { if(isAndroid) { Maui.Android.statusbarColor(Kirigami.Theme.backgroundColor, true) Maui.Android.navBarColor(Kirigami.Theme.backgroundColor, true) } } } diff --git a/services/local/player.h b/services/local/player.h index c6152a6..123642e 100644 --- a/services/local/player.h +++ b/services/local/player.h @@ -1,85 +1,84 @@ #ifndef PLAYER_H #define PLAYER_H #include #include #include #include class Player : public QObject { Q_OBJECT Q_PROPERTY(QUrl url READ getUrl WRITE setUrl NOTIFY urlChanged) Q_PROPERTY(int volume READ getVolume WRITE setVolume NOTIFY volumeChanged) Q_PROPERTY(Player::STATE state READ getState NOTIFY stateChanged) Q_PROPERTY(int duration READ getDuration NOTIFY durationChanged) Q_PROPERTY(bool playing READ getPlaying WRITE setPlaying NOTIFY playingChanged) Q_PROPERTY(bool finished READ getFinished NOTIFY finishedChanged) Q_PROPERTY(int pos READ getPos WRITE setPos NOTIFY posChanged) public: enum STATE : uint_fast8_t { PLAYING, PAUSED, - STOPED, - ERROR + STOPED };Q_ENUM(STATE) explicit Player(QObject *parent = nullptr); void setUrl(const QUrl &value); QUrl getUrl() const; void setVolume(const int &value); int getVolume() const; int getDuration() const; Player::STATE getState() const; void setPlaying(const bool &value); bool getPlaying() const; bool getFinished(); int getPos() const; void setPos(const int &value); private: QMediaPlayer *player; QTimer *updater; int amountBuffers = 0; int pos = 0; int volume = 100; QUrl url; Player::STATE state = STATE::STOPED; bool playing = false; bool finished = false; bool play() const; void pause() const; void update(); void emitState(); signals: void durationChanged(); void urlChanged(); void volumeChanged(); void stateChanged(); void playingChanged(); void finishedChanged(); void posChanged(); public slots: static QString transformTime(const int &pos); void stop(); }; #endif // PLAYER_H diff --git a/vvave.pro b/vvave.pro index 7655e4b..0fa6a48 100644 --- a/vvave.pro +++ b/vvave.pro @@ -1,135 +1,135 @@ QT *= quick \ multimedia \ sql \ network \ qml \ quickcontrols2 \ concurrent \ network CONFIG += ordered CONFIG += c++17 TARGET = vvave TEMPLATE = app VERSION_MAJOR = 1 VERSION_MINOR = 1 -VERSION_BUILD = 0 +VERSION_BUILD = 1 VERSION = $${VERSION_MAJOR}.$${VERSION_MINOR}.$${VERSION_BUILD} DEFINES += VVAVE_VERSION_STRING=\\\"$$VERSION\\\" linux:unix:!android { message(Building for Linux KDE) include($$PWD/kde/kde.pri) LIBS += -lMauiKit } else:android|win32|macos|ios { message(Building helpers for Android or Windows) android { QMAKE_LINK += -nostdlib++ QT *= androidextras ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android_files DISTFILES += $$PWD/android_files/AndroidManifest.xml DEFINES *= ANDROID_OPENSSL } android|ios { #build the sources QT *= webview TAGLIB_REPO = https://github.com/mauikit/taglib exists($$PWD/3rdparty/taglib/taglib.pri) { message("Using TagLib binaries for Android") }else { message("Getting Luv icon theme") system(git clone $$TAGLIB_REPO $$PWD/3rdparty/taglib) } include($$PWD/3rdparty/taglib/taglib.pri) } else:macos { #from brew installation LIBS += -L$$PWD/../../1.11.1/lib/ -ltag.1.17.0 INCLUDEPATH += $$PWD/../../1.11.1/include ICON = $$PWD/macos_files/vvave.icns }else:win32 { #from kde craft with msvc - + QT += webengine LIBS += -L$$PWD/../../../../CraftRoot/lib/ -ltag INCLUDEPATH += $$PWD/../../../../CraftRoot/include DEPENDPATH += $$PWD/../../../../CraftRoot/include RC_ICONS = $$PWD/windows_files/vvave.ico } #DEFAULT COMPONENTS DEFINITIONS DEFINES *= \ COMPONENT_ACCOUNTS \ COMPONENT_FM \ COMPONENT_TAGGING \ MAUIKIT_STYLE include($$PWD/3rdparty/kirigami/kirigami.pri) include($$PWD/3rdparty/mauikit/mauikit.pri) DEFINES += STATIC_KIRIGAMI } else { message("Unknown configuration") } include(pulpo/pulpo.pri) # The following define makes your compiler emit warnings if you use # any feature of Qt which as been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += main.cpp \ db/collectionDB.cpp \ services/local/taginfo.cpp \ services/local/player.cpp \ services/web/youtube.cpp \ vvave.cpp \ models/tracks/tracksmodel.cpp \ models/playlists/playlistsmodel.cpp \ models/albums/albumsmodel.cpp \ services/web/NextCloud/nextmusic.cpp \ services/web/abstractmusicprovider.cpp \ models/cloud/cloud.cpp RESOURCES += qml.qrc \ # Additional import path used to resolve QML modules in Qt Creator's code model QML_IMPORT_PATH = # Additional import path used to resolve QML modules just for Qt Quick Designer QML_DESIGNER_IMPORT_PATH = HEADERS += \ db/collectionDB.h \ utils/bae.h \ services/local/fileloader.h \ services/local/taginfo.h \ services/local/player.h \ services/web/youtube.h \ vvave.h \ models/tracks/tracksmodel.h \ models/playlists/playlistsmodel.h \ models/albums/albumsmodel.h \ services/web/NextCloud/nextmusic.h \ services/web/abstractmusicprovider.h \ models/cloud/cloud.h INCLUDEPATH += \ $$PWD/services/web \ $$PWD/services/web/NextCloud include(install.pri)