diff options
-rw-r--r-- | demos/qmediaplayer/mediaplayer.cpp | 210 | ||||
-rw-r--r-- | demos/qmediaplayer/mediaplayer.h | 45 | ||||
-rw-r--r-- | demos/qmediaplayer/settings.ui | 351 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/mmf_videoplayer.cpp | 73 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/mmf_videoplayer.h | 7 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/objectdump_symbian.cpp | 2 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/videooutput.cpp | 23 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/videooutput.h | 6 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 42 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_p.h | 42 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_s60.cpp | 3 | ||||
-rw-r--r-- | src/s60installs/s60installs.pro | 2 |
12 files changed, 525 insertions, 281 deletions
diff --git a/demos/qmediaplayer/mediaplayer.cpp b/demos/qmediaplayer/mediaplayer.cpp index f8ca8ea..8f6848f 100644 --- a/demos/qmediaplayer/mediaplayer.cpp +++ b/demos/qmediaplayer/mediaplayer.cpp @@ -47,109 +47,114 @@ #include "ui_settings.h" -class MediaVideoWidget : public Phonon::VideoWidget +MediaVideoWidget::MediaVideoWidget(MediaPlayer *player, QWidget *parent) : + Phonon::VideoWidget(parent), m_player(player), m_action(this) +{ + m_action.setCheckable(true); + m_action.setChecked(false); + m_action.setShortcut(QKeySequence( Qt::AltModifier + Qt::Key_Return)); + m_action.setShortcutContext(Qt::WindowShortcut); + connect(&m_action, SIGNAL(toggled(bool)), SLOT(setFullScreen(bool))); + addAction(&m_action); + setAcceptDrops(true); +} + +void MediaVideoWidget::setFullScreen(bool enabled) { -public: - MediaVideoWidget(MediaPlayer *player, QWidget *parent = 0) : - Phonon::VideoWidget(parent), m_player(player), m_action(this) - { - m_action.setCheckable(true); - m_action.setChecked(false); - m_action.setShortcut(QKeySequence( Qt::AltModifier + Qt::Key_Return)); - m_action.setShortcutContext(Qt::WindowShortcut); - connect(&m_action, SIGNAL(toggled(bool)), SLOT(setFullScreen(bool))); - addAction(&m_action); - setAcceptDrops(true); - } + Phonon::VideoWidget::setFullScreen(enabled); + emit fullScreenChanged(enabled); +} -protected: - void mouseDoubleClickEvent(QMouseEvent *e) - { - Phonon::VideoWidget::mouseDoubleClickEvent(e); - setFullScreen(!isFullScreen()); - } +void MediaVideoWidget::mouseDoubleClickEvent(QMouseEvent *e) +{ + Phonon::VideoWidget::mouseDoubleClickEvent(e); + setFullScreen(!isFullScreen()); +} - void keyPressEvent(QKeyEvent *e) - { - if (e->key() == Qt::Key_Space && !e->modifiers()) { +void MediaVideoWidget::keyPressEvent(QKeyEvent *e) +{ + if(!e->modifiers()) { + // On non-QWERTY Symbian key-based devices, there is no space key. + // The zero key typically is marked with a space character. + if (e->key() == Qt::Key_Space || e->key() == Qt::Key_0) { m_player->playPause(); e->accept(); return; - } else if (e->key() == Qt::Key_Escape && !e->modifiers()) { + } + + // On Symbian devices, there is no key which maps to Qt::Key_Escape + // On devices which lack a backspace key (i.e. non-QWERTY devices), + // the 'C' key maps to Qt::Key_Backspace + else if (e->key() == Qt::Key_Escape || e->key() == Qt::Key_Backspace) { setFullScreen(false); e->accept(); return; } - Phonon::VideoWidget::keyPressEvent(e); } + Phonon::VideoWidget::keyPressEvent(e); +} - bool event(QEvent *e) +bool MediaVideoWidget::event(QEvent *e) +{ + switch(e->type()) { - switch(e->type()) - { - case QEvent::Close: - //we just ignore the cose events on the video widget - //this prevents ALT+F4 from having an effect in fullscreen mode - e->ignore(); - return true; - case QEvent::MouseMove: + case QEvent::Close: + //we just ignore the cose events on the video widget + //this prevents ALT+F4 from having an effect in fullscreen mode + e->ignore(); + return true; + case QEvent::MouseMove: #ifndef QT_NO_CURSOR - unsetCursor(); + unsetCursor(); #endif - //fall through - case QEvent::WindowStateChange: - { - //we just update the state of the checkbox, in case it wasn't already - m_action.setChecked(windowState() & Qt::WindowFullScreen); - const Qt::WindowFlags flags = m_player->windowFlags(); - if (windowState() & Qt::WindowFullScreen) { - m_timer.start(1000, this); - } else { - m_timer.stop(); + //fall through + case QEvent::WindowStateChange: + { + //we just update the state of the checkbox, in case it wasn't already + m_action.setChecked(windowState() & Qt::WindowFullScreen); + const Qt::WindowFlags flags = m_player->windowFlags(); + if (windowState() & Qt::WindowFullScreen) { + m_timer.start(1000, this); + } else { + m_timer.stop(); #ifndef QT_NO_CURSOR - unsetCursor(); + unsetCursor(); #endif - } } - break; - default: - break; } - - return Phonon::VideoWidget::event(e); + break; + default: + break; } - void timerEvent(QTimerEvent *e) - { - if (e->timerId() == m_timer.timerId()) { - //let's store the cursor shape + return Phonon::VideoWidget::event(e); +} + +void MediaVideoWidget::timerEvent(QTimerEvent *e) +{ + if (e->timerId() == m_timer.timerId()) { + //let's store the cursor shape #ifndef QT_NO_CURSOR - setCursor(Qt::BlankCursor); + setCursor(Qt::BlankCursor); #endif - } - Phonon::VideoWidget::timerEvent(e); - } - - void dropEvent(QDropEvent *e) - { - m_player->handleDrop(e); } + Phonon::VideoWidget::timerEvent(e); +} - void dragEnterEvent(QDragEnterEvent *e) { - if (e->mimeData()->hasUrls()) - e->acceptProposedAction(); - } +void MediaVideoWidget::dropEvent(QDropEvent *e) +{ + m_player->handleDrop(e); +} -private: - MediaPlayer *m_player; - QBasicTimer m_timer; - QAction m_action; -}; +void MediaVideoWidget::dragEnterEvent(QDragEnterEvent *e) { + if (e->mimeData()->hasUrls()) + e->acceptProposedAction(); +} MediaPlayer::MediaPlayer(const QString &filePath, const bool hasSmallScreen) : - playButton(0), nextEffect(0), settingsDialog(0), ui(0), + playButton(0), nextEffect(0), settingsDialog(0), ui(0), m_AudioOutput(Phonon::VideoCategory), m_videoWidget(new MediaVideoWidget(this)), m_hasSmallScreen(hasSmallScreen) @@ -300,24 +305,32 @@ MediaPlayer::MediaPlayer(const QString &filePath, QAction *scaleActionCrop = scaleMenu->addAction(tr("Scale and crop")); scaleActionCrop->setCheckable(true); scaleGroup->addAction(scaleActionCrop); - - fileMenu->addSeparator(); + + m_fullScreenAction = fileMenu->addAction(tr("Full screen video")); + m_fullScreenAction->setCheckable(true); + m_fullScreenAction->setEnabled(false); // enabled by hasVideoChanged + bool b = connect(m_fullScreenAction, SIGNAL(toggled(bool)), m_videoWidget, SLOT(setFullScreen(bool))); + Q_ASSERT(b); + b = connect(m_videoWidget, SIGNAL(fullScreenChanged(bool)), m_fullScreenAction, SLOT(setChecked(bool))); + Q_ASSERT(b); + + fileMenu->addSeparator(); QAction *settingsAction = fileMenu->addAction(tr("&Settings...")); - + // Setup signal connections: connect(rewindButton, SIGNAL(clicked()), this, SLOT(rewind())); //connect(openButton, SIGNAL(clicked()), this, SLOT(openFile())); openButton->setMenu(fileMenu); - + connect(playButton, SIGNAL(clicked()), this, SLOT(playPause())); connect(forwardButton, SIGNAL(clicked()), this, SLOT(forward())); //connect(openButton, SIGNAL(clicked()), this, SLOT(openFile())); connect(settingsAction, SIGNAL(triggered(bool)), this, SLOT(showSettingsDialog())); connect(openUrlAction, SIGNAL(triggered(bool)), this, SLOT(openUrl())); connect(openFileAction, SIGNAL(triggered(bool)), this, SLOT(openFile())); - - connect(m_videoWidget, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showContextMenu(QPoint))); - connect(this, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showContextMenu(QPoint))); + + connect(m_videoWidget, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &))); + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &))); connect(&m_MediaObject, SIGNAL(metaDataChanged()), this, SLOT(updateInfo())); connect(&m_MediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(updateTime())); connect(&m_MediaObject, SIGNAL(tick(qint64)), this, SLOT(updateTime())); @@ -366,12 +379,12 @@ void MediaPlayer::stateChanged(Phonon::State newstate, Phonon::State oldstate) } QMessageBox::warning(this, "Phonon Mediaplayer", m_MediaObject.errorString(), QMessageBox::Close); break; - case Phonon::PausedState: - case Phonon::StoppedState: - playButton->setIcon(playIcon); + case Phonon::StoppedState: m_videoWidget->setFullScreen(false); - + // Fall through + case Phonon::PausedState: + playButton->setIcon(playIcon); if (m_MediaObject.currentSource().type() != Phonon::MediaSource::Invalid){ playButton->setEnabled(true); rewindButton->setEnabled(true); @@ -474,7 +487,7 @@ void MediaPlayer::effectChanged() void MediaPlayer::showSettingsDialog() { - playPauseForDialog(); + const bool hasPausedForDialog = playPauseForDialog(); if (!settingsDialog) initSettingsDialog(); @@ -522,7 +535,8 @@ void MediaPlayer::showSettingsDialog() ui->audioEffectsCombo->setCurrentIndex(currentEffect); } - playPauseForDialog(); + if (hasPausedForDialog) + m_MediaObject.play(); } void MediaPlayer::initVideoWindow() @@ -659,24 +673,29 @@ void MediaPlayer::setFile(const QString &fileName) m_MediaObject.play(); } -void MediaPlayer::playPauseForDialog() +bool MediaPlayer::playPauseForDialog() { - // If we're running on a small screen, we want to pause the video - // when popping up dialogs. - if (m_hasSmallScreen && - (Phonon::PlayingState == m_MediaObject.state() || - Phonon::PausedState == m_MediaObject.state())) - playPause(); + // If we're running on a small screen, we want to pause the video when + // popping up dialogs. We neither want to tamper with the state if the + // user has paused. + if (m_hasSmallScreen && m_MediaObject.hasVideo()) { + if (Phonon::PlayingState == m_MediaObject.state()) { + m_MediaObject.pause(); + return true; + } + } + return false; } void MediaPlayer::openFile() { - playPauseForDialog(); + const bool hasPausedForDialog = playPauseForDialog(); QStringList fileNames = QFileDialog::getOpenFileNames(this, QString(), QDesktopServices::storageLocation(QDesktopServices::MusicLocation)); - playPauseForDialog(); + if (hasPausedForDialog) + m_MediaObject.play(); m_MediaObject.clearQueue(); if (fileNames.size() > 0) { @@ -916,4 +935,5 @@ void MediaPlayer::hasVideoChanged(bool bHasVideo) { info->setVisible(!bHasVideo); m_videoWindow.setVisible(bHasVideo); + m_fullScreenAction->setEnabled(bHasVideo); } diff --git a/demos/qmediaplayer/mediaplayer.h b/demos/qmediaplayer/mediaplayer.h index a8f18f0..14ed4ac 100644 --- a/demos/qmediaplayer/mediaplayer.h +++ b/demos/qmediaplayer/mediaplayer.h @@ -47,6 +47,8 @@ #include <QtCore/QTimerEvent> #include <QtGui/QShowEvent> #include <QtGui/QIcon> +#include <QtCore/QBasicTimer> +#include <QtGui/QAction> #include <Phonon/AudioOutput> #include <Phonon/BackendCapabilities> @@ -67,6 +69,36 @@ class QMenu; class Ui_settings; QT_END_NAMESPACE +class MediaPlayer; + +class MediaVideoWidget : public Phonon::VideoWidget +{ + Q_OBJECT + +public: + MediaVideoWidget(MediaPlayer *player, QWidget *parent = 0); + +public slots: + // Over-riding non-virtual Phonon::VideoWidget slot + void setFullScreen(bool); + +signals: + void fullScreenChanged(bool); + +protected: + void mouseDoubleClickEvent(QMouseEvent *e); + void keyPressEvent(QKeyEvent *e); + bool event(QEvent *e); + void timerEvent(QTimerEvent *e); + void dropEvent(QDropEvent *e); + void dragEnterEvent(QDragEnterEvent *e); + +private: + MediaPlayer *m_player; + QBasicTimer m_timer; + QAction m_action; +}; + class MediaPlayer : public QWidget { @@ -74,7 +106,7 @@ class MediaPlayer : public: MediaPlayer(const QString &, const bool hasSmallScreen); - + void dragEnterEvent(QDragEnterEvent *e); void dragMoveEvent(QDragMoveEvent *e); void dropEvent(QDropEvent *e); @@ -82,7 +114,7 @@ public: void setFile(const QString &text); void initVideoWindow(); void initSettingsDialog(); - + public slots: void openFile(); void rewind(); @@ -104,7 +136,7 @@ private slots: void stateChanged(Phonon::State newstate, Phonon::State oldstate); void effectChanged(); void showSettingsDialog(); - void showContextMenu(const QPoint &); + void showContextMenu(const QPoint& point); void bufferStatus(int percent); void openUrl(); void openRamFile(); @@ -112,7 +144,7 @@ private slots: void hasVideoChanged(bool); private: - void playPauseForDialog(); + bool playPauseForDialog(); QIcon playIcon; QIcon pauseIcon; @@ -131,11 +163,12 @@ private: Phonon::Effect *nextEffect; QDialog *settingsDialog; Ui_settings *ui; - + QAction *m_fullScreenAction; + QWidget m_videoWindow; Phonon::MediaObject m_MediaObject; Phonon::AudioOutput m_AudioOutput; - Phonon::VideoWidget *m_videoWidget; + MediaVideoWidget *m_videoWidget; Phonon::Path m_audioOutputPath; const bool m_hasSmallScreen; }; diff --git a/demos/qmediaplayer/settings.ui b/demos/qmediaplayer/settings.ui index d2cedd4..03bd70e 100644 --- a/demos/qmediaplayer/settings.ui +++ b/demos/qmediaplayer/settings.ui @@ -1,283 +1,314 @@ -<ui version="4.0" > +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> <class>settings</class> - <widget class="QDialog" name="settings" > - <property name="geometry" > + <widget class="QDialog" name="settings"> + <property name="geometry"> <rect> <x>0</x> <y>0</y> - <width>360</width> - <height>362</height> + <width>175</width> + <height>397</height> </rect> </property> - <property name="windowTitle" > + <property name="windowTitle"> <string>Settings</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_2" > + <layout class="QVBoxLayout" name="verticalLayout_2"> <item> - <widget class="QGroupBox" name="groupBox" > - <property name="title" > + <widget class="QGroupBox" name="groupBox"> + <property name="title"> <string>Video options:</string> </property> - <property name="flat" > + <property name="flat"> <bool>true</bool> </property> - <layout class="QGridLayout" name="gridLayout" > - <item row="0" column="0" > - <widget class="QLabel" name="label_9" > - <property name="text" > + <layout class="QGridLayout" name="gridLayout"> + <item row="5" column="2"> + <widget class="QComboBox" name="scalemodeCombo"> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContentsOnFirstShow</enum> + </property> + <item> + <property name="text"> + <string>Fit in view</string> + </property> + </item> + <item> + <property name="text"> + <string>Scale and crop</string> + </property> + </item> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_9"> + <property name="text"> <string>Contrast:</string> </property> </widget> </item> - <item row="0" column="1" colspan="2" > - <widget class="QSlider" name="contrastSlider" > - <property name="minimum" > + <item row="0" column="1" colspan="2"> + <widget class="QSlider" name="contrastSlider"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="minimum"> <number>-8</number> </property> - <property name="maximum" > + <property name="maximum"> <number>8</number> </property> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="tickPosition" > + <property name="tickPosition"> <enum>QSlider::TicksBelow</enum> </property> - <property name="tickInterval" > + <property name="tickInterval"> <number>4</number> </property> </widget> </item> - <item row="1" column="0" > - <widget class="QLabel" name="label_8" > - <property name="text" > + <item row="1" column="0"> + <widget class="QLabel" name="label_8"> + <property name="text"> <string>Brightness:</string> </property> </widget> </item> - <item row="1" column="1" colspan="2" > - <widget class="QSlider" name="brightnessSlider" > - <property name="minimum" > + <item row="1" column="1" colspan="2"> + <widget class="QSlider" name="brightnessSlider"> + <property name="minimum"> <number>-8</number> </property> - <property name="maximum" > + <property name="maximum"> <number>8</number> </property> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="tickPosition" > + <property name="tickPosition"> <enum>QSlider::TicksBelow</enum> </property> - <property name="tickInterval" > + <property name="tickInterval"> <number>4</number> </property> </widget> </item> - <item row="2" column="0" > - <widget class="QLabel" name="label_7" > - <property name="text" > + <item row="2" column="0"> + <widget class="QLabel" name="label_7"> + <property name="text"> <string>Saturation:</string> </property> </widget> </item> - <item row="2" column="1" colspan="2" > - <widget class="QSlider" name="saturationSlider" > - <property name="minimum" > + <item row="2" column="1" colspan="2"> + <widget class="QSlider" name="saturationSlider"> + <property name="minimum"> <number>-8</number> </property> - <property name="maximum" > + <property name="maximum"> <number>8</number> </property> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="tickPosition" > + <property name="tickPosition"> <enum>QSlider::TicksBelow</enum> </property> - <property name="tickInterval" > + <property name="tickInterval"> <number>4</number> </property> </widget> </item> - <item row="3" column="0" > - <widget class="QLabel" name="label_2" > - <property name="text" > + <item row="3" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> <string>Hue:</string> </property> </widget> </item> - <item row="3" column="1" colspan="2" > - <widget class="QSlider" name="hueSlider" > - <property name="minimum" > + <item row="3" column="1" colspan="2"> + <widget class="QSlider" name="hueSlider"> + <property name="minimum"> <number>-8</number> </property> - <property name="maximum" > + <property name="maximum"> <number>8</number> </property> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="tickPosition" > + <property name="tickPosition"> <enum>QSlider::TicksBelow</enum> </property> - <property name="tickInterval" > + <property name="tickInterval"> <number>4</number> </property> </widget> </item> - <item row="4" column="0" colspan="2" > - <widget class="QLabel" name="label_10" > - <property name="text" > + <item row="4" column="0" colspan="2"> + <widget class="QLabel" name="label_10"> + <property name="text"> <string>Aspect ratio:</string> </property> </widget> </item> - <item row="4" column="2" > - <widget class="QComboBox" name="aspectCombo" > - <property name="minimumSize" > - <size> - <width>180</width> - <height>0</height> - </size> + <item row="4" column="2"> + <widget class="QComboBox" name="aspectCombo"> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContentsOnFirstShow</enum> </property> <item> - <property name="text" > + <property name="text"> <string>Auto</string> </property> </item> <item> - <property name="text" > + <property name="text"> <string>Stretch</string> </property> </item> <item> - <property name="text" > + <property name="text"> <string>4/3</string> </property> </item> <item> - <property name="text" > + <property name="text"> <string>16/9</string> </property> </item> </widget> </item> - <item row="5" column="0" colspan="2" > - <widget class="QLabel" name="label_11" > - <property name="text" > + <item row="5" column="0" colspan="2"> + <widget class="QLabel" name="label_11"> + <property name="text"> <string>Scale Mode:</string> </property> </widget> </item> - <item row="5" column="2" > - <widget class="QComboBox" name="scalemodeCombo" > - <property name="minimumSize" > - <size> - <width>180</width> - <height>0</height> - </size> - </property> - <item> - <property name="text" > - <string>Fit in view</string> - </property> - </item> - <item> - <property name="text" > - <string>Scale and crop</string> - </property> - </item> - </widget> - </item> </layout> + <zorder>scalemodeCombo</zorder> + <zorder>label_9</zorder> + <zorder>contrastSlider</zorder> + <zorder>label_8</zorder> + <zorder>brightnessSlider</zorder> + <zorder>label_7</zorder> + <zorder>saturationSlider</zorder> + <zorder>label_2</zorder> + <zorder>hueSlider</zorder> + <zorder>label_10</zorder> + <zorder>aspectCombo</zorder> + <zorder>label_11</zorder> </widget> </item> <item> - <widget class="QGroupBox" name="groupBox_2" > - <property name="title" > + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> <string>Audio options:</string> </property> - <property name="flat" > + <property name="flat"> <bool>true</bool> </property> - <layout class="QVBoxLayout" name="verticalLayout" > + <layout class="QVBoxLayout" name="verticalLayout"> <item> - <layout class="QHBoxLayout" > + <layout class="QHBoxLayout"> <item> - <widget class="QLabel" name="label" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Preferred" hsizetype="Maximum" > + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimumSize" > + <property name="minimumSize"> <size> - <width>90</width> + <width>10</width> <height>0</height> </size> </property> - <property name="text" > + <property name="text"> <string>Audio device:</string> </property> - <property name="alignment" > + <property name="alignment"> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> </property> </widget> </item> <item> - <widget class="QComboBox" name="deviceCombo" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Fixed" hsizetype="Minimum" > + <widget class="QComboBox" name="deviceCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> + <property name="minimumSize"> + <size> + <width>10</width> + <height>0</height> + </size> + </property> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToMinimumContentsLength</enum> + </property> </widget> </item> </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout" > + <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <widget class="QLabel" name="label_6" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Preferred" hsizetype="Maximum" > + <widget class="QLabel" name="label_6"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimumSize" > + <property name="minimumSize"> <size> - <width>90</width> + <width>10</width> <height>0</height> </size> </property> - <property name="text" > + <property name="text"> <string>Audio effect:</string> </property> - <property name="alignment" > + <property name="alignment"> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> </property> </widget> </item> <item> - <widget class="QComboBox" name="audioEffectsCombo" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Maximum" hsizetype="Minimum" > + <widget class="QComboBox" name="audioEffectsCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> + <property name="minimumSize"> + <size> + <width>10</width> + <height>0</height> + </size> + </property> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToMinimumContentsLength</enum> + </property> </widget> </item> <item> - <widget class="QToolButton" name="effectButton" > - <property name="enabled" > + <widget class="QToolButton" name="effectButton"> + <property name="enabled"> <bool>false</bool> </property> - <property name="text" > + <property name="text"> <string>Setup</string> </property> </widget> @@ -285,123 +316,123 @@ </layout> </item> <item> - <layout class="QHBoxLayout" > + <layout class="QHBoxLayout"> <item> - <widget class="QLabel" name="crossFadeLabel" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Preferred" hsizetype="Maximum" > + <widget class="QLabel" name="crossFadeLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimumSize" > + <property name="minimumSize"> <size> - <width>90</width> + <width>10</width> <height>0</height> </size> </property> - <property name="text" > + <property name="text"> <string>Cross fade:</string> </property> - <property name="alignment" > + <property name="alignment"> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> </property> </widget> </item> <item> - <layout class="QVBoxLayout" > + <layout class="QVBoxLayout"> <item> - <widget class="QSlider" name="crossFadeSlider" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Fixed" hsizetype="Minimum" > + <widget class="QSlider" name="crossFadeSlider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="minimum" > + <property name="minimum"> <number>-20</number> </property> - <property name="maximum" > + <property name="maximum"> <number>20</number> </property> - <property name="singleStep" > + <property name="singleStep"> <number>1</number> </property> - <property name="pageStep" > + <property name="pageStep"> <number>2</number> </property> - <property name="value" > + <property name="value"> <number>0</number> </property> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="tickPosition" > + <property name="tickPosition"> <enum>QSlider::TicksBelow</enum> </property> </widget> </item> <item> - <layout class="QHBoxLayout" > + <layout class="QHBoxLayout"> <item> - <widget class="QLabel" name="crossFadeLabel1" > - <property name="font" > + <widget class="QLabel" name="crossFadeLabel1"> + <property name="font"> <font> <pointsize>9</pointsize> </font> </property> - <property name="text" > + <property name="text"> <string>-10 Sec</string> </property> </widget> </item> <item> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeHint" stdset="0" > + <property name="sizeHint" stdset="0"> <size> - <width>40</width> + <width>0</width> <height>20</height> </size> </property> </spacer> </item> <item> - <widget class="QLabel" name="crossFadeLabel2" > - <property name="font" > + <widget class="QLabel" name="crossFadeLabel2"> + <property name="font"> <font> <pointsize>9</pointsize> </font> </property> - <property name="text" > + <property name="text"> <string>0</string> </property> </widget> </item> <item> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeHint" stdset="0" > + <property name="sizeHint" stdset="0"> <size> - <width>40</width> + <width>0</width> <height>20</height> </size> </property> </spacer> </item> <item> - <widget class="QLabel" name="crossFadeLabel3" > - <property name="font" > + <widget class="QLabel" name="crossFadeLabel3"> + <property name="font"> <font> <pointsize>9</pointsize> </font> </property> - <property name="text" > - <string>10 Sec</string> + <property name="text"> + <string>10 Sec </string> </property> </widget> </item> @@ -415,11 +446,11 @@ </widget> </item> <item> - <widget class="QDialogButtonBox" name="buttonBox" > - <property name="orientation" > + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="standardButtons" > + <property name="standardButtons"> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> </property> </widget> @@ -434,11 +465,11 @@ <receiver>settings</receiver> <slot>accept()</slot> <hints> - <hint type="sourcelabel" > + <hint type="sourcelabel"> <x>248</x> <y>254</y> </hint> - <hint type="destinationlabel" > + <hint type="destinationlabel"> <x>157</x> <y>274</y> </hint> @@ -450,11 +481,11 @@ <receiver>settings</receiver> <slot>reject()</slot> <hints> - <hint type="sourcelabel" > + <hint type="sourcelabel"> <x>316</x> <y>260</y> </hint> - <hint type="destinationlabel" > + <hint type="destinationlabel"> <x>286</x> <y>274</y> </hint> diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp index 2059fbe..b6f53ae 100644 --- a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp +++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp @@ -50,6 +50,8 @@ MMF::VideoPlayer::VideoPlayer() , m_window(0) , m_totalTime(0) , m_pendingChanges(false) + , m_dsaActive(false) + , m_dsaWasActive(false) { construct(); } @@ -61,6 +63,7 @@ MMF::VideoPlayer::VideoPlayer(const AbstractPlayer& player) , m_window(0) , m_totalTime(0) , m_pendingChanges(false) + , m_dsaActive(false) { construct(); } @@ -86,6 +89,9 @@ void MMF::VideoPlayer::construct() )) ); + // CVideoPlayerUtility::NewL starts DSA + m_dsaActive = true; + if (KErrNone != err) changeState(ErrorState); @@ -315,8 +321,7 @@ void MMF::VideoPlayer::getVideoWindow() m_videoOutput->dump(); initVideoOutput(); - m_window = m_videoOutput->videoWindow(); - updateVideoRect(); + videoWindowChanged(); } else // Top-level window m_window = QApplication::activeWindow()->effectiveWinId()->DrawableWindow(); @@ -349,6 +354,18 @@ void MMF::VideoPlayer::initVideoOutput() Q_ASSERT(connected); connected = connect( + m_videoOutput, SIGNAL(beginVideoWindowNativePaint()), + this, SLOT(suspendDirectScreenAccess()) + ); + Q_ASSERT(connected); + + connected = connect( + m_videoOutput, SIGNAL(endVideoWindowNativePaint()), + this, SLOT(resumeDirectScreenAccess()) + ); + Q_ASSERT(connected); + + connected = connect( m_videoOutput, SIGNAL(aspectRatioChanged()), this, SLOT(aspectRatioChanged()) ); @@ -370,12 +387,48 @@ void MMF::VideoPlayer::videoWindowChanged() TRACE_ENTRY("state %d", state()); m_window = m_videoOutput->videoWindow(); - updateVideoRect(); TRACE_EXIT_0(); } +void MMF::VideoPlayer::suspendDirectScreenAccess() +{ + m_dsaWasActive = stopDirectScreenAccess(); +} + +void MMF::VideoPlayer::resumeDirectScreenAccess() +{ + if(m_dsaWasActive) { + startDirectScreenAccess(); + m_dsaWasActive = false; + } +} + +void MMF::VideoPlayer::startDirectScreenAccess() +{ + if(!m_dsaActive) { + TRAPD(err, m_player->StartDirectScreenAccessL()); + if(KErrNone == err) + m_dsaActive = true; + else + setError(NormalError); + } +} + +bool MMF::VideoPlayer::stopDirectScreenAccess() +{ + const bool dsaWasActive = m_dsaActive; + if(m_dsaActive) { + TRAPD(err, m_player->StopDirectScreenAccessL()); + if(KErrNone == err) + m_dsaActive = false; + else + setError(NormalError); + } + return dsaWasActive; +} + // Helper function for aspect ratio / scale mode handling QSize scaleToAspect(const QSize& srcRect, int aspectWidth, int aspectHeight) { @@ -393,7 +446,18 @@ QSize scaleToAspect(const QSize& srcRect, int aspectWidth, int aspectHeight) void MMF::VideoPlayer::updateVideoRect() { QRect videoRect; - const QRect windowRect = m_videoOutput->videoWindowRect(); + QRect windowRect = m_videoOutput->videoWindowRect(); + + // Clip to physical window size + // This is due to a defect in the layout when running on S60 3.2, which + // results in the rectangle of the video widget extending outside the + // screen in certain circumstances. These include the initial startup + // of the mediaplayer demo in portrait mode. When this rectangle is + // passed to the CVideoPlayerUtility, no video is rendered. + const TSize screenSize = m_screenDevice.SizeInPixels(); + const QRect screenRect(0, 0, screenSize.iWidth, screenSize.iHeight); + windowRect = windowRect.intersected(screenRect); + const QSize windowSize = windowRect.size(); // Calculate size of smallest rect which contains video frame size @@ -553,6 +617,7 @@ void MMF::VideoPlayer::applyVideoWindowChange() TRACE("SetDisplayWindowL err %d", err); setError(NormalError); } else { + m_dsaActive = true; TRAP(err, m_player->SetScaleFactorL(m_scaleWidth, m_scaleHeight, antialias)); if(KErrNone != err) { TRACE("SetScaleFactorL (2) err %d", err); diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.h b/src/3rdparty/phonon/mmf/mmf_videoplayer.h index 599bb88..abb1da8 100644 --- a/src/3rdparty/phonon/mmf/mmf_videoplayer.h +++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.h @@ -72,6 +72,8 @@ public Q_SLOTS: void videoWindowChanged(); void aspectRatioChanged(); void scaleModeChanged(); + void suspendDirectScreenAccess(); + void resumeDirectScreenAccess(); private: void construct(); @@ -89,6 +91,9 @@ private: void applyPendingChanges(); void applyVideoWindowChange(); + void startDirectScreenAccess(); + bool stopDirectScreenAccess(); + // AbstractMediaPlayer virtual int numberOfMetaDataEntries() const; virtual QPair<QString, QString> metaDataEntry(int index) const; @@ -111,6 +116,8 @@ private: qint64 m_totalTime; bool m_pendingChanges; + bool m_dsaActive; + bool m_dsaWasActive; }; diff --git a/src/3rdparty/phonon/mmf/objectdump_symbian.cpp b/src/3rdparty/phonon/mmf/objectdump_symbian.cpp index 2efebdb..edad537 100644 --- a/src/3rdparty/phonon/mmf/objectdump_symbian.cpp +++ b/src/3rdparty/phonon/mmf/objectdump_symbian.cpp @@ -46,7 +46,7 @@ QList<QByteArray> QAnnotatorWidget::annotation(const QObject& object) stream << "widget (Symbian): "; stream << "activated " << extra->activated << ' '; - stream << "disableBlit " << extra->disableBlit << ' '; + stream << "nativePaintMode " << extra->nativePaintMode << ' '; stream.flush(); result.append(array); diff --git a/src/3rdparty/phonon/mmf/videooutput.cpp b/src/3rdparty/phonon/mmf/videooutput.cpp index ddf30de..119dcb1 100644 --- a/src/3rdparty/phonon/mmf/videooutput.cpp +++ b/src/3rdparty/phonon/mmf/videooutput.cpp @@ -34,6 +34,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <coecntrl.h> +#include <coemain.h> // for CCoeEnv + QT_BEGIN_NAMESPACE using namespace Phonon; @@ -72,12 +74,8 @@ MMF::VideoOutput::VideoOutput setAttribute(Qt::WA_NoSystemBackground, true); setAutoFillBackground(false); - // Causes QSymbianControl::Draw not to BitBlt this widget's region of the - // backing store. Since the backing store is (by default) a 16MU bitmap, - // blitting it results in this widget's screen region in the final - // framebuffer having opaque alpha values. This in turn causes the video - // to be invisible when running on the target device. - qt_widget_private(this)->extraData()->disableBlit = true; + qt_widget_private(this)->extraData()->nativePaintMode = QWExtra::ZeroFill; + qt_widget_private(this)->extraData()->receiveNativePaintEvents = true; getVideoWindowRect(); registerForAncestorMoved(); @@ -288,5 +286,18 @@ void MMF::VideoOutput::dump() const #endif } +void MMF::VideoOutput::beginNativePaintEvent(const QRect& /*controlRect*/) +{ + emit beginVideoWindowNativePaint(); +} + +void MMF::VideoOutput::endNativePaintEvent(const QRect& /*controlRect*/) +{ + // Ensure that draw ops are executed into the WSERV output framebuffer + CCoeEnv::Static()->WsSession().Flush(); + + emit endVideoWindowNativePaint(); +} + QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/videooutput.h b/src/3rdparty/phonon/mmf/videooutput.h index 6dfe69d..2788401 100644 --- a/src/3rdparty/phonon/mmf/videooutput.h +++ b/src/3rdparty/phonon/mmf/videooutput.h @@ -63,10 +63,16 @@ public: // Debugging output void dump() const; +public Q_SLOTS: + void beginNativePaintEvent(const QRect& /*controlRect*/); + void endNativePaintEvent(const QRect& /*controlRect*/); + Q_SIGNALS: void videoWindowChanged(); void aspectRatioChanged(); void scaleModeChanged(); + void beginVideoWindowNativePaint(); + void endVideoWindowNativePaint(); protected: // Override QWidget functions diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 89d961c..ab57c32 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -823,6 +823,12 @@ void QSymbianControl::Draw(const TRect& controlRect) const if (!engine) return; + const bool sendNativePaintEvents = qwidget->d_func()->extraData()->receiveNativePaintEvents; + if (sendNativePaintEvents) { + const QRect r = qt_TRect2QRect(controlRect); + QMetaObject::invokeMethod(qwidget, "beginNativePaintEvent", Qt::DirectConnection, Q_ARG(QRect, r)); + } + // Map source rectangle into coordinates of the backing store. const QPoint controlBase(controlRect.iTl.iX, controlRect.iTl.iY); const QPoint backingStoreBase = qwidget->mapTo(qwidget->window(), controlBase); @@ -833,14 +839,48 @@ void QSymbianControl::Draw(const TRect& controlRect) const CFbsBitmap *bitmap = s60Surface->symbianBitmap(); CWindowGc &gc = SystemGc(); - if(!qwidget->d_func()->extraData()->disableBlit) { + switch(qwidget->d_func()->extraData()->nativePaintMode) { + case QWExtra::Disable: + // Do nothing + break; + + case QWExtra::Blit: if (qwidget->d_func()->isOpaque) gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); gc.BitBlt(controlRect.iTl, bitmap, backingStoreRect); + break; + + case QWExtra::ZeroFill: + if (Window().DisplayMode() == EColor16MA) { + gc.SetBrushStyle(CGraphicsContext::ESolidBrush); + gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); + gc.SetBrushColor(TRgb::Color16MA(0)); + gc.Clear(controlRect); + } else { + gc.SetBrushColor(TRgb(0x000000)); + gc.Clear(controlRect); + }; + break; + + default: + Q_ASSERT(false); } } else { surface->flush(qwidget, QRegion(qt_TRect2QRect(backingStoreRect)), QPoint()); } + + if (sendNativePaintEvents) { + const QRect r = qt_TRect2QRect(controlRect); + // The draw ops aren't actually sent to WSERV until the graphics + // context is deactivated, which happens in the function calling + // this one. We therefore delay the delivery of endNativePaintEvent, + // to ensure that drawing has completed by the time the widget + // receives the event. Note that, if the widget needs to ensure + // that the draw ops have actually been executed into the output + // framebuffer, a call to RWsSession::Flush is required in the + // endNativePaintEvent implementation. + QMetaObject::invokeMethod(qwidget, "endNativePaintEvent", Qt::QueuedConnection, Q_ARG(QRect, r)); + } } void QSymbianControl::SizeChanged() diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 66efcb5..04cf4bb 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -230,12 +230,42 @@ struct QWExtra { #elif defined(Q_OS_SYMBIAN) // <----------------------------------------------------- Symbian uint activated : 1; // RWindowBase::Activated has been called - // If set, QSymbianControl::Draw does not blit this widget - // This is to allow, for use cases such as video, widgets which, from the Qt point - // of view, are just placeholders in the scene. For these widgets, any necessary - // drawing to the UI framebuffer is done by the relevant Symbian subsystem. For - // video rendering, this would be an MMF controller, or MDF post-processor. - uint disableBlit : 1; + /** + * Defines the behaviour of QSymbianControl::Draw. + */ + enum NativePaintMode { + /** + * Normal drawing mode: blits the required region of the backing store + * via WSERV. + */ + Blit, + + /** + * Disable drawing for this widget. + */ + Disable, + + /** + * Paint zeros into the WSERV framebuffer, using BitGDI APIs. For windows + * with an EColor16MU display mode, zero is written only into the R, G and B + * channels of the pixel. + */ + ZeroFill, + + Default = Blit + }; + + NativePaintMode nativePaintMode : 2; + + /** + * If this bit is set, each native widget receives the signals from the + * Symbian control immediately before and immediately after draw ops are + * sent to the window server for this control: + * void beginNativePaintEvent(const QRect &paintRect); + * void endNativePaintEvent(const QRect &paintRect); + */ + uint receiveNativePaintEvents : 1; + #endif }; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 359df2a..37614c7 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -881,7 +881,8 @@ void QWidgetPrivate::deleteTLSysExtra() void QWidgetPrivate::createSysExtra() { extra->activated = 0; - extra->disableBlit = 0; + extra->nativePaintMode = QWExtra::Default; + extra->receiveNativePaintEvents = 0; } void QWidgetPrivate::deleteSysExtra() diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index 2d9c489..37adfa9 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -90,7 +90,7 @@ symbian: { } contains(QT_CONFIG, phonon): { - qtlibraries.sources += Phonon.dll + qtlibraries.sources += phonon.dll } contains(QT_CONFIG, script): { |