xref: /OK3568_Linux_fs/app/forlinx/forlinx_qt/musicplayer/musicplayer.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /****************************************************************************
2*4882a593Smuzhiyun **
3*4882a593Smuzhiyun ** Copyright (C) 2015 The Qt Company Ltd.
4*4882a593Smuzhiyun ** Contact: http://www.qt.io/licensing/
5*4882a593Smuzhiyun **
6*4882a593Smuzhiyun ** This file is part of the examples of the Qt Toolkit.
7*4882a593Smuzhiyun **
8*4882a593Smuzhiyun ** $QT_BEGIN_LICENSE:BSD$
9*4882a593Smuzhiyun ** You may use this file under the terms of the BSD license as follows:
10*4882a593Smuzhiyun **
11*4882a593Smuzhiyun ** "Redistribution and use in source and binary forms, with or without
12*4882a593Smuzhiyun ** modification, are permitted provided that the following conditions are
13*4882a593Smuzhiyun ** met:
14*4882a593Smuzhiyun **   * Redistributions of source code must retain the above copyright
15*4882a593Smuzhiyun **     notice, this list of conditions and the following disclaimer.
16*4882a593Smuzhiyun **   * Redistributions in binary form must reproduce the above copyright
17*4882a593Smuzhiyun **     notice, this list of conditions and the following disclaimer in
18*4882a593Smuzhiyun **     the documentation and/or other materials provided with the
19*4882a593Smuzhiyun **     distribution.
20*4882a593Smuzhiyun **   * Neither the name of The Qt Company Ltd nor the names of its
21*4882a593Smuzhiyun **     contributors may be used to endorse or promote products derived
22*4882a593Smuzhiyun **     from this software without specific prior written permission.
23*4882a593Smuzhiyun **
24*4882a593Smuzhiyun **
25*4882a593Smuzhiyun ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26*4882a593Smuzhiyun ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27*4882a593Smuzhiyun ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28*4882a593Smuzhiyun ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29*4882a593Smuzhiyun ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30*4882a593Smuzhiyun ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31*4882a593Smuzhiyun ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32*4882a593Smuzhiyun ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33*4882a593Smuzhiyun ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34*4882a593Smuzhiyun ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35*4882a593Smuzhiyun ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36*4882a593Smuzhiyun **
37*4882a593Smuzhiyun ** $QT_END_LICENSE$
38*4882a593Smuzhiyun **
39*4882a593Smuzhiyun ****************************************************************************/
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #include "musicplayer.h"
42*4882a593Smuzhiyun #include "volumebutton.h"
43*4882a593Smuzhiyun #include <QDebug>
44*4882a593Smuzhiyun #include <QtWidgets>
45*4882a593Smuzhiyun #include <QApplication>
46*4882a593Smuzhiyun #include <QSlider>
47*4882a593Smuzhiyun #include <QPainter>
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 
MusicPlayer(QWidget * parent)51*4882a593Smuzhiyun MusicPlayer::MusicPlayer(QWidget *parent) : QWidget(parent)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	setWindowState(Qt::WindowMaximized);
54*4882a593Smuzhiyun     setWindowFlags(Qt::FramelessWindowHint);
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun     createWidgets();
57*4882a593Smuzhiyun     createShortcuts();
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun     connect(&mediaPlayer, &QMediaPlayer::positionChanged, this, &MusicPlayer::updatePosition);
60*4882a593Smuzhiyun     connect(&mediaPlayer, &QMediaPlayer::durationChanged, this, &MusicPlayer::updateDuration);
61*4882a593Smuzhiyun     connect(&mediaPlayer, &QMediaObject::metaDataAvailableChanged, this, &MusicPlayer::updateInfo);
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun     typedef void(QMediaPlayer::*ErrorSignal)(QMediaPlayer::Error);
64*4882a593Smuzhiyun     connect(&mediaPlayer, static_cast<ErrorSignal>(&QMediaPlayer::error),
65*4882a593Smuzhiyun             this, &MusicPlayer::handleError);
66*4882a593Smuzhiyun     connect(&mediaPlayer, &QMediaPlayer::stateChanged,
67*4882a593Smuzhiyun             this, &MusicPlayer::updateState);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun     setAcceptDrops(true);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun 
supportedMimeTypes()72*4882a593Smuzhiyun QStringList MusicPlayer::supportedMimeTypes()
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun     QStringList result = QMediaPlayer::supportedMimeTypes();
75*4882a593Smuzhiyun     if (result.isEmpty())
76*4882a593Smuzhiyun         result.append(QStringLiteral("audio/mpeg"));
77*4882a593Smuzhiyun     return result;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun 
openFile()80*4882a593Smuzhiyun void MusicPlayer::openFile()
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun     QFileDialog fileDialog(this);
83*4882a593Smuzhiyun     fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
84*4882a593Smuzhiyun     fileDialog.setWindowTitle(tr("Open File"));
85*4882a593Smuzhiyun     fileDialog.setMimeTypeFilters(MusicPlayer::supportedMimeTypes());
86*4882a593Smuzhiyun     fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::MusicLocation).value(0, QDir::homePath()));
87*4882a593Smuzhiyun     if (fileDialog.exec() == QDialog::Accepted)
88*4882a593Smuzhiyun     {
89*4882a593Smuzhiyun          playUrl(fileDialog.selectedUrls().constFirst());
90*4882a593Smuzhiyun     }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
playUrl(const QUrl & url)94*4882a593Smuzhiyun void MusicPlayer::playUrl(const QUrl &url)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun     playButton->setEnabled(true);
97*4882a593Smuzhiyun     if (url.isLocalFile()) {
98*4882a593Smuzhiyun         const QString filePath = url.toLocalFile();
99*4882a593Smuzhiyun         setWindowFilePath(filePath);
100*4882a593Smuzhiyun         infoLabel->setText(QDir::toNativeSeparators(filePath));
101*4882a593Smuzhiyun         fileName = QFileInfo(filePath).fileName();
102*4882a593Smuzhiyun     } else {
103*4882a593Smuzhiyun         setWindowFilePath(QString());
104*4882a593Smuzhiyun         infoLabel->setText(url.toString());
105*4882a593Smuzhiyun         fileName.clear();
106*4882a593Smuzhiyun     }
107*4882a593Smuzhiyun     mediaPlayer.setMedia(url);
108*4882a593Smuzhiyun     mediaPlayer.play();
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
togglePlayback()111*4882a593Smuzhiyun void MusicPlayer::togglePlayback()
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun     if (mediaPlayer.mediaStatus() == QMediaPlayer::NoMedia)
114*4882a593Smuzhiyun         openFile();
115*4882a593Smuzhiyun     else if (mediaPlayer.state() == QMediaPlayer::PlayingState)
116*4882a593Smuzhiyun         mediaPlayer.pause();
117*4882a593Smuzhiyun     else
118*4882a593Smuzhiyun         mediaPlayer.play();
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
seekForward()121*4882a593Smuzhiyun void MusicPlayer::seekForward()
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun     positionSlider->triggerAction(QSlider::SliderPageStepAdd);
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
seekBackward()126*4882a593Smuzhiyun void MusicPlayer::seekBackward()
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun     positionSlider->triggerAction(QSlider::SliderPageStepSub);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun //! [0]
event(QEvent * event)132*4882a593Smuzhiyun bool MusicPlayer::event(QEvent *event)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun     return QWidget::event(event);
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun //! [0]
137*4882a593Smuzhiyun 
canHandleDrop(const QDropEvent * event)138*4882a593Smuzhiyun static bool canHandleDrop(const QDropEvent *event)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun     const QList<QUrl> urls = event->mimeData()->urls();
141*4882a593Smuzhiyun     if (urls.size() != 1)
142*4882a593Smuzhiyun         return false;
143*4882a593Smuzhiyun     QMimeDatabase mimeDatabase;
144*4882a593Smuzhiyun     return MusicPlayer::supportedMimeTypes().
145*4882a593Smuzhiyun         contains(mimeDatabase.mimeTypeForUrl(urls.constFirst()).name());
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun 
dragEnterEvent(QDragEnterEvent * event)148*4882a593Smuzhiyun void MusicPlayer::dragEnterEvent(QDragEnterEvent *event)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun     event->setAccepted(canHandleDrop(event));
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
dropEvent(QDropEvent * event)153*4882a593Smuzhiyun void MusicPlayer::dropEvent(QDropEvent *event)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun     event->accept();
156*4882a593Smuzhiyun    // playUrl(event->mimeData()->urls().constFirst());
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
mousePressEvent(QMouseEvent * event)159*4882a593Smuzhiyun void MusicPlayer::mousePressEvent(QMouseEvent *event)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun     offset = event->globalPos() - pos();
162*4882a593Smuzhiyun     event->accept();
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
mouseMoveEvent(QMouseEvent * event)165*4882a593Smuzhiyun void MusicPlayer::mouseMoveEvent(QMouseEvent *event)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun     //move(event->globalPos() - offset);
168*4882a593Smuzhiyun     event->accept();
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun 
mouseReleaseEvent(QMouseEvent * event)171*4882a593Smuzhiyun void MusicPlayer::mouseReleaseEvent(QMouseEvent *event)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun     offset = QPoint();
174*4882a593Smuzhiyun     event->accept();
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
updateState(QMediaPlayer::State state)177*4882a593Smuzhiyun void MusicPlayer::updateState(QMediaPlayer::State state)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun     if (state == QMediaPlayer::PlayingState) {
180*4882a593Smuzhiyun         playButton->setToolTip(tr("Pause"));
181*4882a593Smuzhiyun         playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
182*4882a593Smuzhiyun     } else {
183*4882a593Smuzhiyun         playButton->setToolTip(tr("Play"));
184*4882a593Smuzhiyun         playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
185*4882a593Smuzhiyun     }
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
formatTime(qint64 timeMilliSeconds)188*4882a593Smuzhiyun static QString formatTime(qint64 timeMilliSeconds)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun     qint64 seconds = timeMilliSeconds / 1000;
191*4882a593Smuzhiyun     const qint64 minutes = seconds / 60;
192*4882a593Smuzhiyun     seconds -= minutes * 60;
193*4882a593Smuzhiyun     return QStringLiteral("%1:%2")
194*4882a593Smuzhiyun         .arg(minutes, 2, 10, QLatin1Char('0'))
195*4882a593Smuzhiyun         .arg(seconds, 2, 10, QLatin1Char('0'));
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun 
updatePosition(qint64 position)198*4882a593Smuzhiyun void MusicPlayer::updatePosition(qint64 position)
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun     positionSlider->setValue(position);
202*4882a593Smuzhiyun     positionLabel->setText(formatTime(position));
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
updateDuration(qint64 duration)205*4882a593Smuzhiyun void MusicPlayer::updateDuration(qint64 duration)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun     positionSlider->setRange(0, duration);
208*4882a593Smuzhiyun     positionSlider->setEnabled(duration > 0);
209*4882a593Smuzhiyun     positionSlider->setPageStep(duration / 10);
210*4882a593Smuzhiyun     updateInfo();
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 
setPosition(int position)214*4882a593Smuzhiyun void MusicPlayer::setPosition(int position)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun     // avoid seeking when the slider value change is triggered from updatePosition()
217*4882a593Smuzhiyun     if (qAbs(mediaPlayer.position() - position) > 99)
218*4882a593Smuzhiyun     {
219*4882a593Smuzhiyun         mediaPlayer.setPosition(position);
220*4882a593Smuzhiyun     }
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun 
updateInfo()223*4882a593Smuzhiyun void MusicPlayer::updateInfo()
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun     QStringList info;
226*4882a593Smuzhiyun     if (!fileName.isEmpty())
227*4882a593Smuzhiyun         info.append(fileName);
228*4882a593Smuzhiyun     if (mediaPlayer.isMetaDataAvailable()) {
229*4882a593Smuzhiyun         QString author = mediaPlayer.metaData(QStringLiteral("Author")).toString();
230*4882a593Smuzhiyun         if (!author.isEmpty())
231*4882a593Smuzhiyun             info.append(author);
232*4882a593Smuzhiyun         QString title = mediaPlayer.metaData(QStringLiteral("Title")).toString();
233*4882a593Smuzhiyun         if (!title.isEmpty())
234*4882a593Smuzhiyun             info.append(title);
235*4882a593Smuzhiyun     }
236*4882a593Smuzhiyun     info.append(formatTime(mediaPlayer.duration()));
237*4882a593Smuzhiyun     infoLabel->setText(info.join(tr(" - ")));
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
handleError()240*4882a593Smuzhiyun void MusicPlayer::handleError()
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun     playButton->setEnabled(false);
243*4882a593Smuzhiyun     const QString errorString = mediaPlayer.errorString();
244*4882a593Smuzhiyun     infoLabel->setText(errorString.isEmpty()
245*4882a593Smuzhiyun                        ? tr("Unknown error #%1").arg(int(mediaPlayer.error()))
246*4882a593Smuzhiyun                        : tr("Error: %1").arg(errorString));
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
createWidgets()249*4882a593Smuzhiyun void MusicPlayer::createWidgets()
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun     playButton = new QToolButton(this);
252*4882a593Smuzhiyun     playButton->setEnabled(false);
253*4882a593Smuzhiyun     playButton->setToolTip(tr("Play"));
254*4882a593Smuzhiyun     playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
255*4882a593Smuzhiyun     playButton->setFixedSize(55,35);
256*4882a593Smuzhiyun     connect(playButton, &QAbstractButton::clicked, this, &MusicPlayer::togglePlayback);
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun     QAbstractButton *openButton = new QToolButton(this);
259*4882a593Smuzhiyun     openButton->setText(tr("..."));
260*4882a593Smuzhiyun     openButton->setToolTip(tr("Open a file..."));
261*4882a593Smuzhiyun     openButton->setFixedSize(55,35);
262*4882a593Smuzhiyun     connect(openButton, &QAbstractButton::clicked, this, &MusicPlayer::openFile);
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	QPushButton *exitBtn = new QPushButton(this);
265*4882a593Smuzhiyun 	exitBtn->setText(tr("Exit"));
266*4882a593Smuzhiyun 	exitBtn->setFixedSize(55,35);
267*4882a593Smuzhiyun 	connect(exitBtn, &QPushButton::clicked, this, [=](){
268*4882a593Smuzhiyun     close();
269*4882a593Smuzhiyun     });
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun     volumeButton = new VolumeButton(this);
273*4882a593Smuzhiyun     volumeButton->setToolTip(tr("Adjust volume"));
274*4882a593Smuzhiyun     volumeButton->setVolume(mediaPlayer.volume());
275*4882a593Smuzhiyun     volumeButton->setFixedSize(55,35);
276*4882a593Smuzhiyun     connect(volumeButton, &VolumeButton::volumeChanged, &mediaPlayer, &QMediaPlayer::setVolume);
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun     positionSlider = new QSlider(Qt::Horizontal, this);
279*4882a593Smuzhiyun     positionSlider->setEnabled(false);
280*4882a593Smuzhiyun     positionSlider->setToolTip(tr("Seek"));
281*4882a593Smuzhiyun     positionSlider->setMaximum(1000000);
282*4882a593Smuzhiyun     positionSlider->setMinimum(0);
283*4882a593Smuzhiyun     positionSlider->setValue(0);
284*4882a593Smuzhiyun     positionSlider->setMinimumWidth(120);
285*4882a593Smuzhiyun     connect(positionSlider, &QSlider::valueChanged, this, &MusicPlayer::setPosition);
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun     infoLabel = new QLabel(this);
288*4882a593Smuzhiyun     QFont font;
289*4882a593Smuzhiyun     font.setPointSize(14);
290*4882a593Smuzhiyun     infoLabel->setFont(font);
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun     positionLabel = new QLabel(tr("00:00"), this);
293*4882a593Smuzhiyun     positionLabel->setMinimumWidth(positionLabel->sizeHint().width());
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun     QGridLayout *controlLayout = new QGridLayout(this);
296*4882a593Smuzhiyun     controlLayout->addWidget(openButton,1,0);
297*4882a593Smuzhiyun     controlLayout->addWidget(playButton,1,1);
298*4882a593Smuzhiyun     controlLayout->addWidget(positionSlider,1,2);
299*4882a593Smuzhiyun     controlLayout->addWidget(positionLabel,1,3);
300*4882a593Smuzhiyun     controlLayout->addWidget(volumeButton,1,4);
301*4882a593Smuzhiyun 	controlLayout->addWidget(exitBtn, 1, 5);
302*4882a593Smuzhiyun     controlLayout->addWidget(infoLabel,0,2);
303*4882a593Smuzhiyun     controlLayout->setSpacing(25);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
createShortcuts()307*4882a593Smuzhiyun void MusicPlayer::createShortcuts()
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun     QShortcut *quitShortcut = new QShortcut(QKeySequence::Quit, this);
310*4882a593Smuzhiyun     connect(quitShortcut, &QShortcut::activated, QCoreApplication::quit);
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun     QShortcut *openShortcut = new QShortcut(QKeySequence::Open, this);
313*4882a593Smuzhiyun     connect(openShortcut, &QShortcut::activated, this, &MusicPlayer::openFile);
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun     QShortcut *toggleShortcut = new QShortcut(Qt::Key_Space, this);
316*4882a593Smuzhiyun     connect(toggleShortcut, &QShortcut::activated, this, &MusicPlayer::togglePlayback);
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun     QShortcut *forwardShortcut = new QShortcut(Qt::Key_Right, this);
319*4882a593Smuzhiyun     connect(forwardShortcut, &QShortcut::activated, this, &MusicPlayer::seekForward);
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun     QShortcut *backwardShortcut = new QShortcut(Qt::Key_Left, this);
322*4882a593Smuzhiyun     connect(backwardShortcut, &QShortcut::activated, this, &MusicPlayer::seekBackward);
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun     QShortcut *increaseShortcut = new QShortcut(Qt::Key_Up, this);
325*4882a593Smuzhiyun     connect(increaseShortcut, &QShortcut::activated, volumeButton, &VolumeButton::increaseVolume);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun     QShortcut *decreaseShortcut = new QShortcut(Qt::Key_Down, this);
328*4882a593Smuzhiyun     connect(decreaseShortcut, &QShortcut::activated, volumeButton, &VolumeButton::descreaseVolume);
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun 
331