musicplayer.cpp Example File
					 
					
						musicplayer/musicplayer.cpp
					 
					
/****************************************************************************
**
** 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 & mediaPlayer,  & QMediaPlayer :: positionChanged,  this ,  & MusicPlayer:: updatePosition);
    connect(& mediaPlayer,  & QMediaPlayer :: durationChanged,  this ,  & MusicPlayer:: updateDuration);
    connect(& mediaPlayer,  & QMediaObject :: metaDataAvailableChanged,  this ,  & MusicPlayer:: updateInfo);
    connect(& mediaPlayer,  QOverload < QMediaPlayer :: Error> :: of(& QMediaPlayer :: error), 
            this ,  & MusicPlayer:: handleError);
    connect(& mediaPlayer,  & QMediaPlayer :: stateChanged, 
            this ,  & MusicPlayer:: updateState);
    stylize();
    setAcceptDrops(true );
}
QStringList :: supportedMimeTypes()
{
    QStringList =  QMediaPlayer :: supportedMimeTypes();
    if  (result. isEmpty())
        result. append(QStringLiteral "audio/mpeg" ));
    return  result;
}
void  MusicPlayer:: openFile()
{
    QFileDialog 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 & url)
{
    playButton- > setEnabled(true );
    if  (url. isLocalFile()) {
        const  QString =  url. toLocalFile();
        setWindowFilePath(filePath);
        infoLabel- > setText(QDir :: toNativeSeparators(filePath));
        fileName =  QFileInfo . fileName();
    } else  {
        setWindowFilePath(QString - > 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- > triggerAction(QSlider :: SliderPageStepAdd);
}
void  MusicPlayer:: seekBackward()
{
    positionSlider- > triggerAction(QSlider :: SliderPageStepSub);
}
bool MusicPlayer:: event(QEvent * event)
{
    if  (event- > type() = =  QWinEvent :: CompositionChange | |  event- > type() = =  QWinEvent :: ColorizationChange)
        stylize();
    return  QWidget :: event(event);
}
static  bool canHandleDrop(const  QDropEvent * event)
{
    const  QList < QUrl >  urls =  event- > mimeData()- > urls();
    if  (urls. size() ! =  1 )
        return  false ;
    QMimeDatabase return  MusicPlayer:: supportedMimeTypes(). 
        contains(mimeDatabase. mimeTypeForUrl(urls. constFirst()). name());
}
void  MusicPlayer:: dragEnterEvent(QDragEnterEvent * event)
{
    event- > setAccepted(canHandleDrop(event));
}
void  MusicPlayer:: dropEvent(QDropEvent * event)
{
    event- > accept();
    playUrl(event- > mimeData()- > urls(). constFirst());
}
void  MusicPlayer:: mousePressEvent(QMouseEvent * event)
{
    offset =  event- > globalPos() -  pos();
    event- > accept();
}
void  MusicPlayer:: mouseMoveEvent(QMouseEvent * event)
{
    move(event- > globalPos() -  offset);
    event- > accept();
}
void  MusicPlayer:: mouseReleaseEvent(QMouseEvent * event)
{
    offset =  QPoint - > accept();
}
void  MusicPlayer:: stylize()
{
    if  (QOperatingSystemVersion :: current() <  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- > stylize();
    }
}
void  MusicPlayer:: updateState(QMediaPlayer :: State state)
{
    if  (state = =  QMediaPlayer :: PlayingState) {
        playButton- > setToolTip(tr("Pause" ));
        playButton- > setIcon(style()- > standardIcon(QStyle :: SP_MediaPause));
    } else  {
        playButton- > setToolTip(tr("Play" ));
        playButton- > setIcon(style()- > standardIcon(QStyle :: SP_MediaPlay));
    }
}
static  QString qint64 qint64 =  timeMilliSeconds /  1000 ;
    const  qint64 =  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 - > setValue(position);
    positionLabel- > setText(formatTime(position));
}
void  MusicPlayer:: updateDuration(qint64 - > setRange(0 ,  duration);
    positionSlider- > setEnabled(duration >  0 );
    positionSlider- > 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) >  99 )
        mediaPlayer. setPosition(position);
}
void  MusicPlayer:: updateInfo()
{
    QStringList if  (! fileName. isEmpty())
        info. append(fileName);
    if  (mediaPlayer. isMetaDataAvailable()) {
        QString =  mediaPlayer. metaData(QStringLiteral "Author" )). toString();
        if  (! author. isEmpty())
            info. append(author);
        QString =  mediaPlayer. metaData(QStringLiteral "Title" )). toString();
        if  (! title. isEmpty())
            info. append(title);
    }
    info. append(formatTime(mediaPlayer. duration()));
    infoLabel- > setText(info. join(tr(" - " )));
}
void  MusicPlayer:: handleError()
{
    playButton- > setEnabled(false );
    const  QString =  mediaPlayer. errorString();
    infoLabel- > 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- > setOverlayIcon(style()- > standardIcon(QStyle :: SP_MediaPlay));
        taskbarProgress- > show();
        taskbarProgress- > resume();
        break ;
    case  QMediaPlayer :: PausedState:
        taskbarButton- > setOverlayIcon(style()- > standardIcon(QStyle :: SP_MediaPause));
        taskbarProgress- > show();
        taskbarProgress- > pause();
        break ;
    case  QMediaPlayer :: StoppedState:
        taskbarButton- > setOverlayIcon(style()- > standardIcon(QStyle :: SP_MediaStop));
        taskbarProgress- > hide();
        break ;
    }
}
void  MusicPlayer:: updateThumbnailToolBar()
{
    playToolButton- > setEnabled(mediaPlayer. duration() >  0 );
    backwardToolButton- > setEnabled(mediaPlayer. position() >  0 );
    forwardToolButton- > setEnabled(mediaPlayer. position() <  mediaPlayer. duration());
    if  (mediaPlayer. state() = =  QMediaPlayer :: PlayingState) {
        playToolButton- > setToolTip(tr("Pause" ));
        playToolButton- > setIcon(style()- > standardIcon(QStyle :: SP_MediaPause));
    } else  {
        playToolButton- > setToolTip(tr("Play" ));
        playToolButton- > setIcon(style()- > standardIcon(QStyle :: SP_MediaPlay));
    }
}
void  MusicPlayer:: createWidgets()
{
    playButton =  new  QToolButton this );
    playButton- > setEnabled(false );
    playButton- > setToolTip(tr("Play" ));
    playButton- > setIcon(style()- > standardIcon(QStyle :: SP_MediaPlay));
    connect(playButton,  & QAbstractButton :: clicked,  this ,  & MusicPlayer:: togglePlayback);
    QAbstractButton * openButton =  new  QToolButton this );
    openButton- > setText(tr("..." ));
    openButton- > setToolTip(tr("Open a file..." ));
    openButton- > setFixedSize(playButton- > sizeHint());
    connect(openButton,  & QAbstractButton :: clicked,  this ,  & MusicPlayer:: openFile);
    volumeButton =  new  VolumeButton(this );
    volumeButton- > setToolTip(tr("Adjust volume" ));
    volumeButton- > setVolume(mediaPlayer. volume());
    connect(volumeButton,  & VolumeButton:: volumeChanged,  & mediaPlayer,  & QMediaPlayer :: setVolume);
    positionSlider =  new  QSlider Qt :: Horizontal,  this );
    positionSlider- > setEnabled(false );
    positionSlider- > setToolTip(tr("Seek" ));
    connect(positionSlider,  & QAbstractSlider :: valueChanged,  this ,  & MusicPlayer:: setPosition);
    infoLabel =  new  QLabel this );
    positionLabel =  new  QLabel "00:00" ),  this );
    positionLabel- > setMinimumWidth(positionLabel- > sizeHint(). width());
    QBoxLayout * controlLayout =  new  QHBoxLayout - > setMargin(0 );
    controlLayout- > addWidget(openButton);
    controlLayout- > addWidget(playButton);
    controlLayout- > addWidget(positionSlider);
    controlLayout- > addWidget(positionLabel);
    controlLayout- > addWidget(volumeButton);
    QBoxLayout * mainLayout =  new  QVBoxLayout this );
    mainLayout- > addWidget(infoLabel);
    mainLayout- > addLayout(controlLayout);
}
void  MusicPlayer:: createShortcuts()
{
    QShortcut * quitShortcut =  new  QShortcut QKeySequence :: Quit,  this );
    connect(quitShortcut,  & QShortcut :: activated,  QCoreApplication :: quit);
    QShortcut * openShortcut =  new  QShortcut QKeySequence :: Open,  this );
    connect(openShortcut,  & QShortcut :: activated,  this ,  & MusicPlayer:: openFile);
    QShortcut * toggleShortcut =  new  QShortcut Qt :: Key_Space,  this );
    connect(toggleShortcut,  & QShortcut :: activated,  this ,  & MusicPlayer:: togglePlayback);
    QShortcut * forwardShortcut =  new  QShortcut Qt :: Key_Right,  this );
    connect(forwardShortcut,  & QShortcut :: activated,  this ,  & MusicPlayer:: seekForward);
    QShortcut * backwardShortcut =  new  QShortcut Qt :: Key_Left,  this );
    connect(backwardShortcut,  & QShortcut :: activated,  this ,  & MusicPlayer:: seekBackward);
    QShortcut * increaseShortcut =  new  QShortcut Qt :: Key_Up,  this );
    connect(increaseShortcut,  & QShortcut :: activated,  volumeButton,  & VolumeButton:: increaseVolume);
    QShortcut * decreaseShortcut =  new  QShortcut Qt :: Key_Down,  this );
    connect(decreaseShortcut,  & QShortcut :: activated,  volumeButton,  & VolumeButton:: descreaseVolume);
}
void  MusicPlayer:: createJumpList()
{
    QWinJumpList . recent()- > setVisible(true );
}
void  MusicPlayer:: createTaskbar()
{
    taskbarButton =  new  QWinTaskbarButton this );
    taskbarButton- > setWindow(windowHandle());
    taskbarProgress =  taskbarButton- > progress();
    connect(positionSlider,  & QAbstractSlider :: valueChanged,  taskbarProgress,  & QWinTaskbarProgress :: setValue);
    connect(positionSlider,  & QAbstractSlider :: rangeChanged,  taskbarProgress,  & QWinTaskbarProgress :: setRange);
    connect(& mediaPlayer,  & QMediaPlayer :: stateChanged,  this ,  & MusicPlayer:: updateTaskbar);
}
void  MusicPlayer:: createThumbnailToolBar()
{
    thumbnailToolBar =  new  QWinThumbnailToolBar this );
    thumbnailToolBar- > setWindow(windowHandle());
    playToolButton =  new  QWinThumbnailToolButton - > setEnabled(false );
    playToolButton- > setToolTip(tr("Play" ));
    playToolButton- > setIcon(style()- > standardIcon(QStyle :: SP_MediaPlay));
    connect(playToolButton,  & QWinThumbnailToolButton :: clicked,  this ,  & MusicPlayer:: togglePlayback);
    forwardToolButton =  new  QWinThumbnailToolButton - > setEnabled(false );
    forwardToolButton- > setToolTip(tr("Fast forward" ));
    forwardToolButton- > setIcon(style()- > standardIcon(QStyle :: SP_MediaSeekForward));
    connect(forwardToolButton,  & QWinThumbnailToolButton :: clicked,  this ,  & MusicPlayer:: seekForward);
    backwardToolButton =  new  QWinThumbnailToolButton - > setEnabled(false );
    backwardToolButton- > setToolTip(tr("Rewind" ));
    backwardToolButton- > setIcon(style()- > standardIcon(QStyle :: SP_MediaSeekBackward));
    connect(backwardToolButton,  & QWinThumbnailToolButton :: clicked,  this ,  & MusicPlayer:: seekBackward);
    thumbnailToolBar- > addButton(backwardToolButton);
    thumbnailToolBar- > addButton(playToolButton);
    thumbnailToolBar- > addButton(forwardToolButton);
    connect(& mediaPlayer,  & QMediaPlayer :: positionChanged,  this ,  & MusicPlayer:: updateThumbnailToolBar);
    connect(& mediaPlayer,  & QMediaPlayer :: durationChanged,  this ,  & MusicPlayer:: updateThumbnailToolBar);
    connect(& mediaPlayer,  & QMediaPlayer :: stateChanged,  this ,  & MusicPlayer:: updateThumbnailToolBar);
}