Logo Search packages:      
Sourcecode: qtgain version File versions  Download package

QtGain.cpp

/***************************************************************************
 *   Copyright (C) 2007-2010 by Vegeta                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
#include <QDragEnterEvent>
#include <QUrl>
#include <QAction>
#include <QTimer>
#include <QDirIterator>
#include "QtGain.h"
#include "Preferences.h"


QtGain::QtGain(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags){
    ui.setupUi(this);

    startupInitiations();
    loadSettings();

    setWindowTitle("QtGain 0.8.2");
    show();

    if (isShowBrowserAtStatup()) openDirectoryDialog();
}

QtGain::~QtGain(){
}

// *********************************************************************************************
// Generate Contextmenu, Timer etc.
// *********************************************************************************************
void QtGain::startupInitiations(){
    actionAbout = new QAction(tr("About..."), this);
    connect(actionAbout, SIGNAL(triggered()), this, SLOT(showAboutDialog()));

    actionCancelOperation = new QAction(tr("&Stop..."), this);
    actionCancelOperation->setShortcut(tr("Ctrl+S"));
    connect(actionCancelOperation, SIGNAL(triggered()), this, SLOT(cancelOperation()));

    actionShowSettings = new QAction(tr("&Configure"), this);
    actionShowSettings->setShortcut(tr("Ctrl+C"));
    connect(actionShowSettings, SIGNAL(triggered()), this, SLOT(showPreferencesDialog()));

    QAction *Separator = new QAction(this);
    Separator->setSeparator(true);

    actionQuit = new QAction(tr("E&xit"), this);
    actionQuit->setShortcut(tr("Ctrl+X"));
    connect(actionQuit, SIGNAL(triggered()), this, SLOT(Quit()));

    this->addAction(actionAbout);
    this->addAction(actionCancelOperation);
    this->addAction(actionShowSettings);
    this->addAction(Separator);
    this->addAction(actionQuit);

    actionCancelOperation->setEnabled(false);
    ui.centralWidget->setContextMenuPolicy(Qt::ActionsContextMenu);

    // Timer
    Timer = new QTimer(this);
    connect(Timer, SIGNAL(timeout()), this, SLOT(updateGUI()));

    myProcess = new QProcess(this);
    myProcess->setReadChannelMode(QProcess::MergedChannels);
    connect (myProcess, SIGNAL(finished(int)), this, SLOT(processFiles()));
}


// *********************************************************************************************
// Change state of context menu
// *********************************************************************************************
void QtGain::ContextmenuSetModus(bool isIdle){
    if (isIdle){
        actionCancelOperation->setEnabled(false);
        Timer->stop();
    } else {
        actionCancelOperation->setEnabled(true);
        setStartTime();
        Timer->start(1000);

        ui.progressBar->setValue(0);
        ui.Fertig->setNum(0);
        ui.Uebersprungen->setNum(0);
        ui.Errors->setNum(0);
        ui.AnzahlDateien->display(0);
        ui.Status->setText("Working...");
        ui.Zeitanzeige->setText("00:00:00");
    }

    actionAbout->setEnabled(isIdle);
    actionShowSettings->setEnabled(isIdle);
    actionQuit->setEnabled(isIdle);
}


// *********************************************************************************************
// Start gaining of files
// *********************************************************************************************
void QtGain::processFiles(){

    // Cancel gaining
    if (isOperationCanceled()){
        resetVariables();
        ContextmenuSetModus(true);
        ui.Status->setText("Operation aborted...");
        ui.Dateiname->clear();
        ui.Folder->clear();
        showErrors();
        return;
    }


    // Check output of replay gain tools
    processOutput();

    if (finishedFiles() < allFiles.size()){
        QStringList Parameter;
        QFileInfo file(allFiles[finishedFiles()]);
        ui.Folder->setText(file.path().mid(file.path().lastIndexOf("/") + 1)); // current folder

        // MP3
        if (allFiles[finishedFiles()].endsWith(".mp3", Qt::CaseInsensitive)){
            (isTrackGain()) ? Parameter << "-r" : Parameter << "-a";
            if (Volume() != 89) Parameter << "-m" << QString::number(Volume() - 89);
            Parameter << "-k" << "-c" << allFiles[finishedFiles()];
            myProcess->start(MP3GainBinaryPath(), Parameter);
        }

        // MP4 / m4a
        else if (allFiles[finishedFiles()].contains(QRegExp("\\.(mp4|m4a)$", Qt::CaseInsensitive))){
            (isTrackGain()) ? Parameter << "-r" : Parameter << "-a";
            if (Volume() != 89) Parameter << "-m" << QString::number(Volume() - 89);
            Parameter << "-k" << "-c" << allFiles[finishedFiles()];
            myProcess->start(MP4GainBinaryPath(), Parameter);
        }

        // Ogg-Vorbis
        else if (allFiles[finishedFiles()].endsWith(".ogg", Qt::CaseInsensitive)){
            if (!isTrackGain()) Parameter << "-g " << QString::number(Volume() - 89);
            Parameter << "-f" << allFiles[finishedFiles()];
            myProcess->start(VorbisGainBinaryPath(), Parameter);
        }

        // FLAC
        else if (allFiles[finishedFiles()].endsWith(".flac", Qt::CaseInsensitive)){
            Parameter << "--add-replay-gain" << allFiles[finishedFiles()];
            myProcess->start(FlacGainBinaryPath(), Parameter);
        }

        ui.Dateiname->setText(FilenameWithoutPath(finishedFiles()));
    }

    ui.Fertig->setNum(finishedFiles() - skippedFiles() - Errors());
    ui.Uebersprungen->setNum(skippedFiles());
    ui.AnzahlDateien->display(allFiles.size() - finishedFiles());
    ui.Errors->setNum(Errors());
    ui.progressBar->setValue((finishedFiles() * 100) / allFiles.size());

    if (allFiles.size() == finishedFiles()) {
        ContextmenuSetModus(true);
        ui.Dateiname->clear();
        ui.Folder->clear();
        ui.Status->setText("Finished...");
        showErrors();
        resetVariables();
    }
    else {
        setCurrentFileName(allFiles.at(finishedFiles()));
        addFinishedFiles();
    }
}


// *********************************************************************************************
// Check the output of Replay gain tools
// *********************************************************************************************
void QtGain::processOutput(){
    QString Dummy(myProcess->readAll());

    // No media file
    if (Dummy.contains("not a layer III file")                        ||
        Dummy.contains("File does not contain Vorbis data")           ||
        Dummy.contains("The file does not appear to be a FLAC file.") ||
        Dummy.contains("Can't find any valid MP3 frames in file")
        ){
        addErrors();
        addToErrorlog(QString("<font color='red'>Not a valid media file</font> :: %1<br>").arg(currentFileName()));
    }

    // Cannot access file
    else if (Dummy.contains("for reading")){
        addErrors();
        addToErrorlog(QString("<font color='red'>Cannot read file</font> :: %1<br>").arg(currentFileName()));
    }

    // Cannot write
    else if (Dummy.contains("Permission denied") || Dummy.contains("for modifying")){
        addErrors();
        addToErrorlog(QString("<font color='red'>Cannot write file</font> :: %1<br>").arg(currentFileName()));
    }

    // File already gained (only MP3 and Ogg-Vorbis)
    else if (Dummy.contains("are necessary") || Dummy.contains("Tags present;")){
        addSkippedFiles();
        if (isLogSkippedFiles()) addToErrorlog(QString("<font color='green'>File already gained -> skipped</font> :: %1<br>").arg(currentFileName()));
    }

}


// *********************************************************************************************
// Search for all files, including subdirs
// *********************************************************************************************
void QtGain::findFiles(const QString &dirName){
    if (!Timer->isActive()) ContextmenuSetModus(false);
    ui.Status->setText("Scanning directories...");

    QDirIterator it(dirName, QDirIterator::Subdirectories);
    while (it.hasNext()) {
        qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
        ui.AnzahlDateien->display(allFiles.size());
        if (isOperationCanceled()) return;
        QString temp = it.next();
        if (
                ((temp.endsWith(".mp3",  Qt::CaseInsensitive) && isMP3GainFound())    ||
                 (temp.endsWith(".ogg",  Qt::CaseInsensitive) && isVorbisGainFound()) ||
                 (temp.endsWith(".flac", Qt::CaseInsensitive) && isFlacGainFound())   ||
                 (temp.contains(QRegExp("\\.(mp4|m4a)$", Qt::CaseInsensitive)) && isMP4Gain_found())
                 ) && !allFiles.contains(temp)) allFiles << temp;
    }

    ui.AnzahlDateien->display(allFiles.size());
}


void QtGain::dragEnterEvent(QDragEnterEvent *event){
    if (event->mimeData()->hasFormat("text/uri-list")) event->acceptProposedAction();
}


// *********************************************************************************************
// Add files/directories via drag & drop
// *********************************************************************************************
void QtGain::dropEvent(QDropEvent *event){
    QFileInfo Tempfile;
    QList<QUrl> urls = event->mimeData()->urls();
    if (urls.isEmpty()) return;

    for (int i=0; i<urls.count(); i++){
        Tempfile = urls.at(i).toLocalFile();
        QString temp = Tempfile.absoluteFilePath();

        if (
                ((temp.endsWith(".mp3",  Qt::CaseInsensitive) && isMP3GainFound())    ||
                 (temp.endsWith(".ogg",  Qt::CaseInsensitive) && isVorbisGainFound()) ||
                 (temp.endsWith(".flac", Qt::CaseInsensitive) && isFlacGainFound())   ||
                 (temp.contains(QRegExp("\\.(mp4|m4a)$", Qt::CaseInsensitive)) && isMP4Gain_found())
                 ) && !Tempfile.isDir() && !allFiles.contains(temp)) allFiles << temp;
        else if (Tempfile.isDir()) findFiles(Tempfile.absoluteFilePath());
    }

    if (allFiles.size() > 0){
        ContextmenuSetModus(false);
        processFiles();
    } else {
        ui.Status->setText("No media files found...");
        ContextmenuSetModus(true);
    }
}


// *********************************************************************************************
// Show file dialog at startup
// *********************************************************************************************
void QtGain::openDirectoryDialog(){
    QString directory = QFileDialog::getExistingDirectory(this,
                                                          tr("Please choose a directory"),
                                                          "",
                                                          QFileDialog::DontResolveSymlinks
                                                          | QFileDialog::ShowDirsOnly);
    if (directory.isEmpty()) return;

    findFiles(directory);
    if (allFiles.size() > 0){
        ContextmenuSetModus(false);
        processFiles();
    } else {
        resetVariables();
        ContextmenuSetModus(true);
        ui.Status->setText("No media files found...");
    }
}


// *********************************************************************************************
// Show settings dialog
// *********************************************************************************************
void QtGain::showPreferencesDialog(){
    Preferences Preferences(this);

    Preferences.MP3GainPfad->setText(MP3GainBinaryPath());
    Preferences.MP4GainPfad->setText(MP4GainBinaryPath());
    Preferences.VorbisGainPfad->setText(VorbisGainBinaryPath());
    Preferences.FlacGainPfad->setText(FlacGainBinaryPath());
    Preferences.setIcons();

    Preferences.Pegel->setValue(Volume());
    if (!isTrackGain()) Preferences.isAlbumGain->setChecked(true);
    Preferences.isStartBrowserAtStartup->setChecked(isShowBrowserAtStatup());
    Preferences.isLogSkippedFiles->setChecked(isLogSkippedFiles());
    Preferences.exec();

    if (Preferences.result()){
        setMP3GainBinaryPath(Preferences.MP3GainPfad->text());
        setMP4GainBinaryPath(Preferences.MP4GainPfad->text());
        setVorbisGainBinaryPath(Preferences.VorbisGainPfad->text());
        setVolume(Preferences.Pegel->value());
        setTrackGain(Preferences.isTrackGain->isChecked());
        setShowBrowserAtStatup(Preferences.isStartBrowserAtStartup->isChecked());
        setIsLogSkippedFiles(Preferences.isLogSkippedFiles->isChecked());

        // Check if Replay gain tools are available
        setIsMP3GainFound(QFile::exists(MP3GainBinaryPath()));
        setIsMP4GainFound(QFile::exists(MP4GainBinaryPath()));
        setIsVorbisGainFound(QFile::exists(VorbisGainBinaryPath()));
        setIsFlacGainFound(QFile::exists(FlacGainBinaryPath()));
    }
}


// *********************************************************************************************
// Load settings
// *********************************************************************************************
void QtGain::loadSettings(){
    QSettings settings("Vegeta", "QtGain");
    move(settings.value("pos", QPoint(200, 200)).toPoint());
    setMP3GainBinaryPath   (settings.value("MP3Gain",    "/usr/bin/mp3gain").toString());
    setMP4GainBinaryPath   (settings.value("aacgain",    "/usr/bin/aacgain").toString());
    setVorbisGainBinaryPath(settings.value("VorbisGain", "/usr/bin/vorbisgain").toString());
    setFlacGainBinaryPath  (settings.value("FlacGain",   "/usr/bin/metaflac").toString());
    setVolume(settings.value("Volume", 89).toInt());
    setTrackGain(settings.value("TrackGain", true).toBool());
    setShowBrowserAtStatup(settings.value("ShowBrowser", false).toBool());
    setStatistic(settings.value("filesProcessed", 0).toInt(), settings.value("filesGained", 0).toInt(), settings.value("installDate", QDate::currentDate()).toDate());
    setIsLogSkippedFiles(settings.value("isLogSkippedFiles", false).toBool());

    // Fallback falls Replay-Gain-Tools über die geladenen Infos nicht gefunden werden können
    if (!QFile::exists(MP3GainBinaryPath()))    setMP3GainBinaryPath("/usr/bin/mp3gain");
    if (!QFile::exists(MP4GainBinaryPath()))    setMP4GainBinaryPath("/usr/bin/aacgain");
    if (!QFile::exists(VorbisGainBinaryPath())) setVorbisGainBinaryPath("/usr/bin/vorbisgain");
    if (!QFile::exists(FlacGainBinaryPath()))   setFlacGainBinaryPath("/usr/bin/metaflac");

    // Check if Replay gain tools are available
    setIsMP3GainFound   (QFile::exists(MP3GainBinaryPath()));
    setIsMP4GainFound   (QFile::exists(MP4GainBinaryPath()));
    setIsVorbisGainFound(QFile::exists(VorbisGainBinaryPath()));
    setIsFlacGainFound  (QFile::exists(FlacGainBinaryPath()));

    if (!isMP3GainFound() && !isMP3GainFound() && !isVorbisGainFound() && !isFlacGainFound()) {
        ui.Status->setText("Error");
        ui.Dateiname->setText("No replay gain tools found!");
    }
}


// *********************************************************************************************
// Save settings
// *********************************************************************************************
void QtGain::saveSettings(){
    QSettings settings("Vegeta", "QtGain");
    settings.setValue("pos",               pos());
    settings.setValue("MP3Gain",           MP3GainBinaryPath());
    settings.setValue("aacgain",           MP4GainBinaryPath());
    settings.setValue("VorbisGain",        VorbisGainBinaryPath());
    settings.setValue("FlacGain",          FlacGainBinaryPath());
    settings.setValue("Volume",            Volume());
    settings.setValue("TrackGain",         isTrackGain());
    settings.setValue("ShowBrowser",       isShowBrowserAtStatup());
    settings.setValue("isLogSkippedFiles", isLogSkippedFiles());

    int filesProcessed, filesGained;
    QDate installDate;
    Statistic(filesProcessed, filesGained, installDate);
    settings.setValue("filesProcessed",    filesProcessed);
    settings.setValue("filesGained",       filesGained);
    settings.setValue("installDate",       installDate);
}


// *********************************************************************************************
// Close the application and save settings
// *********************************************************************************************
void QtGain::Quit() {
    saveSettings();
    QApplication::quit();
}

void QtGain::closeEvent(QCloseEvent *event){
    Q_UNUSED(event);
    Quit();
}


// *********************************************************************************************
// About dialog
// *********************************************************************************************
void QtGain::showAboutDialog() {
    int filesProcessed, filesGained;
    QDate installDate;
    Statistic(filesProcessed, filesGained, installDate);

    QMessageBox::information(this, "About QtGain",
                             QString("<i>Mp3Gain, VorbisGain, AACGain and Metaflac frontend</i><br><br>"
                                     "(c) 2007-2010, Vegeta<br>"
                                     "<a href='http://qt-apps.org/content/show.php/QtGain?content=56842'>Project page</a><br><br>"
                                     "QtGain is free software; you can redistribute it and/or modify it "
                                     "under the terms of the GNU General Public License version 2 as published by the Free Software Foundation.<br><br>"
                                     "<b>Statistic:</b><br>QtGain has %1 files processed (%2 files were replay gained) since %3.").arg(filesProcessed).arg(filesGained).arg(installDate.toString("dd.MM.yyyy"))
                             );
}


// *********************************************************************************************
// Updates the time that has left since starting gaining
// *********************************************************************************************
void QtGain::updateGUI() {
    ui.Zeitanzeige->setText(TimeUpdateString());
}


// *********************************************************************************************
// Show Error-Log
// *********************************************************************************************
void QtGain::showErrors() {
    if (ErrorLog().isEmpty()) return;

    QDialog window(this);
    QTextEdit Text;
    Text.setReadOnly(true);
    Text.setText(ErrorLog());
    window.setWindowTitle("Errorlog");
    window.setMinimumSize(850, 500);
    QPushButton showMessageButton("Close");
    showMessageButton.setDefault(true);

    QGridLayout messageLayout;
    messageLayout.addWidget(&Text,0,0);
    messageLayout.addWidget(&showMessageButton);
    window.setLayout(&messageLayout);

    connect(&showMessageButton, SIGNAL(clicked()), &window, SLOT(close()));
    window.exec();
}

Generated by  Doxygen 1.6.0   Back to index