source: trunk/demos/qmediaplayer/mediaplayer.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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