diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-05-17 17:19:31 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-05-17 17:19:31 +0000 |
commit | c4c7069a8a0b4ffc5de8758c2aa154118449aa62 (patch) | |
tree | 9a330d88b3e3d40dbdcfbdddd0f85aa409a77cbf /firmware/target | |
parent | f4d6ef2292c6a2b482af106e7d73588f65845e94 (diff) | |
download | rockbox-c4c7069a8a0b4ffc5de8758c2aa154118449aa62.tar.gz rockbox-c4c7069a8a0b4ffc5de8758c2aa154118449aa62.zip |
Fix FS#11280
SDL docs say SDL_PumpEvent (implicitely called by SDL_Poll/WaitEvent)
may only be called from the thread that initializes the video subsystem,
apparently because Windows requires that.
So create an (or bring it back) SDL thread (with preemtive behavior) to read the
event queue for buttons and initialize the video subsystem.
I'd probably would have done that anyway because it enables an interrupt-like method to read them (no polling).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26113 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/hosted/sdl/button-sdl.c | 14 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/system-sdl.c | 71 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/system-sdl.h | 1 |
3 files changed, 73 insertions, 13 deletions
diff --git a/firmware/target/hosted/sdl/button-sdl.c b/firmware/target/hosted/sdl/button-sdl.c index cfe08de1d2..e9fc03792c 100644 --- a/firmware/target/hosted/sdl/button-sdl.c +++ b/firmware/target/hosted/sdl/button-sdl.c | |||
@@ -85,20 +85,21 @@ bool remote_button_hold(void) { | |||
85 | static void button_event(int key, bool pressed); | 85 | static void button_event(int key, bool pressed); |
86 | extern bool debug_wps; | 86 | extern bool debug_wps; |
87 | extern bool mapping; | 87 | extern bool mapping; |
88 | static void gui_message_loop(void) | 88 | |
89 | void gui_message_loop(void) | ||
89 | { | 90 | { |
90 | SDL_Event event; | 91 | SDL_Event event; |
91 | static int x,y,xybutton = 0; | 92 | static int x,y,xybutton = 0; |
92 | 93 | ||
93 | if (SDL_PollEvent(&event)) | 94 | while (SDL_WaitEvent(&event)) |
94 | { | 95 | { |
96 | sim_enter_irq_handler(); | ||
95 | switch(event.type) | 97 | switch(event.type) |
96 | { | 98 | { |
97 | case SDL_KEYDOWN: | 99 | case SDL_KEYDOWN: |
98 | button_event(event.key.keysym.sym, true); | ||
99 | break; | ||
100 | case SDL_KEYUP: | 100 | case SDL_KEYUP: |
101 | button_event(event.key.keysym.sym, false); | 101 | button_event(event.key.keysym.sym, event.type == SDL_KEYDOWN); |
102 | break; | ||
102 | case SDL_MOUSEBUTTONDOWN: | 103 | case SDL_MOUSEBUTTONDOWN: |
103 | switch ( event.button.button ) { | 104 | switch ( event.button.button ) { |
104 | #ifdef HAVE_SCROLLWHEEL | 105 | #ifdef HAVE_SCROLLWHEEL |
@@ -174,6 +175,7 @@ static void gui_message_loop(void) | |||
174 | 175 | ||
175 | case SDL_QUIT: | 176 | case SDL_QUIT: |
176 | { | 177 | { |
178 | sim_exit_irq_handler(); | ||
177 | exit(EXIT_SUCCESS); | 179 | exit(EXIT_SUCCESS); |
178 | break; | 180 | break; |
179 | } | 181 | } |
@@ -181,6 +183,7 @@ static void gui_message_loop(void) | |||
181 | /*printf("Unhandled event\n"); */ | 183 | /*printf("Unhandled event\n"); */ |
182 | break; | 184 | break; |
183 | } | 185 | } |
186 | sim_exit_irq_handler(); | ||
184 | } | 187 | } |
185 | } | 188 | } |
186 | 189 | ||
@@ -1502,7 +1505,6 @@ int button_read_device(void) | |||
1502 | return BUTTON_NONE; | 1505 | return BUTTON_NONE; |
1503 | else | 1506 | else |
1504 | #endif | 1507 | #endif |
1505 | gui_message_loop(); | ||
1506 | 1508 | ||
1507 | return btn; | 1509 | return btn; |
1508 | } | 1510 | } |
diff --git a/firmware/target/hosted/sdl/system-sdl.c b/firmware/target/hosted/sdl/system-sdl.c index 693e8d1b57..3d67de425b 100644 --- a/firmware/target/hosted/sdl/system-sdl.c +++ b/firmware/target/hosted/sdl/system-sdl.c | |||
@@ -70,14 +70,37 @@ void sys_poweroff(void) | |||
70 | SDL_Quit(); | 70 | SDL_Quit(); |
71 | } | 71 | } |
72 | 72 | ||
73 | void system_init(void) | 73 | /* |
74 | * Button read loop */ | ||
75 | void gui_message_loop(void); | ||
76 | |||
77 | /* | ||
78 | * This callback let's the main thread run again after SDL has been initialized | ||
79 | **/ | ||
80 | static uint32_t cond_signal(uint32_t interval, void *param) | ||
81 | { | ||
82 | (void)interval; | ||
83 | SDL_cond *c = (SDL_cond*)param; | ||
84 | /* remove timer, CondSignal returns 0 on success */ | ||
85 | return SDL_CondSignal(c); | ||
86 | } | ||
87 | |||
88 | /* | ||
89 | * This thread will read the buttons in an interrupt like fashion, and | ||
90 | * also initializes SDL_INIT_VIDEO and the surfaces | ||
91 | * | ||
92 | * it must be done in the same thread (at least on windows) because events only | ||
93 | * work in the thread which called SDL_Init(SubSystem) with SDL_INIT_VIDEO | ||
94 | * | ||
95 | * This is an SDL thread and relies on preemptive behavoir of the host | ||
96 | **/ | ||
97 | static int sdl_event_thread(void * param) | ||
74 | { | 98 | { |
99 | SDL_InitSubSystem(SDL_INIT_VIDEO); | ||
100 | |||
75 | SDL_Surface *picture_surface; | 101 | SDL_Surface *picture_surface; |
76 | int width, height; | 102 | int width, height; |
77 | 103 | ||
78 | if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER)) | ||
79 | panicf("%s", SDL_GetError()); | ||
80 | |||
81 | /* Try and load the background image. If it fails go without */ | 104 | /* Try and load the background image. If it fails go without */ |
82 | if (background) { | 105 | if (background) { |
83 | picture_surface = SDL_LoadBMP("UI256.bmp"); | 106 | picture_surface = SDL_LoadBMP("UI256.bmp"); |
@@ -122,10 +145,43 @@ void system_init(void) | |||
122 | sim_lcd_remote_init(); | 145 | sim_lcd_remote_init(); |
123 | #endif | 146 | #endif |
124 | 147 | ||
125 | if (background && picture_surface != NULL) { | 148 | if (background && picture_surface != NULL) |
126 | SDL_BlitSurface(picture_surface, NULL, gui_surface, NULL); | 149 | SDL_BlitSurface(picture_surface, NULL, gui_surface, NULL); |
127 | SDL_UpdateRect(gui_surface, 0, 0, 0, 0); | 150 | |
128 | } | 151 | /* calling SDL_CondSignal() right away here doesn't work reliably so |
152 | * post-pone it a bit */ | ||
153 | SDL_AddTimer(100, cond_signal, param); | ||
154 | /* | ||
155 | * finally enter the button loop */ | ||
156 | while(1) | ||
157 | gui_message_loop(); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | |||
163 | void system_init(void) | ||
164 | { | ||
165 | SDL_cond *c; | ||
166 | SDL_mutex *m; | ||
167 | if (SDL_Init(SDL_INIT_TIMER)) | ||
168 | panicf("%s", SDL_GetError()); | ||
169 | atexit(SDL_Quit); | ||
170 | |||
171 | c = SDL_CreateCond(); | ||
172 | m = SDL_CreateMutex(); | ||
173 | |||
174 | SDL_CreateThread(sdl_event_thread, c); | ||
175 | |||
176 | /* Lock mutex and wait for sdl_event_thread to run so that it can | ||
177 | * initialize the surfaces and video subsystem needed for SDL events */ | ||
178 | SDL_LockMutex(m); | ||
179 | SDL_CondWait(c, m); | ||
180 | SDL_UnlockMutex(m); | ||
181 | |||
182 | /* cleanup */ | ||
183 | SDL_DestroyCond(c); | ||
184 | SDL_DestroyMutex(m); | ||
129 | } | 185 | } |
130 | 186 | ||
131 | void system_exception_wait(void) | 187 | void system_exception_wait(void) |
@@ -138,6 +194,7 @@ void system_reboot(void) | |||
138 | sim_thread_exception_wait(); | 194 | sim_thread_exception_wait(); |
139 | } | 195 | } |
140 | 196 | ||
197 | |||
141 | void sys_handle_argv(int argc, char *argv[]) | 198 | void sys_handle_argv(int argc, char *argv[]) |
142 | { | 199 | { |
143 | if (argc >= 1) | 200 | if (argc >= 1) |
diff --git a/firmware/target/hosted/sdl/system-sdl.h b/firmware/target/hosted/sdl/system-sdl.h index 917e6e89da..ad7aa709ab 100644 --- a/firmware/target/hosted/sdl/system-sdl.h +++ b/firmware/target/hosted/sdl/system-sdl.h | |||
@@ -44,6 +44,7 @@ void sim_exit_irq_handler(void); | |||
44 | void sim_kernel_shutdown(void); | 44 | void sim_kernel_shutdown(void); |
45 | void sys_poweroff(void); | 45 | void sys_poweroff(void); |
46 | void sys_handle_argv(int argc, char *argv[]); | 46 | void sys_handle_argv(int argc, char *argv[]); |
47 | void gui_message_loop(void); | ||
47 | 48 | ||
48 | extern bool background; /* True if the background image is enabled */ | 49 | extern bool background; /* True if the background image is enabled */ |
49 | extern int display_zoom; | 50 | extern int display_zoom; |