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