OSDN Git Service

Added support for importing Meta tags from a CSV files.
[lamexp/LameXP.git] / src / Thread_FileAnalyzer.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2012 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
21
22 #include "Thread_FileAnalyzer.h"
23
24 #include "Global.h"
25 #include "LockedFile.h"
26 #include "Model_AudioFile.h"
27 #include "PlaylistImporter.h"
28
29 #include <QDir>
30 #include <QFileInfo>
31 #include <QProcess>
32 #include <QDate>
33 #include <QTime>
34 #include <QDebug>
35 #include <QImage>
36
37 #include <math.h>
38
39 ////////////////////////////////////////////////////////////
40 // Constructor
41 ////////////////////////////////////////////////////////////
42
43 FileAnalyzer::FileAnalyzer(const QStringList &inputFiles)
44 :
45         m_inputFiles(inputFiles),
46         m_mediaInfoBin(lamexp_lookup_tool("mediainfo.exe")),
47         m_avs2wavBin(lamexp_lookup_tool("avs2wav.exe")),
48         m_abortFlag(false)
49 {
50         m_bSuccess = false;
51         m_bAborted = false;
52                 
53         if(m_mediaInfoBin.isEmpty())
54         {
55                 qFatal("Invalid path to MediaInfo binary. Tool not initialized properly.");
56         }
57
58         m_filesAccepted = 0;
59         m_filesRejected = 0;
60         m_filesDenied = 0;
61         m_filesDummyCDDA = 0;
62         m_filesCueSheet = 0;
63 }
64
65 ////////////////////////////////////////////////////////////
66 // Thread Main
67 ////////////////////////////////////////////////////////////
68
69 void FileAnalyzer::run()
70 {
71         m_bSuccess = false;
72         m_bAborted = false;
73
74         m_filesAccepted = 0;
75         m_filesRejected = 0;
76         m_filesDenied = 0;
77         m_filesDummyCDDA = 0;
78         m_filesCueSheet = 0;
79
80         m_inputFiles.sort();
81         m_recentlyAdded.clear();
82         m_abortFlag = false;
83
84         while(!m_inputFiles.isEmpty())
85         {
86                 int fileType = fileTypeNormal;
87                 QString currentFile = QDir::fromNativeSeparators(m_inputFiles.takeFirst());
88                 qDebug("Analyzing: %s", currentFile.toUtf8().constData());
89                 emit fileSelected(QFileInfo(currentFile).fileName());
90                 AudioFileModel file = analyzeFile(currentFile, &fileType);
91                 
92                 if(m_abortFlag)
93                 {
94                         MessageBeep(MB_ICONERROR);
95                         m_bAborted = true;
96                         qWarning("Operation cancelled by user!");
97                         return;
98                 }
99                 if(fileType == fileTypeSkip)
100                 {
101                         qWarning("File was recently added, skipping!");
102                         continue;
103                 }
104                 if(fileType == fileTypeDenied)
105                 {
106                         m_filesDenied++;
107                         qWarning("Cannot access file for reading, skipping!");
108                         continue;
109                 }
110                 if(fileType == fileTypeCDDA)
111                 {
112                         m_filesDummyCDDA++;
113                         qWarning("Dummy CDDA file detected, skipping!");
114                         continue;
115                 }
116                 
117                 if(file.fileName().isEmpty() || file.formatContainerType().isEmpty() || file.formatAudioType().isEmpty())
118                 {
119                         if(PlaylistImporter::importPlaylist(m_inputFiles, currentFile))
120                         {
121                                 qDebug("Imported playlist file.");
122                         }
123                         else if(!QFileInfo(currentFile).suffix().compare("cue", Qt::CaseInsensitive))
124                         {
125                                 qWarning("Cue Sheet file detected, skipping!");
126                                 m_filesCueSheet++;
127                         }
128                         else if(!QFileInfo(currentFile).suffix().compare("avs", Qt::CaseInsensitive))
129                         {
130                                 qDebug("Found a potential Avisynth script, investigating...");
131                                 if(analyzeAvisynthFile(currentFile, file))
132                                 {
133                                         m_filesAccepted++;
134                                         emit fileAnalyzed(file);
135                                 }
136                                 else
137                                 {
138                                         qDebug("Rejected Avisynth file: %s", file.filePath().toUtf8().constData());
139                                         m_filesRejected++;
140                                 }
141                         }
142                         else
143                         {
144                                 qDebug("Rejected file of unknown type: %s", file.filePath().toUtf8().constData());
145                                 m_filesRejected++;
146                         }
147                         continue;
148                 }
149
150                 m_filesAccepted++;
151                 m_recentlyAdded.append(file.filePath());
152                 emit fileAnalyzed(file);
153         }
154
155         qDebug("All files added.\n");
156         m_bSuccess = true;
157 }
158
159 ////////////////////////////////////////////////////////////
160 // Privtae Functions
161 ////////////////////////////////////////////////////////////
162
163 const AudioFileModel FileAnalyzer::analyzeFile(const QString &filePath, int *type)
164 {
165         *type = fileTypeNormal;
166         
167         AudioFileModel audioFile(filePath);
168         m_currentSection = sectionOther;
169         m_currentCover = coverNone;
170
171         if(m_recentlyAdded.contains(filePath, Qt::CaseInsensitive))
172         {
173                 *type = fileTypeSkip;
174                 return audioFile;
175         }
176
177         QFile readTest(filePath);
178         if(!readTest.open(QIODevice::ReadOnly))
179         {
180                 *type = fileTypeDenied;
181                 return audioFile;
182         }
183         
184         if(checkFile_CDDA(readTest))
185         {
186                 *type = fileTypeCDDA;
187                 return audioFile;
188         }
189         
190         readTest.close();
191
192         QProcess process;
193         process.setProcessChannelMode(QProcess::MergedChannels);
194         process.setReadChannel(QProcess::StandardOutput);
195         process.start(m_mediaInfoBin, QStringList() << QDir::toNativeSeparators(filePath));
196                 
197         if(!process.waitForStarted())
198         {
199                 qWarning("MediaInfo process failed to create!");
200                 qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData());
201                 process.kill();
202                 process.waitForFinished(-1);
203                 return audioFile;
204         }
205
206         while(process.state() != QProcess::NotRunning)
207         {
208                 if(m_abortFlag)
209                 {
210                         process.kill();
211                         qWarning("Process was aborted on user request!");
212                         break;
213                 }
214                 
215                 if(!process.waitForReadyRead())
216                 {
217                         if(process.state() == QProcess::Running)
218                         {
219                                 qWarning("MediaInfo time out. Killing process and skipping file!");
220                                 process.kill();
221                                 process.waitForFinished(-1);
222                                 return audioFile;
223                         }
224                 }
225
226                 QByteArray data;
227
228                 while(process.canReadLine())
229                 {
230                         QString line = QString::fromUtf8(process.readLine().constData()).simplified();
231                         if(!line.isEmpty())
232                         {
233                                 int index = line.indexOf(':');
234                                 if(index > 0)
235                                 {
236                                         QString key = line.left(index-1).trimmed();
237                                         QString val = line.mid(index+1).trimmed();
238                                         if(!key.isEmpty() && !val.isEmpty())
239                                         {
240                                                 updateInfo(audioFile, key, val);
241                                         }
242                                 }
243                                 else
244                                 {
245                                         updateSection(line);
246                                 }
247                         }
248                 }
249         }
250
251         if(audioFile.fileName().isEmpty())
252         {
253                 QString baseName = QFileInfo(filePath).fileName();
254                 int index = baseName.lastIndexOf(".");
255
256                 if(index >= 0)
257                 {
258                         baseName = baseName.left(index);
259                 }
260
261                 baseName = baseName.replace("_", " ").simplified();
262                 index = baseName.lastIndexOf(" - ");
263
264                 if(index >= 0)
265                 {
266                         baseName = baseName.mid(index + 3).trimmed();
267                 }
268
269                 audioFile.setFileName(baseName);
270         }
271         
272         process.waitForFinished();
273         if(process.state() != QProcess::NotRunning)
274         {
275                 process.kill();
276                 process.waitForFinished(-1);
277         }
278
279         if(m_currentCover != coverNone)
280         {
281                 retrieveCover(audioFile, filePath);
282         }
283
284         return audioFile;
285 }
286
287 void FileAnalyzer::updateSection(const QString &section)
288 {
289         if(section.startsWith("General", Qt::CaseInsensitive))
290         {
291                 m_currentSection = sectionGeneral;
292         }
293         else if(!section.compare("Audio", Qt::CaseInsensitive) || section.startsWith("Audio #1", Qt::CaseInsensitive))
294         {
295                 m_currentSection = sectionAudio;
296         }
297         else if(section.startsWith("Audio", Qt::CaseInsensitive) || section.startsWith("Video", Qt::CaseInsensitive) || section.startsWith("Text", Qt::CaseInsensitive) ||
298                 section.startsWith("Menu", Qt::CaseInsensitive) || section.startsWith("Image", Qt::CaseInsensitive) || section.startsWith("Chapters", Qt::CaseInsensitive))
299         {
300                 m_currentSection = sectionOther;
301         }
302         else
303         {
304                 m_currentSection = sectionOther;
305                 qWarning("Unknown section: %s", section.toUtf8().constData());
306         }
307 }
308
309 void FileAnalyzer::updateInfo(AudioFileModel &audioFile, const QString &key, const QString &value)
310 {
311         switch(m_currentSection)
312         {
313         case sectionGeneral:
314                 if(!key.compare("Title", Qt::CaseInsensitive) || !key.compare("Track", Qt::CaseInsensitive) || !key.compare("Track Name", Qt::CaseInsensitive))
315                 {
316                         if(audioFile.fileName().isEmpty()) audioFile.setFileName(value);
317                 }
318                 else if(!key.compare("Duration", Qt::CaseInsensitive))
319                 {
320                         if(!audioFile.fileDuration()) audioFile.setFileDuration(parseDuration(value));
321                 }
322                 else if(!key.compare("Artist", Qt::CaseInsensitive) || !key.compare("Performer", Qt::CaseInsensitive))
323                 {
324                         if(audioFile.fileArtist().isEmpty()) audioFile.setFileArtist(value);
325                 }
326                 else if(!key.compare("Album", Qt::CaseInsensitive))
327                 {
328                         if(audioFile.fileAlbum().isEmpty()) audioFile.setFileAlbum(value);
329                 }
330                 else if(!key.compare("Genre", Qt::CaseInsensitive))
331                 {
332                         if(audioFile.fileGenre().isEmpty()) audioFile.setFileGenre(value);
333                 }
334                 else if(!key.compare("Year", Qt::CaseInsensitive) || !key.compare("Recorded Date", Qt::CaseInsensitive) || !key.compare("Encoded Date", Qt::CaseInsensitive))
335                 {
336                         if(!audioFile.fileYear()) audioFile.setFileYear(parseYear(value));
337                 }
338                 else if(!key.compare("Comment", Qt::CaseInsensitive))
339                 {
340                         if(audioFile.fileComment().isEmpty()) audioFile.setFileComment(value);
341                 }
342                 else if(!key.compare("Track Name/Position", Qt::CaseInsensitive))
343                 {
344                         if(!audioFile.filePosition()) audioFile.setFilePosition(value.toInt());
345                 }
346                 else if(!key.compare("Format", Qt::CaseInsensitive))
347                 {
348                         if(audioFile.formatContainerType().isEmpty()) audioFile.setFormatContainerType(value);
349                 }
350                 else if(!key.compare("Format Profile", Qt::CaseInsensitive))
351                 {
352                         if(audioFile.formatContainerProfile().isEmpty()) audioFile.setFormatContainerProfile(value);
353                 }
354                 else if(!key.compare("Cover", Qt::CaseInsensitive) || !key.compare("Cover type", Qt::CaseInsensitive))
355                 {
356                         if(m_currentCover == coverNone) m_currentCover = coverJpeg;
357                 }
358                 else if(!key.compare("Cover MIME", Qt::CaseInsensitive))
359                 {
360                         QString temp = value.split(" ", QString::SkipEmptyParts, Qt::CaseInsensitive).first();
361                         if(!temp.compare("image/jpeg", Qt::CaseInsensitive))
362                         {
363                                 m_currentCover = coverJpeg;
364                         }
365                         else if(!temp.compare("image/png", Qt::CaseInsensitive))
366                         {
367                                 m_currentCover = coverPng;
368                         }
369                         else if(!temp.compare("image/gif", Qt::CaseInsensitive))
370                         {
371                                 m_currentCover = coverGif;
372                         }
373                 }
374                 break;
375
376         case sectionAudio:
377                 if(!key.compare("Year", Qt::CaseInsensitive) || !key.compare("Recorded Date", Qt::CaseInsensitive) || !key.compare("Encoded Date", Qt::CaseInsensitive))
378                 {
379                         if(!audioFile.fileYear()) audioFile.setFileYear(parseYear(value));
380                 }
381                 else if(!key.compare("Format", Qt::CaseInsensitive))
382                 {
383                         if(audioFile.formatAudioType().isEmpty()) audioFile.setFormatAudioType(value);
384                 }
385                 else if(!key.compare("Format Profile", Qt::CaseInsensitive))
386                 {
387                         if(audioFile.formatAudioProfile().isEmpty()) audioFile.setFormatAudioProfile(value);
388                 }
389                 else if(!key.compare("Format Version", Qt::CaseInsensitive))
390                 {
391                         if(audioFile.formatAudioVersion().isEmpty()) audioFile.setFormatAudioVersion(value);
392                 }
393                 else if(!key.compare("Channel(s)", Qt::CaseInsensitive))
394                 {
395                         if(!audioFile.formatAudioChannels()) audioFile.setFormatAudioChannels(value.split(" ", QString::SkipEmptyParts).first().toUInt());
396                 }
397                 else if(!key.compare("Sampling rate", Qt::CaseInsensitive))
398                 {
399                         if(!audioFile.formatAudioSamplerate())
400                         {
401                                 bool ok = false;
402                                 float fTemp = abs(value.split(" ", QString::SkipEmptyParts).first().toFloat(&ok));
403                                 if(ok) audioFile.setFormatAudioSamplerate(static_cast<unsigned int>(floor(fTemp * 1000.0f + 0.5f)));
404                         }
405                 }
406                 else if(!key.compare("Bit depth", Qt::CaseInsensitive))
407                 {
408                         if(!audioFile.formatAudioBitdepth()) audioFile.setFormatAudioBitdepth(value.split(" ", QString::SkipEmptyParts).first().toUInt());
409                 }
410                 else if(!key.compare("Duration", Qt::CaseInsensitive))
411                 {
412                         if(!audioFile.fileDuration()) audioFile.setFileDuration(parseDuration(value));
413                 }
414                 else if(!key.compare("Bit rate", Qt::CaseInsensitive))
415                 {
416                         if(!audioFile.formatAudioBitrate())
417                         {
418                                 bool ok = false;
419                                 unsigned int uiTemp = value.split(" ", QString::SkipEmptyParts).first().toUInt(&ok);
420                                 if(ok)
421                                 {
422                                         audioFile.setFormatAudioBitrate(uiTemp);
423                                 }
424                                 else
425                                 {
426                                         float fTemp = abs(value.split(" ", QString::SkipEmptyParts).first().toFloat(&ok));
427                                         if(ok) audioFile.setFormatAudioBitrate(static_cast<unsigned int>(floor(fTemp + 0.5f)));
428                                 }
429                         }
430                 }
431                 else if(!key.compare("Bit rate mode", Qt::CaseInsensitive))
432                 {
433                         if(audioFile.formatAudioBitrateMode() == AudioFileModel::BitrateModeUndefined)
434                         {
435                                 if(!value.compare("Constant", Qt::CaseInsensitive)) audioFile.setFormatAudioBitrateMode(AudioFileModel::BitrateModeConstant);
436                                 if(!value.compare("Variable", Qt::CaseInsensitive)) audioFile.setFormatAudioBitrateMode(AudioFileModel::BitrateModeVariable);
437                         }
438                 }
439                 break;
440         }
441 }
442
443 unsigned int FileAnalyzer::parseYear(const QString &str)
444 {
445         if(str.startsWith("UTC", Qt::CaseInsensitive))
446         {
447                 QDate date = QDate::fromString(str.mid(3).trimmed().left(10), "yyyy-MM-dd");
448                 if(date.isValid())
449                 {
450                         return date.year();
451                 }
452                 else
453                 {
454                         return 0;
455                 }
456         }
457         else
458         {
459                 bool ok = false;
460                 int year = str.toInt(&ok);
461                 if(ok && year > 0)
462                 {
463                         return year;
464                 }
465                 else
466                 {
467                         return 0;
468                 }
469         }
470 }
471
472 unsigned int FileAnalyzer::parseDuration(const QString &str)
473 {
474         QTime time;
475
476         time = QTime::fromString(str, "z'ms'");
477         if(time.isValid())
478         {
479                 return qMax(1, (time.hour() * 60 * 60) + (time.minute() * 60) + time.second());
480         }
481
482         time = QTime::fromString(str, "s's 'z'ms'");
483         if(time.isValid())
484         {
485                 return qMax(1, (time.hour() * 60 * 60) + (time.minute() * 60) + time.second());
486         }
487
488         time = QTime::fromString(str, "m'mn 's's'");
489         if(time.isValid())
490         {
491                 return qMax(1, (time.hour() * 60 * 60) + (time.minute() * 60) + time.second());
492         }
493
494         time = QTime::fromString(str, "h'h 'm'mn'");
495         if(time.isValid())
496         {
497                 return qMax(1, (time.hour() * 60 * 60) + (time.minute() * 60) + time.second());
498         }
499
500         return 0;
501 }
502
503 bool FileAnalyzer::checkFile_CDDA(QFile &file)
504 {
505         file.reset();
506         QByteArray data = file.read(128);
507         
508         int i = data.indexOf("RIFF");
509         int j = data.indexOf("CDDA");
510         int k = data.indexOf("fmt ");
511
512         return ((i >= 0) && (j >= 0) && (k >= 0) && (k > j) && (j > i));
513 }
514
515 void FileAnalyzer::retrieveCover(AudioFileModel &audioFile, const QString &filePath)
516 {
517         qDebug("Retrieving cover from: %s", filePath.toUtf8().constData());
518         QString extension;
519
520         switch(m_currentCover)
521         {
522         case coverPng:
523                 extension = QString::fromLatin1("png");
524                 break;
525         case coverGif:
526                 extension = QString::fromLatin1("gif");
527                 break;
528         default:
529                 extension = QString::fromLatin1("jpg");
530                 break;
531         }
532         
533         QProcess process;
534         process.setProcessChannelMode(QProcess::MergedChannels);
535         process.setReadChannel(QProcess::StandardOutput);
536         process.start(m_mediaInfoBin, QStringList() << "-f" << QDir::toNativeSeparators(filePath));
537         
538         if(!process.waitForStarted())
539         {
540                 qWarning("MediaInfo process failed to create!");
541                 qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData());
542                 process.kill();
543                 process.waitForFinished(-1);
544                 return;
545         }
546
547         while(process.state() != QProcess::NotRunning)
548         {
549                 if(m_abortFlag)
550                 {
551                         process.kill();
552                         qWarning("Process was aborted on user request!");
553                         break;
554                 }
555                 
556                 if(!process.waitForReadyRead())
557                 {
558                         if(process.state() == QProcess::Running)
559                         {
560                                 qWarning("MediaInfo time out. Killing process and skipping file!");
561                                 process.kill();
562                                 process.waitForFinished(-1);
563                                 return;
564                         }
565                 }
566
567                 while(process.canReadLine())
568                 {
569                         QString line = QString::fromUtf8(process.readLine().constData()).simplified();
570                         if(!line.isEmpty())
571                         {
572                                 int index = line.indexOf(':');
573                                 if(index > 0)
574                                 {
575                                         QString key = line.left(index-1).trimmed();
576                                         QString val = line.mid(index+1).trimmed();
577                                         if(!key.isEmpty() && !val.isEmpty())
578                                         {
579                                                 if(!key.compare("Cover_Data", Qt::CaseInsensitive))
580                                                 {
581                                                         if(val.indexOf(" ") > 0)
582                                                         {
583                                                                 val = val.split(" ", QString::SkipEmptyParts, Qt::CaseInsensitive).first();
584                                                         }
585                                                         QByteArray coverData = QByteArray::fromBase64(val.toLatin1());
586                                                         if(!(QImage::fromData(coverData, extension.toUpper().toLatin1().constData()).isNull()))
587                                                         {
588                                                                 QFile coverFile(QString("%1/%2.%3").arg(lamexp_temp_folder2(), lamexp_rand_str(), extension));
589                                                                 if(coverFile.open(QIODevice::WriteOnly))
590                                                                 {
591                                                                         coverFile.write(coverData);
592                                                                         coverFile.close();
593                                                                         audioFile.setFileCover(coverFile.fileName(), true);
594                                                                 }
595                                                         }
596                                                         else
597                                                         {
598                                                                 qWarning("Image data seems to be invalid :-(");
599                                                         }
600                                                         break;
601                                                 }
602                                         }
603                                 }
604                         }
605                 }
606         }
607
608         process.waitForFinished();
609         if(process.state() != QProcess::NotRunning)
610         {
611                 process.kill();
612                 process.waitForFinished(-1);
613         }
614 }
615
616 bool FileAnalyzer::analyzeAvisynthFile(const QString &filePath, AudioFileModel &info)
617 {
618         QProcess process;
619         process.setProcessChannelMode(QProcess::MergedChannels);
620         process.setReadChannel(QProcess::StandardOutput);
621         process.start(m_avs2wavBin, QStringList() << QDir::toNativeSeparators(filePath) << "?");
622
623         if(!process.waitForStarted())
624         {
625                 qWarning("AVS2WAV process failed to create!");
626                 qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData());
627                 process.kill();
628                 process.waitForFinished(-1);
629                 return false;
630         }
631
632         bool bInfoHeaderFound = false;
633
634         while(process.state() != QProcess::NotRunning)
635         {
636                 if(m_abortFlag)
637                 {
638                         process.kill();
639                         qWarning("Process was aborted on user request!");
640                         break;
641                 }
642                 
643                 if(!process.waitForReadyRead())
644                 {
645                         if(process.state() == QProcess::Running)
646                         {
647                                 qWarning("AVS2WAV time out. Killing process and skipping file!");
648                                 process.kill();
649                                 process.waitForFinished(-1);
650                                 return false;
651                         }
652                 }
653
654                 QByteArray data;
655
656                 while(process.canReadLine())
657                 {
658                         QString line = QString::fromUtf8(process.readLine().constData()).simplified();
659                         if(!line.isEmpty())
660                         {
661                                 int index = line.indexOf(':');
662                                 if(index > 0)
663                                 {
664                                         QString key = line.left(index).trimmed();
665                                         QString val = line.mid(index+1).trimmed();
666
667                                         if(bInfoHeaderFound && !key.isEmpty() && !val.isEmpty())
668                                         {
669                                                 if(key.compare("TotalSeconds", Qt::CaseInsensitive) == 0)
670                                                 {
671                                                         bool ok = false;
672                                                         unsigned int duration = val.toUInt(&ok);
673                                                         if(ok) info.setFileDuration(duration);
674                                                 }
675                                                 if(key.compare("SamplesPerSec", Qt::CaseInsensitive) == 0)
676                                                 {
677                                                         bool ok = false;
678                                                         unsigned int samplerate = val.toUInt(&ok);
679                                                         if(ok) info.setFormatAudioSamplerate (samplerate);
680                                                 }
681                                                 if(key.compare("Channels", Qt::CaseInsensitive) == 0)
682                                                 {
683                                                         bool ok = false;
684                                                         unsigned int channels = val.toUInt(&ok);
685                                                         if(ok) info.setFormatAudioChannels(channels);
686                                                 }
687                                                 if(key.compare("BitsPerSample", Qt::CaseInsensitive) == 0)
688                                                 {
689                                                         bool ok = false;
690                                                         unsigned int bitdepth = val.toUInt(&ok);
691                                                         if(ok) info.setFormatAudioBitdepth(bitdepth);
692                                                 }                                       
693                                         }
694                                 }
695                                 else
696                                 {
697                                         if(line.contains("[Audio Info]", Qt::CaseInsensitive))
698                                         {
699                                                 info.setFormatAudioType("Avisynth");
700                                                 info.setFormatContainerType("Avisynth");
701                                                 bInfoHeaderFound = true;
702                                         }
703                                 }
704                         }
705                 }
706         }
707         
708         process.waitForFinished();
709         if(process.state() != QProcess::NotRunning)
710         {
711                 process.kill();
712                 process.waitForFinished(-1);
713         }
714
715         //Check exit code
716         switch(process.exitCode())
717         {
718         case 0:
719                 qDebug("Avisynth script was analyzed successfully.");
720                 return true;
721                 break;
722         case -5:
723                 qWarning("It appears that Avisynth is not installed on the system!");
724                 return false;
725                 break;
726         default:
727                 qWarning("Failed to open the Avisynth script, bad AVS file?");
728                 return false;
729                 break;
730         }
731 }
732
733 ////////////////////////////////////////////////////////////
734 // Public Functions
735 ////////////////////////////////////////////////////////////
736
737 unsigned int FileAnalyzer::filesAccepted(void)
738 {
739         return m_filesAccepted;
740 }
741
742 unsigned int FileAnalyzer::filesRejected(void)
743 {
744         return m_filesRejected;
745 }
746
747 unsigned int FileAnalyzer::filesDenied(void)
748 {
749         return m_filesDenied;
750 }
751
752 unsigned int FileAnalyzer::filesDummyCDDA(void)
753 {
754         return m_filesDummyCDDA;
755 }
756
757 unsigned int FileAnalyzer::filesCueSheet(void)
758 {
759         return m_filesCueSheet;
760 }
761
762 ////////////////////////////////////////////////////////////
763 // EVENTS
764 ////////////////////////////////////////////////////////////
765
766 /*NONE*/