diff --git a/.gitignore b/.gitignore index 56accb7..cf45d4e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ build-LenaPi-Desktop-Debug build-LenaPi-RasPi-Debug build-LenaPi-RasPi-Release LenaPi/LenaPi.pro.user.4.8-pre1 +musik diff --git a/LenaPi/LenaPi.pro b/LenaPi/LenaPi.pro index 5750661..baa2c3a 100644 --- a/LenaPi/LenaPi.pro +++ b/LenaPi/LenaPi.pro @@ -1,16 +1,15 @@ TEMPLATE = app -QT += qml quick +QT += qml quick multimedia CONFIG += c++11 -LIBS += -lVLCQtCore -lVLCQtQml +LIBS += SOURCES += main.cpp \ + controllers/MusicPlayer.cpp \ models/NavigationListModel.cpp \ models/NavigationItemModel.cpp \ controllers/NavigationController.cpp \ models/UiStateModel.cpp \ - controllers/MusicController.cpp \ - models/MusicModel.cpp \ MouseEventSpy.cpp \ EnergySaver.cpp \ controllers/SettingsHandler.cpp @@ -41,12 +40,12 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target HEADERS += \ + controllers/MusicPlayer.h \ + models/MusicPlayer.h \ models/NavigationListModel.h \ models/NavigationItemModel.h \ controllers/NavigationController.h \ models/UiStateModel.h \ - controllers/MusicController.h \ - models/MusicModel.h \ MouseEventSpy.h \ EnergySaver.h \ controllers/SettingsHandler.h diff --git a/LenaPi/LenaPi.pro.user b/LenaPi/LenaPi.pro.user index 430c2b1..bcdddb7 100644 --- a/LenaPi/LenaPi.pro.user +++ b/LenaPi/LenaPi.pro.user @@ -1,10 +1,10 @@ - + EnvironmentId - {76cb87c9-a04b-479b-87ff-1b3ddab073a7} + {0510cc5f-8237-43aa-9f4f-ce9a2d4944ec} ProjectExplorer.Project.ActiveTarget @@ -49,209 +49,206 @@ true true true + *.md, *.MD, Makefile false + true ProjectExplorer.Project.PluginSettings + + true + true + true + true + true + + + 0 + true true + Builtin.Questionable + + true + true + Builtin.DefaultTidyAndClazy + 2 + + + + true + ProjectExplorer.Project.Target.0 + Desktop Desktop Desktop - {f9938f31-357c-4785-aa6e-21a3feac2ebf} + {ebe72439-b95e-4a0f-b855-a910128856ec} 0 0 0 - /home/araemer/source/LenaPi/build-LenaPi-Desktop-Debug + 0 + /home/araemer/source/lenapi/build-LenaPi-Desktop-Debug + /home/araemer/source/lenapi/build-LenaPi-Desktop-Debug true - qmake - QtProjectManager.QMakeBuildStep - true false - false - false + true - Make - Qt4ProjectManager.MakeStep - - false - - - false 2 Build - + Build ProjectExplorer.BuildSteps.Build true - Make - Qt4ProjectManager.MakeStep - - true clean - - false 1 Clean - + Clean ProjectExplorer.BuildSteps.Clean 2 false + - Debug - + Debug Qt4ProjectManager.Qt4BuildConfiguration 2 - true + 0 - /home/ar/source/LenaPi/build-LenaPi-Desktop-Release + /home/araemer/source/lenapi/build-LenaPi-Desktop-Release + /home/araemer/source/lenapi/build-LenaPi-Desktop-Release true - qmake - QtProjectManager.QMakeBuildStep - false false - false - false + true - Make - Qt4ProjectManager.MakeStep - - false - - - false 2 Build - + Build ProjectExplorer.BuildSteps.Build true - Make - Qt4ProjectManager.MakeStep - - true clean - - false 1 Clean - + Clean ProjectExplorer.BuildSteps.Clean 2 false + - Release - + Release Qt4ProjectManager.Qt4BuildConfiguration 0 - true + 0 + 0 - /home/ar/source/LenaPi/build-LenaPi-Desktop-Profile + 0 + /home/araemer/source/lenapi/build-LenaPi-Desktop-Profile + /home/araemer/source/lenapi/build-LenaPi-Desktop-Profile true - qmake - QtProjectManager.QMakeBuildStep - true false - true - false + true - Make - Qt4ProjectManager.MakeStep - - false - - - false 2 Build - + Build ProjectExplorer.BuildSteps.Build true - Make - Qt4ProjectManager.MakeStep - - true clean - - false 1 Clean - + Clean ProjectExplorer.BuildSteps.Clean 2 false + - Profile - + Profile Qt4ProjectManager.Qt4BuildConfiguration 0 - true + 0 + 0 + 0 3 0 Deploy - + Deploy ProjectExplorer.BuildSteps.Deploy 1 - Deploy locally - + + false ProjectExplorer.DefaultDeployConfiguration 1 - + dwarf + + cpu-cycles + + + 250 + + -e + cpu-cycles + --call-graph + dwarf,4096 + -F + 250 + + -F + true + 4096 false false 1000 @@ -266,6 +263,7 @@ 0.01 10 true + kcachegrind 1 25 @@ -291,22 +289,16 @@ 13 14 + 2 - LenaPi - LenaPi2 - Qt4ProjectManager.Qt4RunConfiguration:/home/ar/source/LenaPi/LenaPi/LenaPi.pro - LenaPi.pro - - 3768 + Qt4ProjectManager.Qt4RunConfiguration:/home/araemer/source/lenapi/LenaPi/LenaPi.pro + /home/araemer/source/lenapi/LenaPi/LenaPi.pro false true true - false false true - - /home/araemer/source/LenaPi/build-LenaPi-Desktop-Debug 1 @@ -317,10 +309,10 @@ ProjectExplorer.Project.Updater.FileVersion - 20 + 22 Version - 20 + 22 diff --git a/LenaPi/controllers/MusicController.cpp b/LenaPi/controllers/MusicController.cpp deleted file mode 100644 index 4b51a00..0000000 --- a/LenaPi/controllers/MusicController.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "MusicController.h" - -#include -#include -#include -#include "EnergySaver.h" - -MusicController::MusicController(QObject *parent) : QObject(parent) -{ - mVlc = new VlcInstance(VlcCommon::args(), this); - mModel = new MusicModel(mVlc, this); - mPlayer = new VlcMediaListPlayer(mVlc); - mVlcAudio = new VlcAudio(mPlayer->mediaPlayer()); - - connect(mModel, &MusicModel::navigateTo, this, &MusicController::onNavigationRequest); - - //connect(mModel, &MusicModel::play, mPlayer, &VlcMediaListPlayer::play); - connect(mModel, &MusicModel::play, [this](){ - mVlcAudio->setVolume(mModel->getAudioVolume()); - mPlayer->play(); - }); - connect(mModel, &MusicModel::stop, mPlayer, &VlcMediaListPlayer::stop); - connect(mModel, &MusicModel::previous, mPlayer, &VlcMediaListPlayer::previous); - connect(mModel, &MusicModel::next, mPlayer, &VlcMediaListPlayer::next); - connect(mModel, &MusicModel::pause, mPlayer->mediaPlayer(), &VlcMediaPlayer::pause); - connect(mModel, &MusicModel::audioVolumeChanged, mVlcAudio, &VlcAudio::setVolume); - - connect(mPlayer, SIGNAL(nextItemSet(VlcMedia*)), mModel, SLOT(onNextMediaSet(VlcMedia*))); - connect(mPlayer->mediaPlayer(), &VlcMediaPlayer::lengthChanged, mModel, &MusicModel::onLengthChanged); - connect(mPlayer->mediaPlayer(), &VlcMediaPlayer::timeChanged, mModel, &MusicModel::onTimeChanged); - - // hand over player signals to energy saver in order to determine player activity. - connect(mPlayer->mediaPlayer(), &VlcMediaPlayer::timeChanged, EnergySaver::instance(), &EnergySaver::restartTimer); -} - -MusicController::~MusicController() -{ - mPlayer->deleteLater(); - mVlcAudio->deleteLater(); -} - -void MusicController::initPlayer(NavigationItemModel *item) -{ - if(item != mModel->getCurrentItem()){ - mPlayer->stop(); - mModel->init(item); - } - if(!mIsMediaListSet){ - mPlayer->setMediaList(mModel->getMedia()); - mIsMediaListSet = true; - } -} - -void MusicController::setContext(QQmlContext *context) -{ - mContext = context; - setContextProperties(); -} - -void MusicController::setContextProperties() -{ - if(!mContext) return; - mContext->setContextProperty("musicModel", mModel); -} - -void MusicController::onNavigationRequest(NavigationItemModel *item) -{ - if(mModel->isPlaying()) { - mModel->playPause(); - } - emit navigateTo(item); -} diff --git a/LenaPi/controllers/MusicController.h b/LenaPi/controllers/MusicController.h deleted file mode 100644 index 4bdf01f..0000000 --- a/LenaPi/controllers/MusicController.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MUSICCONTROLLER_H -#define MUSICCONTROLLER_H - -#include -#include -#include - -#include -#include -#include -#include - -class MusicModel; - -class MusicController : public QObject -{ - Q_OBJECT - -signals: - void navigateTo(NavigationItemModel* item); - -public: - MusicController(QObject *parent = Q_NULLPTR); - ~MusicController(); - - void initPlayer(NavigationItemModel* item); - - void setContext(QQmlContext* context); - -private: - void setContextProperties(); - - QQmlContext* mContext = Q_NULLPTR; - - MusicModel* mModel = Q_NULLPTR; - - VlcInstance* mVlc = Q_NULLPTR; - VlcMediaListPlayer* mPlayer = Q_NULLPTR; - VlcAudio* mVlcAudio = Q_NULLPTR; - - bool mIsMediaListSet = false; - - private slots: - /** - * @brief Stop player if necessary and forward signal navigatTo - * @param item target of navigation request - * @see navigateTo(NavigationItemModel* item); - */ - void onNavigationRequest(NavigationItemModel* item); -}; - -#endif // MUSICCONTROLLER_H diff --git a/LenaPi/controllers/MusicPlayer.cpp b/LenaPi/controllers/MusicPlayer.cpp new file mode 100644 index 0000000..df43e10 --- /dev/null +++ b/LenaPi/controllers/MusicPlayer.cpp @@ -0,0 +1,194 @@ +#include "MusicPlayer.h" +#include +#include + + + +MusicPlayer::MusicPlayer(QObject *parent) : QMediaPlayer(parent) +{ + /* nothing */ +} + +MusicPlayer::~MusicPlayer() +{ +} + +void MusicPlayer::init(NavigationItemModel *item) +{ + if(mCurrentItem == item){ + return; + } + mCurrentItem = item; + emit currentItemChanged(); + + reset(); + clearMediaList(); + + readMedia(mCurrentItem->getPath()); +} + +void MusicPlayer::navigateBack() +{ + emit navigateTo(mCurrentItem); +} + +void MusicPlayer::playPause() +{ + mIsPlaying = !mIsPlaying; + emit isPlayingChanged(); + if(mIsPlaying) + play(); + else + pause(); +} + +void MusicPlayer::stopMusic() +{ + if(mIsPlaying){ + mIsPlaying = false; + emit isPlayingChanged(); + + reset(); + + emit stop(); + } +} + +void MusicPlayer::playNext() +{ + //emit next(); + if(!mIsPlaying){ + mIsPlaying = true; + emit isPlayingChanged(); + } +} + +void MusicPlayer::playPrevious() +{ + //emit previous(); + if(!mIsPlaying){ + mIsPlaying = true; + emit isPlayingChanged(); + } +} + +NavigationItemModel *MusicPlayer::getCurrentItem() +{ + return mCurrentItem; +} + +bool MusicPlayer::isPlaying() const +{ + return mIsPlaying; +} + +bool MusicPlayer::hasNext() const +{ + return mHasNext; +} + +bool MusicPlayer::hasPrevious() const +{ + return mHasPrevious; +} + +void MusicPlayer::setAudioVolume(int newVolume) +{ + if(newVolume != mAudioVolume){ + if(newVolume > 100){ + mAudioVolume = 100; + } else if(newVolume < 0){ + mAudioVolume = 0; + } else { + mAudioVolume = newVolume; + } + emit audioVolumeChanged(mAudioVolume); + } +} + +double MusicPlayer::getProgress() const +{ + return mCurrentMediaItemProgress; +} + +QString MusicPlayer::getMediaTitle() const +{ + return mMediaTitle; +} + +QString MusicPlayer::getMediaLength() +{ + return timeToString(mCurrentMediaItemLength); +} + +QString MusicPlayer::getTime() +{ + return timeToString(mCurrentTime); +} + +void MusicPlayer::onTimeChanged(int time) +{ + mCurrentMediaItemProgress = (double) time / mCurrentMediaItemLength; + mCurrentTime = time; + emit progressChanged(); +} + +void MusicPlayer::onLengthChanged(int length) +{ + mCurrentMediaItemLength= length; + emit mediaLengthChanged(); +} + +void MusicPlayer::reset() +{ + mHasNext = false; + mHasPrevious = false; + emit hasNextChanged(); + emit hasPreviousChanged(); + + mCurrentMediaItemProgress = 0.0; + mCurrentTime = 0.0; + emit progressChanged(); + + mCurrentMediaItemLength = 0.0; + emit mediaLengthChanged(); +} + +void MusicPlayer::clearMediaList() +{ + if(playlist()){ + playlist()->clear(); + } +} + +void MusicPlayer::readMedia(const QString& path) +{ + auto dir = QDir(path); + if(!dir.exists()) return; + + // create playlist if necessary + auto playList = playlist(); + if(!playList){ + playList = new QMediaPlaylist(this); + setPlaylist(playList); + } + + // add audio files to playlist + dir.setNameFilters({"*.mp3", "*.flac"}); + auto files = dir.entryInfoList(QDir::Files); + for(auto file:files){ + auto fileName = file.absoluteFilePath(); + auto fileUrl = QUrl::fromLocalFile(fileName); + qDebug() << fileName << fileUrl; + playList->addMedia(QMediaContent(fileUrl)); + } +} + +QString MusicPlayer::timeToString(int time) +{ + int sec = time/1000; + int min = sec/60; + sec = sec-min*60; + QString secStr = (sec < 10) ? "0"+QString::number(sec) : QString::number(sec); + return QString::number(min) + ":" + secStr; +} diff --git a/LenaPi/models/MusicModel.h b/LenaPi/controllers/MusicPlayer.h similarity index 76% rename from LenaPi/models/MusicModel.h rename to LenaPi/controllers/MusicPlayer.h index 764d79a..4d59071 100644 --- a/LenaPi/models/MusicModel.h +++ b/LenaPi/controllers/MusicPlayer.h @@ -1,12 +1,11 @@ -#ifndef MUSICMODEL_H -#define MUSICMODEL_H +#ifndef MUSICPLAYER_H +#define MUSICPLAYER_H #include - +#include #include -#include -class MusicModel : public QObject +class MusicPlayer : public QMediaPlayer { Q_OBJECT @@ -23,11 +22,6 @@ class MusicModel : public QObject signals: void navigateTo(NavigationItemModel *item); void currentItemChanged(); - void play(); - void pause(); - void stop(); - void previous(); - void next(); void hasPreviousChanged(); void hasNextChanged(); void isPlayingChanged(); @@ -37,20 +31,13 @@ signals: void audioVolumeChanged(int newVolume); public: - MusicModel(VlcInstance* instance, QObject *parent = Q_NULLPTR); - ~MusicModel(); + MusicPlayer(QObject *parent = Q_NULLPTR); + ~MusicPlayer(); void init(NavigationItemModel* item); - Q_INVOKABLE void navigateBack(); - Q_INVOKABLE void playPause(); - Q_INVOKABLE void stopMusic(); - Q_INVOKABLE void playNext(); - Q_INVOKABLE void playPrevious(); - NavigationItemModel *getCurrentItem(); - VlcMediaList *getMedia(); bool isPlaying() const; bool hasNext() const; @@ -72,7 +59,12 @@ public: QString getTime(); public slots: - void onNextMediaSet(VlcMedia* media); + void navigateBack(); + void playPause(); + void stopMusic(); + void playNext(); + void playPrevious(); + void onTimeChanged(int time); void onLengthChanged(int length); @@ -80,7 +72,6 @@ private: void reset(); void clearMediaList(); void readMedia(const QString& path); - void setMediaTitle(VlcMedia* media); QString timeToString(int time); @@ -92,9 +83,7 @@ private: double mCurrentMediaItemProgress = 0; int mAudioVolume{50}; QString mMediaTitle = QString(""); - NavigationItemModel* mCurrentItem = Q_NULLPTR; - VlcMediaList* mMedia = Q_NULLPTR; - VlcInstance* mVlc = Q_NULLPTR; + NavigationItemModel* mCurrentItem = nullptr; }; -#endif // MUSICMODEL_H +#endif // MUSICPLAYER_H diff --git a/LenaPi/controllers/NavigationController.cpp b/LenaPi/controllers/NavigationController.cpp index 1eb5c59..0dc4a4f 100644 --- a/LenaPi/controllers/NavigationController.cpp +++ b/LenaPi/controllers/NavigationController.cpp @@ -6,15 +6,15 @@ #include #include #include -#include +#include NavigationController::NavigationController(QObject *parent) : QObject(parent), mRootItem(new NavigationItemModel(this)), mNavList(new NavigationListModel(this)), mUiState(new UiStateModel(this)), - mMusicController(new MusicController(this)) + mMediaPlayer(new MusicPlayer(this)) { - connect(mMusicController, &MusicController::navigateTo, [this](NavigationItemModel* item) { + connect(mMediaPlayer, &MusicPlayer::navigateTo, [this](NavigationItemModel* item) { mUiState->showNavigation(); mNavList->navigateTo(item); }); @@ -40,7 +40,6 @@ void NavigationController::setContext(QQmlContext *context) { mContext = context; setContextProperties(); - mMusicController->setContext(mContext); } void NavigationController::setContextProperties() @@ -48,6 +47,7 @@ void NavigationController::setContextProperties() if(!mContext) return; mContext->setContextProperty("navigationList", mNavList); mContext->setContextProperty("uiStateModel", mUiState); + mContext->setContextProperty("musicModel", mMediaPlayer); } void NavigationController::add(const QString &path, NavigationItemModel *parentItem) @@ -99,7 +99,7 @@ void NavigationController::onNavigationRequest() if(item->hasChildren()) mNavList->setModelItems(item->getChildren()); else { - mMusicController->initPlayer(item); + mMediaPlayer->init(item); mUiState->showMusicPlayer(); } } diff --git a/LenaPi/controllers/NavigationController.h b/LenaPi/controllers/NavigationController.h index 8761160..6f40c5b 100644 --- a/LenaPi/controllers/NavigationController.h +++ b/LenaPi/controllers/NavigationController.h @@ -7,7 +7,7 @@ class NavigationItemModel; class NavigationListModel; class UiStateModel; -class MusicController; +class MusicPlayer; /** * @brief Main controller controlling ui state, navigation and music player. @@ -59,7 +59,7 @@ private: NavigationListModel* mNavList; UiStateModel* mUiState; - MusicController* mMusicController; + MusicPlayer* mMediaPlayer; QString mRootPath = "."; diff --git a/LenaPi/models/MusicModel.cpp b/LenaPi/models/MusicModel.cpp deleted file mode 100644 index 9383ea4..0000000 --- a/LenaPi/models/MusicModel.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "MusicModel.h" -#include -#include -#include - -MusicModel::MusicModel(VlcInstance* instance, QObject *parent) : QObject(parent), - mVlc(instance), mMedia(new VlcMediaList(instance)) -{ - /* nothing */ -} - -MusicModel::~MusicModel() -{ - // do not delete! will cause segmentation fault - //if(mMedia) - // mMedia->deleteLater(); -} - -void MusicModel::init(NavigationItemModel *item) -{ - if(mCurrentItem == item){ - return; - } - mCurrentItem = item; - emit currentItemChanged(); - - reset(); - clearMediaList(); - - readMedia(mCurrentItem->getPath()); - - setMediaTitle(mMedia->at(0)); -} - -void MusicModel::navigateBack() -{ - emit navigateTo(mCurrentItem); -} - -void MusicModel::playPause() -{ - mIsPlaying = !mIsPlaying; - emit isPlayingChanged(); - if(mIsPlaying) - emit play(); - else - emit pause(); -} - -void MusicModel::stopMusic() -{ - if(mIsPlaying){ - mIsPlaying = false; - emit isPlayingChanged(); - - reset(); - - emit stop(); - } -} - -void MusicModel::playNext() -{ - emit next(); - if(!mIsPlaying){ - mIsPlaying = true; - emit isPlayingChanged(); - } -} - -void MusicModel::playPrevious() -{ - emit previous(); - if(!mIsPlaying){ - mIsPlaying = true; - emit isPlayingChanged(); - } -} - -NavigationItemModel *MusicModel::getCurrentItem() -{ - return mCurrentItem; -} - -VlcMediaList *MusicModel::getMedia() -{ - return mMedia; -} - -bool MusicModel::isPlaying() const -{ - return mIsPlaying; -} - -bool MusicModel::hasNext() const -{ - return mHasNext; -} - -bool MusicModel::hasPrevious() const -{ - return mHasPrevious; -} - -void MusicModel::setAudioVolume(int newVolume) -{ - if(newVolume != mAudioVolume){ - if(newVolume > 100){ - mAudioVolume = 100; - } else if(newVolume < 0){ - mAudioVolume = 0; - } else { - mAudioVolume = newVolume; - } - emit audioVolumeChanged(mAudioVolume); - } -} - -double MusicModel::getProgress() const -{ - return mCurrentMediaItemProgress; -} - -QString MusicModel::getMediaTitle() const -{ - return mMediaTitle; -} - -QString MusicModel::getMediaLength() -{ - return timeToString(mCurrentMediaItemLength); -} - -QString MusicModel::getTime() -{ - return timeToString(mCurrentTime); -} - -void MusicModel::onNextMediaSet(VlcMedia *media) -{ - setMediaTitle(media); - - mHasNext = true; - mHasPrevious = true; - if(mMedia->at(0) == media){ - mHasPrevious = false; - } - if(mMedia->at(mMedia->count()-1) == media){ - mHasNext = false; - } - emit hasPreviousChanged(); - emit hasNextChanged(); -} - -void MusicModel::onTimeChanged(int time) -{ - mCurrentMediaItemProgress = (double) time / mCurrentMediaItemLength; - mCurrentTime = time; - emit progressChanged(); -} - -void MusicModel::onLengthChanged(int length) -{ - mCurrentMediaItemLength= length; - emit mediaLengthChanged(); -} - -void MusicModel::reset() -{ - mHasNext = false; - mHasPrevious = false; - emit hasNextChanged(); - emit hasPreviousChanged(); - - mCurrentMediaItemProgress = 0.0; - mCurrentTime = 0.0; - emit progressChanged(); - - mCurrentMediaItemLength = 0.0; - emit mediaLengthChanged(); -} - -void MusicModel::clearMediaList() -{ - while(mMedia->count() > 0){ - mMedia->removeMedia(0); - } -} - -void MusicModel::readMedia(const QString& path) -{ - auto dir = QDir(path); - if(!dir.exists()) return; - - auto fileNames = dir.entryList(QDir::Files); - for(auto file:fileNames){ - if(file.endsWith(".flac") || file.endsWith(".mp3")){ - mMedia->addMedia(new VlcMedia(dir.filePath(file), true, mVlc)); - } - } -} - -QString MusicModel::timeToString(int time) -{ - int sec = time/1000; - int min = sec/60; - sec = sec-min*60; - QString secStr = (sec < 10) ? "0"+QString::number(sec) : QString::number(sec); - return QString::number(min) + ":" + secStr; -} - -void MusicModel::setMediaTitle(VlcMedia *media) -{ - auto list = media->currentLocation().split("/"); - auto title = list.at(list.count() -1 ); - mMediaTitle = title.left(title.lastIndexOf(".")); - emit mediaTitleChanged(); -}