xref: /OK3568_Linux_fs/app/qplayer/qplayer.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the examples of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** BSD License Usage
18 ** Alternatively, you may use this file under the terms of the BSD license
19 ** as follows:
20 **
21 ** "Redistribution and use in source and binary forms, with or without
22 ** modification, are permitted provided that the following conditions are
23 ** met:
24 **   * Redistributions of source code must retain the above copyright
25 **     notice, this list of conditions and the following disclaimer.
26 **   * Redistributions in binary form must reproduce the above copyright
27 **     notice, this list of conditions and the following disclaimer in
28 **     the documentation and/or other materials provided with the
29 **     distribution.
30 **   * Neither the name of The Qt Company Ltd nor the names of its
31 **     contributors may be used to endorse or promote products derived
32 **     from this software without specific prior written permission.
33 **
34 **
35 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 **
47 ** $QT_END_LICENSE$
48 **
49 ****************************************************************************/
50 
51 #include "qplayer.h"
52 #include <QtWidgets>
53 #include <QVideoSurfaceFormat>
54 
55 #define MIME_IS_GIF(s)   !(s).compare("image/gif")
56 #define MIME_IS_IMAGE(s) ((s).startsWith("image/") && !MIME_IS_GIF(s))
57 #define MIME_IS_VIDEO(s) ((s).startsWith("video/") || MIME_IS_GIF(s))
58 #define MIME_IS_AUDIO(s) (s).startsWith("audio/")
59 
QPlayer()60 QPlayer::QPlayer()
61     : player(nullptr, QMediaPlayer::VideoSurface)
62     , list(nullptr)
63     , playButton(nullptr)
64     , positionSlider(nullptr)
65 {
66     exitButton = new QPushButton(tr("Exit"));
67     connect(exitButton, &QAbstractButton::clicked, this, &QPlayer::exit);
68 
69     playButton = new QPushButton;
70     playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
71 
72     connect(playButton, &QAbstractButton::clicked, this, &QPlayer::play);
73 
74     positionSlider = new QSlider(Qt::Horizontal);
75     positionSlider->setRange(0, 0);
76     connect(positionSlider, &QAbstractSlider::sliderMoved, this, &QPlayer::setPosition);
77     connect(positionSlider, &QAbstractSlider::sliderReleased, this, &QPlayer::unMute);
78 
79     controlLayout = new QHBoxLayout;
80     controlLayout->addWidget(exitButton);
81     controlLayout->addWidget(playButton);
82     controlLayout->addWidget(positionSlider);
83     controlLayout->setMargin(0);
84     control = new QWidget();
85     control->setLayout(controlLayout);
86     control->setWindowFlag(Qt::FramelessWindowHint);
87 
88     videoViewer = new QVideoWidget;
89     imageViewer = new QLabel();
90     imageViewer->setAlignment(Qt::AlignCenter);
91     QBoxLayout *mainLayout = new QVBoxLayout();
92     mainLayout->setMargin(0);
93     mainLayout->setSpacing(0);
94     mainLayout->addWidget(videoViewer);
95     mainLayout->addWidget(imageViewer);
96     mainLayout->addWidget(control);
97 
98     QWidget *widget = new QWidget();
99     widget->setLayout(mainLayout);
100 
101     list = new QMediaPlaylist;
102     player.setVideoOutput(videoViewer);
103 
104     setCentralWidget(widget);
105     setWindowState(Qt::WindowMaximized);
106     setWindowFlags(Qt::FramelessWindowHint);
107 
108     QPalette palette = QWidget::palette();
109     palette.setColor(QPalette::Window, Qt::black);
110     setPalette(palette);
111 
112     connect(&player, &QMediaPlayer::stateChanged, this, &QPlayer::mediaStateChanged);
113     connect(&player, &QMediaPlayer::positionChanged, this, &QPlayer::positionChanged);
114     connect(&player, &QMediaPlayer::durationChanged, this, &QPlayer::durationChanged);
115     connect(&player, &QMediaPlayer::currentMediaChanged, this, &QPlayer::currentMediaChanged);
116     connect(&player, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error),
117             this, &QPlayer::handleError);
118     connect(&timer1, &QTimer::timeout, this, &QPlayer::displayImage);
119     connect(&timer2, &QTimer::timeout, this, &QPlayer::next);
120 }
121 
~QPlayer()122 QPlayer::~QPlayer()
123 {
124 }
125 
isPlayerAvailable() const126 bool QPlayer::isPlayerAvailable() const
127 {
128     return player.isAvailable();
129 }
130 
mouseDoubleClickEvent(QMouseEvent * e)131 void QPlayer::mouseDoubleClickEvent(QMouseEvent *e)
132 {
133     if(e->button() == Qt::LeftButton){
134         if(isFullScreen()){
135             showMaximized();
136             control->show();
137         }else {
138             showFullScreen();
139             control->hide();
140         }
141     }
142 }
143 
mouseReleaseEvent(QMouseEvent * e)144 void QPlayer::mouseReleaseEvent(QMouseEvent *e)
145 {
146     if(e->button() == Qt::LeftButton){
147 
148     }
149 }
150 
keyReleaseEvent(QKeyEvent * e)151 void QPlayer::keyReleaseEvent(QKeyEvent *e)
152 {
153     int v;
154 
155     switch(e->key())
156     {
157         case Qt::Key_VolumeUp:
158         case Qt::Key_Up:
159             v = player.volume();
160             if(v < 100){
161                 v = v + 10;
162                 v = v<100?v:100;
163                 player.setVolume(v);
164                 qDebug() << "Key_VolumeUp: " << v;
165             }
166             break;
167         case Qt::Key_VolumeDown:
168         case Qt::Key_Down:
169             v = player.volume();
170             if(v > 0){
171                 v = v - 10;
172                 v = v>0?v:0;
173                 player.setVolume(v);
174                 qDebug() << "Key_VolumeDown: " << v;
175             }
176             break;
177     }
178 }
179 
exit()180 void QPlayer::exit()
181 {
182     qApp->exit(0);
183 }
184 
displayImage()185 void QPlayer::displayImage()
186 {
187     QMimeDatabase db;
188     QUrl url = list->currentMedia().canonicalUrl();
189     QString s = db.mimeTypeForUrl(url).name();
190 
191     player.pause();
192     timer1.stop();
193     if(MIME_IS_IMAGE(s)){
194         QImage img;
195         img.load(url.toLocalFile());
196         int w = geometry().width();
197         int h = geometry().height() * 4 /5;
198         imageViewer->setPixmap(QPixmap::fromImage(img.scaled(w, h, Qt::KeepAspectRatio)));
199         imageViewer->show();
200         if(list->mediaCount() > 1){
201             timer2.start(5000);
202         }
203     }
204 }
205 
next()206 void QPlayer::next()
207 {
208     timer2.stop();
209     list->setCurrentIndex(list->nextIndex());
210     play();
211 }
212 
setPlaylist(QStringList l)213 void QPlayer::setPlaylist(QStringList l)
214 {
215     if(! l.empty()){
216         for(int i = 0; i < l.size(); i++){
217             QString str = l.at(i);
218             QFile f(l.at(i));
219             QUrl u(str);
220 
221             if(f.exists()){
222                 list->addMedia(QUrl::fromLocalFile(str));
223             }else if(u.isValid()){
224                 list->addMedia(u);
225             }
226 
227         }
228         list->setCurrentIndex(1);
229         player.setPlaylist(list);
230     }
231 
232     if(list->mediaCount() > 1){
233         list->setPlaybackMode(QMediaPlaylist::Loop);
234     } else {
235         list->setPlaybackMode(QMediaPlaylist::CurrentItemOnce);
236     }
237 }
238 
load(const QUrl & url)239 void QPlayer::load(const QUrl &url)
240 {
241     player.setMedia(url);
242     playButton->setEnabled(true);
243 }
244 
play()245 void QPlayer::play()
246 {
247     switch(player.state()) {
248     case QMediaPlayer::PlayingState:
249         player.pause();
250         break;
251     default:
252         player.play();
253         break;
254     }
255 }
256 
mediaStateChanged(QMediaPlayer::State state)257 void QPlayer::mediaStateChanged(QMediaPlayer::State state)
258 {
259     switch(state) {
260     case QMediaPlayer::PlayingState:
261         playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
262         break;
263     case QMediaPlayer::StoppedState:
264         qApp->exit(0);
265         break;
266     default:
267         playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
268         break;
269     }
270 }
271 
positionChanged(qint64 position)272 void QPlayer::positionChanged(qint64 position)
273 {
274     positionSlider->setValue(position);
275 }
276 
durationChanged(qint64 duration)277 void QPlayer::durationChanged(qint64 duration)
278 {
279     positionSlider->setRange(0, duration);
280 }
281 
setPosition(int position)282 void QPlayer::setPosition(int position)
283 {
284     if(! player.isSeekable())
285         return;
286     if(! player.isMuted())
287         player.setMuted(true);
288     player.setPosition(position);
289 }
290 
unMute()291 void QPlayer::unMute()
292 {
293     player.setMuted(false);
294 }
295 
currentMediaChanged(const QMediaContent & media)296 void QPlayer::currentMediaChanged(const QMediaContent &media)
297 {
298         QUrl url = media.canonicalUrl();
299         QMimeDatabase db;
300         QMimeType mt = db.mimeTypeForUrl(url);
301         QString s = mt.name();
302         if(MIME_IS_IMAGE(s)){
303             imageViewer->show();
304             player.setVideoOutput(new QVideoWidget);
305             timer1.start(1);
306         }else if (MIME_IS_AUDIO(s)){
307             int w = geometry().width();
308             int h = geometry().height() - controlLayout->sizeHint().height();
309             imageViewer->setPixmap(QPixmap(":/album.jpeg").scaled(w*2/3, h*2/3, Qt::KeepAspectRatio));
310             imageViewer->show();
311             player.setVideoOutput(new QVideoWidget);
312         }else if(MIME_IS_VIDEO(s)){
313             imageViewer->hide();
314             player.setVideoOutput(videoViewer);
315             videoViewer->show();
316         }
317 }
318 
handleError()319 void QPlayer::handleError()
320 {
321     const QString errorString = player.errorString();
322     QString message = "Error: ";
323     if (errorString.isEmpty())
324         message += " #" + QString::number(int(player.error()));
325     else
326         message += errorString;
327     qDebug() << message;
328 
329     if(QMessageBox::critical(this, "Qplayer Error", message)){
330         exit();
331     }
332 }
333