OSDN Git Service

Removed a lot of old cruft and use MUtils functions where possible.
[x264-launcher/x264-launcher.git] / src / thread_avisynth.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Simple x264 Launcher
3 // Copyright (C) 2004-2015 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_avisynth.h"
23
24 #include <QLibrary>
25 #include <QEventLoop>
26 #include <QTimer>
27 #include <QMutexLocker>
28 #include <QApplication>
29
30 //Internal
31 #include "global.h"
32 #include "3rd_party/avisynth_c.h"
33
34 //MUtils
35 #include <MUtils/Global.h>
36
37 QMutex AvisynthCheckThread::m_avsLock;
38 QLibrary *AvisynthCheckThread::m_avsLib = NULL;
39
40 //-------------------------------------
41 // External API
42 //-------------------------------------
43
44 int AvisynthCheckThread::detect(volatile double *version)
45 {
46         *version = 0.0;
47         QMutexLocker lock(&m_avsLock);
48
49         QEventLoop loop;
50         AvisynthCheckThread thread;
51
52         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
53
54         connect(&thread, SIGNAL(finished()), &loop, SLOT(quit()));
55         connect(&thread, SIGNAL(terminated()), &loop, SLOT(quit()));
56         
57         thread.start();
58         QTimer::singleShot(15000, &loop, SLOT(quit()));
59         
60         qDebug("Avisynth thread has been created, please wait...");
61         loop.exec(QEventLoop::ExcludeUserInputEvents);
62         qDebug("Avisynth thread finished.");
63
64         QApplication::restoreOverrideCursor();
65
66         if(!thread.wait(1000))
67         {
68                 qWarning("Avisynth thread encountered timeout -> probably deadlock!");
69                 thread.terminate();
70                 thread.wait();
71                 return -1;
72         }
73
74         if(thread.getException())
75         {
76                 qWarning("Avisynth thread encountered an exception !!!");
77                 return -1;
78         }
79         
80         if(thread.getSuccess())
81         {
82                 *version = thread.getVersion();
83                 qDebug("Version check completed: %.2f", *version);
84                 return 1;
85         }
86
87         qWarning("Avisynth thread failed to determine the version!");
88         return 0;
89 }
90
91 void AvisynthCheckThread::unload(void)
92 {
93         QMutexLocker lock(&m_avsLock);
94
95         if(m_avsLib)
96         {
97                 if(m_avsLib->isLoaded())
98                 {
99                         m_avsLib->unload();
100                 }
101         }
102
103         MUTILS_DELETE(m_avsLib);
104 }
105
106 //-------------------------------------
107 // Thread class
108 //-------------------------------------
109
110 AvisynthCheckThread::AvisynthCheckThread(void)
111 {
112         m_success = false;
113         m_exception = false;
114         m_version = 0.0;
115 }
116
117 AvisynthCheckThread::~AvisynthCheckThread(void)
118 {
119 }
120
121 void AvisynthCheckThread::run(void)
122 {
123         m_exception = m_success = false;
124         m_success = detectAvisynthVersion1(&m_version, &m_exception);
125 }
126
127 bool AvisynthCheckThread::detectAvisynthVersion1(volatile double *version_number, volatile bool *exception)
128 {
129         __try
130         {
131                 return detectAvisynthVersion2(version_number, exception);
132         }
133         __except(1)
134         {
135                 *exception = true;
136                 qWarning("Unhandled exception error in Avisynth thread !!!");
137                 return false;
138         }
139 }
140
141 bool AvisynthCheckThread::detectAvisynthVersion2(volatile double *version_number, volatile bool *exception)
142 {
143         try
144         {
145                 return detectAvisynthVersion3(version_number);
146         }
147         catch(...)
148         {
149                 *exception = true;
150                 qWarning("Avisynth initializdation raised an C++ exception!");
151                 return false;
152         }
153 }
154
155 bool AvisynthCheckThread::detectAvisynthVersion3(volatile double *version_number)
156 {
157         bool success = false;
158         *version_number = 0.0;
159
160         if(!m_avsLib)
161         {
162                 m_avsLib = new QLibrary("avisynth.dll");
163         }
164
165         if(m_avsLib->isLoaded() || m_avsLib->load())
166         {
167                 avs_create_script_environment_func avs_create_script_environment_ptr = (avs_create_script_environment_func) m_avsLib->resolve("avs_create_script_environment");
168                 avs_invoke_func avs_invoke_ptr = (avs_invoke_func) m_avsLib->resolve("avs_invoke");
169                 avs_function_exists_func avs_function_exists_ptr = (avs_function_exists_func) m_avsLib->resolve("avs_function_exists");
170                 avs_delete_script_environment_func avs_delete_script_environment_ptr = (avs_delete_script_environment_func) m_avsLib->resolve("avs_delete_script_environment");
171                 avs_release_value_func avs_release_value_ptr = (avs_release_value_func) m_avsLib->resolve("avs_release_value");
172         
173                 if((avs_create_script_environment_ptr != NULL) && (avs_invoke_ptr != NULL) && (avs_function_exists_ptr != NULL))
174                 {
175                         qDebug("avs_create_script_environment_ptr(AVS_INTERFACE_25)");
176                         AVS_ScriptEnvironment* avs_env = avs_create_script_environment_ptr(AVS_INTERFACE_25);
177                         if(avs_env != NULL)
178                         {
179                                 qDebug("avs_function_exists_ptr(avs_env, \"VersionNumber\")");
180                                 if(avs_function_exists_ptr(avs_env, "VersionNumber"))
181                                 {
182                                         qDebug("avs_invoke_ptr(avs_env, \"VersionNumber\", avs_new_value_array(NULL, 0), NULL)");
183                                         AVS_Value avs_version = avs_invoke_ptr(avs_env, "VersionNumber", avs_new_value_array(NULL, 0), NULL);
184                                         if(!avs_is_error(avs_version))
185                                         {
186                                                 if(avs_is_float(avs_version))
187                                                 {
188                                                         qDebug("Avisynth version: v%.2f", avs_as_float(avs_version));
189                                                         *version_number = avs_as_float(avs_version);
190                                                         if(avs_release_value_ptr) avs_release_value_ptr(avs_version);
191                                                         success = true;
192                                                 }
193                                                 else
194                                                 {
195                                                         qWarning("Failed to determine version number, Avisynth didn't return a float!");
196                                                 }
197                                         }
198                                         else
199                                         {
200                                                 qWarning("Failed to determine version number, Avisynth returned an error!");
201                                         }
202                                 }
203                                 else
204                                 {
205                                         qWarning("The 'VersionNumber' function does not exist in your Avisynth DLL, can't determine version!");
206                                 }
207                                 if(avs_delete_script_environment_ptr != NULL)
208                                 {
209                                         avs_delete_script_environment_ptr(avs_env);
210                                         avs_env = NULL;
211                                 }
212                         }
213                         else
214                         {
215                                 qWarning("The Avisynth DLL failed to create the script environment!");
216                         }
217                 }
218                 else
219                 {
220                         qWarning("It seems the Avisynth DLL is missing required API functions!");
221                 }
222         }
223         else
224         {
225                 qWarning("Failed to load Avisynth.dll library!");
226         }
227
228         return success;
229 }