OSDN Git Service

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