blob: 821c7f5b2a3b011561d5be3a098c51be79ccfeaf [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -04001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <linux/input.h>
18#include <pthread.h>
19#include <stdarg.h>
20#include <stdio.h>
21#include <errno.h>
22#include <stdlib.h>
23#include <string.h>
24#include <fcntl.h>
25#include <sys/reboot.h>
26#include <sys/stat.h>
27#include <sys/time.h>
28#include <sys/mman.h>
29#include <sys/types.h>
30#include <sys/ioctl.h>
31#include <sys/mount.h>
32#include <time.h>
33#include <unistd.h>
34#include <stdlib.h>
35
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050036extern "C"
37{
Dees_Troy2673cec2013-04-02 20:22:16 +000038#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040039#include "../minuitwrp/minui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040040#include "../minzip/Zip.h"
41#include <pixelflinger/pixelflinger.h>
42}
43
44#include "rapidxml.hpp"
45#include "objects.hpp"
46#include "../data.hpp"
47#include "../variables.h"
Dees_Troy5bf43922012-09-07 16:07:55 -040048#include "../partitions.hpp"
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050049#include "../twrp-functions.hpp"
50#include "blanktimer.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040051
Dees_Troy51a0e822012-09-05 15:24:24 -040052const static int CURTAIN_FADE = 32;
53
54using namespace rapidxml;
55
56// Global values
57static gr_surface gCurtain = NULL;
58static int gGuiInitialized = 0;
59static int gGuiConsoleRunning = 0;
60static int gGuiConsoleTerminate = 0;
61static int gForceRender = 0;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050062pthread_mutex_t gForceRendermutex;
Dees_Troyc8b199c2012-09-24 11:55:07 -040063static int gNoAnimation = 1;
Dees_Troy4bc09ae2013-01-18 17:00:54 +000064static int gGuiInputRunning = 0;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050065blanktimer blankTimer;
Dees_Troy51a0e822012-09-05 15:24:24 -040066
67// Needed by pages.cpp too
68int gGuiRunning = 0;
69
70static int gRecorder = -1;
71
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020072extern "C" void gr_write_frame_to_file(int fd);
Dees_Troy51a0e822012-09-05 15:24:24 -040073
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020074void flip(void)
Dees_Troy51a0e822012-09-05 15:24:24 -040075{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020076 if (gRecorder != -1)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050077 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020078 timespec time;
79 clock_gettime(CLOCK_MONOTONIC, &time);
80 write(gRecorder, &time, sizeof(timespec));
81 gr_write_frame_to_file(gRecorder);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050082 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020083 gr_flip();
Dees_Troy51a0e822012-09-05 15:24:24 -040084}
85
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020086void rapidxml::parse_error_handler(const char *what, void *where)
Dees_Troy51a0e822012-09-05 15:24:24 -040087{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020088 fprintf(stderr, "Parser error: %s\n", what);
89 fprintf(stderr, " Start of string: %s\n",(char *) where);
90 LOGERR("Error parsing XML file.\n");
91 //abort();
Dees_Troy51a0e822012-09-05 15:24:24 -040092}
93
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020094static void curtainSet()
Dees_Troy51a0e822012-09-05 15:24:24 -040095{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020096 gr_color(0, 0, 0, 255);
97 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
98 gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain), gr_get_height(gCurtain), 0, 0);
99 gr_flip();
Dees_Troy51a0e822012-09-05 15:24:24 -0400100}
101
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200102static void curtainRaise(gr_surface surface)
Dees_Troy51a0e822012-09-05 15:24:24 -0400103{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200104 int sy = 0;
105 int h = gr_get_height(gCurtain) - 1;
106 int w = gr_get_width(gCurtain);
107 int fy = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400108
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200109 int msw = gr_get_width(surface);
110 int msh = gr_get_height(surface);
111 int CURTAIN_RATE = msh / 30;
Dees_Troy51a0e822012-09-05 15:24:24 -0400112
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200113 if (gNoAnimation == 0)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500114 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200115 for (; h > 0; h -= CURTAIN_RATE, sy += CURTAIN_RATE, fy += CURTAIN_RATE)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500116 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200117 gr_blit(surface, 0, 0, msw, msh, 0, 0);
118 gr_blit(gCurtain, 0, sy, w, h, 0, 0);
119 gr_flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500120 }
121 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200122 gr_blit(surface, 0, 0, msw, msh, 0, 0);
123 flip();
Dees_Troy51a0e822012-09-05 15:24:24 -0400124}
125
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200126void curtainClose()
Dees_Troy51a0e822012-09-05 15:24:24 -0400127{
128#if 0
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200129 int w = gr_get_width(gCurtain);
130 int h = 1;
131 int sy = gr_get_height(gCurtain) - 1;
132 int fbh = gr_fb_height();
133 int CURTAIN_RATE = fbh / 30;
Dees_Troy51a0e822012-09-05 15:24:24 -0400134
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200135 if (gNoAnimation == 0)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500136 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200137 for (; h < fbh; h += CURTAIN_RATE, sy -= CURTAIN_RATE)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500138 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200139 gr_blit(gCurtain, 0, sy, w, h, 0, 0);
140 gr_flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500141 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200142 gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain),
143 gr_get_height(gCurtain), 0, 0);
144 gr_flip();
Dees_Troy51a0e822012-09-05 15:24:24 -0400145
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200146 if (gRecorder != -1)
147 close(gRecorder);
Dees_Troy51a0e822012-09-05 15:24:24 -0400148
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200149 int fade;
150 for (fade = 16; fade < 255; fade += CURTAIN_FADE)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500151 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200152 gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain),
153 gr_get_height(gCurtain), 0, 0);
154 gr_color(0, 0, 0, fade);
155 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
156 gr_flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500157 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200158 gr_color(0, 0, 0, 255);
159 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
160 gr_flip();
Dees_Troy51a0e822012-09-05 15:24:24 -0400161 }
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500162#else
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200163 gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain), gr_get_height(gCurtain), 0, 0);
164 gr_flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500165#endif
Dees_Troy51a0e822012-09-05 15:24:24 -0400166}
167
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200168static void * input_thread(void *cookie)
Dees_Troy51a0e822012-09-05 15:24:24 -0400169{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200170 int drag = 0;
171 static int touch_and_hold = 0, dontwait = 0;
172 static int touch_repeat = 0, key_repeat = 0;
173 static int x = 0, y = 0;
174 static int lshift = 0, rshift = 0;
175 static struct timeval touchStart;
176 HardwareKeyboard kb;
177 string seconds;
Dees_Troy51a0e822012-09-05 15:24:24 -0400178
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200179 //start screen timeout threads
180 blankTimer.setTimerThread();
181 DataManager::GetValue("tw_screen_timeout_secs", seconds);
182 blankTimer.setTime(atoi(seconds.c_str()));
Dees_Troy51a0e822012-09-05 15:24:24 -0400183
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200184 for (;;)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500185 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200186 // wait for the next event
187 struct input_event ev;
188 int state = 0, ret = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400189
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200190 ret = ev_get(&ev, dontwait);
Dees_Troy51a0e822012-09-05 15:24:24 -0400191
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200192 if (ret < 0)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500193 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200194 struct timeval curTime;
195 gettimeofday(&curTime, NULL);
196 long mtime, seconds, useconds;
Dees_Troy51a0e822012-09-05 15:24:24 -0400197
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200198 seconds = curTime.tv_sec - touchStart.tv_sec;
199 useconds = curTime.tv_usec - touchStart.tv_usec;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500200
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200201 mtime = ((seconds) * 1000 + useconds / 1000.0) + 0.5;
202 if (touch_and_hold && mtime > 500)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500203 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200204 touch_and_hold = 0;
205 touch_repeat = 1;
206 gettimeofday(&touchStart, NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400207#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200208 LOGERR("TOUCH_HOLD: %d,%d\n", x, y);
Dees_Troy51a0e822012-09-05 15:24:24 -0400209#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200210 PageManager::NotifyTouch(TOUCH_HOLD, x, y);
211 blankTimer.resetTimerAndUnblank();
Dees_Troy51a0e822012-09-05 15:24:24 -0400212 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200213 else if (touch_repeat && mtime > 100)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500214 {
215#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200216 LOGERR("TOUCH_REPEAT: %d,%d\n", x, y);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500217#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200218 gettimeofday(&touchStart, NULL);
219 PageManager::NotifyTouch(TOUCH_REPEAT, x, y);
220 blankTimer.resetTimerAndUnblank();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500221 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200222 else if (key_repeat == 1 && mtime > 500)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500223 {
224#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200225 LOGERR("KEY_HOLD: %d,%d\n", x, y);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500226#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200227 gettimeofday(&touchStart, NULL);
228 key_repeat = 2;
229 kb.KeyRepeat();
230 blankTimer.resetTimerAndUnblank();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500231 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200232 else if (key_repeat == 2 && mtime > 100)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500233 {
234#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200235 LOGERR("KEY_REPEAT: %d,%d\n", x, y);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500236#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200237 gettimeofday(&touchStart, NULL);
238 kb.KeyRepeat();
239 blankTimer.resetTimerAndUnblank();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500240 }
241 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200242 else if (ev.type == EV_ABS)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500243 {
Dees_Troy51a0e822012-09-05 15:24:24 -0400244
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200245 x = ev.value >> 16;
246 y = ev.value & 0xFFFF;
Dees_Troy51a0e822012-09-05 15:24:24 -0400247
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200248 if (ev.code == 0)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500249 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200250 if (state == 0)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500251 {
Dees_Troy51a0e822012-09-05 15:24:24 -0400252#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200253 LOGERR("TOUCH_RELEASE: %d,%d\n", x, y);
Dees_Troy51a0e822012-09-05 15:24:24 -0400254#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200255 PageManager::NotifyTouch(TOUCH_RELEASE, x, y);
256 blankTimer.resetTimerAndUnblank();
257 touch_and_hold = 0;
258 touch_repeat = 0;
259 if (!key_repeat)
260 dontwait = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400261 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200262 state = 0;
263 drag = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400264 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200265 else
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500266 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200267 if (!drag)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500268 {
269#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200270 LOGERR("TOUCH_START: %d,%d\n", x, y);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500271#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200272 if (PageManager::NotifyTouch(TOUCH_START, x, y) > 0)
273 state = 1;
274 drag = 1;
275 touch_and_hold = 1;
276 dontwait = 1;
277 key_repeat = 0;
278 gettimeofday(&touchStart, NULL);
279 blankTimer.resetTimerAndUnblank();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500280 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200281 else
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500282 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200283 if (state == 0)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500284 {
285#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200286 LOGERR("TOUCH_DRAG: %d,%d\n", x, y);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500287#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200288 if (PageManager::NotifyTouch(TOUCH_DRAG, x, y) > 0)
289 state = 1;
290 key_repeat = 0;
291 blankTimer.resetTimerAndUnblank();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500292 }
293 }
294 }
295 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200296 else if (ev.type == EV_KEY)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500297 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200298 // Handle key-press here
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500299#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200300 LOGERR("TOUCH_KEY: %d\n", ev.code);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500301#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200302 if (ev.value != 0)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500303 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200304 // This is a key press
305 if (kb.KeyDown(ev.code))
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500306 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200307 key_repeat = 1;
308 touch_and_hold = 0;
309 touch_repeat = 0;
310 dontwait = 1;
311 gettimeofday(&touchStart, NULL);
312 blankTimer.resetTimerAndUnblank();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500313 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200314 else
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500315 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200316 key_repeat = 0;
317 touch_and_hold = 0;
318 touch_repeat = 0;
319 dontwait = 0;
320 blankTimer.resetTimerAndUnblank();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500321 }
322 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200323 else
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500324 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200325 // This is a key release
326 kb.KeyUp(ev.code);
327 key_repeat = 0;
328 touch_and_hold = 0;
329 touch_repeat = 0;
330 dontwait = 0;
331 blankTimer.resetTimerAndUnblank();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500332 }
333 }
334 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200335 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400336}
337
338// This special function will return immediately the first time, but then
339// always returns 1/30th of a second (or immediately if called later) from
340// the last time it was called
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200341static void loopTimer(void)
Dees_Troy51a0e822012-09-05 15:24:24 -0400342{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200343 static timespec lastCall;
344 static int initialized = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400345
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200346 if (!initialized)
Dees_Troyc8b199c2012-09-24 11:55:07 -0400347 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200348 clock_gettime(CLOCK_MONOTONIC, &lastCall);
349 initialized = 1;
350 return;
Dees_Troyc8b199c2012-09-24 11:55:07 -0400351 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400352
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200353 do
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500354 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200355 timespec curTime;
356 clock_gettime(CLOCK_MONOTONIC, &curTime);
Dees_Troy51a0e822012-09-05 15:24:24 -0400357
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200358 timespec diff = TWFunc::timespec_diff(lastCall, curTime);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500359
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200360 // This is really 30 times per second
361 if (diff.tv_sec || diff.tv_nsec > 33333333)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500362 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200363 lastCall = curTime;
364 return;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500365 }
366
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200367 // We need to sleep some period time microseconds
368 unsigned int sleepTime = 33333 -(diff.tv_nsec / 1000);
369 usleep(sleepTime);
370 } while (1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400371}
372
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200373static int runPages(void)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500374{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200375 // Raise the curtain
376 if (gCurtain != NULL)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500377 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200378 gr_surface surface;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500379
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200380 PageManager::Render();
381 gr_get_surface(&surface);
382 curtainRaise(surface);
383 gr_free_surface(surface);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500384 }
385
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200386 gGuiRunning = 1;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500387
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200388 DataManager::SetValue("tw_loaded", 1);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500389
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200390 for (;;)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500391 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200392 loopTimer();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500393
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200394 if (!gForceRender)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500395 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200396 int ret;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500397
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200398 ret = PageManager::Update();
399 if (ret > 1)
400 PageManager::Render();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500401
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200402 if (ret > 0)
403 flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500404 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200405 else
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500406 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200407 pthread_mutex_lock(&gForceRendermutex);
408 gForceRender = 0;
409 pthread_mutex_unlock(&gForceRendermutex);
410 PageManager::Render();
411 flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500412 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200413
Dees_Troy6ef66352013-02-21 08:26:57 -0600414 if (DataManager::GetIntValue("tw_gui_done") != 0)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200415 break;
416 }
417
418 gGuiRunning = 0;
419 return 0;
420}
421
422static int runPage(const char *page_name)
423{
424 gui_changePage(page_name);
425
426 // Raise the curtain
427 if (gCurtain != NULL)
428 {
429 gr_surface surface;
430
431 PageManager::Render();
432 gr_get_surface(&surface);
433 curtainRaise(surface);
434 gr_free_surface(surface);
435 }
436
437 gGuiRunning = 1;
438
439 DataManager::SetValue("tw_loaded", 1);
440
441 for (;;)
442 {
443 loopTimer();
444
445 if (!gForceRender)
Dees_Troy6ef66352013-02-21 08:26:57 -0600446 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200447 int ret;
448
449 ret = PageManager::Update();
450 if (ret > 1)
451 PageManager::Render();
452
453 if (ret > 0)
454 flip();
455 }
456 else
457 {
458 pthread_mutex_lock(&gForceRendermutex);
459 gForceRender = 0;
460 pthread_mutex_unlock(&gForceRendermutex);
461 PageManager::Render();
462 flip();
463 }
464 if (DataManager::GetIntValue("tw_page_done") != 0)
465 {
466 gui_changePage("main");
Dees_Troy6ef66352013-02-21 08:26:57 -0600467 break;
468 }
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500469 }
470
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200471 gGuiRunning = 0;
472 return 0;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500473}
474
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200475int gui_forceRender(void)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500476{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200477 pthread_mutex_lock(&gForceRendermutex);
478 gForceRender = 1;
479 pthread_mutex_unlock(&gForceRendermutex);
480 return 0;
481}
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500482
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200483int gui_changePage(std::string newPage)
484{
485 LOGINFO("Set page: '%s'\n", newPage.c_str());
486 PageManager::ChangePage(newPage);
487 pthread_mutex_lock(&gForceRendermutex);
488 gForceRender = 1;
489 pthread_mutex_unlock(&gForceRendermutex);
490 return 0;
491}
492
493int gui_changeOverlay(std::string overlay)
494{
495 PageManager::ChangeOverlay(overlay);
496 pthread_mutex_lock(&gForceRendermutex);
497 gForceRender = 1;
498 pthread_mutex_unlock(&gForceRendermutex);
499 return 0;
500}
501
502int gui_changePackage(std::string newPackage)
503{
504 PageManager::SelectPackage(newPackage);
505 pthread_mutex_lock(&gForceRendermutex);
506 gForceRender = 1;
507 pthread_mutex_unlock(&gForceRendermutex);
508 return 0;
509}
510
511std::string gui_parse_text(string inText)
512{
513 // Copied from std::string GUIText::parseText(void)
514 // This function parses text for DataManager values encompassed by %value% in the XML
515 static int counter = 0;
516 std::string str = inText;
517 size_t pos = 0;
518 size_t next = 0, end = 0;
519
520 while (1)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500521 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200522 next = str.find('%', pos);
523 if (next == std::string::npos)
524 return str;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500525
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200526 end = str.find('%', next + 1);
527 if (end == std::string::npos)
528 return str;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500529
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200530 // We have a block of data
531 std::string var = str.substr(next + 1,(end - next) - 1);
532 str.erase(next,(end - next) + 1);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500533
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200534 if (next + 1 == end)
535 str.insert(next, 1, '%');
536 else
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500537 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200538 std::string value;
539 if (DataManager::GetValue(var, value) == 0)
540 str.insert(next, value);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500541 }
542
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200543 pos = next + 1;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500544 }
545}
546
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200547extern "C" int gui_init(void)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500548{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200549 int fd;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500550
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200551 gr_init();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500552
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200553 if (res_create_surface("/res/images/curtain.jpg", &gCurtain))
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500554 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200555 printf
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500556 ("Unable to locate '/res/images/curtain.jpg'\nDid you set a DEVICE_RESOLUTION in your config files?\n");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200557 return -1;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500558 }
559
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200560 curtainSet();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500561
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200562 ev_init();
563 return 0;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500564}
565
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200566extern "C" int gui_loadResources(void)
Dees_Troy51a0e822012-09-05 15:24:24 -0400567{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200568 // unlink("/sdcard/video.last");
569 // rename("/sdcard/video.bin", "/sdcard/video.last");
570 // gRecorder = open("/sdcard/video.bin", O_CREAT | O_WRONLY);
Dees_Troy51a0e822012-09-05 15:24:24 -0400571
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200572 int check = 0;
573 DataManager::GetValue(TW_IS_ENCRYPTED, check);
574 if (check)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500575 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200576 if (PageManager::LoadPackage("TWRP", "/res/ui.xml", "decrypt"))
Dees_Troy5bf43922012-09-07 16:07:55 -0400577 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200578 LOGERR("Failed to load base packages.\n");
579 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400580 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200581 else
582 check = 1;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500583 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400584
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200585 if (check == 0 && PageManager::LoadPackage("TWRP", "/script/ui.xml", "main"))
586 {
587 std::string theme_path;
588
589 theme_path = DataManager::GetSettingsStoragePath();
590 if (!PartitionManager.Mount_Settings_Storage(false))
Dees_Troy51a0e822012-09-05 15:24:24 -0400591 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200592 int retry_count = 5;
593 while (retry_count > 0 && !PartitionManager.Mount_Settings_Storage(false))
Dees_Troy51a0e822012-09-05 15:24:24 -0400594 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200595 usleep(500000);
596 retry_count--;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500597 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200598
599 if (!PartitionManager.Mount_Settings_Storage(false))
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500600 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200601 LOGERR("Unable to mount %s during GUI startup.\n",
602 theme_path.c_str());
603 check = 1;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500604 }
605 }
606
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200607 theme_path += "/TWRP/theme/ui.zip";
608 if (check || PageManager::LoadPackage("TWRP", theme_path, "main"))
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500609 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200610 if (PageManager::LoadPackage("TWRP", "/res/ui.xml", "main"))
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500611 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200612 LOGERR("Failed to load base packages.\n");
613 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400614 }
615 }
616 }
617
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200618 // Set the default package
619 PageManager::SelectPackage("TWRP");
Dees_Troy51a0e822012-09-05 15:24:24 -0400620
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200621 gGuiInitialized = 1;
622 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400623
624error:
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200625 LOGERR("An internal error has occurred.\n");
626 gGuiInitialized = 0;
627 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400628}
629
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200630extern "C" int gui_start(void)
Dees_Troy51a0e822012-09-05 15:24:24 -0400631{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200632 if (!gGuiInitialized)
633 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400634
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200635 gGuiConsoleTerminate = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400636
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200637 while (gGuiConsoleRunning)
638 loopTimer();
Dees_Troy51a0e822012-09-05 15:24:24 -0400639
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200640 // Set the default package
641 PageManager::SelectPackage("TWRP");
642
643 if (!gGuiInputRunning)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500644 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200645 // Start by spinning off an input handler.
646 pthread_t t;
647 pthread_create(&t, NULL, input_thread, NULL);
648 gGuiInputRunning = 1;
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000649 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400650
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200651 return runPages();
Dees_Troy51a0e822012-09-05 15:24:24 -0400652}
653
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200654extern "C" int gui_startPage(const char *page_name)
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000655{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200656 if (!gGuiInitialized)
657 return -1;
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000658
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200659 gGuiConsoleTerminate = 1;
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000660
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200661 while (gGuiConsoleRunning)
662 loopTimer();
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000663
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200664 // Set the default package
665 PageManager::SelectPackage("TWRP");
666
667 if (!gGuiInputRunning)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500668 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200669 // Start by spinning off an input handler.
670 pthread_t t;
671 pthread_create(&t, NULL, input_thread, NULL);
672 gGuiInputRunning = 1;
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000673 }
674
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200675 DataManager::SetValue("tw_page_done", 0);
676 return runPage(page_name);
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000677}
678
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200679static void * console_thread(void *cookie)
Dees_Troy51a0e822012-09-05 15:24:24 -0400680{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200681 PageManager::SwitchToConsole();
Dees_Troy51a0e822012-09-05 15:24:24 -0400682
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200683 while (!gGuiConsoleTerminate)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500684 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200685 loopTimer();
Dees_Troy51a0e822012-09-05 15:24:24 -0400686
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200687 if (!gForceRender)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500688 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200689 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400690
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200691 ret = PageManager::Update();
692 if (ret > 1)
693 PageManager::Render();
Dees_Troy51a0e822012-09-05 15:24:24 -0400694
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200695 if (ret > 0)
696 flip();
Dees_Troy51a0e822012-09-05 15:24:24 -0400697
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200698 if (ret < 0)
699 LOGERR("An update request has failed.\n");
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500700 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200701 else
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500702 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200703 pthread_mutex_lock(&gForceRendermutex);
704 gForceRender = 0;
705 pthread_mutex_unlock(&gForceRendermutex);
706 PageManager::Render();
707 flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500708 }
709 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200710 gGuiConsoleRunning = 0;
711 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400712}
713
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200714extern "C" int gui_console_only(void)
Dees_Troy51a0e822012-09-05 15:24:24 -0400715{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200716 if (!gGuiInitialized)
717 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400718
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200719 gGuiConsoleTerminate = 0;
720 gGuiConsoleRunning = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400721
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200722 // Start by spinning off an input handler.
723 pthread_t t;
724 pthread_create(&t, NULL, console_thread, NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400725
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200726 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400727}