Music Player▲
Sélectionnez
/**
**************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
***************************************************************************
*/
#include
"musicplayer.h"
#include
"volumebutton.h"
#include <QtWidgets>
#include <QtWinExtras>
MusicPlayer::
MusicPlayer(QWidget *
parent) : QWidget(parent)
{
createWidgets();
createShortcuts();
createJumpList();
createTaskbar();
createThumbnailToolBar();
connect(&
amp;mediaPlayer, &
amp;QMediaPlayer::
positionChanged, this
, &
amp;MusicPlayer::
updatePosition);
connect(&
amp;mediaPlayer, &
amp;QMediaPlayer::
durationChanged, this
, &
amp;MusicPlayer::
updateDuration);
connect(&
amp;mediaPlayer, &
amp;QMediaObject::
metaDataAvailableChanged, this
, &
amp;MusicPlayer::
updateInfo);
connect(&
amp;mediaPlayer, QOverload&
lt;QMediaPlayer::
Error&
gt;::
of(&
amp;QMediaPlayer::
error),
this
, &
amp;MusicPlayer::
handleError);
connect(&
amp;mediaPlayer, &
amp;QMediaPlayer::
stateChanged,
this
, &
amp;MusicPlayer::
updateState);
stylize();
setAcceptDrops(true
);
}
QStringList MusicPlayer::
supportedMimeTypes()
{
QStringList result =
QMediaPlayer::
supportedMimeTypes();
if
(result.isEmpty())
result.append(QStringLiteral("audio/mpeg"
));
return
result;
}
void
MusicPlayer::
openFile()
{
QFileDialog fileDialog(this
);
fileDialog.setAcceptMode(QFileDialog::
AcceptOpen);
fileDialog.setWindowTitle(tr("Open File"
));
fileDialog.setMimeTypeFilters(MusicPlayer::
supportedMimeTypes());
fileDialog.setDirectory(QStandardPaths::
standardLocations(QStandardPaths::
MusicLocation).value(0
, QDir::
homePath()));
if
(fileDialog.exec() ==
QDialog::
Accepted)
playUrl(fileDialog.selectedUrls().constFirst());
}
void
MusicPlayer::
playUrl(const
QUrl &
amp;url)
{
playButton-&
gt;setEnabled(true
);
if
(url.isLocalFile()) {
const
QString filePath =
url.toLocalFile();
setWindowFilePath(filePath);
infoLabel-&
gt;setText(QDir::
toNativeSeparators(filePath));
fileName =
QFileInfo(filePath).fileName();
}
else
{
setWindowFilePath(QString());
infoLabel-&
gt;setText(url.toString());
fileName.clear();
}
mediaPlayer.setMedia(url);
mediaPlayer.play();
}
void
MusicPlayer::
togglePlayback()
{
if
(mediaPlayer.mediaStatus() ==
QMediaPlayer::
NoMedia)
openFile();
else
if
(mediaPlayer.state() ==
QMediaPlayer::
PlayingState)
mediaPlayer.pause();
else
mediaPlayer.play();
}
void
MusicPlayer::
seekForward()
{
positionSlider-&
gt;triggerAction(QSlider::
SliderPageStepAdd);
}
void
MusicPlayer::
seekBackward()
{
positionSlider-&
gt;triggerAction(QSlider::
SliderPageStepSub);
}
bool
MusicPlayer::
event(QEvent *
event)
{
if
(event-&
gt;type() ==
QWinEvent::
CompositionChange ||
event-&
gt;type() ==
QWinEvent::
ColorizationChange)
stylize();
return
QWidget::
event(event);
}
static
bool
canHandleDrop(const
QDropEvent *
event)
{
const
QList&
lt;QUrl&
gt; urls =
event-&
gt;mimeData()-&
gt;urls();
if
(urls.size() !=
1
)
return
false
;
QMimeDatabase mimeDatabase;
return
MusicPlayer::
supportedMimeTypes().
contains(mimeDatabase.mimeTypeForUrl(urls.constFirst()).name());
}
void
MusicPlayer::
dragEnterEvent(QDragEnterEvent *
event)
{
event-&
gt;setAccepted(canHandleDrop(event));
}
void
MusicPlayer::
dropEvent(QDropEvent *
event)
{
event-&
gt;accept();
playUrl(event-&
gt;mimeData()-&
gt;urls().constFirst());
}
void
MusicPlayer::
mousePressEvent(QMouseEvent *
event)
{
offset =
event-&
gt;globalPos() -
pos();
event-&
gt;accept();
}
void
MusicPlayer::
mouseMoveEvent(QMouseEvent *
event)
{
move(event-&
gt;globalPos() -
offset);
event-&
gt;accept();
}
void
MusicPlayer::
mouseReleaseEvent(QMouseEvent *
event)
{
offset =
QPoint();
event-&
gt;accept();
}
void
MusicPlayer::
stylize()
{
if
(QOperatingSystemVersion::
current() &
lt; QOperatingSystemVersion::
Windows8) {
// Set styling options relevant only to Windows 7.
if
(QtWin::
isCompositionEnabled()) {
QtWin::
extendFrameIntoClientArea(this
, -
1
, -
1
, -
1
, -
1
);
setAttribute(Qt::
WA_TranslucentBackground, true
);
setAttribute(Qt::
WA_NoSystemBackground, false
);
setStyleSheet(QStringLiteral("MusicPlayer { background: transparent; }"
));
}
else
{
QtWin::
resetExtendedFrame(this
);
setAttribute(Qt::
WA_TranslucentBackground, false
);
setStyleSheet(QStringLiteral("MusicPlayer { background: %1; }"
).arg(QtWin::
realColorizationColor().name()));
}
volumeButton-&
gt;stylize();
}
}
void
MusicPlayer::
updateState(QMediaPlayer::
State state)
{
if
(state ==
QMediaPlayer::
PlayingState) {
playButton-&
gt;setToolTip(tr("Pause"
));
playButton-&
gt;setIcon(style()-&
gt;standardIcon(QStyle::
SP_MediaPause));
}
else
{
playButton-&
gt;setToolTip(tr("Play"
));
playButton-&
gt;setIcon(style()-&
gt;standardIcon(QStyle::
SP_MediaPlay));
}
}
static
QString formatTime(qint64 timeMilliSeconds)
{
qint64 seconds =
timeMilliSeconds /
1000
;
const
qint64 minutes =
seconds /
60
;
seconds -=
minutes *
60
;
return
QStringLiteral("%1:%2"
)
.arg(minutes, 2
, 10
, QLatin1Char('0'
))
.arg(seconds, 2
, 10
, QLatin1Char('0'
));
}
void
MusicPlayer::
updatePosition(qint64 position)
{
positionSlider-&
gt;setValue(position);
positionLabel-&
gt;setText(formatTime(position));
}
void
MusicPlayer::
updateDuration(qint64 duration)
{
positionSlider-&
gt;setRange(0
, duration);
positionSlider-&
gt;setEnabled(duration &
gt; 0
);
positionSlider-&
gt;setPageStep(duration /
10
);
updateInfo();
}
void
MusicPlayer::
setPosition(int
position)
{
// avoid seeking when the slider value change is triggered from updatePosition()
if
(qAbs(mediaPlayer.position() -
position) &
gt; 99
)
mediaPlayer.setPosition(position);
}
void
MusicPlayer::
updateInfo()
{
QStringList info;
if
(!
fileName.isEmpty())
info.append(fileName);
if
(mediaPlayer.isMetaDataAvailable()) {
QString author =
mediaPlayer.metaData(QStringLiteral("Author"
)).toString();
if
(!
author.isEmpty())
info.append(author);
QString title =
mediaPlayer.metaData(QStringLiteral("Title"
)).toString();
if
(!
title.isEmpty())
info.append(title);
}
info.append(formatTime(mediaPlayer.duration()));
infoLabel-&
gt;setText(info.join(tr(" - "
)));
}
void
MusicPlayer::
handleError()
{
playButton-&
gt;setEnabled(false
);
const
QString errorString =
mediaPlayer.errorString();
infoLabel-&
gt;setText(errorString.isEmpty()
? tr("Unknown error #%1"
).arg(int
(mediaPlayer.error()))
:
tr("Error: %1"
).arg(errorString));
}
void
MusicPlayer::
updateTaskbar()
{
switch
(mediaPlayer.state()) {
case
QMediaPlayer::
PlayingState:
taskbarButton-&
gt;setOverlayIcon(style()-&
gt;standardIcon(QStyle::
SP_MediaPlay));
taskbarProgress-&
gt;show();
taskbarProgress-&
gt;resume();
break
;
case
QMediaPlayer::
PausedState:
taskbarButton-&
gt;setOverlayIcon(style()-&
gt;standardIcon(QStyle::
SP_MediaPause));
taskbarProgress-&
gt;show();
taskbarProgress-&
gt;pause();
break
;
case
QMediaPlayer::
StoppedState:
taskbarButton-&
gt;setOverlayIcon(style()-&
gt;standardIcon(QStyle::
SP_MediaStop));
taskbarProgress-&
gt;hide();
break
;
}
}
void
MusicPlayer::
updateThumbnailToolBar()
{
playToolButton-&
gt;setEnabled(mediaPlayer.duration() &
gt; 0
);
backwardToolButton-&
gt;setEnabled(mediaPlayer.position() &
gt; 0
);
forwardToolButton-&
gt;setEnabled(mediaPlayer.position() &
lt; mediaPlayer.duration());
if
(mediaPlayer.state() ==
QMediaPlayer::
PlayingState) {
playToolButton-&
gt;setToolTip(tr("Pause"
));
playToolButton-&
gt;setIcon(style()-&
gt;standardIcon(QStyle::
SP_MediaPause));
}
else
{
playToolButton-&
gt;setToolTip(tr("Play"
));
playToolButton-&
gt;setIcon(style()-&
gt;standardIcon(QStyle::
SP_MediaPlay));
}
}
void
MusicPlayer::
createWidgets()
{
playButton =
new
QToolButton(this
);
playButton-&
gt;setEnabled(false
);
playButton-&
gt;setToolTip(tr("Play"
));
playButton-&
gt;setIcon(style()-&
gt;standardIcon(QStyle::
SP_MediaPlay));
connect(playButton, &
amp;QAbstractButton::
clicked, this
, &
amp;MusicPlayer::
togglePlayback);
QAbstractButton *
openButton =
new
QToolButton(this
);
openButton-&
gt;setText(tr("..."
));
openButton-&
gt;setToolTip(tr("Open a file..."
));
openButton-&
gt;setFixedSize(playButton-&
gt;sizeHint());
connect(openButton, &
amp;QAbstractButton::
clicked, this
, &
amp;MusicPlayer::
openFile);
volumeButton =
new
VolumeButton(this
);
volumeButton-&
gt;setToolTip(tr("Adjust volume"
));
volumeButton-&
gt;setVolume(mediaPlayer.volume());
connect(volumeButton, &
amp;VolumeButton::
volumeChanged, &
amp;mediaPlayer, &
amp;QMediaPlayer::
setVolume);
positionSlider =
new
QSlider(Qt::
Horizontal, this
);
positionSlider-&
gt;setEnabled(false
);
positionSlider-&
gt;setToolTip(tr("Seek"
));
connect(positionSlider, &
amp;QAbstractSlider::
valueChanged, this
, &
amp;MusicPlayer::
setPosition);
infoLabel =
new
QLabel(this
);
positionLabel =
new
QLabel(tr("00:00"
), this
);
positionLabel-&
gt;setMinimumWidth(positionLabel-&
gt;sizeHint().width());
QBoxLayout *
controlLayout =
new
QHBoxLayout;
controlLayout-&
gt;setMargin(0
);
controlLayout-&
gt;addWidget(openButton);
controlLayout-&
gt;addWidget(playButton);
controlLayout-&
gt;addWidget(positionSlider);
controlLayout-&
gt;addWidget(positionLabel);
controlLayout-&
gt;addWidget(volumeButton);
QBoxLayout *
mainLayout =
new
QVBoxLayout(this
);
mainLayout-&
gt;addWidget(infoLabel);
mainLayout-&
gt;addLayout(controlLayout);
}
void
MusicPlayer::
createShortcuts()
{
QShortcut *
quitShortcut =
new
QShortcut(QKeySequence::
Quit, this
);
connect(quitShortcut, &
amp;QShortcut::
activated, QCoreApplication::
quit);
QShortcut *
openShortcut =
new
QShortcut(QKeySequence::
Open, this
);
connect(openShortcut, &
amp;QShortcut::
activated, this
, &
amp;MusicPlayer::
openFile);
QShortcut *
toggleShortcut =
new
QShortcut(Qt::
Key_Space, this
);
connect(toggleShortcut, &
amp;QShortcut::
activated, this
, &
amp;MusicPlayer::
togglePlayback);
QShortcut *
forwardShortcut =
new
QShortcut(Qt::
Key_Right, this
);
connect(forwardShortcut, &
amp;QShortcut::
activated, this
, &
amp;MusicPlayer::
seekForward);
QShortcut *
backwardShortcut =
new
QShortcut(Qt::
Key_Left, this
);
connect(backwardShortcut, &
amp;QShortcut::
activated, this
, &
amp;MusicPlayer::
seekBackward);
QShortcut *
increaseShortcut =
new
QShortcut(Qt::
Key_Up, this
);
connect(increaseShortcut, &
amp;QShortcut::
activated, volumeButton, &
amp;VolumeButton::
increaseVolume);
QShortcut *
decreaseShortcut =
new
QShortcut(Qt::
Key_Down, this
);
connect(decreaseShortcut, &
amp;QShortcut::
activated, volumeButton, &
amp;VolumeButton::
descreaseVolume);
}
void
MusicPlayer::
createJumpList()
{
QWinJumpList jumplist;
jumplist.recent()-&
gt;setVisible(true
);
}
void
MusicPlayer::
createTaskbar()
{
taskbarButton =
new
QWinTaskbarButton(this
);
taskbarButton-&
gt;setWindow(windowHandle());
taskbarProgress =
taskbarButton-&
gt;progress();
connect(positionSlider, &
amp;QAbstractSlider::
valueChanged, taskbarProgress, &
amp;QWinTaskbarProgress::
setValue);
connect(positionSlider, &
amp;QAbstractSlider::
rangeChanged, taskbarProgress, &
amp;QWinTaskbarProgress::
setRange);
connect(&
amp;mediaPlayer, &
amp;QMediaPlayer::
stateChanged, this
, &
amp;MusicPlayer::
updateTaskbar);
}
void
MusicPlayer::
createThumbnailToolBar()
{
thumbnailToolBar =
new
QWinThumbnailToolBar(this
);
thumbnailToolBar-&
gt;setWindow(windowHandle());
playToolButton =
new
QWinThumbnailToolButton(thumbnailToolBar);
playToolButton-&
gt;setEnabled(false
);
playToolButton-&
gt;setToolTip(tr("Play"
));
playToolButton-&
gt;setIcon(style()-&
gt;standardIcon(QStyle::
SP_MediaPlay));
connect(playToolButton, &
amp;QWinThumbnailToolButton::
clicked, this
, &
amp;MusicPlayer::
togglePlayback);
forwardToolButton =
new
QWinThumbnailToolButton(thumbnailToolBar);
forwardToolButton-&
gt;setEnabled(false
);
forwardToolButton-&
gt;setToolTip(tr("Fast forward"
));
forwardToolButton-&
gt;setIcon(style()-&
gt;standardIcon(QStyle::
SP_MediaSeekForward));
connect(forwardToolButton, &
amp;QWinThumbnailToolButton::
clicked, this
, &
amp;MusicPlayer::
seekForward);
backwardToolButton =
new
QWinThumbnailToolButton(thumbnailToolBar);
backwardToolButton-&
gt;setEnabled(false
);
backwardToolButton-&
gt;setToolTip(tr("Rewind"
));
backwardToolButton-&
gt;setIcon(style()-&
gt;standardIcon(QStyle::
SP_MediaSeekBackward));
connect(backwardToolButton, &
amp;QWinThumbnailToolButton::
clicked, this
, &
amp;MusicPlayer::
seekBackward);
thumbnailToolBar-&
gt;addButton(backwardToolButton);
thumbnailToolBar-&
gt;addButton(playToolButton);
thumbnailToolBar-&
gt;addButton(forwardToolButton);
connect(&
amp;mediaPlayer, &
amp;QMediaPlayer::
positionChanged, this
, &
amp;MusicPlayer::
updateThumbnailToolBar);
connect(&
amp;mediaPlayer, &
amp;QMediaPlayer::
durationChanged, this
, &
amp;MusicPlayer::
updateThumbnailToolBar);
connect(&
amp;mediaPlayer, &
amp;QMediaPlayer::
stateChanged, this
, &
amp;MusicPlayer::
updateThumbnailToolBar);
}