45 |
45 |
46 #include "mediaplayer.h" |
46 #include "mediaplayer.h" |
47 #include "ui_settings.h" |
47 #include "ui_settings.h" |
48 |
48 |
49 |
49 |
50 class MediaVideoWidget : public Phonon::VideoWidget |
50 MediaVideoWidget::MediaVideoWidget(MediaPlayer *player, QWidget *parent) : |
51 { |
51 Phonon::VideoWidget(parent), m_player(player), m_action(this) |
52 public: |
52 { |
53 MediaVideoWidget(MediaPlayer *player, QWidget *parent = 0) : |
53 m_action.setCheckable(true); |
54 Phonon::VideoWidget(parent), m_player(player), m_action(this) |
54 m_action.setChecked(false); |
55 { |
55 m_action.setShortcut(QKeySequence( Qt::AltModifier + Qt::Key_Return)); |
56 m_action.setCheckable(true); |
56 m_action.setShortcutContext(Qt::WindowShortcut); |
57 m_action.setChecked(false); |
57 connect(&m_action, SIGNAL(toggled(bool)), SLOT(setFullScreen(bool))); |
58 m_action.setShortcut(QKeySequence( Qt::AltModifier + Qt::Key_Return)); |
58 addAction(&m_action); |
59 m_action.setShortcutContext(Qt::WindowShortcut); |
59 setAcceptDrops(true); |
60 connect(&m_action, SIGNAL(toggled(bool)), SLOT(setFullScreen(bool))); |
60 } |
61 addAction(&m_action); |
61 |
62 setAcceptDrops(true); |
62 void MediaVideoWidget::setFullScreen(bool enabled) |
63 } |
63 { |
64 |
64 Phonon::VideoWidget::setFullScreen(enabled); |
65 protected: |
65 emit fullScreenChanged(enabled); |
66 void mouseDoubleClickEvent(QMouseEvent *e) |
66 } |
67 { |
67 |
68 Phonon::VideoWidget::mouseDoubleClickEvent(e); |
68 void MediaVideoWidget::mouseDoubleClickEvent(QMouseEvent *e) |
69 setFullScreen(!isFullScreen()); |
69 { |
70 } |
70 Phonon::VideoWidget::mouseDoubleClickEvent(e); |
71 |
71 setFullScreen(!isFullScreen()); |
72 void keyPressEvent(QKeyEvent *e) |
72 } |
73 { |
73 |
74 if (e->key() == Qt::Key_Space && !e->modifiers()) { |
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) { |
75 m_player->playPause(); |
80 m_player->playPause(); |
76 e->accept(); |
81 e->accept(); |
77 return; |
82 return; |
78 } else if (e->key() == Qt::Key_Escape && !e->modifiers()) { |
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) { |
79 setFullScreen(false); |
89 setFullScreen(false); |
80 e->accept(); |
90 e->accept(); |
81 return; |
91 return; |
82 } |
92 } |
83 Phonon::VideoWidget::keyPressEvent(e); |
93 } |
84 } |
94 Phonon::VideoWidget::keyPressEvent(e); |
85 |
95 } |
86 bool event(QEvent *e) |
96 |
|
97 bool MediaVideoWidget::event(QEvent *e) |
|
98 { |
|
99 switch(e->type()) |
87 { |
100 { |
88 switch(e->type()) |
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: |
89 { |
112 { |
90 case QEvent::Close: |
113 //we just update the state of the checkbox, in case it wasn't already |
91 //we just ignore the cose events on the video widget |
114 m_action.setChecked(windowState() & Qt::WindowFullScreen); |
92 //this prevents ALT+F4 from having an effect in fullscreen mode |
115 const Qt::WindowFlags flags = m_player->windowFlags(); |
93 e->ignore(); |
116 if (windowState() & Qt::WindowFullScreen) { |
94 return true; |
117 m_timer.start(1000, this); |
95 case QEvent::MouseMove: |
118 } else { |
|
119 m_timer.stop(); |
96 #ifndef QT_NO_CURSOR |
120 #ifndef QT_NO_CURSOR |
97 unsetCursor(); |
121 unsetCursor(); |
98 #endif |
122 #endif |
99 //fall through |
123 } |
100 case QEvent::WindowStateChange: |
124 } |
101 { |
125 break; |
102 //we just update the state of the checkbox, in case it wasn't already |
126 default: |
103 m_action.setChecked(windowState() & Qt::WindowFullScreen); |
127 break; |
104 const Qt::WindowFlags flags = m_player->windowFlags(); |
128 } |
105 if (windowState() & Qt::WindowFullScreen) { |
129 |
106 m_timer.start(1000, this); |
130 return Phonon::VideoWidget::event(e); |
107 } else { |
131 } |
108 m_timer.stop(); |
132 |
|
133 void MediaVideoWidget::timerEvent(QTimerEvent *e) |
|
134 { |
|
135 if (e->timerId() == m_timer.timerId()) { |
|
136 //let's store the cursor shape |
109 #ifndef QT_NO_CURSOR |
137 #ifndef QT_NO_CURSOR |
110 unsetCursor(); |
138 setCursor(Qt::BlankCursor); |
111 #endif |
139 #endif |
112 } |
140 } |
113 } |
141 Phonon::VideoWidget::timerEvent(e); |
114 break; |
142 } |
115 default: |
143 |
116 break; |
144 void MediaVideoWidget::dropEvent(QDropEvent *e) |
117 } |
145 { |
118 |
146 m_player->handleDrop(e); |
119 return Phonon::VideoWidget::event(e); |
147 } |
120 } |
148 |
121 |
149 void MediaVideoWidget::dragEnterEvent(QDragEnterEvent *e) { |
122 void timerEvent(QTimerEvent *e) |
150 if (e->mimeData()->hasUrls()) |
123 { |
151 e->acceptProposedAction(); |
124 if (e->timerId() == m_timer.timerId()) { |
152 } |
125 //let's store the cursor shape |
|
126 #ifndef QT_NO_CURSOR |
|
127 setCursor(Qt::BlankCursor); |
|
128 #endif |
|
129 } |
|
130 Phonon::VideoWidget::timerEvent(e); |
|
131 } |
|
132 |
|
133 void dropEvent(QDropEvent *e) |
|
134 { |
|
135 m_player->handleDrop(e); |
|
136 } |
|
137 |
|
138 void dragEnterEvent(QDragEnterEvent *e) { |
|
139 if (e->mimeData()->hasUrls()) |
|
140 e->acceptProposedAction(); |
|
141 } |
|
142 |
|
143 private: |
|
144 MediaPlayer *m_player; |
|
145 QBasicTimer m_timer; |
|
146 QAction m_action; |
|
147 }; |
|
148 |
153 |
149 |
154 |
150 MediaPlayer::MediaPlayer(const QString &filePath, |
155 MediaPlayer::MediaPlayer(const QString &filePath, |
151 const bool hasSmallScreen) : |
156 const bool hasSmallScreen) : |
152 playButton(0), nextEffect(0), settingsDialog(0), ui(0), |
157 playButton(0), nextEffect(0), settingsDialog(0), ui(0), |
153 m_AudioOutput(Phonon::VideoCategory), |
158 m_AudioOutput(Phonon::VideoCategory), |
154 m_videoWidget(new MediaVideoWidget(this)), |
159 m_videoWidget(new MediaVideoWidget(this)), |
155 m_hasSmallScreen(hasSmallScreen) |
160 m_hasSmallScreen(hasSmallScreen) |
156 { |
161 { |
157 setWindowTitle(tr("Media Player")); |
162 setWindowTitle(tr("Media Player")); |
264 |
269 |
265 // Create menu bar: |
270 // Create menu bar: |
266 fileMenu = new QMenu(this); |
271 fileMenu = new QMenu(this); |
267 QAction *openFileAction = fileMenu->addAction(tr("Open &File...")); |
272 QAction *openFileAction = fileMenu->addAction(tr("Open &File...")); |
268 QAction *openUrlAction = fileMenu->addAction(tr("Open &Location...")); |
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())); |
269 |
277 |
270 fileMenu->addSeparator(); |
278 fileMenu->addSeparator(); |
271 QMenu *aspectMenu = fileMenu->addMenu(tr("&Aspect ratio")); |
279 QMenu *aspectMenu = fileMenu->addMenu(tr("&Aspect ratio")); |
272 QActionGroup *aspectGroup = new QActionGroup(aspectMenu); |
280 QActionGroup *aspectGroup = new QActionGroup(aspectMenu); |
273 connect(aspectGroup, SIGNAL(triggered(QAction *)), this, SLOT(aspectChanged(QAction *))); |
281 connect(aspectGroup, SIGNAL(triggered(QAction*)), this, SLOT(aspectChanged(QAction*))); |
274 aspectGroup->setExclusive(true); |
282 aspectGroup->setExclusive(true); |
275 QAction *aspectActionAuto = aspectMenu->addAction(tr("Auto")); |
283 QAction *aspectActionAuto = aspectMenu->addAction(tr("Auto")); |
276 aspectActionAuto->setCheckable(true); |
284 aspectActionAuto->setCheckable(true); |
277 aspectActionAuto->setChecked(true); |
285 aspectActionAuto->setChecked(true); |
278 aspectGroup->addAction(aspectActionAuto); |
286 aspectGroup->addAction(aspectActionAuto); |
286 aspectAction4_3->setCheckable(true); |
294 aspectAction4_3->setCheckable(true); |
287 aspectGroup->addAction(aspectAction4_3); |
295 aspectGroup->addAction(aspectAction4_3); |
288 |
296 |
289 QMenu *scaleMenu = fileMenu->addMenu(tr("&Scale mode")); |
297 QMenu *scaleMenu = fileMenu->addMenu(tr("&Scale mode")); |
290 QActionGroup *scaleGroup = new QActionGroup(scaleMenu); |
298 QActionGroup *scaleGroup = new QActionGroup(scaleMenu); |
291 connect(scaleGroup, SIGNAL(triggered(QAction *)), this, SLOT(scaleChanged(QAction *))); |
299 connect(scaleGroup, SIGNAL(triggered(QAction*)), this, SLOT(scaleChanged(QAction*))); |
292 scaleGroup->setExclusive(true); |
300 scaleGroup->setExclusive(true); |
293 QAction *scaleActionFit = scaleMenu->addAction(tr("Fit in view")); |
301 QAction *scaleActionFit = scaleMenu->addAction(tr("Fit in view")); |
294 scaleActionFit->setCheckable(true); |
302 scaleActionFit->setCheckable(true); |
295 scaleActionFit->setChecked(true); |
303 scaleActionFit->setChecked(true); |
296 scaleGroup->addAction(scaleActionFit); |
304 scaleGroup->addAction(scaleActionFit); |
297 QAction *scaleActionCrop = scaleMenu->addAction(tr("Scale and crop")); |
305 QAction *scaleActionCrop = scaleMenu->addAction(tr("Scale and crop")); |
298 scaleActionCrop->setCheckable(true); |
306 scaleActionCrop->setCheckable(true); |
299 scaleGroup->addAction(scaleActionCrop); |
307 scaleGroup->addAction(scaleActionCrop); |
300 |
308 |
301 fileMenu->addSeparator(); |
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(); |
302 QAction *settingsAction = fileMenu->addAction(tr("&Settings...")); |
318 QAction *settingsAction = fileMenu->addAction(tr("&Settings...")); |
303 |
319 |
304 // Setup signal connections: |
320 // Setup signal connections: |
305 connect(rewindButton, SIGNAL(clicked()), this, SLOT(rewind())); |
321 connect(rewindButton, SIGNAL(clicked()), this, SLOT(rewind())); |
306 //connect(openButton, SIGNAL(clicked()), this, SLOT(openFile())); |
322 //connect(openButton, SIGNAL(clicked()), this, SLOT(openFile())); |
307 openButton->setMenu(fileMenu); |
323 openButton->setMenu(fileMenu); |
308 |
324 |
309 connect(playButton, SIGNAL(clicked()), this, SLOT(playPause())); |
325 connect(playButton, SIGNAL(clicked()), this, SLOT(playPause())); |
310 connect(forwardButton, SIGNAL(clicked()), this, SLOT(forward())); |
326 connect(forwardButton, SIGNAL(clicked()), this, SLOT(forward())); |
311 //connect(openButton, SIGNAL(clicked()), this, SLOT(openFile())); |
327 //connect(openButton, SIGNAL(clicked()), this, SLOT(openFile())); |
312 connect(settingsAction, SIGNAL(triggered(bool)), this, SLOT(showSettingsDialog())); |
328 connect(settingsAction, SIGNAL(triggered(bool)), this, SLOT(showSettingsDialog())); |
313 connect(openUrlAction, SIGNAL(triggered(bool)), this, SLOT(openUrl())); |
329 connect(openUrlAction, SIGNAL(triggered(bool)), this, SLOT(openUrl())); |
314 connect(openFileAction, SIGNAL(triggered(bool)), this, SLOT(openFile())); |
330 connect(openFileAction, SIGNAL(triggered(bool)), this, SLOT(openFile())); |
315 |
331 |
316 connect(m_videoWidget, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &))); |
332 connect(m_videoWidget, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &))); |
317 connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &))); |
333 connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(showContextMenu(const QPoint &))); |
318 connect(&m_MediaObject, SIGNAL(metaDataChanged()), this, SLOT(updateInfo())); |
334 connect(&m_MediaObject, SIGNAL(metaDataChanged()), this, SLOT(updateInfo())); |
319 connect(&m_MediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(updateTime())); |
335 connect(&m_MediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(updateTime())); |
320 connect(&m_MediaObject, SIGNAL(tick(qint64)), this, SLOT(updateTime())); |
336 connect(&m_MediaObject, SIGNAL(tick(qint64)), this, SLOT(updateTime())); |
321 connect(&m_MediaObject, SIGNAL(finished()), this, SLOT(finished())); |
337 connect(&m_MediaObject, SIGNAL(finished()), this, SLOT(finished())); |
322 connect(&m_MediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged(Phonon::State, Phonon::State))); |
338 connect(&m_MediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(stateChanged(Phonon::State,Phonon::State))); |
323 connect(&m_MediaObject, SIGNAL(bufferStatus(int)), this, SLOT(bufferStatus(int))); |
339 connect(&m_MediaObject, SIGNAL(bufferStatus(int)), this, SLOT(bufferStatus(int))); |
324 connect(&m_MediaObject, SIGNAL(hasVideoChanged(bool)), this, SLOT(hasVideoChanged(bool))); |
340 connect(&m_MediaObject, SIGNAL(hasVideoChanged(bool)), this, SLOT(hasVideoChanged(bool))); |
325 |
341 |
326 rewindButton->setEnabled(false); |
342 rewindButton->setEnabled(false); |
327 playButton->setEnabled(false); |
343 playButton->setEnabled(false); |
353 } |
369 } |
354 } |
370 } |
355 |
371 |
356 switch (newstate) { |
372 switch (newstate) { |
357 case Phonon::ErrorState: |
373 case Phonon::ErrorState: |
358 QMessageBox::warning(this, "Phonon Mediaplayer", m_MediaObject.errorString(), QMessageBox::Close); |
|
359 if (m_MediaObject.errorType() == Phonon::FatalError) { |
374 if (m_MediaObject.errorType() == Phonon::FatalError) { |
360 playButton->setEnabled(false); |
375 playButton->setEnabled(false); |
361 rewindButton->setEnabled(false); |
376 rewindButton->setEnabled(false); |
362 } else { |
377 } else { |
363 m_MediaObject.pause(); |
378 m_MediaObject.pause(); |
364 } |
379 } |
|
380 QMessageBox::warning(this, "Phonon Mediaplayer", m_MediaObject.errorString(), QMessageBox::Close); |
365 break; |
381 break; |
|
382 |
|
383 case Phonon::StoppedState: |
|
384 m_videoWidget->setFullScreen(false); |
|
385 // Fall through |
366 case Phonon::PausedState: |
386 case Phonon::PausedState: |
367 case Phonon::StoppedState: |
|
368 playButton->setIcon(playIcon); |
387 playButton->setIcon(playIcon); |
369 |
|
370 m_videoWidget->setFullScreen(false); |
|
371 |
|
372 if (m_MediaObject.currentSource().type() != Phonon::MediaSource::Invalid){ |
388 if (m_MediaObject.currentSource().type() != Phonon::MediaSource::Invalid){ |
373 playButton->setEnabled(true); |
389 playButton->setEnabled(true); |
374 rewindButton->setEnabled(true); |
390 rewindButton->setEnabled(true); |
375 } else { |
391 } else { |
376 playButton->setEnabled(false); |
392 playButton->setEnabled(false); |
650 setWindowTitle(fileName.right(fileName.length() - fileName.lastIndexOf('/') - 1)); |
671 setWindowTitle(fileName.right(fileName.length() - fileName.lastIndexOf('/') - 1)); |
651 m_MediaObject.setCurrentSource(Phonon::MediaSource(fileName)); |
672 m_MediaObject.setCurrentSource(Phonon::MediaSource(fileName)); |
652 m_MediaObject.play(); |
673 m_MediaObject.play(); |
653 } |
674 } |
654 |
675 |
|
676 bool MediaPlayer::playPauseForDialog() |
|
677 { |
|
678 // If we're running on a small screen, we want to pause the video when |
|
679 // popping up dialogs. We neither want to tamper with the state if the |
|
680 // user has paused. |
|
681 if (m_hasSmallScreen && m_MediaObject.hasVideo()) { |
|
682 if (Phonon::PlayingState == m_MediaObject.state()) { |
|
683 m_MediaObject.pause(); |
|
684 return true; |
|
685 } |
|
686 } |
|
687 return false; |
|
688 } |
|
689 |
655 void MediaPlayer::openFile() |
690 void MediaPlayer::openFile() |
656 { |
691 { |
|
692 const bool hasPausedForDialog = playPauseForDialog(); |
|
693 |
657 QStringList fileNames = QFileDialog::getOpenFileNames(this, QString(), |
694 QStringList fileNames = QFileDialog::getOpenFileNames(this, QString(), |
658 QDesktopServices::storageLocation(QDesktopServices::MusicLocation)); |
695 QDesktopServices::storageLocation(QDesktopServices::MusicLocation)); |
|
696 |
|
697 if (hasPausedForDialog) |
|
698 m_MediaObject.play(); |
|
699 |
659 m_MediaObject.clearQueue(); |
700 m_MediaObject.clearQueue(); |
660 if (fileNames.size() > 0) { |
701 if (fileNames.size() > 0) { |
661 QString fileName = fileNames[0]; |
702 QString fileName = fileNames[0]; |
662 setFile(fileName); |
703 setFile(fileName); |
663 for (int i=1; i<fileNames.size(); i++) |
704 for (int i=1; i<fileNames.size(); i++) |
814 m_MediaObject.play(); |
855 m_MediaObject.play(); |
815 settings.setValue("location", sourceURL); |
856 settings.setValue("location", sourceURL); |
816 } |
857 } |
817 } |
858 } |
818 |
859 |
|
860 /*! |
|
861 \since 4.6 |
|
862 */ |
|
863 void MediaPlayer::openRamFile() |
|
864 { |
|
865 QSettings settings; |
|
866 settings.beginGroup(QLatin1String("BrowserMainWindow")); |
|
867 |
|
868 const QStringList fileNameList(QFileDialog::getOpenFileNames(this, |
|
869 QString(), |
|
870 settings.value("openRamFile").toString(), |
|
871 QLatin1String("RAM files (*.ram)"))); |
|
872 |
|
873 if (fileNameList.isEmpty()) |
|
874 return; |
|
875 |
|
876 QFile linkFile; |
|
877 QList<QUrl> list; |
|
878 QByteArray sourceURL; |
|
879 for (int i = 0; i < fileNameList.count(); i++ ) { |
|
880 linkFile.setFileName(fileNameList[i]); |
|
881 if (linkFile.open(QIODevice::ReadOnly | QIODevice::Text)) { |
|
882 while (!linkFile.atEnd()) { |
|
883 sourceURL = linkFile.readLine().trimmed(); |
|
884 if (!sourceURL.isEmpty()) { |
|
885 const QUrl url(QUrl::fromEncoded(sourceURL)); |
|
886 if (url.isValid()) |
|
887 list.append(url); |
|
888 } |
|
889 } |
|
890 linkFile.close(); |
|
891 } |
|
892 } |
|
893 |
|
894 if (!list.isEmpty()) { |
|
895 m_MediaObject.setCurrentSource(Phonon::MediaSource(list[0])); |
|
896 m_MediaObject.play(); |
|
897 for (int i = 1; i < list.count(); i++) |
|
898 m_MediaObject.enqueue(Phonon::MediaSource(list[i])); |
|
899 } |
|
900 |
|
901 forwardButton->setEnabled(!m_MediaObject.queue().isEmpty()); |
|
902 settings.setValue("openRamFile", fileNameList[0]); |
|
903 } |
|
904 |
819 void MediaPlayer::finished() |
905 void MediaPlayer::finished() |
820 { |
906 { |
821 } |
907 } |
822 |
908 |
823 void MediaPlayer::showContextMenu(const QPoint &p) |
909 void MediaPlayer::showContextMenu(const QPoint &p) |