1 /*****************************************************************************
2 ** QNapi
3 ** Copyright (C) 2008-2017 Piotr Krzemiński <pio.krzeminski@gmail.com>
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 file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12 **
13 *****************************************************************************/
14 
15 #include "qnapi.h"
16 #include "libqnapi.h"
17 #include "subtitlematcher.h"
18 #include "subtitlepostprocessor.h"
19 
20 #include "config/configreader.h"
21 
22 #include <QtAlgorithms>
23 
QNapi(const QNapiConfig & config,const Maybe<QString> & specificEngine)24 QNapi::QNapi(const QNapiConfig& config, const Maybe<QString>& specificEngine)
25     : enginesRegistry(LibQNapi::subtitleDownloadEngineRegistry()),
26       config(config) {
27   if (specificEngine) {
28     enginesList << enginesRegistry->createEngine(specificEngine.value(),
29                                                  config);
30   } else {
31     enginesList << enginesRegistry->createEnabledEngines(config);
32   }
33 }
34 
~QNapi()35 QNapi::~QNapi() { cleanup(); }
36 
checkP7ZipPath()37 bool QNapi::checkP7ZipPath() {
38   return QFileInfo(config.generalConfig().p7zipPath()).isExecutable();
39 }
40 
checkTmpPath()41 bool QNapi::checkTmpPath() {
42   QFileInfo f(config.generalConfig().tmpPath());
43   return f.isDir() && f.isWritable();
44 }
45 
ppEnabled()46 bool QNapi::ppEnabled() { return config.postProcessingConfig().enabled(); }
47 
setMoviePath(QString path)48 void QNapi::setMoviePath(QString path) {
49   movie = path;
50   currentEngine = QSharedPointer<SubtitleDownloadEngine>();
51 }
52 
moviePath()53 QString QNapi::moviePath() { return movie; }
54 
checkWritePermissions()55 bool QNapi::checkWritePermissions() {
56   return QFileInfo(QFileInfo(movie).path()).isWritable();
57 }
58 
clearSubtitlesList()59 void QNapi::clearSubtitlesList() {
60   subtitlesList.clear();
61   foreach (QSharedPointer<SubtitleDownloadEngine> e, enginesList) {
62     e->clearSubtitlesList();
63   }
64 }
65 
checksum()66 void QNapi::checksum() {
67   foreach (QSharedPointer<SubtitleDownloadEngine> e, enginesList) {
68     e->checksum(movie);
69   }
70 }
71 
lookForSubtitles(QString lang,QString engine)72 bool QNapi::lookForSubtitles(QString lang, QString engine) {
73   bool result = false;
74 
75   if (engine.isEmpty()) {
76     foreach (QSharedPointer<SubtitleDownloadEngine> e, enginesList) {
77       e->setMoviePath(movie);
78       result = e->lookForSubtitles(lang) || result;
79     }
80   } else {
81     QSharedPointer<SubtitleDownloadEngine> e = engineByName(engine);
82     if (e) {
83       e->setMoviePath(movie);
84       result = e->lookForSubtitles(lang);
85     }
86   }
87 
88   if (!result) {
89     errorMsg = QObject::tr("No subtitles found!");
90   }
91 
92   return result;
93 }
94 
listSubtitles()95 QList<SubtitleInfo> QNapi::listSubtitles() {
96   subtitlesList.clear();
97 
98   foreach (QSharedPointer<SubtitleDownloadEngine> e, enginesList) {
99     QList<SubtitleInfo> list = e->listSubtitles();
100     subtitlesList << list;
101   }
102 
103   QString mainLang = config.generalConfig().language();
104   QString backupLang = config.generalConfig().backupLanguage();
105 
106   auto langRank = [&](QString lang) {
107     if (lang == mainLang) return 0;
108     if (lang == backupLang) return 1;
109     return 2;
110   };
111 
112   qStableSort(subtitlesList.begin(), subtitlesList.end(),
113               [&](const SubtitleInfo& si1, const SubtitleInfo& si2) {
114                 return langRank(si1.lang) < langRank(si2.lang);
115               });
116 
117   return subtitlesList;
118 }
119 
needToShowList()120 bool QNapi::needToShowList() {
121   theBestIdx = 0;
122 
123   int i = 0;
124   bool foundBestIdx = false;
125   foreach (SubtitleInfo s, listSubtitles()) {
126     if (s.resolution == SUBTITLE_GOOD) {
127       theBestIdx = i;
128       foundBestIdx = true;
129       break;
130     }
131     ++i;
132   }
133 
134   if (config.generalConfig().downloadPolicy() == DP_ALWAYS_SHOW_LIST)
135     return true;
136   if (config.generalConfig().downloadPolicy() == DP_NEVER_SHOW_LIST)
137     return false;
138 
139   if (listSubtitles().size() <= 1) return false;
140 
141   return !foundBestIdx;
142 }
143 
bestIdx()144 int QNapi::bestIdx() { return theBestIdx; }
145 
download(int i)146 bool QNapi::download(int i) {
147   SubtitleInfo s = subtitlesList[i];
148   currentEngine = engineByName(s.engine);
149   if (!currentEngine) return false;
150   return currentEngine->download(s.id);
151 }
152 
unpack(int i)153 bool QNapi::unpack(int i) {
154   return currentEngine ? currentEngine->unpack(subtitlesList[i].id) : false;
155 }
156 
matchSubtitles()157 bool QNapi::matchSubtitles() {
158   if (currentEngine) {
159     QSharedPointer<const SubtitleMatcher> matcher =
160         LibQNapi::subtitleMatcher(config);
161     return matcher->matchSubtitles(currentEngine->subtitlesTmp,
162                                    currentEngine->movie);
163   }
164 
165   return false;
166 }
167 
postProcessSubtitles() const168 void QNapi::postProcessSubtitles() const {
169   if (currentEngine) {
170     QSharedPointer<const SubtitlePostProcessor> postProcessor =
171         LibQNapi::subtitlePostProcessor(config.postProcessingConfig());
172 
173     postProcessor->perform(currentEngine->movie, currentEngine->subtitlesTmp);
174   }
175 }
176 
cleanup()177 void QNapi::cleanup() {
178   foreach (QSharedPointer<SubtitleDownloadEngine> e, enginesList) {
179     e->cleanup();
180   }
181 }
182 
error()183 QString QNapi::error() { return errorMsg; }
184 
listLoadedEngines() const185 QStringList QNapi::listLoadedEngines() const {
186   QStringList list;
187   foreach (QSharedPointer<SubtitleDownloadEngine> e, enginesList) {
188     list << e->meta().name();
189   }
190   return list;
191 }
192 
engineByName(QString name) const193 QSharedPointer<SubtitleDownloadEngine> QNapi::engineByName(QString name) const {
194   foreach (QSharedPointer<SubtitleDownloadEngine> e, enginesList) {
195     if (name == e->meta().name()) {
196       return e;
197     }
198   }
199 
200   return QSharedPointer<SubtitleDownloadEngine>();
201 }
202