diff options
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | mainwindow.cc | 102 | ||||
-rw-r--r-- | mainwindow.h | 17 | ||||
-rw-r--r-- | mainwindow.ui | 62 | ||||
-rw-r--r-- | scribiu.pro | 3 |
5 files changed, 116 insertions, 74 deletions
@@ -10,8 +10,8 @@ It also allows you to export individual pages as PNG files or voice memos as AAC # Requirements -Scribiu requires Qt 5, including the core, gui, widgets, and svg modules. -It also requires phonon, libudev, openobex (>=1.7), libusb (>=1.0) and QuaZip (1.0). +Scribiu requires Qt 5, including the core, gui, widgets, svg and multimedia modules. +It also requires libudev, openobex (>=1.7), libusb (>=1.0) and QuaZip (1.0). Most of these should be packaged by your distribution. For example, on Ubuntu, these correspond with packages: @@ -19,7 +19,7 @@ For example, on Ubuntu, these correspond with packages: ` qtbase5-dev libqt5svg5-dev -libphonon4qt5-dev +qtmultimedia5-dev libudev-dev libopenobex2-dev libusb-1.0-0-dev diff --git a/mainwindow.cc b/mainwindow.cc index d8a935c..b66423a 100644 --- a/mainwindow.cc +++ b/mainwindow.cc @@ -25,13 +25,14 @@ #include "mainwindow.h" #include "ui_mainwindow.h" +#define PAPER_REPLAY_SLIDER_SCALE 100LL /* in msec */ + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), _notebooks(new NotebookModel(this)), _manager(new SmartpenManager(this)), - _media(new Phonon::MediaObject(this)), - _mediaOutput(new Phonon::AudioOutput(this)), + _player(new QMediaPlayer(this)), _replay(new PaperReplay(this)), _replayModel(new PaperReplayModel(_replay, this)), _statusLabel(new QLabel) @@ -42,14 +43,15 @@ MainWindow::MainWindow(QWidget *parent) : ui->notebookTree->header()->setSectionResizeMode(1, QHeaderView::Fixed); ui->notebookTree->header()->setSectionResizeMode(2, QHeaderView::Fixed); ui->notebookTree->expandAll(); + ui->replaySlider->setSingleStep(5000 / PAPER_REPLAY_SLIDER_SCALE); + ui->replaySlider->setPageStep(30000 / PAPER_REPLAY_SLIDER_SCALE); ui->paperReplayView->setModel(_replayModel); ui->paperReplayView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); ui->paperReplayView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Fixed); - Phonon::createPath(_media, _mediaOutput); - _media->setTickInterval(500); - ui->replaySlider->setMediaObject(_media); ui->pauseButton->setVisible(false); ui->statusBar->addWidget(_statusLabel, 1); + _player->setAudioRole(QAudio::VideoRole); + connect(_notebooks, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(handleNotebookRowsInserted(QModelIndex,int,int))); connect(_manager, SIGNAL(pensBeingSynchronizedChanged()), @@ -58,12 +60,14 @@ MainWindow::MainWindow(QWidget *parent) : this, SLOT(handlePenSyncComplete(QString))); connect(_manager, SIGNAL(syncFailed(QString)), this, SLOT(handlePenSyncFailed(QString))); - connect(_media, SIGNAL(stateChanged(Phonon::State,Phonon::State)), - this, SLOT(handleMediaStateChange(Phonon::State))); - connect(_media, SIGNAL(totalTimeChanged(qint64)), - this, SLOT(handleMediaTotalTimeChanged(qint64))); - connect(_media, SIGNAL(tick(qint64)), - this, SLOT(handleMediaTick(qint64))); + connect(_player, SIGNAL(stateChanged(QMediaPlayer::State)), + this, SLOT(handlePlayerStateChanged(QMediaPlayer::State))); + connect(_player, SIGNAL(durationChanged(qint64)), + this, SLOT(handlePlayerDurationChanged(qint64))); + connect(_player, SIGNAL(positionChanged(qint64)), + this, SLOT(handlePlayerPositionChanged(qint64))); + connect(_player, SIGNAL(seekableChanged(bool)), + this, SLOT(handlePlayerSeekableChanged(bool))); QSettings settings; settings.beginGroup("mainwindow"); @@ -168,8 +172,8 @@ void MainWindow::exportCurrentPageAsInkML(const QString &file) void MainWindow::exportCurrentPaperReplayAsAac(const QString &file) { - QString src = _media->currentSource().fileName(); - if (src.isEmpty()) { + QString src = currentPlayerMediaPath(); + if (src.isNull()) { QMessageBox::warning(this, tr("Export audio"), tr("No audio file is selected")); return; @@ -229,75 +233,80 @@ void MainWindow::handlePaperReplayRequested(const QString &file, qint64 time) QString filePath = finfo.canonicalFilePath(); - if (_media->currentSource().fileName() != filePath) { + if (currentPlayerMediaPath() != filePath) { qDebug() << "requesting media " << filePath; - _media->setCurrentSource(QUrl::fromLocalFile(filePath)); + _player->setMedia(QUrl::fromLocalFile(filePath)); } - qDebug() << "requesting media seek to" << time << "/" << _media->totalTime(); + qDebug() << "requesting media seek to" << time << "/" << _player->duration(); - switch (_media->state()) { - case Phonon::PlayingState: - case Phonon::BufferingState: - case Phonon::PausedState: + if (_player->isSeekable()) { + // Media is loaded and ready to go _pendingSeek = 0; - _media->seek(time); - break; - default: + _player->setPosition(time); + } else { + // Otherwise delay the seek until after media starts playing _pendingSeek = time; - break; } - _media->play(); + _player->play(); } void MainWindow::handlePaperReplayPlay() { - _media->play(); + _player->play(); } void MainWindow::handlePaperReplayPause() { - _media->pause(); + _player->pause(); } -void MainWindow::handleMediaStateChange(Phonon::State state) +void MainWindow::handlePaperReplaySliderChanged(int value) +{ + _player->setPosition(value * PAPER_REPLAY_SLIDER_SCALE); +} + +void MainWindow::handlePlayerStateChanged(QMediaPlayer::State state) { switch (state) { - case Phonon::PlayingState: + case QMediaPlayer::PlayingState: ui->playButton->setVisible(false); ui->pauseButton->setVisible(true); - if (_pendingSeek) { - qDebug() << "requesting (pending) media seek to" << _pendingSeek << "/" << _media->totalTime(); - _media->seek(_pendingSeek); - _pendingSeek = 0; - } - ui->mediaPosLabel->setText(formatDuration(_media->currentTime())); - ui->mediaLenLabel->setText("/ " + formatDuration(_media->totalTime())); break; - case Phonon::PausedState: + case QMediaPlayer::PausedState: ui->playButton->setVisible(true); ui->pauseButton->setVisible(false); - ui->mediaPosLabel->setText(formatDuration(_media->currentTime())); - ui->mediaLenLabel->setText("/ " + formatDuration(_media->totalTime())); break; default: ui->playButton->setVisible(true); ui->pauseButton->setVisible(false); - ui->mediaPosLabel->setText(QString()); - ui->mediaLenLabel->setText(QString()); break; } } -void MainWindow::handleMediaTotalTimeChanged(qint64 time) +void MainWindow::handlePlayerDurationChanged(qint64 time) { ui->mediaLenLabel->setText("/ " + formatDuration(time)); + ui->replaySlider->setMaximum(time / PAPER_REPLAY_SLIDER_SCALE); } -void MainWindow::handleMediaTick(qint64 time) +void MainWindow::handlePlayerPositionChanged(qint64 time) { ui->mediaPosLabel->setText(formatDuration(time)); + if (!ui->replaySlider->isSliderDown()) { + QSignalBlocker blocker(ui->replaySlider); + ui->replaySlider->setValue(time / PAPER_REPLAY_SLIDER_SCALE); + } +} + +void MainWindow::handlePlayerSeekableChanged(bool seekable) +{ + if (seekable && _pendingSeek) { + qDebug() << "requesting (pending) media seek to" << _pendingSeek << "/" << _player->duration(); + _player->setPosition(_pendingSeek); + _pendingSeek = 0; + } } void MainWindow::handlePensBeingSynchronizedChanged() @@ -431,7 +440,7 @@ void MainWindow::closeEvent(QCloseEvent *event) settings.endGroup(); } -QString MainWindow::formatDuration(qint64 time) +QString MainWindow::formatDuration(qint64 time) const { int secs = time / 1000; int mins = secs / 60; @@ -446,3 +455,8 @@ QString MainWindow::formatDuration(qint64 time) return QString("%2:%3").arg(mins).arg(secs, 2, 10, fill); } } + +QString MainWindow::currentPlayerMediaPath() const +{ + return _player->media().request().url().toLocalFile(); +} diff --git a/mainwindow.h b/mainwindow.h index 2f5575c..03479a2 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -21,8 +21,7 @@ #include <QtWidgets/QMainWindow> #include <QtWidgets/QLabel> -#include <phonon/MediaObject> -#include <phonon/AudioOutput> +#include <QtMultimedia/QMediaPlayer> #include "notebookmodel.h" #include "paperreplaymodel.h" #include "smartpenmanager.h" @@ -57,9 +56,11 @@ private slots: void handlePaperReplayRequested(const QString &file, qint64 time); void handlePaperReplayPlay(); void handlePaperReplayPause(); - void handleMediaStateChange(Phonon::State state); - void handleMediaTotalTimeChanged(qint64 time); - void handleMediaTick(qint64 time); + void handlePaperReplaySliderChanged(int value); + void handlePlayerStateChanged(QMediaPlayer::State state); + void handlePlayerDurationChanged(qint64 time); + void handlePlayerPositionChanged(qint64 time); + void handlePlayerSeekableChanged(bool seekable); void handlePensBeingSynchronizedChanged(); void handlePenSyncComplete(const QString &penName); void handlePenSyncFailed(const QString &penName); @@ -70,15 +71,15 @@ protected: void closeEvent(QCloseEvent *event); private: - QString formatDuration(qint64 time); + QString formatDuration(qint64 time) const; + QString currentPlayerMediaPath() const; private: Ui::MainWindow *ui; NotebookModel *_notebooks; SmartpenManager *_manager; - Phonon::MediaObject *_media; - Phonon::AudioOutput *_mediaOutput; + QMediaPlayer *_player; qint64 _pendingSeek; QString _curPenName; diff --git a/mainwindow.ui b/mainwindow.ui index a56ffba..03ae438 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -259,10 +259,27 @@ </widget> </item> <item> - <widget class="Phonon::SeekSlider" name="replaySlider"/> + <widget class="QSlider" name="replaySlider"> + <property name="maximum"> + <number>0</number> + </property> + <property name="tracking"> + <bool>false</bool> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="tickInterval"> + <number>1</number> + </property> + </widget> </item> <item> - <widget class="QLabel" name="mediaPosLabel"/> + <widget class="QLabel" name="mediaPosLabel"> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> </item> <item> <widget class="QLabel" name="mediaLenLabel"> @@ -346,12 +363,6 @@ <layoutdefault spacing="6" margin="11"/> <customwidgets> <customwidget> - <class>Phonon::SeekSlider</class> - <extends>QWidget</extends> - <header location="global">phonon/seekslider.h</header> - <container>1</container> - </customwidget> - <customwidget> <class>NotebookView</class> <extends>QGraphicsView</extends> <header>notebookview.h</header> @@ -406,7 +417,7 @@ <slot>handlePaperReplayPlay()</slot> <hints> <hint type="sourcelabel"> - <x>357</x> + <x>331</x> <y>356</y> </hint> <hint type="destinationlabel"> @@ -422,7 +433,7 @@ <slot>handlePaperReplayPause()</slot> <hints> <hint type="sourcelabel"> - <x>391</x> + <x>365</x> <y>356</y> </hint> <hint type="destinationlabel"> @@ -502,8 +513,8 @@ <slot>prevPage()</slot> <hints> <hint type="sourcelabel"> - <x>347</x> - <y>46</y> + <x>331</x> + <y>61</y> </hint> <hint type="destinationlabel"> <x>441</x> @@ -518,8 +529,8 @@ <slot>nextPage()</slot> <hints> <hint type="sourcelabel"> - <x>436</x> - <y>38</y> + <x>421</x> + <y>61</y> </hint> <hint type="destinationlabel"> <x>473</x> @@ -566,8 +577,8 @@ <slot>handlePaperReplaySelected(QModelIndex)</slot> <hints> <hint type="sourcelabel"> - <x>367</x> - <y>117</y> + <x>402</x> + <y>95</y> </hint> <hint type="destinationlabel"> <x>778</x> @@ -586,7 +597,7 @@ <y>116</y> </hint> <hint type="destinationlabel"> - <x>613</x> + <x>715</x> <y>62</y> </hint> </hints> @@ -607,6 +618,22 @@ </hint> </hints> </connection> + <connection> + <sender>replaySlider</sender> + <signal>valueChanged(int)</signal> + <receiver>MainWindow</receiver> + <slot>handlePaperReplaySliderChanged(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>416</x> + <y>339</y> + </hint> + <hint type="destinationlabel"> + <x>681</x> + <y>300</y> + </hint> + </hints> + </connection> </connections> <slots> <slot>handleNotebookSelected(QModelIndex)</slot> @@ -616,6 +643,7 @@ <slot>handlePaperReplayPlay()</slot> <slot>handlePaperReplayPause()</slot> <slot>handlePaperReplaySelected(QModelIndex)</slot> + <slot>handlePaperReplaySliderChanged(int)</slot> <slot>handleExport()</slot> <slot>handleAbout()</slot> </slots> diff --git a/scribiu.pro b/scribiu.pro index d25f2fc..1672062 100644 --- a/scribiu.pro +++ b/scribiu.pro @@ -2,8 +2,7 @@ TARGET = scribiu VERSION = 1.4 TEMPLATE = app -QT += core gui widgets svg -QT += phonon4qt5 +QT += core gui widgets svg multimedia CONFIG += c++11 |