1 /*
2  * Cantata
3  *
4  * Copyright (c) 2011-2020 Craig Drummond <craig.p.drummond@gmail.com>
5  *
6  * ----
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; see the file COPYING.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #include "albumscanner.h"
25 #include "config.h"
26 #include <QProcess>
27 #include <QApplication>
28 
AlbumScanner(const QMap<int,QString> & files)29 AlbumScanner::AlbumScanner(const QMap<int, QString> &files)
30     : proc(0)
31 {
32     QMap<int, QString>::ConstIterator it=files.constBegin();
33     QMap<int, QString>::ConstIterator end=files.constEnd();
34 
35     for (int i=0; it!=end; ++it, ++i) {
36         fileNames.append(it.value());
37         trackIndexMap[i]=it.key();
38     }
39 }
40 
~AlbumScanner()41 AlbumScanner::~AlbumScanner()
42 {
43     stop();
44 }
45 
start()46 void AlbumScanner::start()
47 {
48     if (!proc) {
49         proc=new QProcess(this);
50         proc->setProcessChannelMode(QProcess::MergedChannels);
51         proc->setReadChannel(QProcess::StandardOutput);
52         connect(proc, SIGNAL(finished(int)), this, SLOT(procFinished()));
53         connect(proc, SIGNAL(readyReadStandardOutput()), this, SLOT(read()));
54         proc->start(Utils::helper(QLatin1String("cantata-replaygain")), fileNames, QProcess::ReadOnly);
55     }
56 }
57 
stop()58 void AlbumScanner::stop()
59 {
60     if (proc) {
61         disconnect(proc, SIGNAL(finished(int)), this, SLOT(procFinished()));
62         disconnect(proc, SIGNAL(readyReadStandardOutput()), this, SLOT(read()));
63         proc->terminate();
64         proc->deleteLater();
65         proc=0;
66     }
67 }
68 
69 static const QString constProgLine=QLatin1String("PROGRESS: ");
70 static const QString constTrackLine=QLatin1String("TRACK: ");
71 static const QString constAlbumLine=QLatin1String("ALBUM: ");
72 
read()73 void AlbumScanner::read()
74 {
75     if (!proc) {
76         return;
77     }
78 
79     QString output = proc->readAllStandardOutput().data();
80     if (output.isEmpty()) {
81         return;
82     }
83 
84     QStringList lines=output.split("\n", QString::SkipEmptyParts);
85 
86     for (const QString &line: lines) {
87         if (line.startsWith(constProgLine)) {
88             emit progress(line.mid(constProgLine.length()).toUInt());
89         } else if (line.startsWith(constTrackLine)) {
90             QStringList parts=line.mid(constTrackLine.length()).split(" ", QString::SkipEmptyParts);
91             if (!parts.isEmpty()) {
92                 int num=parts[0].toUInt();
93                 Values vals;
94                 if (parts.length()>=3) {
95                     vals.gain=parts[1].toDouble();
96                     vals.peak=parts[2].toDouble();
97                     vals.ok=true;
98                 }
99                 tracks[trackIndexMap[num]]=vals;
100             }
101         } else if (line.startsWith(constAlbumLine)) {
102             QStringList parts=line.mid(constAlbumLine.length()).split(" ", QString::SkipEmptyParts);
103             if (parts.length()>=2) {
104                 album.gain=parts[0].toDouble();
105                 album.peak=parts[1].toDouble();
106                 album.ok=true;
107             }
108         }
109     }
110 }
111 
procFinished()112 void AlbumScanner::procFinished()
113 {
114     setFinished(true);
115     emit done();
116 }
117 
118 #include "moc_albumscanner.cpp"
119