diff --git a/LenaPi/LenaPi.pro.user b/LenaPi/LenaPi.pro.user index 21cf67f..f9708ee 100644 --- a/LenaPi/LenaPi.pro.user +++ b/LenaPi/LenaPi.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/LenaPi/MusicPlayer.qml b/LenaPi/MusicPlayer.qml index 30dfc1c..41bc541 100644 --- a/LenaPi/MusicPlayer.qml +++ b/LenaPi/MusicPlayer.qml @@ -1,4 +1,5 @@ import QtQuick 2.0 +import QtQuick.Controls 2.4 import QtGraphicalEffects 1.0 Item{ @@ -6,7 +7,7 @@ Item{ property int margins: 20 - RoundButton{ + RoundImageButton{ id: backNavigation anchors.left: parent.left anchors.top: parent.top @@ -16,11 +17,15 @@ Item{ } } - RoundButton{ - id: closeApp + RoundImageButton{ + id: closeAppButton anchors.right: parent.right anchors.top: parent.top - anchors.margins: container.margins + anchors.margins: visible ? container.margins : 0 + + visible: container.height > 500 + diameter: visible ? defaultDiameter : 0 + imageSource: "qrc:/icon_close" onClicked: { Qt.quit(); @@ -49,6 +54,24 @@ Item{ } } + VolumeSlider{ + id: volumeSlider + anchors{ + right: parent.right + top: closeAppButton.bottom + bottom: controlPannel.top + margins: container.margins + topMargin: closeAppButton.visible ? 2*container.margins : container.margins + } + from: 34 // we cannot hear anything if lower than 35% + to: 100 + stepSize: 1 + value: musicModel.pAudioVolume + onValueChanged: { + console.log(musicModel.pAudioVolume, value); + musicModel.pAudioVolume = value; + } + } PlayerControlPannel { id: controlPannel anchors.left: parent.left diff --git a/LenaPi/Navigation.qml b/LenaPi/Navigation.qml index 2f6b0f3..f33382d 100644 --- a/LenaPi/Navigation.qml +++ b/LenaPi/Navigation.qml @@ -6,7 +6,7 @@ import QtQuick 2.0 Item { id: container property int margins: 20 - RoundButton{ + RoundImageButton{ id: back anchors.top: parent.top @@ -16,9 +16,9 @@ Item { visible: navigationList.pIsBackVisible onClicked: navigationList.navigateBack(); - } // RoundButton: navigate back + } // MyRoundButton: navigate back - RoundButton{ + RoundImageButton{ id: closeApp anchors.right: parent.right anchors.top: parent.top @@ -27,7 +27,7 @@ Item { onClicked: { Qt.quit(); } - } // RoundButton: closeApp + } // MyRoundButton: closeApp Rectangle{ anchors.left: parent.left diff --git a/LenaPi/PlayerButtons.qml b/LenaPi/PlayerButtons.qml index 7235629..8fe8b00 100644 --- a/LenaPi/PlayerButtons.qml +++ b/LenaPi/PlayerButtons.qml @@ -9,11 +9,11 @@ Item { anchors.centerIn: parent spacing: container.spacing - RoundButton{ + RoundImageButton{ id: previous anchors.verticalCenter: parent.verticalCenter - width: 60 + diameter: 60 imageSource: "qrc:/icon_previous" enabled: model.pHasPrevious @@ -22,21 +22,21 @@ Item { model.playPrevious(); } } - RoundButton{ + RoundImageButton{ id: playPause anchors.verticalCenter: parent.verticalCenter - width: 80 + diameter: 80 imageSource: model.pIsPlaying ? "qrc:/icon_pause" : "qrc:/icon_play" onClicked:{ model.playPause(); } } - RoundButton{ + RoundImageButton{ id: stop anchors.verticalCenter: parent.verticalCenter - width: 60 + diameter: 60 imageSource: "qrc:/icon_stop" enabled: model.pIsPlaying @@ -45,11 +45,11 @@ Item { model.stopMusic(); } } - RoundButton{ + RoundImageButton{ id: next anchors.verticalCenter: parent.verticalCenter - width: 60 + diameter: 60 imageSource: "qrc:/icon_next" enabled: model.pHasNext diff --git a/LenaPi/RoundButton.qml b/LenaPi/RoundImageButton.qml similarity index 58% rename from LenaPi/RoundButton.qml rename to LenaPi/RoundImageButton.qml index 1838e68..5334465 100644 --- a/LenaPi/RoundButton.qml +++ b/LenaPi/RoundImageButton.qml @@ -7,6 +7,12 @@ import QtQuick.Controls 2.4 Button { id: container property alias imageSource: image.source + // default button diameter -> default width, readonly + readonly property int defaultDiameter: 65 + // button diameter -> width + property int diameter: defaultDiameter + // diameter of content image -> width + property int imageDiameter: 0.5*diameter background: Rectangle{ @@ -15,14 +21,14 @@ Button { color: "white" - implicitWidth: 65 - implicitHeight: width - radius: width/2 + implicitWidth: container.diameter + implicitHeight: container.diameter + radius: container.diameter/2 Image{ id: image anchors.centerIn: parent - width: 30 + width: container.imageDiameter height: width source: "qrc:/icon_back" } @@ -31,7 +37,7 @@ Button { z: 1 visible: !container.enabled anchors.centerIn: parent - width: 30 + width: image.width height: width color: "#99ffffff" } diff --git a/LenaPi/VolumeSlider.qml b/LenaPi/VolumeSlider.qml new file mode 100644 index 0000000..1ca6c9b --- /dev/null +++ b/LenaPi/VolumeSlider.qml @@ -0,0 +1,31 @@ +import QtQuick 2.0 +import QtQuick.Controls 2.4 +import QtQuick.Layouts 1.3 + +ColumnLayout { + property alias from: slider.from + property alias to: slider.to + property alias stepSize: slider.stepSize + property alias value: slider.value + spacing: 5 + RoundImageButton{ + id: increaseButton + imageSource: "qrc:///icon_increase_volume" + onClicked: slider.increase(); + } + Slider{ + id: slider + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + orientation: Qt.Vertical + from: 34 // we cannot hear anything if lower than 35% + to: 100 + stepSize: 1 + value: 50 + } + RoundImageButton{ + id: decreaseButton + imageSource: "qrc:///icon_decrease_volume" + onClicked: slider.decrease(); + } +} diff --git a/LenaPi/controllers/MusicController.cpp b/LenaPi/controllers/MusicController.cpp index 47a23c2..4b51a00 100644 --- a/LenaPi/controllers/MusicController.cpp +++ b/LenaPi/controllers/MusicController.cpp @@ -10,17 +10,20 @@ 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::navigateTo); - connect(mModel, &MusicModel::navigateTo, [this](NavigationItemModel*){ - if(mModel->isPlaying()) mModel->playPause(); + 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::play, mPlayer, &VlcMediaListPlayer::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); @@ -33,6 +36,7 @@ MusicController::MusicController(QObject *parent) : QObject(parent) MusicController::~MusicController() { mPlayer->deleteLater(); + mVlcAudio->deleteLater(); } void MusicController::initPlayer(NavigationItemModel *item) @@ -58,3 +62,11 @@ 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 index 8c2a64d..4bdf01f 100644 --- a/LenaPi/controllers/MusicController.h +++ b/LenaPi/controllers/MusicController.h @@ -8,6 +8,7 @@ #include #include #include +#include class MusicModel; @@ -31,12 +32,21 @@ private: QQmlContext* mContext = Q_NULLPTR; - MusicModel* mModel; + MusicModel* mModel = Q_NULLPTR; - VlcInstance* mVlc; - VlcMediaListPlayer* mPlayer; + 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/lenapi.qrc b/LenaPi/lenapi.qrc index bba9b5d..2a3ca97 100644 --- a/LenaPi/lenapi.qrc +++ b/LenaPi/lenapi.qrc @@ -9,5 +9,7 @@ resources/previous.jpg resources/stop.jpg resources/close.png + resources/speaker_high_volume.png + resources/speaker_low_volume.png diff --git a/LenaPi/models/MusicModel.cpp b/LenaPi/models/MusicModel.cpp index 530c558..9383ea4 100644 --- a/LenaPi/models/MusicModel.cpp +++ b/LenaPi/models/MusicModel.cpp @@ -6,6 +6,7 @@ MusicModel::MusicModel(VlcInstance* instance, QObject *parent) : QObject(parent), mVlc(instance), mMedia(new VlcMediaList(instance)) { + /* nothing */ } MusicModel::~MusicModel() @@ -101,6 +102,20 @@ 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; diff --git a/LenaPi/models/MusicModel.h b/LenaPi/models/MusicModel.h index 88504ee..764d79a 100644 --- a/LenaPi/models/MusicModel.h +++ b/LenaPi/models/MusicModel.h @@ -18,6 +18,7 @@ class MusicModel : public QObject Q_PROPERTY(QString pMediaLength READ getMediaLength NOTIFY mediaLengthChanged) Q_PROPERTY(QString pTime READ getTime NOTIFY progressChanged) Q_PROPERTY(QString pMediaTitle READ getMediaTitle NOTIFY mediaTitleChanged) + Q_PROPERTY(int pAudioVolume READ getAudioVolume WRITE setAudioVolume NOTIFY audioVolumeChanged) signals: void navigateTo(NavigationItemModel *item); @@ -33,6 +34,7 @@ signals: void progressChanged(); void mediaLengthChanged(); void mediaTitleChanged(); + void audioVolumeChanged(int newVolume); public: MusicModel(VlcInstance* instance, QObject *parent = Q_NULLPTR); @@ -54,6 +56,15 @@ public: bool hasNext() const; bool hasPrevious() const; + inline int getAudioVolume() const { return mAudioVolume; } + /** + * @brief Set audio volume. Information is transferred to VlcAudio + * @param newVolume value between 0 and 100 (audio level in percent) + * Ensures that volume is inbetween 0 and 100. If this range is exceeded, + * the volume is set to the lowest and highest allowed value, respectively. + */ + void setAudioVolume(int newVolume); + double getProgress() const; QString getMediaTitle() const; @@ -79,10 +90,11 @@ private: int mCurrentMediaItemLength = 0; int mCurrentTime = 0; double mCurrentMediaItemProgress = 0; + int mAudioVolume{50}; QString mMediaTitle = QString(""); NavigationItemModel* mCurrentItem = Q_NULLPTR; VlcMediaList* mMedia = Q_NULLPTR; - VlcInstance* mVlc; + VlcInstance* mVlc = Q_NULLPTR; }; #endif // MUSICMODEL_H diff --git a/LenaPi/qml.qrc b/LenaPi/qml.qrc index 2a2ac88..d93fa3e 100644 --- a/LenaPi/qml.qrc +++ b/LenaPi/qml.qrc @@ -4,11 +4,12 @@ MainForm.ui.qml NavigationListDelegate.qml MyScrollView.qml - RoundButton.qml + RoundImageButton.qml Navigation.qml MusicPlayer.qml MediaProgress.qml PlayerButtons.qml PlayerControlPannel.qml + VolumeSlider.qml diff --git a/LenaPi/resources/speaker_high_volume.png b/LenaPi/resources/speaker_high_volume.png new file mode 100644 index 0000000..06a9bf8 Binary files /dev/null and b/LenaPi/resources/speaker_high_volume.png differ diff --git a/LenaPi/resources/speaker_low_volume.png b/LenaPi/resources/speaker_low_volume.png new file mode 100644 index 0000000..251754d Binary files /dev/null and b/LenaPi/resources/speaker_low_volume.png differ