3 * Copyright (C) 2012-2014 Dan Dennedy <dan@dennedy.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library 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 GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <framework/mlt.h>
21 #include <QApplication>
25 #include <QWaitCondition>
28 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
32 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
34 class GLWidget : public QGLWidget
37 QGLWidget *renderContext;
40 QWaitCondition condition;
47 : QGLWidget(0, 0, Qt::SplashScreen)
50 , isInitialized(false)
61 bool createRenderContext()
65 condition.wait(&mutex);
69 renderContext = new QGLWidget(0, this, Qt::SplashScreen);
70 renderContext->resize(0, 0);
71 renderContext->makeCurrent();
73 return renderContext->isValid();
87 #include <QOpenGLContext>
88 #include <QOffscreenSurface>
90 typedef void* ( *thread_function_t )( void* );
92 class RenderThread : public QThread
95 RenderThread(thread_function_t function, void *data)
97 , m_function(function)
100 m_context = new QOpenGLContext;
102 m_context->moveToThread(this);
103 m_surface = new QOffscreenSurface();
108 m_surface->destroy();
115 Q_ASSERT(m_context->isValid());
116 m_context->makeCurrent(m_surface);
118 m_context->doneCurrent();
123 thread_function_t m_function;
125 QOpenGLContext* m_context;
126 QOffscreenSurface* m_surface;
129 static void onThreadCreate(mlt_properties owner, mlt_consumer self,
130 RenderThread** thread, int* priority, thread_function_t function, void* data )
134 (*thread) = new RenderThread(function, data);
138 static void onThreadJoin(mlt_properties owner, mlt_consumer self, RenderThread* thread)
145 qApp->processEvents();
152 static void onThreadStarted(mlt_properties owner, mlt_consumer consumer)
154 mlt_service service = MLT_CONSUMER_SERVICE(consumer);
155 mlt_properties properties = MLT_CONSUMER_PROPERTIES(consumer);
156 mlt_filter filter = (mlt_filter) mlt_properties_get_data(properties, "glslManager", NULL);
157 mlt_properties filter_properties = MLT_FILTER_PROPERTIES(filter);
159 mlt_log_debug(service, "%s\n", __FUNCTION__);
160 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
161 GLWidget *widget = (GLWidget*) mlt_properties_get_data(properties, "GLWidget", NULL);
162 if (widget->createRenderContext()) {
166 mlt_events_fire(filter_properties, "init glsl", NULL);
167 if (!mlt_properties_get_int(filter_properties, "glsl_supported")) {
168 mlt_log_fatal(service,
169 "OpenGL Shading Language rendering is not supported on this machine.\n" );
170 mlt_events_fire(properties, "consumer-fatal-error", NULL);
175 static void onThreadStopped(mlt_properties owner, mlt_consumer consumer)
177 mlt_properties properties = MLT_CONSUMER_PROPERTIES(consumer);
178 mlt_filter filter = (mlt_filter) mlt_properties_get_data(properties, "glslManager", NULL);
179 mlt_events_fire(MLT_FILTER_PROPERTIES(filter), "close glsl", NULL);
182 static void onCleanup(mlt_properties owner, mlt_consumer consumer)
184 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
185 GLWidget* widget = (GLWidget*) mlt_properties_get_data( MLT_CONSUMER_PROPERTIES(consumer), "GLWidget", NULL);
187 mlt_properties_set_data(MLT_CONSUMER_PROPERTIES(consumer), "GLWidget", NULL, 0, NULL, NULL);
188 qApp->processEvents();
194 mlt_consumer consumer_qglsl_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
196 mlt_consumer consumer = mlt_factory_consumer(profile, "multi", arg);
198 mlt_filter filter = mlt_factory_filter(profile, "glsl.manager", 0);
200 mlt_properties properties = MLT_CONSUMER_PROPERTIES(consumer);
201 mlt_properties_set_data(properties, "glslManager", filter, 0, (mlt_destructor) mlt_filter_close, NULL);
202 mlt_events_register( properties, "consumer-cleanup", NULL );
203 mlt_events_listen(properties, consumer, "consumer-thread-started", (mlt_listener) onThreadStarted);
204 mlt_events_listen(properties, consumer, "consumer-thread-stopped", (mlt_listener) onThreadStopped);
205 mlt_events_listen(properties, consumer, "consumer-cleanup", (mlt_listener) onCleanup);
206 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
208 if ( getenv("DISPLAY") == 0 ) {
209 mlt_log_error(MLT_CONSUMER_SERVICE(consumer), "The qglsl consumer requires a X11 environment.\nPlease either run melt from an X session or use a fake X server like xvfb:\nxvfb-run -a melt (...)\n" );
215 argv[0] = (char*) "MLT qglsl consumer";
216 new QApplication(argc, argv);
217 const char *localename = mlt_properties_get_lcnumeric(properties);
218 QLocale::setDefault(QLocale(localename));
220 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
221 mlt_properties_set_data(properties, "GLWidget", new GLWidget, 0, NULL, NULL);
223 mlt_events_listen(properties, consumer, "consumer-thread-create", (mlt_listener) onThreadCreate);
224 mlt_events_listen(properties, consumer, "consumer-thread-join", (mlt_listener) onThreadJoin);
226 qApp->processEvents();
229 mlt_consumer_close(consumer);