1 /*
2     Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com)
3 
4     This program is free software; you can redistribute it and/or
5     modify it under the terms of the GNU General Public License
6     as published by the Free Software Foundation; either version
7     3 of the License, or (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include "gource_shell.h"
19 
20 GourceShell* gGourceShell = 0;
21 
22 // GourceShell
23 
GourceShell(ConfFile * conf,FrameExporter * exporter)24 GourceShell::GourceShell(ConfFile* conf, FrameExporter* exporter) {
25 
26     this->conf     = conf;
27     this->exporter = exporter;
28 
29     min_delta_msec = 16;
30 
31     next = false;
32 
33     gource = 0;
34     gource_settings = conf->getSections("gource")->begin();
35 
36     gGourceSettings.repo_count = conf->countSection("gource");
37 
38     toggle_delay = 0.0;
39     transition_texture = 0;
40     transition_interval = 0.0f;
41 
42     if(GLEW_ARB_texture_non_power_of_two || GLEW_VERSION_2_0) {
43         transition_texture = texturemanager.create(display.width, display.height, false, GL_CLAMP_TO_EDGE, GL_RGBA);
44     }
45 }
46 
~GourceShell()47 GourceShell::~GourceShell() {
48     if(gource!=0) delete gource;
49     if(transition_texture!=0) texturemanager.release(transition_texture);
50 }
51 
toggleFullscreen()52 void GourceShell::toggleFullscreen() {
53 
54     if(exporter != 0) return;
55 
56     texturemanager.unload();
57     shadermanager.unload();
58     fontmanager.unload();
59 
60     if(gource!=0) gource->unload();
61 
62     //recreate gl context
63     display.toggleFullscreen();
64 
65     texturemanager.reload();
66     shadermanager.reload();
67     fontmanager.reload();
68 
69     if(gource!=0) gource->reload();
70 }
71 
toggleWindowFrame()72 void GourceShell::toggleWindowFrame() {
73 #if SDL_VERSION_ATLEAST(2,0,0)
74     if(toggle_delay > 0.0) return;
75     if(display.isFullscreen()) return;
76     if(exporter != 0) return;
77 
78     texturemanager.unload();
79     shadermanager.unload();
80     fontmanager.unload();
81 
82     if(gource!=0) gource->unload();
83 
84     display.toggleFrameless();
85 
86     texturemanager.reload();
87     shadermanager.reload();
88     fontmanager.reload();
89 
90     if(gource!=0) gource->reload();
91 
92     toggle_delay = 0.25f;
93 #endif
94 }
95 
96 
resize(int width,int height)97 void GourceShell::resize(int width, int height) {
98 
99     texturemanager.unload();
100     shadermanager.unload();
101     fontmanager.unload();
102 
103     if(gource!=0) gource->unload();
104 
105     //recreate gl context
106     display.resize(width, height);
107 
108     texturemanager.reload();
109     shadermanager.reload();
110     fontmanager.reload();
111 
112     if(gource!=0) gource->reload();
113 }
114 
keyPress(SDL_KeyboardEvent * e)115 void GourceShell::keyPress(SDL_KeyboardEvent *e) {
116 
117     bool repeat = false;
118 #if SDL_VERSION_ATLEAST(2,0,0)
119     repeat = (e->repeat > 0);
120 #endif
121 
122     //Quit demo if the user presses ESC
123     if (e->type == SDL_KEYDOWN && !repeat) {
124 
125 #if SDL_VERSION_ATLEAST(2,0,0)
126         bool key_escape = e->keysym.sym == SDLK_ESCAPE;
127         bool key_return = e->keysym.sym == SDLK_RETURN;
128 #else
129         bool key_escape = e->keysym.unicode == SDLK_ESCAPE;
130         bool key_return = e->keysym.unicode == SDLK_RETURN;
131 #endif
132 
133         if (key_escape) {
134             quit();
135         }
136 
137         if(gGourceSettings.disable_input) {
138             // disable keyboard input other than the escape key
139             return;
140         }
141 
142         if (e->keysym.sym == SDLK_F11) {
143             toggleWindowFrame();
144         }
145 
146         if(key_return) {
147 
148 #if SDL_VERSION_ATLEAST(2,0,0)
149             const Uint8* keystate = SDL_GetKeyboardState(NULL);
150             if(keystate[SDL_SCANCODE_RALT] || keystate[SDL_SCANCODE_LALT]) {
151 #else
152             Uint8* keystate = SDL_GetKeyState(NULL);
153             if(keystate[SDLK_RALT] || keystate[SDLK_LALT]) {
154 #endif
155 
156                 toggleFullscreen();
157 
158             } else {
159                 if(gGourceSettings.repo_count>1)
160                     next = true;
161             }
162         }
163     }
164 
165     if(gource!=0) gource->keyPress(e);
166 }
167 
168 void GourceShell::mouseMove(SDL_MouseMotionEvent *e) {
169     if(gource!=0) gource->mouseMove(e);
170 }
171 
172 #if SDL_VERSION_ATLEAST(2,0,0)
173 void GourceShell::mouseWheel(SDL_MouseWheelEvent *e) {
174     if(gource!=0) gource->mouseWheel(e);
175 }
176 #endif
177 
178 void GourceShell::mouseClick(SDL_MouseButtonEvent *e) {
179     if(gource!=0) gource->mouseClick(e);
180 }
181 
182 void GourceShell::quit() {
183     if(gource!=0) gource->quit();
184     gGourceSettings.shutdown=true;
185 }
186 
187 Gource* GourceShell::getNext() {
188 
189     if(gource != 0) {
190         transition_interval = 1.0f;
191         delete gource;
192         gource = 0;
193     }
194 
195     if(gGourceSettings.shutdown || gource_settings == conf->getSections("gource")->end()) {
196         // done
197         return 0;
198     }
199 
200     gGourceSettings.importGourceSettings(*conf, *gource_settings);
201 
202     //recording a video kind of implies you want this, unless:
203     // -- dont stop requested
204     // -- loop requested
205     // -- reading from STDIN
206     if(exporter!=0 && !(gGourceSettings.dont_stop || gGourceSettings.loop || gGourceSettings.path == "-"))
207         gGourceSettings.stop_at_end = true;
208 
209     //multiple repo special settings
210     if(gGourceSettings.repo_count > 1) {
211 
212         //set a stop condition
213         if(gGourceSettings.stop_at_time <= 0.0f && gGourceSettings.stop_position <= 0.0f) {
214             gGourceSettings.stop_at_time = 60.0f;
215         }
216     }
217 
218     gource_settings++;
219 
220     //loop unless only 1 repo
221     if(gource_settings == conf->getSections("gource")->end()) {
222         if(gGourceSettings.repo_count>1 && exporter==0) {
223             gource_settings = conf->getSections("gource")->begin();
224         }
225     }
226 
227     // replace gource
228     gource = new Gource(exporter);
229 
230     next = false;
231 
232     return gource;
233 }
234 
235 void GourceShell::blendLastFrame(float dt) {
236     if(transition_texture==0 || transition_interval <= 0.0f) return;
237 
238     display.mode2D();
239 
240     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
241     glEnable(GL_BLEND);
242     glEnable(GL_TEXTURE_2D);
243 
244     transition_texture->bind();
245 
246     glColor4f(1.0, 1.0, 1.0, transition_interval);
247 
248     glBegin(GL_QUADS);
249         glTexCoord2f(0.0f, 1.0f);
250         glVertex2f(0.0f, 0.0);
251 
252         glTexCoord2f(1.0, 1.0f);
253         glVertex2f(display.width, 0.0);
254 
255         glTexCoord2f(1.0, 0.0f);
256         glVertex2f(display.width, display.height);
257 
258         glTexCoord2f(0.0f, 0.0f);
259         glVertex2f(0.0f, display.height);
260     glEnd();
261 
262     transition_interval -= dt;
263 }
264 
265 void GourceShell::update(float t, float dt) {
266 
267     if(gource == 0 || gource->isFinished()) {
268         if(!getNext()) appFinished=true;
269 
270         return;
271     }
272 
273     gource->fps = this->fps;
274     gource->update(t, dt);
275 
276     if(toggle_delay > 0.0) toggle_delay -= dt;
277 
278     //copy last frame
279     if( (next|| gource->isFinished()) && transition_texture!=0) {
280 
281         glEnable(GL_TEXTURE_2D);
282         transition_texture->bind();
283         glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, display.width, display.height, 0);
284 
285     } else {
286         //blend last frame of previous scene
287         blendLastFrame(dt);
288     }
289 
290     if(next) {
291         delete gource;
292         gource = 0;
293         transition_interval = 1.0f;
294         next = false;
295     }
296 }
297