1 /* 2 * This file is part of bino, a 3D video player. 3 * 4 * Copyright (C) 2010, 2011, 2012, 2013, 2015, 2016 5 * Martin Lambers <marlam@marlam.de> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef VIDEO_OUTPUT_QT_H 22 #define VIDEO_OUTPUT_QT_H 23 24 #include "config.h" 25 26 #include <GL/glew.h> 27 28 #include <QWidget> 29 #include <QGLWidget> 30 #include <QGLFormat> 31 #include <QTimer> 32 #include <QThread> 33 #include <QMutex> 34 35 #if HAVE_X11 36 # include <GL/glxew.h> 37 #endif 38 39 #include "base/pth.h" 40 41 #include "video_output.h" 42 43 44 /* Internal interface */ 45 46 class video_output_qt; 47 class video_output_qt_widget; 48 49 class gl_thread : public QThread 50 { 51 private: 52 video_output_qt* _vo_qt; 53 video_output_qt_widget* _vo_qt_widget; 54 bool _render; 55 int _w, _h; 56 mutex _wait_mutex; 57 condition _wait_cond; 58 bool _action_activate; 59 bool _action_prepare; 60 bool _action_finished; 61 bool _redisplay; 62 video_frame _next_frame; 63 subtitle_box _next_subtitle; 64 bool _failure; 65 exc _e; 66 // The display frame number 67 int64_t _display_frameno; 68 69 public: 70 gl_thread(video_output_qt* vo_qt, video_output_qt_widget* vo_qt_widget); 71 72 #ifdef GLEW_MX 73 # if HAVE_X11 74 GLXEWContext* glxewGetContext() const; 75 # endif 76 #endif 77 78 void set_render(bool r); 79 void resize(int w, int h); 80 void activate_next_frame(); 81 void prepare_next_frame(const video_frame &frame, const subtitle_box &subtitle); 82 void redisplay(); 83 84 int64_t time_to_next_frame_presentation(); 85 86 void run(); 87 failure()88 bool failure() const 89 { 90 return _failure; 91 } exception()92 const exc& exception() const 93 { 94 return _e; 95 } 96 }; 97 98 class video_output_qt_widget : public QGLWidget 99 { 100 Q_OBJECT 101 private: 102 video_output_qt *_vo; 103 class gl_thread _gl_thread; 104 QTimer _timer; 105 int _width, _height; 106 int _pos_x, _pos_y; 107 108 private slots: 109 void check_gl_thread(); 110 111 public: 112 video_output_qt_widget(video_output_qt *vo, const QGLFormat &format, QWidget *parent = NULL); 113 114 int vo_width() const; 115 int vo_height() const; 116 int vo_pos_x() const; 117 int vo_pos_y() const; 118 119 void start_rendering(); 120 void stop_rendering(); 121 void redisplay(); gl_thread()122 class gl_thread* gl_thread() 123 { 124 return &_gl_thread; 125 } 126 127 protected: 128 #ifdef Q_WS_X11 129 # if QT_VERSION < 0x040800 130 /* Work around a bug in Qt < 4.8: On a hide event, the GLWidget calls 131 * makeCurrent() and glFinish(), but this interferes with our GL thread. 132 * This has been fixed in Qt 4.8. */ event(QEvent * e)133 virtual bool event(QEvent* e) { return QWidget::event(e); } 134 # endif 135 #endif 136 virtual void paintEvent(QPaintEvent* event); 137 virtual void resizeEvent(QResizeEvent* event); 138 virtual void keyPressEvent(QKeyEvent *event); 139 virtual void mouseReleaseEvent(QMouseEvent *event); 140 virtual void mouseDoubleClickEvent(QMouseEvent *event); 141 virtual void focusOutEvent(QFocusEvent *event); 142 }; 143 144 /* Public interface */ 145 146 class video_container_widget : public QWidget, public controller 147 { 148 Q_OBJECT 149 int _w, _h; 150 QTimer *_timer; 151 private slots: 152 void playloop_step(); 153 public: 154 video_container_widget(QWidget *parent = NULL); 155 void start_timer(); 156 void set_recommended_size(int w, int h); 157 void grab_focus(); 158 signals: 159 protected: 160 virtual QSize sizeHint() const; 161 virtual void moveEvent(QMoveEvent* event); 162 virtual void closeEvent(QCloseEvent *event); 163 virtual void receive_notification(const notification& note); 164 }; 165 166 /* Public interface. See the video_output documentation. */ 167 168 class video_output_qt : public video_output 169 { 170 private: 171 #ifdef GLEW_MX 172 # if HAVE_X11 173 GLXEWContext _glxew_context; 174 # endif 175 GLEWContext _glew_context; 176 #endif 177 int _screen_width, _screen_height; 178 float _screen_pixel_aspect_ratio; 179 video_container_widget *_container_widget; 180 bool _container_is_external; 181 video_output_qt_widget *_widget; 182 QGLFormat _format; 183 bool _fullscreen; 184 QRect _geom; 185 bool _screensaver_inhibited; 186 bool _recreate_context; 187 bool _recreate_context_stereo; 188 #ifdef Q_OS_MAC 189 unsigned int _disableDisplaySleepAssertion; 190 #endif 191 192 void create_widget(); 193 void mouse_set_pos(float dest); 194 void mouse_toggle_fullscreen(); 195 void suspend_screensaver(); 196 void resume_screensaver(); 197 198 protected: 199 #ifdef GLEW_MX 200 # if HAVE_X11 201 virtual GLXEWContext* glxewGetContext() const; 202 # endif 203 virtual GLEWContext* glewGetContext() const; 204 #endif 205 virtual bool context_is_stereo() const; 206 virtual void recreate_context(bool stereo); 207 virtual void trigger_resize(int w, int h); 208 209 virtual int screen_width() const; 210 virtual int screen_height() const; 211 virtual float screen_pixel_aspect_ratio() const; 212 virtual int width() const; 213 virtual int height() const; 214 virtual int pos_x() const; 215 virtual int pos_y() const; 216 217 public: 218 /* Constructor, Destructor */ 219 /* If a container widget is given, then it is assumed that this widget is 220 * part of another widget (e.g. a main window). If no container widget is 221 * given, we will use our own, and it will be a top-level window. */ 222 video_output_qt(video_container_widget *container_widget = NULL); 223 virtual ~video_output_qt(); 224 225 virtual void init(); 226 virtual int64_t wait_for_subtitle_renderer(); 227 virtual void deinit(); 228 229 virtual bool supports_stereo() const; 230 231 virtual void center(); 232 virtual void enter_fullscreen(); 233 virtual void exit_fullscreen(); 234 235 virtual void prepare_next_frame(const video_frame &frame, const subtitle_box &subtitle); 236 virtual void activate_next_frame(); 237 virtual int64_t time_to_next_frame_presentation() const; 238 239 virtual void process_events(); 240 virtual void receive_notification(const notification& note); 241 242 friend class gl_thread; 243 friend class video_output_qt_widget; 244 }; 245 246 #endif 247