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