1 /**
2  * projectM-qt -- Qt4 based projectM GUI
3  * Copyright (C)2003-2004 projectM Team
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU 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.
9  *
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.
14  *
15  * You should have received a copy of the GNU 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
18  * See 'LICENSE.txt' included within this release
19  *
20  */
21 
22 #ifndef QPROJECTM_WIDGET_HPP
23 #define QPROJECTM_WIDGET_HPP
24 
25 #include <iostream>
26 #include "qprojectm.hpp"
27 #include <QGLWidget>
28 #include <QMutex>
29 #include <QtDebug>
30 #include <QKeyEvent>
31 #include <QTimer>
32 #include <QApplication>
33 #include <QSettings>
34 
35 class QProjectMWidget : public QGLWidget
36 {
37 
38 		Q_OBJECT        // must include this if you use Qt signals/slots
39 
40 	public:
41 		static const int MOUSE_VISIBLE_TIMEOUT_MS = 5000;
QProjectMWidget(const std::string & config_file,QWidget * parent,QMutex * audioMutex=0)42 		QProjectMWidget ( const std::string & config_file, QWidget * parent, QMutex * audioMutex = 0 )
43 				: QGLWidget ( parent ), m_config_file ( config_file ), m_projectM ( 0 ), m_mouseTimer ( 0 ), m_audioMutex ( audioMutex )
44 		{
45 
46 			m_mouseTimer = new QTimer ( this );
47 
48 			QSettings settings("projectM", "qprojectM");
49 			mouseHideTimeoutSeconds =
50 				settings.value("MouseHideOnTimeout", MOUSE_VISIBLE_TIMEOUT_MS/1000).toInt();
51 
52 			if (mouseHideTimeoutSeconds > 0)
53 				m_mouseTimer->start ( mouseHideTimeoutSeconds * 1000);
54 
55 			connect ( m_mouseTimer, SIGNAL ( timeout() ), this, SLOT ( hideMouse() ) );
56 			this->setMouseTracking ( true );
57 
58 		}
59 
~QProjectMWidget()60 		~QProjectMWidget() { destroyProjectM(); }
61 
62 
63 
resizeGL(int w,int h)64 		void resizeGL ( int w, int h )
65 		{
66 			// Setup viewport, projection etc
67 			setup_opengl ( w,h );
68 			m_projectM->projectM_resetGL ( w, h );
69 		}
70 
configFile()71 		inline const std::string & configFile()
72 		{
73 			return m_config_file;
74 		}
75 
seizePresetLock()76 		inline void seizePresetLock()
77 		{
78 
79 			m_presetSeizeMutex.lock();
80 			m_presetWasLocked = qprojectM()->isPresetLocked();
81 			qprojectM()->setPresetLock ( true );
82 
83 		}
84 
releasePresetLock()85 		inline void releasePresetLock()
86 		{
87 			qprojectM()->setPresetLock ( m_presetWasLocked );
88 			m_presetSeizeMutex.unlock();
89 		}
90 
91 
qprojectM()92 		inline QProjectM * qprojectM() { return m_projectM; }
93 
94 	protected slots:
mouseMoveEvent(QMouseEvent * event)95 		inline void mouseMoveEvent ( QMouseEvent * event )
96 		{
97 			Q_UNUSED(event);
98 
99 			m_mouseTimer->stop();
100 			QApplication::restoreOverrideCursor();
101 			if (mouseHideTimeoutSeconds > 0)
102 				m_mouseTimer->start ( mouseHideTimeoutSeconds*1000 );
103 
104 		}
105 
leaveEvent(QEvent * event)106 		inline void leaveEvent ( QEvent * event )
107 		{
108 			Q_UNUSED(event);
109 			/// @bug testing if this resolves a bug for ubuntu users
110 			QApplication::restoreOverrideCursor();
111 		}
112 
113 	public slots:
114 
resetProjectM()115 		void resetProjectM()
116 		{
117 			std::cout << "resetting" << std::endl;
118 			qDebug() << "reset start";
119 
120 			emit ( projectM_BeforeDestroy() );
121 
122 			if ( m_audioMutex )
123 				m_audioMutex->lock();
124 
125 			destroyProjectM();
126 
127 			// Make a new projectM instance and reset the opengl state
128 			initializeGL();
129 
130 			// Allow audio thread to continue its business
131 			if ( m_audioMutex )
132 			{
133 				m_audioMutex->unlock();
134 			}
135 			qDebug() << "reinit'ed";
136 		}
137 
setAudioMutex(QMutex * mutex)138 		void setAudioMutex ( QMutex * mutex )
139 		{
140 			m_audioMutex = mutex;
141 		}
142 
setPresetLock(int state)143 		void setPresetLock ( int state )
144 		{
145 			m_projectM->setPresetLock ( ( bool ) state );
146 			emit ( presetLockChanged ( ( bool ) state ) );
147 		}
148 
setShuffleEnabled(int state)149 		void setShuffleEnabled ( int state )
150 		{
151 			m_projectM->setShuffleEnabled ( ( bool ) state );
152 			emit ( shuffleEnabledChanged ( ( bool ) state ) );
153 		}
154 
mousePressEvent(QMouseEvent * event)155 		void mousePressEvent ( QMouseEvent * event )
156 		{
157 			Q_UNUSED(event);
158 
159 			this->setFocus();
160 		}
161 
162 	signals:
163 		void projectM_Initialized ( QProjectM * );
164 		void projectM_BeforeDestroy();
165 		void presetLockChanged ( bool isLocked );
166 		void shuffleEnabledChanged ( bool isShuffleEnabled );
167 
168 	private slots:
hideMouse()169 		void hideMouse()
170 		{
171 			if ( this->underMouse() && this->hasFocus() )
172 				QApplication::setOverrideCursor ( Qt::BlankCursor );
173 		}
174 	private:
175 		std::string m_config_file;
176 		QProjectM * m_projectM;
destroyProjectM()177 		void destroyProjectM()
178 		{
179 
180 			if ( m_projectM )
181 			{
182 				delete ( m_projectM );
183 				m_projectM = 0;
184 			}
185 		}
186 
187 		QTimer * m_mouseTimer;
188 		QMutex * m_audioMutex;
189 		QMutex m_presetSeizeMutex;
190 		bool m_presetWasLocked;
191 	protected:
192 
193 
keyReleaseEvent(QKeyEvent * e)194 		void keyReleaseEvent ( QKeyEvent * e )
195 		{
196 
197 			projectMKeycode pkey;
198 			bool ignore = false;
199 			switch ( e->key() )
200 			{
201 				case Qt::Key_F4:
202 					pkey =  PROJECTM_K_F4;
203 					break;
204 				case Qt::Key_F3:
205 					pkey =  PROJECTM_K_F3;
206 					break;
207 				case Qt::Key_F2:
208 					pkey =  PROJECTM_K_F2;
209 					break;
210 				case Qt::Key_F1:
211 					pkey =  PROJECTM_K_F1;
212 					break;
213 				case Qt::Key_R:
214 					if (e->modifiers() & Qt::ShiftModifier)
215 						pkey =  PROJECTM_K_R;
216 					else
217 						pkey =  PROJECTM_K_r;
218 					break;
219 				case Qt::Key_L:
220 					pkey =  PROJECTM_K_l;
221 					ignore = true;
222 					break;
223 				case Qt::Key_N:
224 					if (e->modifiers() & Qt::ShiftModifier)
225 						pkey =  PROJECTM_K_N;
226 					else
227 						pkey =  PROJECTM_K_n;
228 					break;
229 				case Qt::Key_P:
230 					if (e->modifiers() & Qt::ShiftModifier)
231 						pkey =  PROJECTM_K_P;
232 					else
233 						pkey =  PROJECTM_K_p;
234 					break;
235 				case Qt::Key_F5:
236 					pkey =  PROJECTM_K_F5;
237 					break;
238 				case Qt::Key_Plus:
239 					pkey =  PROJECTM_K_PLUS;
240 					break;
241 				case Qt::Key_Minus:
242 					pkey =  PROJECTM_K_MINUS;
243 					break;
244 				case Qt::Key_Equal:
245 					pkey = PROJECTM_K_EQUALS;
246 					break;
247 				default:
248 					e->ignore();
249 					return;
250 			}
251 			projectMModifier modifier = PROJECTM_KMOD_NONE;
252 
253 			m_projectM->key_handler ( PROJECTM_KEYDOWN, pkey, modifier );
254 			if ( ignore )
255 				e->ignore();
256 
257 
258 		}
259 
initializeGL()260 		void initializeGL()
261 		{
262 
263 		        if (m_projectM == 0) {
264 			    this->m_projectM = new QProjectM ( m_config_file );
265 			    projectM_Initialized ( m_projectM );
266 			}
267 		}
268 
paintGL()269 		inline void paintGL()
270 		{
271 			m_projectM->renderFrame();
272 		}
273 
274 	private:
275 		int mouseHideTimeoutSeconds;
setup_opengl(int w,int h)276 		void setup_opengl ( int w, int h )
277 		{
278 
279 			/* Our shading model--Gouraud (smooth). */
280 			glShadeModel ( GL_SMOOTH );
281 			/* Culling. */
282 			//    glCullFace( GL_BACK );
283 			//    glFrontFace( GL_CCW );
284 			//    glEnable( GL_CULL_FACE );
285 			/* Set the clear color. */
286 			glClearColor ( 0, 0, 0, 0 );
287 			/* Setup our viewport. */
288 			glViewport ( 0, 0, w, h );
289 			/*
290 					* Change to the projection matrix and set
291 					* our viewing volume.
292 			*/
293 			glMatrixMode ( GL_TEXTURE );
294 			glLoadIdentity();
295 
296 			//    gluOrtho2D(0.0, (GLfloat) width, 0.0, (GLfloat) height);
297 			glMatrixMode ( GL_PROJECTION );
298 			glLoadIdentity();
299 
300 			//    glFrustum(0.0, height, 0.0,width,10,40);
301 			glMatrixMode ( GL_MODELVIEW );
302 			glLoadIdentity();
303 
304 			glDrawBuffer ( GL_BACK );
305 			glReadBuffer ( GL_BACK );
306 			glEnable ( GL_BLEND );
307 
308 			glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
309 			// glBlendFunc(GL_SRC_ALPHA, GL_ONE);
310 			glEnable ( GL_LINE_SMOOTH );
311 			glEnable ( GL_POINT_SMOOTH );
312 			glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
313 //   glClear(GL_COLOR_BUFFER_BIT);
314 
315 			// glCopyTexImage2D(GL_TEXTURE_2D,0,GL_RGB,0,0,texsize,texsize,0);
316 			//glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,texsize,texsize);
317 			glLineStipple ( 2, 0xAAAA );
318 		}
319 
320 
321 };
322 #endif
323