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