OSDN Git Service

Some improvements and simplifications to error handling functions.
[lamexp/LameXP.git] / src / Global_Tools.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2014 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, but always including the *additional*
9 // restrictions defined in the "License.txt" file.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 //
20 // http://www.gnu.org/licenses/gpl-2.0.txt
21 ///////////////////////////////////////////////////////////////////////////////
22
23 #include "Global.h"
24
25 //Qt includes
26 #include <QApplication>
27 #include <QMap>
28 #include <QReadWriteLock>
29 #include <QReadLocker>
30 #include <QWriteLocker>
31 #include <QString>
32 #include <QStringList>
33 #include <QTranslator>
34 #include <QFileInfo>
35
36 //LameXP includes
37 #include "LockedFile.h"
38
39 ///////////////////////////////////////////////////////////////////////////////
40 // GLOBAL VARS
41 ///////////////////////////////////////////////////////////////////////////////
42
43 //Tools
44 static struct
45 {
46         QMap<QString, LockedFile*> *registry;
47         QMap<QString, unsigned int> *versions;
48         QMap<QString, QString> *tags;
49         QReadWriteLock lock;
50 }
51 g_lamexp_tools;
52
53 //Supported languages
54 static struct
55 {
56         QMap<QString, QString> *files;
57         QMap<QString, QString> *names;
58         QMap<QString, unsigned int> *sysid;
59         QMap<QString, unsigned int> *cntry;
60         QReadWriteLock lock;
61 }
62 g_lamexp_translation;
63
64 //Translator
65 static struct
66 {
67         QTranslator *instance;
68         QReadWriteLock lock;
69 }
70 g_lamexp_currentTranslator;
71
72 ///////////////////////////////////////////////////////////////////////////////
73 // GLOBAL FUNCTIONS
74 ///////////////////////////////////////////////////////////////////////////////
75
76 /*
77  * Register tool
78  */
79 void lamexp_register_tool(const QString &toolName, LockedFile *file, unsigned int version, const QString *tag)
80 {
81         QWriteLocker writeLock(&g_lamexp_tools.lock);
82         
83         if(!g_lamexp_tools.registry) g_lamexp_tools.registry = new QMap<QString, LockedFile*>();
84         if(!g_lamexp_tools.versions) g_lamexp_tools.versions = new QMap<QString, unsigned int>();
85         if(!g_lamexp_tools.tags) g_lamexp_tools.tags = new QMap<QString, QString>();
86
87         if(g_lamexp_tools.registry->contains(toolName.toLower()))
88         {
89                 THROW("lamexp_register_tool: Tool is already registered!");
90         }
91
92         g_lamexp_tools.registry->insert(toolName.toLower(), file);
93         g_lamexp_tools.versions->insert(toolName.toLower(), version);
94         g_lamexp_tools.tags->insert(toolName.toLower(), (tag) ? (*tag) : QString());
95 }
96
97 /*
98  * Check for tool
99  */
100 bool lamexp_check_tool(const QString &toolName)
101 {
102         QReadLocker readLock(&g_lamexp_tools.lock);
103         return (g_lamexp_tools.registry) ? g_lamexp_tools.registry->contains(toolName.toLower()) : false;
104 }
105
106 /*
107  * Lookup tool path
108  */
109 const QString lamexp_lookup_tool(const QString &toolName)
110 {
111         QReadLocker readLock(&g_lamexp_tools.lock);
112
113         if(g_lamexp_tools.registry)
114         {
115                 if(g_lamexp_tools.registry->contains(toolName.toLower()))
116                 {
117                         return g_lamexp_tools.registry->value(toolName.toLower())->filePath();
118                 }
119                 else
120                 {
121                         return QString();
122                 }
123         }
124         else
125         {
126                 return QString();
127         }
128 }
129
130 /*
131  * Lookup tool version
132  */
133 unsigned int lamexp_tool_version(const QString &toolName, QString *tag)
134 {
135         QReadLocker readLock(&g_lamexp_tools.lock);
136         if(tag) tag->clear();
137
138         if(g_lamexp_tools.versions)
139         {
140                 if(g_lamexp_tools.versions->contains(toolName.toLower()))
141                 {
142                         if(tag)
143                         {
144                                 if(g_lamexp_tools.tags->contains(toolName.toLower())) *tag = g_lamexp_tools.tags->value(toolName.toLower());
145                         }
146                         return g_lamexp_tools.versions->value(toolName.toLower());
147                 }
148                 else
149                 {
150                         return UINT_MAX;
151                 }
152         }
153         else
154         {
155                 return UINT_MAX;
156         }
157 }
158
159 /*
160  * Version number to human-readable string
161  */
162 const QString lamexp_version2string(const QString &pattern, unsigned int version, const QString &defaultText, const QString *tag)
163 {
164         if(version == UINT_MAX)
165         {
166                 return defaultText;
167         }
168         
169         QString result = pattern;
170         const int digits = result.count(QChar(L'?'), Qt::CaseInsensitive);
171         
172         if(digits < 1)
173         {
174                 return result;
175         }
176         
177         int pos = 0, index = -1;
178         const QString versionStr = QString().sprintf("%0*u", digits, version);
179         Q_ASSERT(versionStr.length() == digits);
180         
181         while((index = result.indexOf(QChar(L'?'), Qt::CaseInsensitive)) >= 0)
182         {
183                 result[index] = versionStr[pos++];
184         }
185
186         if(tag)
187         {
188                 if((index = result.indexOf(QChar(L'#'), Qt::CaseInsensitive)) >= 0)
189                 {
190                         result.remove(index, 1).insert(index, (*tag));
191                 }
192         }
193
194         return result;
195 }
196
197 /*
198  * Initialize translations and add default language
199  */
200 bool lamexp_translation_init(void)
201 {
202         QWriteLocker writeLockTranslations(&g_lamexp_translation.lock);
203
204         if((!g_lamexp_translation.files) && (!g_lamexp_translation.names))
205         {
206                 g_lamexp_translation.files = new QMap<QString, QString>();
207                 g_lamexp_translation.names = new QMap<QString, QString>();
208                 g_lamexp_translation.files->insert(LAMEXP_DEFAULT_LANGID, "");
209                 g_lamexp_translation.names->insert(LAMEXP_DEFAULT_LANGID, "English");
210                 return true;
211         }
212         else
213         {
214                 qWarning("[lamexp_translation_init] Error: Already initialized!");
215                 return false;
216         }
217 }
218
219 /*
220  * Register a new translation
221  */
222 bool lamexp_translation_register(const QString &langId, const QString &qmFile, const QString &langName, unsigned int &systemId, unsigned int &country)
223 {
224         QWriteLocker writeLockTranslations(&g_lamexp_translation.lock);
225
226         if(qmFile.isEmpty() || langName.isEmpty() || systemId < 1)
227         {
228                 return false;
229         }
230
231         if(!g_lamexp_translation.files) g_lamexp_translation.files = new QMap<QString, QString>();
232         if(!g_lamexp_translation.names) g_lamexp_translation.names = new QMap<QString, QString>();
233         if(!g_lamexp_translation.sysid) g_lamexp_translation.sysid = new QMap<QString, unsigned int>();
234         if(!g_lamexp_translation.cntry) g_lamexp_translation.cntry = new QMap<QString, unsigned int>();
235
236         g_lamexp_translation.files->insert(langId, qmFile);
237         g_lamexp_translation.names->insert(langId, langName);
238         g_lamexp_translation.sysid->insert(langId, systemId);
239         g_lamexp_translation.cntry->insert(langId, country);
240
241         return true;
242 }
243
244 /*
245  * Get list of all translations
246  */
247 QStringList lamexp_query_translations(void)
248 {
249         QReadLocker readLockTranslations(&g_lamexp_translation.lock);
250         return (g_lamexp_translation.files) ? g_lamexp_translation.files->keys() : QStringList();
251 }
252
253 /*
254  * Get translation name
255  */
256 QString lamexp_translation_name(const QString &langId)
257 {
258         QReadLocker readLockTranslations(&g_lamexp_translation.lock);
259         return (g_lamexp_translation.names) ? g_lamexp_translation.names->value(langId.toLower(), QString()) : QString();
260 }
261
262 /*
263  * Get translation system id
264  */
265 unsigned int lamexp_translation_sysid(const QString &langId)
266 {
267         QReadLocker readLockTranslations(&g_lamexp_translation.lock);
268         return (g_lamexp_translation.sysid) ? g_lamexp_translation.sysid->value(langId.toLower(), 0) : 0;
269 }
270
271 /*
272  * Get translation script id
273  */
274 unsigned int lamexp_translation_country(const QString &langId)
275 {
276         QReadLocker readLockTranslations(&g_lamexp_translation.lock);
277         return (g_lamexp_translation.cntry) ? g_lamexp_translation.cntry->value(langId.toLower(), 0) : 0;
278 }
279
280 /*
281  * Install a new translator
282  */
283 bool lamexp_install_translator(const QString &langId)
284 {
285         bool success = false;
286         const QString qmFileToPath(":/localization/%1");
287
288         if(langId.isEmpty() || langId.toLower().compare(LAMEXP_DEFAULT_LANGID) == 0)
289         {
290                 success = lamexp_install_translator_from_file(qmFileToPath.arg(LAMEXP_DEFAULT_TRANSLATION));
291         }
292         else
293         {
294                 QReadLocker readLock(&g_lamexp_translation.lock);
295                 QString qmFile = (g_lamexp_translation.files) ? g_lamexp_translation.files->value(langId.toLower(), QString()) : QString();
296                 readLock.unlock();
297
298                 if(!qmFile.isEmpty())
299                 {
300                         success = lamexp_install_translator_from_file(qmFileToPath.arg(qmFile));
301                 }
302                 else
303                 {
304                         qWarning("Translation '%s' not available!", langId.toLatin1().constData());
305                 }
306         }
307
308         return success;
309 }
310
311 /*
312  * Install a new translator from file
313  */
314 bool lamexp_install_translator_from_file(const QString &qmFile)
315 {
316         QWriteLocker writeLock(&g_lamexp_currentTranslator.lock);
317         bool success = false;
318
319         if(!g_lamexp_currentTranslator.instance)
320         {
321                 g_lamexp_currentTranslator.instance = new QTranslator();
322         }
323
324         if(!qmFile.isEmpty())
325         {
326                 QString qmPath = QFileInfo(qmFile).canonicalFilePath();
327                 QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
328                 if(success = g_lamexp_currentTranslator.instance->load(qmPath))
329                 {
330                         QApplication::installTranslator(g_lamexp_currentTranslator.instance);
331                 }
332                 else
333                 {
334                         qWarning("Failed to load translation:\n\"%s\"", qmPath.toLatin1().constData());
335                 }
336         }
337         else
338         {
339                 QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
340                 success = true;
341         }
342
343         return success;
344 }
345
346 ///////////////////////////////////////////////////////////////////////////////
347 // INITIALIZATION
348 ///////////////////////////////////////////////////////////////////////////////
349
350 extern "C" void _lamexp_global_init_tools(void)
351 {
352         LAMEXP_ZERO_MEMORY(g_lamexp_tools);
353         LAMEXP_ZERO_MEMORY(g_lamexp_currentTranslator);
354         LAMEXP_ZERO_MEMORY(g_lamexp_translation);
355 }
356
357 ///////////////////////////////////////////////////////////////////////////////
358 // FINALIZATION
359 ///////////////////////////////////////////////////////////////////////////////
360
361 extern "C" void _lamexp_global_free_tools(void)
362 {
363         //Free *all* registered translations
364         if(g_lamexp_currentTranslator.instance)
365         {
366                 QApplication::removeTranslator(g_lamexp_currentTranslator.instance);
367                 LAMEXP_DELETE(g_lamexp_currentTranslator.instance);
368         }
369         LAMEXP_DELETE(g_lamexp_translation.files);
370         LAMEXP_DELETE(g_lamexp_translation.names);
371         LAMEXP_DELETE(g_lamexp_translation.cntry);
372         LAMEXP_DELETE(g_lamexp_translation.sysid);
373
374         //Free *all* registered tools
375         if(g_lamexp_tools.registry)
376         {
377                 QStringList keys = g_lamexp_tools.registry->keys();
378                 for(int i = 0; i < keys.count(); i++)
379                 {
380                         LockedFile *lf = g_lamexp_tools.registry->take(keys.at(i));
381                         LAMEXP_DELETE(lf);
382                 }
383                 g_lamexp_tools.registry->clear();
384                 g_lamexp_tools.versions->clear();
385                 g_lamexp_tools.tags->clear();
386         }
387         LAMEXP_DELETE(g_lamexp_tools.registry);
388         LAMEXP_DELETE(g_lamexp_tools.versions);
389         LAMEXP_DELETE(g_lamexp_tools.tags);
390
391 }