Update copyright headers
[qt:qt.git] / demos / qmediaplayer / mediaplayer.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the demonstration applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ***************************************************************************/
41
42 #include <QtGui>
43
44 #define SLIDER_RANGE 8
45
46 #include "mediaplayer.h"
47 #include "ui_settings.h"
48
49 #ifdef Q_OS_SYMBIAN
50 #include <cdbcols.h>
51 #include <cdblen.h>
52 #include <commdb.h>
53 #endif
54
55 MediaVideoWidget::MediaVideoWidget(MediaPlayer *player, QWidget *parent) :
56     Phonon::VideoWidget(parent), m_player(player), m_action(this)
57 {
58     m_action.setCheckable(true);
59     m_action.setChecked(false);
60     m_action.setShortcut(QKeySequence( Qt::AltModifier + Qt::Key_Return));
61     m_action.setShortcutContext(Qt::WindowShortcut);
62     connect(&m_action, SIGNAL(toggled(bool)), SLOT(setFullScreen(bool)));
63     addAction(&m_action);
64     setAcceptDrops(true);
65 }
66
67 void MediaVideoWidget::setFullScreen(bool enabled)
68 {
69     Phonon::VideoWidget::setFullScreen(enabled);
70     emit fullScreenChanged(enabled);
71 }
72
73 void MediaVideoWidget::mouseDoubleClickEvent(QMouseEvent *e)
74 {
75     Phonon::VideoWidget::mouseDoubleClickEvent(e);
76     setFullScreen(!isFullScreen());
77 }
78
79 void MediaVideoWidget::keyPressEvent(QKeyEvent *e)
80 {
81     if(!e->modifiers()) {
82         // On non-QWERTY Symbian key-based devices, there is no space key.
83         // The zero key typically is marked with a space character.
84         if (e->key() == Qt::Key_Space || e->key() == Qt::Key_0) {
85             m_player->playPause();
86             e->accept();
87             return;
88         }
89
90         // On Symbian devices, there is no key which maps to Qt::Key_Escape
91         // On devices which lack a backspace key (i.e. non-QWERTY devices),
92         // the 'C' key maps to Qt::Key_Backspace
93         else if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Backspace) {
94             setFullScreen(false);
95             e->accept();
96             return;
97         }
98     }
99     Phonon::VideoWidget::keyPressEvent(e);
100 }
101
102 bool MediaVideoWidget::event(QEvent *e)
103 {
104     switch(e->type())
105     {
106     case QEvent::Close:
107         //we just ignore the cose events on the video widget
108         //this prevents ALT+F4 from having an effect in fullscreen mode
109         e->ignore();
110         return true;
111     case QEvent::MouseMove:
112 #ifndef QT_NO_CURSOR
113         unsetCursor();
114 #endif
115         //fall through
116     case QEvent::WindowStateChange:
117         {
118             //we just update the state of the checkbox, in case it wasn't already
119             m_action.setChecked(windowState() & Qt::WindowFullScreen);
120             const Qt::WindowFlags flags = m_player->windowFlags();
121             if (windowState() & Qt::WindowFullScreen) {
122                 m_timer.start(1000, this);
123             } else {
124                 m_timer.stop();
125 #ifndef QT_NO_CURSOR
126                 unsetCursor();
127 #endif
128             }
129         }
130         break;
131     default:
132         break;
133     }
134
135     return Phonon::VideoWidget::event(e);
136 }
137
138 void MediaVideoWidget::timerEvent(QTimerEvent *e)
139 {
140     if (e->timerId() == m_timer.timerId()) {
141         //let's store the cursor shape
142 #ifndef QT_NO_CURSOR
143         setCursor(Qt::BlankCursor);
144 #endif
145     }
146     Phonon::VideoWidget::timerEvent(e);
147 }
148
149 void MediaVideoWidget::dropEvent(QDropEvent *e)
150 {
151     m_player->handleDrop(e);
152 }
153
154 void MediaVideoWidget::dragEnterEvent(QDragEnterEvent *e) {
155     if (e->mimeData()->hasUrls())
156         e->acceptProposedAction();
157 }
158
159
160 MediaPlayer::MediaPlayer() :
161         playButton(0), nextEffect(0), settingsDialog(0), ui(0),
162             m_AudioOutput(Phonon::VideoCategory),
163             m_videoWidget(new MediaVideoWidget(this))
164 {
165     setWindowTitle(tr("Media Player"));
166     setContextMenuPolicy(Qt::CustomContextMenu);
167     m_videoWidget->setContextMenuPolicy(Qt::CustomContextMenu);
168  
169     QSize buttonSize(34, 28);
170
171     QPushButton *openButton = new QPushButton(this);
172
173     openButton->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton));
174     QPalette bpal;
175     QColor arrowcolor = bpal.buttonText().color();
176     if (arrowcolor == Qt::black)
177         arrowcolor = QColor(80, 80, 80);
178     bpal.setBrush(QPalette::ButtonText, arrowcolor);
179     openButton->setPalette(bpal);
180
181     rewindButton = new QPushButton(this);
182     rewindButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward));
183
184     forwardButton = new QPushButton(this);
185     forwardButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipForward));
186     forwardButton->setEnabled(false);
187
188     playButton = new QPushButton(this);
189     playIcon = style()->standardIcon(QStyle::SP_MediaPlay);
190     pauseIcon = style()->standardIcon(QStyle::SP_MediaPause);
191     playButton->setIcon(playIcon);
192
193     slider = new Phonon::SeekSlider(this);
194     slider->setMediaObject(&m_MediaObject);
195     volume = new Phonon::VolumeSlider(&m_AudioOutput);
196  
197     QVBoxLayout *vLayout = new QVBoxLayout(this);
198     vLayout->setContentsMargins(8, 8, 8, 8);    
199
200     QHBoxLayout *layout = new QHBoxLayout();
201
202     info = new QLabel(this);
203     info->setMinimumHeight(70);
204     info->setAcceptDrops(false);
205     info->setMargin(2);
206     info->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
207     info->setLineWidth(2);
208     info->setAutoFillBackground(true);
209
210     QPalette palette;
211     palette.setBrush(QPalette::WindowText, Qt::white);
212 #ifndef Q_WS_MAC
213     openButton->setMinimumSize(54, buttonSize.height());
214     rewindButton->setMinimumSize(buttonSize);
215     forwardButton->setMinimumSize(buttonSize);
216     playButton->setMinimumSize(buttonSize);
217 #endif
218     info->setStyleSheet("border-image:url(:/images/screen.png) ; border-width:3px");
219     info->setPalette(palette);
220     info->setText(tr("<center>No media</center>"));
221
222     volume->setFixedWidth(120);
223
224     layout->addWidget(openButton);
225     layout->addWidget(rewindButton);
226     layout->addWidget(playButton);
227     layout->addWidget(forwardButton);
228
229     layout->addStretch();
230     layout->addWidget(volume);
231
232     vLayout->addWidget(info);
233     initVideoWindow();
234     vLayout->addWidget(&m_videoWindow);
235     QVBoxLayout *buttonPanelLayout = new QVBoxLayout();
236     m_videoWindow.hide();
237     buttonPanelLayout->addLayout(layout);
238     
239     timeLabel = new QLabel(this);
240     progressLabel = new QLabel(this);
241     QWidget *sliderPanel = new QWidget(this);
242     QHBoxLayout *sliderLayout = new QHBoxLayout();
243     sliderLayout->addWidget(slider);
244     sliderLayout->addWidget(timeLabel);    
245     sliderLayout->addWidget(progressLabel);    
246     sliderLayout->setContentsMargins(0, 0, 0, 0);
247     sliderPanel->setLayout(sliderLayout);
248
249     buttonPanelLayout->addWidget(sliderPanel);
250     buttonPanelLayout->setContentsMargins(0, 0, 0, 0);
251 #ifdef Q_OS_MAC
252     layout->setSpacing(4);
253     buttonPanelLayout->setSpacing(0);
254     info->setMinimumHeight(100);
255     info->setFont(QFont("verdana", 15));
256     // QStyle *flatButtonStyle = new QWindowsStyle;
257     openButton->setFocusPolicy(Qt::NoFocus);
258     // openButton->setStyle(flatButtonStyle);
259     // playButton->setStyle(flatButtonStyle);
260     // rewindButton->setStyle(flatButtonStyle);
261     // forwardButton->setStyle(flatButtonStyle);
262  #endif
263     QWidget *buttonPanelWidget = new QWidget(this);
264     buttonPanelWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); 
265     buttonPanelWidget->setLayout(buttonPanelLayout);    
266     vLayout->addWidget(buttonPanelWidget);
267  
268     QHBoxLayout *labelLayout = new QHBoxLayout();
269
270     vLayout->addLayout(labelLayout);
271     setLayout(vLayout);
272
273     // Create menu bar:
274     fileMenu = new QMenu(this);
275     QAction *openFileAction = fileMenu->addAction(tr("Open &File..."));
276     QAction *openUrlAction = fileMenu->addAction(tr("Open &Location..."));
277 #ifdef Q_OS_SYMBIAN
278     QAction *selectIAPAction = fileMenu->addAction(tr("Select &IAP..."));
279     connect(selectIAPAction, SIGNAL(triggered(bool)), this, SLOT(selectIAP()));
280 #endif
281     QAction *const openLinkAction = fileMenu->addAction(tr("Open &RAM File..."));
282
283     connect(openLinkAction, SIGNAL(triggered(bool)), this, SLOT(openRamFile()));
284
285     fileMenu->addSeparator();  
286     QMenu *aspectMenu = fileMenu->addMenu(tr("&Aspect ratio"));
287     QActionGroup *aspectGroup = new QActionGroup(aspectMenu);
288     connect(aspectGroup, SIGNAL(triggered(QAction*)), this, SLOT(aspectChanged(QAction*)));
289     aspectGroup->setExclusive(true);
290     QAction *aspectActionAuto = aspectMenu->addAction(tr("Auto"));
291     aspectActionAuto->setCheckable(true);
292     aspectActionAuto->setChecked(true);
293     aspectGroup->addAction(aspectActionAuto);
294     QAction *aspectActionScale = aspectMenu->addAction(tr("Scale"));
295     aspectActionScale->setCheckable(true);
296     aspectGroup->addAction(aspectActionScale);
297     QAction *aspectAction16_9 = aspectMenu->addAction(tr("16/9"));
298     aspectAction16_9->setCheckable(true);
299     aspectGroup->addAction(aspectAction16_9);
300     QAction *aspectAction4_3 = aspectMenu->addAction(tr("4/3"));
301     aspectAction4_3->setCheckable(true);
302     aspectGroup->addAction(aspectAction4_3);
303
304     QMenu *scaleMenu = fileMenu->addMenu(tr("&Scale mode"));
305     QActionGroup *scaleGroup = new QActionGroup(scaleMenu);
306     connect(scaleGroup, SIGNAL(triggered(QAction*)), this, SLOT(scaleChanged(QAction*)));
307     scaleGroup->setExclusive(true);
308     QAction *scaleActionFit = scaleMenu->addAction(tr("Fit in view"));
309     scaleActionFit->setCheckable(true);
310     scaleActionFit->setChecked(true);
311     scaleGroup->addAction(scaleActionFit);
312     QAction *scaleActionCrop = scaleMenu->addAction(tr("Scale and crop"));
313     scaleActionCrop->setCheckable(true);
314     scaleGroup->addAction(scaleActionCrop);
315
316     m_fullScreenAction = fileMenu->addAction(tr("Full screen video"));
317     m_fullScreenAction->setCheckable(true);
318     m_fullScreenAction->setEnabled(false); // enabled by hasVideoChanged
319     bool b = connect(m_fullScreenAction, SIGNAL(toggled(bool)), m_videoWidget, SLOT(setFullScreen(bool)));
320     Q_ASSERT(b);
321     b = connect(m_videoWidget, SIGNAL(fullScreenChanged(bool)), m_fullScreenAction, SLOT(setChecked(bool)));
322     Q_ASSERT(b);
323
324     fileMenu->addSeparator();
325     QAction *settingsAction = fileMenu->addAction(tr("&Settings..."));
326
327     // Setup signal connections:
328     connect(rewindButton, SIGNAL(clicked()), this, SLOT(rewind()));
329     //connect(openButton, SIGNAL(clicked()), this, SLOT(openFile()));
330     openButton->setMenu(fileMenu);
331
332     connect(playButton, SIGNAL(clicked()), this, SLOT(playPause()));
333     connect(forwardButton, SIGNAL(clicked()), this, SLOT(forward()));
334     //connect(openButton, SIGNAL(clicked()), this, SLOT(openFile()));
335     connect(settingsAction, SIGNAL(triggered(bool)), this, SLOT(showSettingsDialog()));
336     connect(openUrlAction, SIGNAL(triggered(bool)), this, SLOT(openUrl()));
337     connect(openFileAction, SIGNAL(triggered(bool)), this, SLOT(openFile()));
338
339     connect(m_videoWidget, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &)));
340     connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &)));
341     connect(&m_MediaObject, SIGNAL(metaDataChanged()), this, SLOT(updateInfo()));
342     connect(&m_MediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(updateTime()));
343     connect(&m_MediaObject, SIGNAL(tick(qint64)), this, SLOT(updateTime()));
344     connect(&m_MediaObject, SIGNAL(finished()), this, SLOT(finished()));
345     connect(&m_MediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(stateChanged(Phonon::State,Phonon::State)));
346     connect(&m_MediaObject, SIGNAL(bufferStatus(int)), this, SLOT(bufferStatus(int)));
347     connect(&m_MediaObject, SIGNAL(hasVideoChanged(bool)), this, SLOT(hasVideoChanged(bool)));
348
349     rewindButton->setEnabled(false);
350     playButton->setEnabled(false);
351     setAcceptDrops(true);
352
353     m_audioOutputPath = Phonon::createPath(&m_MediaObject, &m_AudioOutput);
354     Phonon::createPath(&m_MediaObject, m_videoWidget);
355
356     resize(minimumSizeHint());
357 }
358
359 void MediaPlayer::stateChanged(Phonon::State newstate, Phonon::State oldstate)
360 {
361     Q_UNUSED(oldstate);
362
363     if (oldstate == Phonon::LoadingState) {
364         QRect videoHintRect = QRect(QPoint(0, 0), m_videoWindow.sizeHint());
365         QRect newVideoRect = QApplication::desktop()->screenGeometry().intersected(videoHintRect);
366         if (!m_smallScreen) {
367             if (m_MediaObject.hasVideo()) {
368                 // Flush event que so that sizeHint takes the
369                 // recently shown/hidden m_videoWindow into account:
370                 qApp->processEvents();
371                 resize(sizeHint());
372             } else
373                 resize(minimumSize());
374         }
375     }
376
377     switch (newstate) {
378         case Phonon::ErrorState:
379             if (m_MediaObject.errorType() == Phonon::FatalError) {
380                 playButton->setEnabled(false);
381                 rewindButton->setEnabled(false);
382             } else {
383                 m_MediaObject.pause();
384             }
385             QMessageBox::warning(this, "Phonon Mediaplayer", m_MediaObject.errorString(), QMessageBox::Close);
386             break;
387
388         case Phonon::StoppedState:
389             m_videoWidget->setFullScreen(false);
390             // Fall through
391         case Phonon::PausedState:
392             playButton->setIcon(playIcon);
393             if (m_MediaObject.currentSource().type() != Phonon::MediaSource::Invalid){
394                 playButton->setEnabled(true);
395                 rewindButton->setEnabled(true);
396             } else {
397                 playButton->setEnabled(false);
398                 rewindButton->setEnabled(false);
399             }
400             break;
401         case Phonon::PlayingState:
402             playButton->setEnabled(true);
403             playButton->setIcon(pauseIcon);
404             if (m_MediaObject.hasVideo())
405                 m_videoWindow.show();
406             // Fall through
407         case Phonon::BufferingState:
408             rewindButton->setEnabled(true);
409             break;
410         case Phonon::LoadingState:
411             rewindButton->setEnabled(false);
412             break;
413     }
414
415 }
416
417 void MediaPlayer::initSettingsDialog()
418 {
419     settingsDialog = new QDialog(this);
420     ui = new Ui_settings();
421     ui->setupUi(settingsDialog);
422
423     connect(ui->brightnessSlider, SIGNAL(valueChanged(int)), this, SLOT(setBrightness(int)));
424     connect(ui->hueSlider, SIGNAL(valueChanged(int)), this, SLOT(setHue(int)));
425     connect(ui->saturationSlider, SIGNAL(valueChanged(int)), this, SLOT(setSaturation(int)));
426     connect(ui->contrastSlider , SIGNAL(valueChanged(int)), this, SLOT(setContrast(int)));
427     connect(ui->aspectCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setAspect(int)));
428     connect(ui->scalemodeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setScale(int)));
429
430     ui->brightnessSlider->setValue(int(m_videoWidget->brightness() * SLIDER_RANGE));
431     ui->hueSlider->setValue(int(m_videoWidget->hue() * SLIDER_RANGE));
432     ui->saturationSlider->setValue(int(m_videoWidget->saturation() * SLIDER_RANGE));
433     ui->contrastSlider->setValue(int(m_videoWidget->contrast() * SLIDER_RANGE));
434     ui->aspectCombo->setCurrentIndex(m_videoWidget->aspectRatio());
435     ui->scalemodeCombo->setCurrentIndex(m_videoWidget->scaleMode());
436     connect(ui->effectButton, SIGNAL(clicked()), this, SLOT(configureEffect()));
437
438 #ifdef Q_WS_X11
439     //Cross fading is not currently implemented in the GStreamer backend
440     ui->crossFadeSlider->setVisible(false);
441     ui->crossFadeLabel->setVisible(false);
442     ui->crossFadeLabel1->setVisible(false);
443     ui->crossFadeLabel2->setVisible(false);
444     ui->crossFadeLabel3->setVisible(false);
445 #endif
446     ui->crossFadeSlider->setValue((int)(2 * m_MediaObject.transitionTime() / 1000.0f));
447     
448     // Insert audio devices:
449     QList<Phonon::AudioOutputDevice> devices = Phonon::BackendCapabilities::availableAudioOutputDevices();
450     for (int i=0; i<devices.size(); i++){
451         QString itemText = devices[i].name();
452         if (!devices[i].description().isEmpty()) {
453             itemText += QString::fromLatin1(" (%1)").arg(devices[i].description());
454         }
455         ui->deviceCombo->addItem(itemText);
456         if (devices[i] == m_AudioOutput.outputDevice())
457             ui->deviceCombo->setCurrentIndex(i);
458     }
459
460     // Insert audio effects:
461     ui->audioEffectsCombo->addItem(tr("<no effect>"));
462     QList<Phonon::Effect *> currEffects = m_audioOutputPath.effects();
463     Phonon::Effect *currEffect = currEffects.size() ? currEffects[0] : 0;
464     QList<Phonon::EffectDescription> availableEffects = Phonon::BackendCapabilities::availableAudioEffects();
465     for (int i=0; i<availableEffects.size(); i++){
466         ui->audioEffectsCombo->addItem(availableEffects[i].name());
467         if (currEffect && availableEffects[i] == currEffect->description())
468             ui->audioEffectsCombo->setCurrentIndex(i+1);
469     }
470     connect(ui->audioEffectsCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(effectChanged()));
471
472 }
473
474 void MediaPlayer::setVolume(qreal volume)
475 {
476     m_AudioOutput.setVolume(volume);
477 }
478
479 void MediaPlayer::setSmallScreen(bool smallScreen)
480 {
481     m_smallScreen = smallScreen;
482 }
483
484 void MediaPlayer::effectChanged()
485 {
486     int currentIndex = ui->audioEffectsCombo->currentIndex();
487     if (currentIndex) {
488         QList<Phonon::EffectDescription> availableEffects = Phonon::BackendCapabilities::availableAudioEffects();
489         Phonon::EffectDescription chosenEffect = availableEffects[currentIndex - 1];
490
491         QList<Phonon::Effect *> currEffects = m_audioOutputPath.effects();
492         Phonon::Effect *currentEffect = currEffects.size() ? currEffects[0] : 0;
493
494         // Deleting the running effect will stop playback, it is deleted when removed from path
495         if (nextEffect && !(currentEffect && (currentEffect->description().name() == nextEffect->description().name())))
496             delete nextEffect;
497
498         nextEffect = new Phonon::Effect(chosenEffect);
499     }
500     ui->effectButton->setEnabled(currentIndex);
501 }
502
503 void MediaPlayer::showSettingsDialog()
504 {
505     const bool hasPausedForDialog = playPauseForDialog();
506
507     if (!settingsDialog)
508         initSettingsDialog();
509
510     float oldBrightness = m_videoWidget->brightness();
511     float oldHue = m_videoWidget->hue();
512     float oldSaturation = m_videoWidget->saturation();
513     float oldContrast = m_videoWidget->contrast();
514     Phonon::VideoWidget::AspectRatio oldAspect = m_videoWidget->aspectRatio();
515     Phonon::VideoWidget::ScaleMode oldScale = m_videoWidget->scaleMode();
516     int currentEffect = ui->audioEffectsCombo->currentIndex();
517     settingsDialog->exec();
518     
519     if (settingsDialog->result() == QDialog::Accepted){
520         m_MediaObject.setTransitionTime((int)(1000 * float(ui->crossFadeSlider->value()) / 2.0f));
521         QList<Phonon::AudioOutputDevice> devices = Phonon::BackendCapabilities::availableAudioOutputDevices();
522         m_AudioOutput.setOutputDevice(devices[ui->deviceCombo->currentIndex()]);
523         QList<Phonon::Effect *> currEffects = m_audioOutputPath.effects();
524         QList<Phonon::EffectDescription> availableEffects = Phonon::BackendCapabilities::availableAudioEffects();
525
526         if (ui->audioEffectsCombo->currentIndex() > 0){
527             Phonon::Effect *currentEffect = currEffects.size() ? currEffects[0] : 0;    
528             if (!currentEffect || currentEffect->description() != nextEffect->description()){
529                 foreach(Phonon::Effect *effect, currEffects) {
530                     m_audioOutputPath.removeEffect(effect);
531                     delete effect;
532                 }
533                 m_audioOutputPath.insertEffect(nextEffect);
534             }
535         } else {
536             foreach(Phonon::Effect *effect, currEffects) {
537                 m_audioOutputPath.removeEffect(effect);
538                 delete effect;
539                 nextEffect = 0;
540             }
541         }
542     } else {
543         // Restore previous settings
544         m_videoWidget->setBrightness(oldBrightness);
545         m_videoWidget->setSaturation(oldSaturation);
546         m_videoWidget->setHue(oldHue);
547         m_videoWidget->setContrast(oldContrast);
548         m_videoWidget->setAspectRatio(oldAspect);
549         m_videoWidget->setScaleMode(oldScale);
550         ui->audioEffectsCombo->setCurrentIndex(currentEffect);
551     }
552
553     if (hasPausedForDialog)
554         m_MediaObject.play();
555 }
556
557 void MediaPlayer::initVideoWindow()
558 {
559     QVBoxLayout *videoLayout = new QVBoxLayout();
560     videoLayout->addWidget(m_videoWidget);
561     videoLayout->setContentsMargins(0, 0, 0, 0);
562     m_videoWindow.setLayout(videoLayout);
563     m_videoWindow.setMinimumSize(100, 100);
564 }
565
566
567 void MediaPlayer::configureEffect()
568 {
569     if (!nextEffect)
570         return;
571
572
573     QList<Phonon::Effect *> currEffects = m_audioOutputPath.effects();
574     const QList<Phonon::EffectDescription> availableEffects = Phonon::BackendCapabilities::availableAudioEffects();
575     if (ui->audioEffectsCombo->currentIndex() > 0) {
576         Phonon::EffectDescription chosenEffect = availableEffects[ui->audioEffectsCombo->currentIndex() - 1];
577
578         QDialog effectDialog;
579         effectDialog.setWindowTitle(tr("Configure effect"));
580         QVBoxLayout *topLayout = new QVBoxLayout(&effectDialog);
581
582         QLabel *description = new QLabel("<b>Description:</b><br>" + chosenEffect.description(), &effectDialog);
583         description->setWordWrap(true); 
584         topLayout->addWidget(description);
585
586         QScrollArea *scrollArea = new QScrollArea(&effectDialog);
587         topLayout->addWidget(scrollArea);
588
589         QVariantList savedParamValues;
590         foreach(Phonon::EffectParameter param, nextEffect->parameters()) {
591             savedParamValues << nextEffect->parameterValue(param);
592         }
593
594         QWidget *scrollWidget = new Phonon::EffectWidget(nextEffect);
595         scrollWidget->setMinimumWidth(320);
596         scrollWidget->setContentsMargins(10, 10, 10,10);
597         scrollArea->setWidget(scrollWidget);
598
599         QDialogButtonBox *bbox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &effectDialog);
600         connect(bbox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), &effectDialog, SLOT(accept()));
601         connect(bbox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), &effectDialog, SLOT(reject()));
602         topLayout->addWidget(bbox);
603
604         effectDialog.exec();
605
606         if (effectDialog.result() != QDialog::Accepted) {
607             //we need to restore the parameters values
608             int currentIndex = 0;
609             foreach(Phonon::EffectParameter param, nextEffect->parameters()) {
610                 nextEffect->setParameterValue(param, savedParamValues.at(currentIndex++));
611             }
612
613         }
614     }
615 }
616
617 void MediaPlayer::handleDrop(QDropEvent *e)
618 {
619     QList<QUrl> urls = e->mimeData()->urls();
620     if (e->proposedAction() == Qt::MoveAction){
621         // Just add to the queue:
622         for (int i=0; i<urls.size(); i++)
623             m_MediaObject.enqueue(Phonon::MediaSource(urls[i].toLocalFile()));
624     } else {
625         // Create new queue:
626         m_MediaObject.clearQueue();
627         if (urls.size() > 0) {
628             QString fileName = urls[0].toLocalFile();
629             QDir dir(fileName);
630             if (dir.exists()) {
631                 dir.setFilter(QDir::Files);            
632                 QStringList entries = dir.entryList();
633                 if (entries.size() > 0) {
634                     setFile(fileName + QDir::separator() +  entries[0]);
635                     for (int i=1; i< entries.size(); ++i)
636                         m_MediaObject.enqueue(fileName + QDir::separator() + entries[i]);
637                 }
638             } else {
639                 setFile(fileName);
640                 for (int i=1; i<urls.size(); i++)
641                     m_MediaObject.enqueue(Phonon::MediaSource(urls[i].toLocalFile()));
642             }        
643         }
644     }
645     forwardButton->setEnabled(m_MediaObject.queue().size() > 0);
646     m_MediaObject.play();
647 }
648
649 void MediaPlayer::dropEvent(QDropEvent *e)
650 {
651     if (e->mimeData()->hasUrls() && e->proposedAction() != Qt::LinkAction) {
652         e->acceptProposedAction();
653         handleDrop(e);
654     } else {
655         e->ignore(); 
656     }
657 }
658
659 void MediaPlayer::dragEnterEvent(QDragEnterEvent *e)
660 {
661     dragMoveEvent(e);
662 }
663
664 void MediaPlayer::dragMoveEvent(QDragMoveEvent *e)
665 {
666     if (e->mimeData()->hasUrls()) {
667         if (e->proposedAction() == Qt::CopyAction || e->proposedAction() == Qt::MoveAction){
668             e->acceptProposedAction();
669         }
670     }
671 }
672
673 void MediaPlayer::playPause()
674 {
675     if (m_MediaObject.state() == Phonon::PlayingState)
676         m_MediaObject.pause();
677     else {
678         if (m_MediaObject.currentTime() == m_MediaObject.totalTime())
679             m_MediaObject.seek(0);
680         m_MediaObject.play();
681     }
682 }
683
684 void MediaPlayer::setFile(const QString &fileName)
685 {
686     setWindowTitle(fileName.right(fileName.length() - fileName.lastIndexOf('/') - 1));
687     m_MediaObject.setCurrentSource(Phonon::MediaSource(fileName));
688     m_MediaObject.play();
689 }
690
691 void MediaPlayer::setLocation(const QString& location)
692 {
693     setWindowTitle(location.right(location.length() - location.lastIndexOf('/') - 1));
694     m_MediaObject.setCurrentSource(Phonon::MediaSource(QUrl::fromEncoded(location.toUtf8())));
695     m_MediaObject.play();
696 }
697
698 bool MediaPlayer::playPauseForDialog()
699 {
700     // If we're running on a small screen, we want to pause the video when
701     // popping up dialogs. We neither want to tamper with the state if the
702     // user has paused.
703     if (m_smallScreen && m_MediaObject.hasVideo()) {
704         if (Phonon::PlayingState == m_MediaObject.state()) {
705             m_MediaObject.pause();
706             return true;
707         }
708     }
709     return false;
710 }
711
712 void MediaPlayer::openFile()
713 {
714     const bool hasPausedForDialog = playPauseForDialog();
715
716     QStringList fileNames = QFileDialog::getOpenFileNames(this, QString(),
717                                                           QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
718
719     if (hasPausedForDialog)
720         m_MediaObject.play();
721
722     m_MediaObject.clearQueue();
723     if (fileNames.size() > 0) {
724         QString fileName = fileNames[0];
725         setFile(fileName);
726         for (int i=1; i<fileNames.size(); i++)
727             m_MediaObject.enqueue(Phonon::MediaSource(fileNames[i]));
728     }
729     forwardButton->setEnabled(m_MediaObject.queue().size() > 0);
730 }
731
732 void MediaPlayer::bufferStatus(int percent)
733 {
734     if (percent == 100)
735         progressLabel->setText(QString());
736     else {
737         QString str = QString::fromLatin1("(%1%)").arg(percent);
738         progressLabel->setText(str);
739     }
740 }
741
742 void MediaPlayer::setSaturation(int val)
743 {
744     m_videoWidget->setSaturation(val / qreal(SLIDER_RANGE));
745 }
746
747 void MediaPlayer::setHue(int val)
748 {
749     m_videoWidget->setHue(val / qreal(SLIDER_RANGE));
750 }
751
752 void MediaPlayer::setAspect(int val)
753 {
754     m_videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatio(val));
755 }
756
757 void MediaPlayer::setScale(int val)
758 {
759     m_videoWidget->setScaleMode(Phonon::VideoWidget::ScaleMode(val));
760 }
761
762 void MediaPlayer::setBrightness(int val)
763 {
764     m_videoWidget->setBrightness(val / qreal(SLIDER_RANGE));
765 }
766
767 void MediaPlayer::setContrast(int val)
768 {
769     m_videoWidget->setContrast(val / qreal(SLIDER_RANGE));
770 }
771
772 void MediaPlayer::updateInfo()
773 {
774     int maxLength = 30;
775     QString font = "<font color=#ffeeaa>";
776     QString fontmono = "<font family=\"monospace,courier new\" color=#ffeeaa>";
777
778     QMap <QString, QString> metaData = m_MediaObject.metaData();
779     QString trackArtist = metaData.value("ARTIST");
780     if (trackArtist.length() > maxLength)
781         trackArtist = trackArtist.left(maxLength) + "...";
782     
783     QString trackTitle = metaData.value("TITLE");
784     int trackBitrate = metaData.value("BITRATE").toInt();
785
786     QString fileName;
787     if (m_MediaObject.currentSource().type() == Phonon::MediaSource::Url) {
788         fileName = m_MediaObject.currentSource().url().toString();
789     } else {
790         fileName = m_MediaObject.currentSource().fileName();
791         fileName = fileName.right(fileName.length() - fileName.lastIndexOf('/') - 1);
792         if (fileName.length() > maxLength)
793             fileName = fileName.left(maxLength) + "...";
794     }
795     
796     QString title;    
797     if (!trackTitle.isEmpty()) {
798         if (trackTitle.length() > maxLength)
799             trackTitle = trackTitle.left(maxLength) + "...";
800         title = "Title: " + font + trackTitle + "<br></font>";
801     } else if (!fileName.isEmpty()) {
802         if (fileName.length() > maxLength)
803             fileName = fileName.left(maxLength) + "...";
804         title = font + fileName + "</font>";
805         if (m_MediaObject.currentSource().type() == Phonon::MediaSource::Url) {
806             title.prepend("Url: ");
807         } else {
808             title.prepend("File: ");
809         }
810     }
811         
812     QString artist;
813     if (!trackArtist.isEmpty())
814         artist = "Artist:  " + font + trackArtist + "</font>";
815
816     QString bitrate;
817     if (trackBitrate != 0)
818         bitrate = "<br>Bitrate:  " + font + QString::number(trackBitrate/1000) + "kbit</font>";
819
820     info->setText(title + artist + bitrate);
821 }
822
823 void MediaPlayer::updateTime()
824 {
825     long len = m_MediaObject.totalTime();
826     long pos = m_MediaObject.currentTime();
827     QString timeString;    
828     if (pos || len)
829     {
830         int sec = pos/1000;
831         int min = sec/60;
832         int hour = min/60;
833         int msec = pos;
834
835         QTime playTime(hour%60, min%60, sec%60, msec%1000);
836         sec = len / 1000;
837         min = sec / 60;
838         hour = min / 60;
839         msec = len;
840
841         QTime stopTime(hour%60, min%60, sec%60, msec%1000);
842         QString timeFormat = "m:ss";
843         if (hour > 0)
844             timeFormat = "h:mm:ss";        
845         timeString = playTime.toString(timeFormat);
846         if (len)
847             timeString += " / " + stopTime.toString(timeFormat);
848     }
849     timeLabel->setText(timeString);
850 }
851
852 void MediaPlayer::rewind()
853 {
854     m_MediaObject.seek(0);
855 }
856
857 void MediaPlayer::forward()
858 {
859     QList<Phonon::MediaSource> queue = m_MediaObject.queue();
860     if (queue.size() > 0) {
861         m_MediaObject.setCurrentSource(queue[0]);
862         forwardButton->setEnabled(queue.size() > 1);
863         m_MediaObject.play();
864     }
865 }
866
867 void MediaPlayer::openUrl()
868 {
869     QSettings settings;
870     settings.beginGroup(QLatin1String("BrowserMainWindow"));
871     QString sourceURL = settings.value("location").toString();
872     bool ok = false;
873     sourceURL = QInputDialog::getText(this, tr("Open Location"), tr("Please enter a valid address here:"), QLineEdit::Normal, sourceURL, &ok);
874     if (ok && !sourceURL.isEmpty()) {
875         setLocation(sourceURL);
876         settings.setValue("location", sourceURL);
877     }
878 }
879
880 /*!
881  \since 4.6
882  */
883 void MediaPlayer::openRamFile()
884 {
885     QSettings settings;
886     settings.beginGroup(QLatin1String("BrowserMainWindow"));
887
888     const QStringList fileNameList(QFileDialog::getOpenFileNames(this,
889                                                                   QString(),
890                                                                   settings.value("openRamFile").toString(),
891                                                                   QLatin1String("RAM files (*.ram)")));
892
893     if (fileNameList.isEmpty())
894         return;
895
896     QFile linkFile;
897     QList<QUrl> list;
898     QByteArray sourceURL;
899     for (int i = 0; i < fileNameList.count(); i++ ) {
900         linkFile.setFileName(fileNameList[i]);
901         if (linkFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
902             while (!linkFile.atEnd()) {
903                 sourceURL = linkFile.readLine().trimmed();
904                 if (!sourceURL.isEmpty()) {
905                     const QUrl url(QUrl::fromEncoded(sourceURL));
906                     if (url.isValid())
907                         list.append(url);
908                 }
909             }
910             linkFile.close();
911         }
912     }
913
914     if (!list.isEmpty()) {
915         m_MediaObject.clearQueue();
916         setLocation(list[0].toString());
917         for (int i = 1; i < list.count(); i++)
918             m_MediaObject.enqueue(Phonon::MediaSource(list[i]));
919         m_MediaObject.play();
920     }
921
922     forwardButton->setEnabled(!m_MediaObject.queue().isEmpty());
923     settings.setValue("openRamFile", fileNameList[0]);
924 }
925
926 void MediaPlayer::finished()
927 {
928 }
929
930 void MediaPlayer::showContextMenu(const QPoint &p)
931 {
932     fileMenu->popup(m_videoWidget->isFullScreen() ? p : mapToGlobal(p));
933 }
934
935 void MediaPlayer::scaleChanged(QAction *act)
936 {
937     if (act->text() == tr("Scale and crop"))
938         m_videoWidget->setScaleMode(Phonon::VideoWidget::ScaleAndCrop);
939     else 
940         m_videoWidget->setScaleMode(Phonon::VideoWidget::FitInView);    
941 }
942
943 void MediaPlayer::aspectChanged(QAction *act)
944 {
945     if (act->text() == tr("16/9"))
946         m_videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatio16_9);
947     else if (act->text() == tr("Scale"))
948         m_videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatioWidget);
949     else if (act->text() == tr("4/3"))
950         m_videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatio4_3);
951     else
952         m_videoWidget->setAspectRatio(Phonon::VideoWidget::AspectRatioAuto);    
953 }
954
955 void MediaPlayer::hasVideoChanged(bool bHasVideo)
956 {
957     info->setVisible(!bHasVideo);
958     m_videoWindow.setVisible(bHasVideo);
959     m_fullScreenAction->setEnabled(bHasVideo);
960 }
961
962 #ifdef Q_OS_SYMBIAN
963 void MediaPlayer::selectIAP()
964 {
965     TRAPD(err, selectIAPL());
966     if (KErrNone != err)
967         QMessageBox::warning(this, "Phonon Mediaplayer", "Error selecting IAP", QMessageBox::Close);
968 }
969
970 void MediaPlayer::selectIAPL()
971 {
972     QVariant currentIAPValue = m_MediaObject.property("InternetAccessPointName");
973     QString currentIAPString = currentIAPValue.toString();
974     bool ok = false;
975     CCommsDatabase *commsDb = CCommsDatabase::NewL(EDatabaseTypeIAP);
976     CleanupStack::PushL(commsDb);
977     commsDb->ShowHiddenRecords();
978     CCommsDbTableView* view = commsDb->OpenTableLC(TPtrC(IAP));
979     QStringList items;
980     TInt currentIAP = 0;
981     for (TInt l = view->GotoFirstRecord(), i = 0; l != KErrNotFound; l = view->GotoNextRecord(), i++) {
982        TBuf<KCommsDbSvrMaxColumnNameLength> iapName;
983        view->ReadTextL(TPtrC(COMMDB_NAME), iapName);
984        QString iapString = QString::fromUtf16(iapName.Ptr(), iapName.Length());
985        items << iapString;
986        if (iapString == currentIAPString)
987            currentIAP = i;
988     }
989     currentIAPString = QInputDialog::getItem(this, tr("Select Access Point"), tr("Select Access Point"), items, currentIAP, false, &ok);
990     if (ok)
991         m_MediaObject.setProperty("InternetAccessPointName", currentIAPString);
992     CleanupStack::PopAndDestroy(2); //commsDB, view
993 }
994 #endif