From 2f0ace0e367489eb20a75a69c95d463fcb04830f Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 26 Sep 2009 22:25:02 -0400 Subject: More gui work and dvd loading. --- AnyRip.pro | 6 ++-- dvddrive.cpp | 7 +---- dvddrive.h | 3 +- dvdimagejobgui.cpp | 1 + dvdimagejobgui.h | 4 +-- encodemp4job.cpp | 50 ++++++++++++++++++++++--------- encodemp4job.h | 3 ++ encodemp4jobgui.cpp | 34 ++++++++++++++++++++++ encodemp4jobgui.h | 26 +++++++++++++++++ main.cpp | 1 + mainwindow.cpp | 48 +++++++++--------------------- mainwindow.h | 6 ++-- newdvdgui.cpp | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++ newdvdgui.h | 36 +++++++++++++++++++++++ video.cpp | 41 ++++++++++++++++++++++---- video.h | 7 +++++ 16 files changed, 289 insertions(+), 68 deletions(-) create mode 100644 encodemp4jobgui.cpp create mode 100644 encodemp4jobgui.h create mode 100644 newdvdgui.cpp create mode 100644 newdvdgui.h diff --git a/AnyRip.pro b/AnyRip.pro index 787350b..2bf4c2e 100644 --- a/AnyRip.pro +++ b/AnyRip.pro @@ -11,7 +11,8 @@ SOURCES += main.cpp \ titleloadjob.cpp \ videogui.cpp \ mainwindow.cpp \ - encodemp4jobgui.cpp + encodemp4jobgui.cpp \ + newdvdgui.cpp HEADERS += dvdimagejob.h \ dvdimagejobgui.h \ job.h \ @@ -24,7 +25,8 @@ HEADERS += dvdimagejob.h \ titleloadjob.h \ videogui.h \ mainwindow.h \ - encodemp4jobgui.h + encodemp4jobgui.h \ + newdvdgui.h LIBS += -ldvdcss \ -ldvdread QT += dbus diff --git a/dvddrive.cpp b/dvddrive.cpp index 31042c4..07e4a34 100644 --- a/dvddrive.cpp +++ b/dvddrive.cpp @@ -62,12 +62,7 @@ bool DVDDrive::dvdInserted() const void DVDDrive::eject() { if (m_halDisc) { - QString path = m_halDisc->path(); - deviceRemoved(path); - m_halDisc = new QDBusInterface(QLatin1String("org.freedesktop.Hal"), path, QLatin1String("org.freedesktop.Hal.Device.Volume"), QDBusConnection::systemBus(), this); - m_halDisc->call(QLatin1String("Eject"), QStringList()); - delete m_halDisc; - m_halDisc = 0; + QDBusInterface(QLatin1String("org.freedesktop.Hal"), m_halDisc->path(), QLatin1String("org.freedesktop.Hal.Device.Volume"), QDBusConnection::systemBus(), this).call(QLatin1String("Eject"), QStringList()); } } DVDDrive* DVDDrive::s_instance = 0; diff --git a/dvddrive.h b/dvddrive.h index 254dd85..16f5059 100644 --- a/dvddrive.h +++ b/dvddrive.h @@ -12,7 +12,6 @@ public: QString dvdName() const; QString dvdDevice() const; bool dvdInserted() const; - void eject(); static DVDDrive* instance(); private: QDBusInterface *m_halManager; @@ -21,6 +20,8 @@ private: private slots: bool deviceAdded(const QString &device); void deviceRemoved(const QString &device); +public slots: + void eject(); signals: void dvdAdded(); void dvdRemoved(); diff --git a/dvdimagejobgui.cpp b/dvdimagejobgui.cpp index 08cb444..6d88a61 100644 --- a/dvdimagejobgui.cpp +++ b/dvdimagejobgui.cpp @@ -16,6 +16,7 @@ DVDImageJobGui::DVDImageJobGui(DVDImageJob *job) : layout->addWidget(m_progressBar); layout->addWidget(m_progressLabel); setLayout(layout); + setFrameStyle(QFrame::StyledPanel); connect(job, SIGNAL(extractProgress(int,int)), this, SLOT(extractProgress(int,int))); } void DVDImageJobGui::extractProgress(int current, int maximum) diff --git a/dvdimagejobgui.h b/dvdimagejobgui.h index 122cdd4..58a7fa9 100644 --- a/dvdimagejobgui.h +++ b/dvdimagejobgui.h @@ -1,13 +1,13 @@ #ifndef DVDIMAGEJOBGUI_H #define DVDIMAGEJOBGUI_H -#include +#include #include class QLabel; class QProgressBar; class DVDImageJob; -class DVDImageJobGui : public QWidget +class DVDImageJobGui : public QFrame { Q_OBJECT diff --git a/encodemp4job.cpp b/encodemp4job.cpp index dba84f4..9713193 100644 --- a/encodemp4job.cpp +++ b/encodemp4job.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -33,6 +32,7 @@ bool EncodeMP4Job::executeJob() arguments << "-6" << "stereo"; arguments << "-N" << "eng" << "--native-dub"; arguments << "-f" << "mp4"; + arguments << "--dvdnav" << "-t" << QString::number(video()->dvdTitle()); arguments << "--loose-anamorphic" << "--modulus" << "16"; arguments << "--optimize" << "--decomb" << "--deblock" << "--denoise=\"weak\""; arguments << "-x" << "ref=3:mixed-refs:bframes=6:weightb:direct=auto:b-pyramid:me=umh:subme=9:analyse=all:8x8dct:trellis=1:no-fast-pskip:psy-rd=1,1"; @@ -42,25 +42,22 @@ bool EncodeMP4Job::executeJob() process.start(QLatin1String("./HandBrakeCLI"), arguments, QIODevice::ReadOnly); if (!process.waitForStarted()) return false; - QTextStream reader(&process); QRegExp percentLinePattern(QLatin1String("^Encoding: task ([0-9]*) of ([0-9]*), ([0-9]*\\.[0-9]*) % (\\(([0-9]*\\.[0-9]*) fps, avg ([0-9]*\\.[0-9]*) fps, ETA ([0-9]{2})h([0-9]{2})m([0-9]{2})s\\))?")); QRegExp lessPercentLinePattern(QLatin1String("^Encoding: task ([0-9]*) of ([0-9]*), ([0-9]*\\.[0-9]*) %")); while (process.waitForReadyRead(-1)) { - QString line = reader.readLine().trimmed(); + QString line = QString(process.readLine()).trimmed(); if (percentLinePattern.exactMatch(line)) { - QStringList captured = percentLinePattern.capturedTexts(); - int currentTask = captured.at(1).toInt(); - int totalTasks = captured.at(2).toInt(); - float percent = captured.at(3).toFloat(); - float currentFps = captured.at(5).toFloat(); - float avgFps = captured.at(6).toFloat(); - QTime timeRemaining(captured.at(7).toInt(), captured.at(8).toInt(), captured.at(9).toInt()); + int currentTask = percentLinePattern.cap(1).toInt(); + int totalTasks = percentLinePattern.cap(2).toInt(); + float percent = percentLinePattern.cap(3).toFloat(); + float currentFps = percentLinePattern.cap(5).toFloat(); + float avgFps = percentLinePattern.cap(6).toFloat(); + QTime timeRemaining(percentLinePattern.cap(7).toInt(), percentLinePattern.cap(8).toInt(), percentLinePattern.cap(9).toInt()); emit encodeProgress(currentTask, totalTasks, percent, currentFps, avgFps, timeRemaining); } else if(lessPercentLinePattern.exactMatch(line)) { - QStringList captured = lessPercentLinePattern.capturedTexts(); - int currentTask = captured.at(1).toInt(); - int totalTasks = captured.at(2).toInt(); - float percent = captured.at(3).toFloat(); + int currentTask = lessPercentLinePattern.cap(1).toInt(); + int totalTasks = lessPercentLinePattern.cap(2).toInt(); + float percent = lessPercentLinePattern.cap(3).toFloat(); emit encodeProgress(currentTask, totalTasks, percent, -1, -1, QTime()); } } @@ -71,3 +68,28 @@ QWidget* EncodeMP4Job::gui() { return new EncodeMP4JobGui(this); } +QMap EncodeMP4Job::titles() const +{ + return titles(m_encodePath); +} +QMap EncodeMP4Job::titles(const QString &location) +{ + QMap titles; + QProcess process; + QStringList arguments; + arguments << "-i" << location; + arguments << "-t" << "0"; + arguments << "--dvdnav"; + process.start(QLatin1String("./HandBrakeCLI"), arguments, QIODevice::ReadOnly); + if (!process.waitForStarted()) + return titles; + process.waitForFinished(-1); + QRegExp titleDurationPattern(QLatin1String("\\+ title ([0-9]*):\\n[^\\n]*\\n[^\\n]*\\n \\+ duration: ([0-9]{2}:[0-9]{2}:[0-9]{2})")); + QString output(process.readAllStandardError()); + int matchLocation = 0; + while ((matchLocation = titleDurationPattern.indexIn(output, matchLocation)) != -1) { + matchLocation += titleDurationPattern.matchedLength(); + titles.insert(titleDurationPattern.cap(1).toInt(), titleDurationPattern.cap(2)); + } + return titles; +} diff --git a/encodemp4job.h b/encodemp4job.h index 592922f..ea0c1fd 100644 --- a/encodemp4job.h +++ b/encodemp4job.h @@ -4,6 +4,7 @@ #include "job.h" #include "video.h" #include +#include class EncodeMP4Job : public Job { @@ -11,6 +12,8 @@ class EncodeMP4Job : public Job public: EncodeMP4Job(Video *video, QString encodePath, QString imagePath); Video::Jobs jobType() const; + static QMap titles(const QString &location); + QMap titles() const; protected: bool executeJob(); QWidget* gui(); diff --git a/encodemp4jobgui.cpp b/encodemp4jobgui.cpp new file mode 100644 index 0000000..5a679f1 --- /dev/null +++ b/encodemp4jobgui.cpp @@ -0,0 +1,34 @@ +#include "encodemp4jobgui.h" +#include "encodemp4job.h" +#include +#include +#include + +EncodeMP4JobGui::EncodeMP4JobGui(EncodeMP4Job *job) +{ + m_progressBar = new QProgressBar; + m_progressBar->setMaximum(10000); + m_progressLabel = new QLabel; + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(new QLabel(tr("Encoding MP4 of %1").arg(job->video()->title()))); + layout->addWidget(m_progressBar); + layout->addWidget(m_progressLabel); + setLayout(layout); + setFrameStyle(QFrame::StyledPanel); + connect(job, SIGNAL(encodeProgress(int,int,float,float,float,QTime)), this, SLOT(encodeProgress(int,int,float,float,float,QTime))); +} +void EncodeMP4JobGui::encodeProgress(int currentTask, int totalTasks, float percent, float currentFps, float avgFps, QTime timeRemaining) +{ + m_progressBar->setValue((int)(percent * 100)); + if (!timeRemaining.isNull() && avgFps != -1 && currentFps != -1) + m_progressLabel->setText(tr("task %1 of %2, %4 fps (avg %5 fps), %3 remaining") + .arg(QString::number(currentTask)) + .arg(QString::number(totalTasks)) + .arg(timeRemaining.toString()) + .arg(QString::number(currentFps, 'f', 2)) + .arg(QString::number(avgFps, 'f', 2))); + else + m_progressLabel->setText(tr("task %1 of %2") + .arg(QString::number(currentTask)) + .arg(QString::number(totalTasks))); +} diff --git a/encodemp4jobgui.h b/encodemp4jobgui.h new file mode 100644 index 0000000..cd90d5c --- /dev/null +++ b/encodemp4jobgui.h @@ -0,0 +1,26 @@ +#ifndef ENCODEMP4JOBGUI_H +#define ENCODEMP4JOBGUI_H + +#include +#include +class QLabel; +class QProgressBar; +class EncodeMP4Job; + +class EncodeMP4JobGui : public QFrame +{ + Q_OBJECT + +public: + EncodeMP4JobGui(EncodeMP4Job *job); + +private: + QProgressBar* m_progressBar; + QLabel* m_progressLabel; + EncodeMP4Job *m_job; + +private slots: + void encodeProgress(int currentTask, int totalTasks, float percent, float currentFps, float avgFps, QTime timeRemaining); +}; + +#endif // ENCODEMP4JOBGUI_H diff --git a/main.cpp b/main.cpp index 0873bef..9f6e83f 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,6 @@ #include "mainwindow.h" #include +#include int main(int argc, char *argv[]) { diff --git a/mainwindow.cpp b/mainwindow.cpp index dd66ced..9723e70 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -4,7 +4,8 @@ #include "videoqueue.h" #include "dvddrive.h" #include "job.h" -#include +#include "newdvdgui.h" +#include #include #include #include @@ -13,23 +14,18 @@ MainWindow::MainWindow() { - connect(DVDDrive::instance(), SIGNAL(dvdAdded()), this, SLOT(dvdAdded())); - connect(DVDDrive::instance(), SIGNAL(dvdRemoved()), this, SLOT(dvdRemoved())); m_queue = new VideoQueue; connect(m_queue, SIGNAL(runningJob(Job*)), this, SLOT(runningJob(Job*))); m_videoGuis = new QVBoxLayout; m_jobGuis = new QVBoxLayout; - QHBoxLayout *sides = new QHBoxLayout; - sides->addLayout(m_videoGuis); - sides->addLayout(m_jobGuis); - QHBoxLayout *heading = new QHBoxLayout; - heading->addWidget(new QLabel(tr("Videos in Queue")), 1); - m_currentlyInserted = new QPushButton; - connect(m_currentlyInserted, SIGNAL(clicked()), this, SLOT(newVideoFromDVD())); - heading->addWidget(m_currentlyInserted); - QVBoxLayout *layout = new QVBoxLayout; - layout->addLayout(heading); - layout->addLayout(sides); + QGridLayout *layout = new QGridLayout; + layout->addWidget(new QLabel(tr("Video Queue")), 0, 0); + layout->addWidget(new QLabel(tr("Job Queue")), 0, 1); + layout->addLayout(m_videoGuis, 1, 0); + layout->addLayout(m_jobGuis, 1, 1); + NewDVDGui *newDvdGui = new NewDVDGui; + connect(newDvdGui, SIGNAL(newDVD(QString,QMap)), this, SLOT(newVideoFromDVD(QString,QMap))); + m_jobGuis->addWidget(newDvdGui); QSettings settings; settings.beginGroup(QLatin1String("Videos")); foreach(QString title, settings.childGroups()) { @@ -39,34 +35,18 @@ MainWindow::MainWindow() else settings.remove(title); } - if (DVDDrive::instance()->dvdInserted()) - dvdAdded(); - else - dvdRemoved(); setLayout(layout); } -void MainWindow::dvdAdded() -{ - QSettings settings; - settings.beginGroup(QLatin1String("Videos")); - QString dvdName = DVDDrive::instance()->dvdName(); - m_currentlyInserted->setEnabled(!settings.childGroups().contains(dvdName)); - m_currentlyInserted->setText(tr("Rip %1").arg(dvdName)); -} -void MainWindow::dvdRemoved() -{ - m_currentlyInserted->setEnabled(false); - m_currentlyInserted->setText(tr("Insert DVD...")); -} void MainWindow::addVideo(Video *video) { m_videoGuis->addWidget(video->widget()); m_queue->newVideo(video); } -void MainWindow::newVideoFromDVD() +void MainWindow::newVideoFromDVD(QString name, QMap titles) { - m_currentlyInserted->setEnabled(false); - addVideo(new Video(DVDDrive::instance()->dvdName(), this)); + Video *video = new Video(name); + video->setDvdTitles(titles); + addVideo(video); } void MainWindow::runningJob(Job *job) { diff --git a/mainwindow.h b/mainwindow.h index cc78ddd..18ac521 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -2,6 +2,7 @@ #define MAINWINDOW_H #include +#include #include "dvddrive.h" class QVBoxLayout; class QPushButton; @@ -17,13 +18,10 @@ public: private: QVBoxLayout *m_videoGuis; QVBoxLayout *m_jobGuis; - QPushButton *m_currentlyInserted; VideoQueue *m_queue; void addVideo(Video *video); private slots: - void dvdAdded(); - void dvdRemoved(); - void newVideoFromDVD(); + void newVideoFromDVD(QString name, QMap titles); void runningJob(Job *job); void completedJob(bool success); }; diff --git a/newdvdgui.cpp b/newdvdgui.cpp new file mode 100644 index 0000000..defa9ff --- /dev/null +++ b/newdvdgui.cpp @@ -0,0 +1,84 @@ +#include "newdvdgui.h" +#include "dvddrive.h" +#include "encodemp4job.h" +#include +#include +#include +#include +#include +#include +#include + +NewDVDGui::NewDVDGui() : + m_insertDvd(tr("Please insert video DVD.")), + m_loadingTitles(tr("%1 inserted. Scanning titles...")), + m_ripping(tr("Created new video from DVD.")) +{ + m_watcher = new QFutureWatcher >; + m_watcher->setParent(this); + connect(m_watcher, SIGNAL(finished()), this, SLOT(loadedTitles())); + m_status = new QLabel; + m_dvdName = new QLineEdit; + connect(m_dvdName, SIGNAL(textChanged(QString)), this, SLOT(validateName(QString))); + m_rip = new QPushButton(tr("&Rip DVD")); + connect(m_rip, SIGNAL(clicked()), this, SLOT(rip())); + m_eject = new QPushButton(tr("&Eject")); + connect(m_eject, SIGNAL(clicked()), DVDDrive::instance(), SLOT(eject())); + QHBoxLayout *buttons = new QHBoxLayout; + buttons->addWidget(m_rip); + buttons->addWidget(m_eject); + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(m_status, 0, Qt::AlignHCenter); + layout->addWidget(m_dvdName); + layout->addLayout(buttons); + if (DVDDrive::instance()->dvdInserted()) + dvdAdded(); + else + dvdRemoved(); + connect(DVDDrive::instance(), SIGNAL(dvdAdded()), this, SLOT(dvdAdded())); + connect(DVDDrive::instance(), SIGNAL(dvdRemoved()), this, SLOT(dvdRemoved())); + setFrameStyle(QFrame::StyledPanel); + setLayout(layout); +} +void NewDVDGui::dvdAdded() +{ + QString name = DVDDrive::instance()->dvdName(); + m_status->setText(m_loadingTitles.arg(name)); + m_dvdName->setText(name); //Calls validateName + m_dvdName->setVisible(false); + m_status->setVisible(true); + m_rip->setVisible(false); + m_eject->setVisible(false); + m_watcher->setFuture(QtConcurrent::run(&EncodeMP4Job::titles, DVDDrive::instance()->dvdDevice())); +} +void NewDVDGui::validateName(const QString &name) +{ + QSettings settings; + settings.beginGroup(QLatin1String("Videos")); + m_rip->setEnabled(!settings.childGroups().contains(name)); +} +void NewDVDGui::loadedTitles() +{ + m_titles = m_watcher->result(); + m_rip->setVisible(true); + m_eject->setVisible(true); + m_status->setVisible(false); + m_dvdName->setVisible(true); +} +void NewDVDGui::rip() +{ + m_rip->setEnabled(false); + m_dvdName->setVisible(false); + m_status->setText(m_ripping); + m_status->setVisible(true); + emit newDVD(m_dvdName->text(), m_titles); +} + +void NewDVDGui::dvdRemoved() +{ + m_status->setText(m_insertDvd); + m_status->setVisible(true); + m_dvdName->setVisible(false); + m_rip->setVisible(false); + m_eject->setVisible(false); +} diff --git a/newdvdgui.h b/newdvdgui.h new file mode 100644 index 0000000..0096de4 --- /dev/null +++ b/newdvdgui.h @@ -0,0 +1,36 @@ +#ifndef NEWDVDGUI_H +#define NEWDVDGUI_H + +#include +#include +#include +class QLineEdit; +class QLabel; +class QPushButton; + +class NewDVDGui : public QFrame +{ + Q_OBJECT +public: + NewDVDGui(); +private: + QLineEdit *m_dvdName; + QLabel *m_status; + QMap m_titles; + const QString m_insertDvd; + const QString m_loadingTitles; + const QString m_ripping; + QPushButton *m_rip; + QPushButton *m_eject; + QFutureWatcher > *m_watcher; +private slots: + void dvdAdded(); + void dvdRemoved(); + void validateName(const QString &name); + void rip(); + void loadedTitles(); +signals: + void newDVD(QString name, QMap titles); +}; + +#endif // NEWDVDGUI_H diff --git a/video.cpp b/video.cpp index 5842cf9..39d1e8a 100644 --- a/video.cpp +++ b/video.cpp @@ -12,14 +12,20 @@ Video::Video(QString title, QObject *parent) : QObject(parent), m_jobsCompleted(QBitArray(6)), - m_jobsInProgress(QBitArray(6)) + m_jobsInProgress(QBitArray(6)), + m_dvdTitle(1) { - m_settingsKey = QString("Videos/%1/Jobs Completed").arg(title.replace(QChar('/'), QChar('-'))); + QString topKey = QString("Videos/%1").arg(title.replace(QChar('/'), QChar('-'))); + m_settingsKey = topKey.append(QLatin1String("/%1")); QSettings settings; - if (settings.contains(m_settingsKey)) { - m_jobsCompleted = settings.value(m_settingsKey).toBitArray(); + if (settings.contains(topKey)) { + m_jobsCompleted = settings.value(m_settingsKey.arg("Jobs Completed")).toBitArray(); if (m_jobsCompleted.size() != 6) m_jobsCompleted.resize(6); + m_dvdTitle = settings.value(m_settingsKey.arg("DVD Title"), 1).toInt(); + settings.beginGroup(m_settingsKey.arg("DVD Titles")); + foreach(QString titleNumber, settings.childKeys()) + m_dvdTitles.insert(titleNumber.toInt(), settings.value(titleNumber).toString()); } m_title = title; m_rootPath = QString("%1/AnyRip/%2").arg(QDir::homePath()).arg(m_title); @@ -32,7 +38,14 @@ Video::Video(QString title, QObject *parent) : void Video::saveState() { QSettings settings; - settings.setValue(m_settingsKey, m_jobsCompleted); + settings.setValue(m_settingsKey.arg("Jobs Completed"), m_jobsCompleted); + settings.setValue(m_settingsKey.arg("DVD Title"), m_dvdTitle); + settings.remove(m_settingsKey.arg("DVD Titles")); + QMapIterator i(m_dvdTitles); + while (i.hasNext()) { + i.next(); + settings.setValue(QString("%1/%2").arg(m_settingsKey.arg("DVD Titles")).arg(QString::number(i.key())), i.value()); + } } void Video::completedJob(bool success) { @@ -128,3 +141,21 @@ bool Video::isJobCompleted(Video::Jobs job) const { return m_jobsCompleted.at(job); } +int Video::dvdTitle() const +{ + return m_dvdTitle; +} +void Video::setDvdTitle(int title) +{ + m_dvdTitle = title; + saveState(); +} +QMap Video::dvdTitles() const +{ + return m_dvdTitles; +} +void Video::setDvdTitles(QMap titles) +{ + m_dvdTitles = titles; + saveState(); +} diff --git a/video.h b/video.h index b59aced..139dbf6 100644 --- a/video.h +++ b/video.h @@ -4,6 +4,7 @@ #include #include #include +#include class QIODevice; class DVDImageJob; @@ -27,8 +28,12 @@ public: TitleLoadJob* titleLoadJob(); QList availableJobs(); QString title() const; + int dvdTitle() const; + void setDvdTitle(int title); VideoGui* widget(); bool isJobCompleted(Video::Jobs job) const; + void setDvdTitles(QMap titles); + QMap dvdTitles() const; private: QBitArray m_jobsCompleted; QBitArray m_jobsInProgress; @@ -39,6 +44,8 @@ private: QString m_subtitlePath; QString m_posterPath; QString m_settingsKey; + QMap m_dvdTitles; + int m_dvdTitle; void saveState(); private slots: void completedJob(bool success); -- cgit v1.2.3-59-g8ed1b