Merge lp:~widelands-dev/widelands/remove-record into lp:widelands
- remove-record
- Merge into trunk
Proposed by
Hans Joachim Desserud
Status: | Merged |
---|---|
Merged at revision: | 6871 |
Proposed branch: | lp:~widelands-dev/widelands/remove-record |
Merge into: | lp:widelands |
Diff against target: |
1174 lines (+42/-985) 7 files modified
src/helper.h (+0/-16) src/journal.cc (+0/-484) src/journal.h (+0/-137) src/journal_exceptions.cc (+0/-59) src/journal_exceptions.h (+0/-90) src/wlapplication.cc (+41/-195) src/wlapplication.h (+1/-4) |
To merge this branch: | bzr merge lp:~widelands-dev/widelands/remove-record |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Hans Joachim Desserud | Approve | ||
SirVer | Approve | ||
Review via email:
|
Commit message
Description of the change
Like we talked about back when updating/tweaking the readme, I've removed the --record and --playback options since they weren't in use.
I started out following the methods called by the option when running Widelands, but ended up removing all of journal and journal_exception when I discovered it wasn't used for anything else. I was also able to remove a helper function which wasn't used elsewhere.
A couple of places has been marked FIXME to get some feedback on them.
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Hans Joachim Desserud (hjd) wrote : | # |
Nice, let's merge this then. :)
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/helper.h' | |||
2 | --- src/helper.h 2013-07-26 19:16:51 +0000 | |||
3 | +++ src/helper.h 2014-03-11 20:49:20 +0000 | |||
4 | @@ -135,22 +135,6 @@ | |||
5 | 135 | return x; | 135 | return x; |
6 | 136 | } | 136 | } |
7 | 137 | 137 | ||
8 | 138 | /* Convert any sstream-compatible type to std::string | ||
9 | 139 | * | ||
10 | 140 | * \note In a just world, this would be implemented with gnu::autosprintf. But | ||
11 | 141 | * many distributions don't carry that lib despite the fact that it is part of | ||
12 | 142 | * glibc. | ||
13 | 143 | * | ||
14 | 144 | * \see http://www.experts-exchange.com/Programming/ | ||
15 | 145 | * Programming_Languages/Cplusplus/Q_20670737.html | ||
16 | 146 | * \author AssafLavie on http://www.experts-exchange.com | ||
17 | 147 | */ | ||
18 | 148 | template<typename T> std::string toString(const T & x) { | ||
19 | 149 | std::ostringstream oss; | ||
20 | 150 | oss << x; | ||
21 | 151 | return oss.str(); | ||
22 | 152 | } | ||
23 | 153 | |||
24 | 154 | std::vector<std::string> split_string | 138 | std::vector<std::string> split_string |
25 | 155 | (const std::string &, char const * separators); | 139 | (const std::string &, char const * separators); |
26 | 156 | void remove_spaces(std::string &); | 140 | void remove_spaces(std::string &); |
27 | 157 | 141 | ||
28 | === removed file 'src/journal.cc' | |||
29 | --- src/journal.cc 2013-07-26 19:16:51 +0000 | |||
30 | +++ src/journal.cc 1970-01-01 00:00:00 +0000 | |||
31 | @@ -1,484 +0,0 @@ | |||
32 | 1 | /* | ||
33 | 2 | * Copyright (C) 2006-2009 by the Widelands Development Team | ||
34 | 3 | * | ||
35 | 4 | * This program is free software; you can redistribute it and/or | ||
36 | 5 | * modify it under the terms of the GNU General Public License | ||
37 | 6 | * as published by the Free Software Foundation; either version 2 | ||
38 | 7 | * of the License, or (at your option) any later version. | ||
39 | 8 | * | ||
40 | 9 | * This program is distributed in the hope that it will be useful, | ||
41 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
42 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
43 | 12 | * GNU General Public License for more details. | ||
44 | 13 | * | ||
45 | 14 | * You should have received a copy of the GNU General Public License | ||
46 | 15 | * along with this program; if not, write to the Free Software | ||
47 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
48 | 17 | * | ||
49 | 18 | */ | ||
50 | 19 | |||
51 | 20 | #include "journal.h" | ||
52 | 21 | |||
53 | 22 | #include <cassert> | ||
54 | 23 | |||
55 | 24 | #include "io/filesystem/filesystem.h" | ||
56 | 25 | #include "log.h" | ||
57 | 26 | #include "machdep.h" | ||
58 | 27 | |||
59 | 28 | /** | ||
60 | 29 | * Write a signed 8bit value to the recording file. | ||
61 | 30 | * \param v The character to be written | ||
62 | 31 | */ | ||
63 | 32 | void Journal::write(int8_t const v) { | ||
64 | 33 | m_recordstream.write(reinterpret_cast<const char *>(&v), sizeof(v)); | ||
65 | 34 | } | ||
66 | 35 | |||
67 | 36 | /// \overload | ||
68 | 37 | void Journal::write(uint8_t const v) { | ||
69 | 38 | m_recordstream.write(reinterpret_cast<const char *>(&v), sizeof(v)); | ||
70 | 39 | } | ||
71 | 40 | |||
72 | 41 | /// \overload | ||
73 | 42 | void Journal::write(int16_t v) { | ||
74 | 43 | v = Little16(v); | ||
75 | 44 | m_recordstream.write(reinterpret_cast<const char *>(&v), sizeof(v)); | ||
76 | 45 | } | ||
77 | 46 | /// \overload | ||
78 | 47 | void Journal::write(uint16_t v) { | ||
79 | 48 | v = Little16(v); | ||
80 | 49 | m_recordstream.write(reinterpret_cast<const char *>(&v), sizeof(v)); | ||
81 | 50 | } | ||
82 | 51 | |||
83 | 52 | /// \overload | ||
84 | 53 | void Journal::write(int32_t v) { | ||
85 | 54 | v = Little32(v); | ||
86 | 55 | m_recordstream.write(reinterpret_cast<const char *>(&v), sizeof(v)); | ||
87 | 56 | } | ||
88 | 57 | |||
89 | 58 | /// \overload | ||
90 | 59 | void Journal::write(uint32_t v) { | ||
91 | 60 | v = Little32(v); | ||
92 | 61 | m_recordstream.write(reinterpret_cast<const char *>(&v), sizeof(v)); | ||
93 | 62 | } | ||
94 | 63 | |||
95 | 64 | /// \overload | ||
96 | 65 | /// SDLKey is an enum, and enums are implemented as int32_t. Consequently, | ||
97 | 66 | /// SDLKey changes size on 64bit machines :-( | ||
98 | 67 | /// So we force it to be 32bit, discarding the higher 32 bits (hopefully no-one | ||
99 | 68 | /// will have so many keys). | ||
100 | 69 | /// | ||
101 | 70 | /// On 32bit systems, it does not matter whether this method or | ||
102 | 71 | /// \ref write(Uint32 v) actually gets used. | ||
103 | 72 | /// | ||
104 | 73 | /// \sa write(SDLMod v) | ||
105 | 74 | /// \sa read(SDLMod &v) | ||
106 | 75 | void Journal::write(SDLKey v) | ||
107 | 76 | { | ||
108 | 77 | write(static_cast<uint32_t>(v)); | ||
109 | 78 | } | ||
110 | 79 | |||
111 | 80 | /** | ||
112 | 81 | * \overload | ||
113 | 82 | * \sa write(SDLKey v) | ||
114 | 83 | */ | ||
115 | 84 | void Journal::write(SDLMod v) | ||
116 | 85 | { | ||
117 | 86 | write(static_cast<uint32_t>(v)); | ||
118 | 87 | } | ||
119 | 88 | |||
120 | 89 | /** | ||
121 | 90 | * Write a signed char value to the recording file. | ||
122 | 91 | * \param v Reference where the read character will be stored. | ||
123 | 92 | */ | ||
124 | 93 | void Journal::read (int8_t & v) | ||
125 | 94 | { | ||
126 | 95 | m_playbackstream.read(reinterpret_cast<char *>(&v), sizeof(uint8_t)); | ||
127 | 96 | } | ||
128 | 97 | |||
129 | 98 | /** | ||
130 | 99 | * \overload | ||
131 | 100 | */ | ||
132 | 101 | void Journal::read(uint8_t & v) | ||
133 | 102 | { | ||
134 | 103 | m_playbackstream.read(reinterpret_cast<char *>(&v), sizeof(uint8_t)); | ||
135 | 104 | } | ||
136 | 105 | |||
137 | 106 | /** | ||
138 | 107 | * \overload | ||
139 | 108 | */ | ||
140 | 109 | void Journal::read (int16_t & v) { | ||
141 | 110 | m_playbackstream.read(reinterpret_cast<char *>(&v), sizeof(int16_t)); | ||
142 | 111 | v = Little16(v); | ||
143 | 112 | } | ||
144 | 113 | |||
145 | 114 | /** | ||
146 | 115 | * \overload | ||
147 | 116 | */ | ||
148 | 117 | void Journal::read(uint16_t & v) { | ||
149 | 118 | m_playbackstream.read(reinterpret_cast<char *>(&v), sizeof(uint16_t)); | ||
150 | 119 | v = Little16(v); | ||
151 | 120 | } | ||
152 | 121 | |||
153 | 122 | /** | ||
154 | 123 | * \overload | ||
155 | 124 | */ | ||
156 | 125 | void Journal::read (int32_t & v) { | ||
157 | 126 | m_playbackstream.read(reinterpret_cast<char *>(&v), sizeof(int32_t)); | ||
158 | 127 | v = Little32(v); | ||
159 | 128 | } | ||
160 | 129 | |||
161 | 130 | /** | ||
162 | 131 | * \overload | ||
163 | 132 | */ | ||
164 | 133 | void Journal::read(uint32_t & v) { | ||
165 | 134 | m_playbackstream.read(reinterpret_cast<char *>(&v), sizeof(uint32_t)); | ||
166 | 135 | v = Little32(v); | ||
167 | 136 | } | ||
168 | 137 | |||
169 | 138 | /** | ||
170 | 139 | * \overload | ||
171 | 140 | * \sa read(SDLKey v) | ||
172 | 141 | */ | ||
173 | 142 | void Journal::read(SDLKey & v) | ||
174 | 143 | { | ||
175 | 144 | uint32_t x; | ||
176 | 145 | read(x); | ||
177 | 146 | v = static_cast<SDLKey>(x); | ||
178 | 147 | } | ||
179 | 148 | |||
180 | 149 | /** | ||
181 | 150 | * \overload | ||
182 | 151 | * \sa read(SDLKey v) | ||
183 | 152 | */ | ||
184 | 153 | void Journal::read(SDLMod & v) | ||
185 | 154 | { | ||
186 | 155 | uint32_t x; | ||
187 | 156 | read(x); | ||
188 | 157 | v = static_cast<SDLMod>(x); | ||
189 | 158 | } | ||
190 | 159 | |||
191 | 160 | /** | ||
192 | 161 | * \todo Document me | ||
193 | 162 | */ | ||
194 | 163 | void Journal::ensure_code(uint8_t code) | ||
195 | 164 | { | ||
196 | 165 | uint8_t filecode; | ||
197 | 166 | |||
198 | 167 | read(filecode); | ||
199 | 168 | if (filecode != code) { | ||
200 | 169 | throw BadRecord_error(m_playbackname, filecode, code); | ||
201 | 170 | } | ||
202 | 171 | } | ||
203 | 172 | |||
204 | 173 | /** | ||
205 | 174 | * Standard ctor | ||
206 | 175 | */ | ||
207 | 176 | Journal::Journal() | ||
208 | 177 | : | ||
209 | 178 | m_recordname(""), m_playbackname(""), | ||
210 | 179 | m_record(false), m_playback(false) | ||
211 | 180 | { | ||
212 | 181 | m_recordstream.exceptions | ||
213 | 182 | (std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit); | ||
214 | 183 | |||
215 | 184 | m_playbackstream.exceptions | ||
216 | 185 | (std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit); | ||
217 | 186 | } | ||
218 | 187 | |||
219 | 188 | /** | ||
220 | 189 | * Close any open journal files | ||
221 | 190 | */ | ||
222 | 191 | Journal::~Journal() | ||
223 | 192 | { | ||
224 | 193 | stop_recording(); | ||
225 | 194 | stop_playback(); | ||
226 | 195 | } | ||
227 | 196 | |||
228 | 197 | /** | ||
229 | 198 | * Start recording events handed to us | ||
230 | 199 | * \param filename File the events should be written to | ||
231 | 200 | * \todo set the filename somewhere else | ||
232 | 201 | */ | ||
233 | 202 | void Journal::start_recording(const std::string & filename) | ||
234 | 203 | { | ||
235 | 204 | assert(!m_recordstream.is_open()); | ||
236 | 205 | |||
237 | 206 | //TODO: m_recordname = FileSystem::FS_CanonicalizeName(filename); | ||
238 | 207 | m_recordname = filename; | ||
239 | 208 | if (m_recordname.empty()) | ||
240 | 209 | assert(false); //TODO: barf in a controlled way | ||
241 | 210 | |||
242 | 211 | try { | ||
243 | 212 | m_recordstream.open | ||
244 | 213 | (m_recordname.c_str(), std::ios::binary|std::ios::trunc); | ||
245 | 214 | write(RFC_MAGIC); | ||
246 | 215 | m_recordstream << std::flush; | ||
247 | 216 | m_record = true; | ||
248 | 217 | log("Recording into %s\n", m_recordname.c_str()); | ||
249 | 218 | } | ||
250 | 219 | catch (std::ofstream::failure &) { | ||
251 | 220 | //TODO: use exception mask to find out what happened | ||
252 | 221 | //TODO: there should be a messagebox to tell the user. | ||
253 | 222 | log | ||
254 | 223 | ("Problem while opening record file %s for writing.\n", | ||
255 | 224 | m_recordname.c_str()); | ||
256 | 225 | stop_recording(); | ||
257 | 226 | throw Journalfile_error(m_recordname); | ||
258 | 227 | } | ||
259 | 228 | } | ||
260 | 229 | |||
261 | 230 | /** | ||
262 | 231 | * Stop recording events. | ||
263 | 232 | * It's safe to call this even if recording has not been | ||
264 | 233 | * started yet. | ||
265 | 234 | */ | ||
266 | 235 | void Journal::stop_recording() | ||
267 | 236 | { | ||
268 | 237 | m_record = false; | ||
269 | 238 | |||
270 | 239 | if (m_recordstream.is_open()) { | ||
271 | 240 | m_recordstream<<std::flush; | ||
272 | 241 | m_recordstream.close(); | ||
273 | 242 | } | ||
274 | 243 | } | ||
275 | 244 | |||
276 | 245 | /** | ||
277 | 246 | * Start playing back events | ||
278 | 247 | * \param filename File to get events from | ||
279 | 248 | * \todo set the filename somewhere else | ||
280 | 249 | */ | ||
281 | 250 | void Journal::start_playback(const std::string & filename) | ||
282 | 251 | { | ||
283 | 252 | assert(!m_playbackstream.is_open()); | ||
284 | 253 | |||
285 | 254 | //TODO: m_playbackname = FileSystem::FS_CanonicalizeName(filename); | ||
286 | 255 | m_playbackname = filename; | ||
287 | 256 | if (m_playbackname.empty()) | ||
288 | 257 | assert(false); //TODO: barf in a controlled way | ||
289 | 258 | |||
290 | 259 | try { | ||
291 | 260 | uint32_t magic; | ||
292 | 261 | |||
293 | 262 | m_playbackstream.open(m_playbackname.c_str(), std::ios::binary); | ||
294 | 263 | read(magic); | ||
295 | 264 | if (magic != RFC_MAGIC) | ||
296 | 265 | throw BadMagic_error(m_playbackname); | ||
297 | 266 | m_playback = true; | ||
298 | 267 | log("Playing back from %s\n", m_playbackname.c_str()); | ||
299 | 268 | } | ||
300 | 269 | catch (std::ifstream::failure &) { | ||
301 | 270 | //TODO: use exception mask to find out what happened | ||
302 | 271 | //TODO: there should be a messagebox to tell the user. | ||
303 | 272 | log | ||
304 | 273 | ("ERROR: problem while opening playback file for reading. Playback " | ||
305 | 274 | "deactivated.\n"); | ||
306 | 275 | stop_playback(); | ||
307 | 276 | throw Journalfile_error(m_recordname); | ||
308 | 277 | } | ||
309 | 278 | } | ||
310 | 279 | |||
311 | 280 | /** | ||
312 | 281 | * Stop playing back events. | ||
313 | 282 | * It's safe to call this even if playback has not been | ||
314 | 283 | * started yet. | ||
315 | 284 | */ | ||
316 | 285 | void Journal::stop_playback() | ||
317 | 286 | { | ||
318 | 287 | m_playback = false; | ||
319 | 288 | |||
320 | 289 | if (m_playbackstream.is_open()) { | ||
321 | 290 | m_playbackstream.close(); | ||
322 | 291 | } | ||
323 | 292 | } | ||
324 | 293 | |||
325 | 294 | /** | ||
326 | 295 | * Record an event into the playback file. This entails serializing the | ||
327 | 296 | * event and writing it out. | ||
328 | 297 | * | ||
329 | 298 | * \param e The event to be recorded | ||
330 | 299 | */ | ||
331 | 300 | void Journal::record_event(const SDL_Event & e) | ||
332 | 301 | { | ||
333 | 302 | if (!m_record) | ||
334 | 303 | return; | ||
335 | 304 | |||
336 | 305 | try { | ||
337 | 306 | //Note: the following lines are *inside* the switch on purpose: | ||
338 | 307 | // write(RFC_EVENT); | ||
339 | 308 | // m_recordstream<<std::flush; | ||
340 | 309 | //If they were outside, they'd get executed on every mainloop | ||
341 | 310 | //iteration, which would yield a) huge files and b) lots of | ||
342 | 311 | //completely unnecessary overhad. | ||
343 | 312 | switch (e.type) { | ||
344 | 313 | case SDL_KEYDOWN: | ||
345 | 314 | write(static_cast<uint8_t>(RFC_EVENT)); | ||
346 | 315 | write(static_cast<uint8_t>(RFC_KEYDOWN)); | ||
347 | 316 | write(e.key.keysym.mod); | ||
348 | 317 | write(e.key.keysym.sym); | ||
349 | 318 | write(e.key.keysym.unicode); | ||
350 | 319 | m_recordstream << std::flush; | ||
351 | 320 | break; | ||
352 | 321 | case SDL_KEYUP: | ||
353 | 322 | write(static_cast<uint8_t>(RFC_EVENT)); | ||
354 | 323 | write(static_cast<uint8_t>(RFC_KEYUP)); | ||
355 | 324 | write(e.key.keysym.mod); | ||
356 | 325 | write(e.key.keysym.sym); | ||
357 | 326 | write(e.key.keysym.unicode); | ||
358 | 327 | m_recordstream << std::flush; | ||
359 | 328 | break; | ||
360 | 329 | case SDL_MOUSEBUTTONDOWN: | ||
361 | 330 | write(static_cast<uint8_t>(RFC_EVENT)); | ||
362 | 331 | write(static_cast<uint8_t>(RFC_MOUSEBUTTONDOWN)); | ||
363 | 332 | write(e.button.button); | ||
364 | 333 | write(e.button.x); | ||
365 | 334 | write(e.button.y); | ||
366 | 335 | write(e.button.state); | ||
367 | 336 | m_recordstream << std::flush; | ||
368 | 337 | break; | ||
369 | 338 | case SDL_MOUSEBUTTONUP: | ||
370 | 339 | write(static_cast<uint8_t>(RFC_EVENT)); | ||
371 | 340 | write(static_cast<uint8_t>(RFC_MOUSEBUTTONUP)); | ||
372 | 341 | write(e.button.button); | ||
373 | 342 | write(e.button.x); | ||
374 | 343 | write(e.button.y); | ||
375 | 344 | write(e.button.state); | ||
376 | 345 | m_recordstream << std::flush; | ||
377 | 346 | break; | ||
378 | 347 | case SDL_MOUSEMOTION: | ||
379 | 348 | write(static_cast<uint8_t>(RFC_EVENT)); | ||
380 | 349 | write(static_cast<uint8_t>(RFC_MOUSEMOTION)); | ||
381 | 350 | write(e.motion.state); | ||
382 | 351 | write(e.motion.x); | ||
383 | 352 | write(e.motion.y); | ||
384 | 353 | write(e.motion.xrel); | ||
385 | 354 | write(e.motion.yrel); | ||
386 | 355 | m_recordstream << std::flush; | ||
387 | 356 | break; | ||
388 | 357 | case SDL_QUIT: | ||
389 | 358 | write(static_cast<uint8_t>(RFC_EVENT)); | ||
390 | 359 | write(static_cast<uint8_t>(RFC_QUIT)); | ||
391 | 360 | m_recordstream << std::flush; | ||
392 | 361 | break; | ||
393 | 362 | default: | ||
394 | 363 | // can't really do anything useful with this event | ||
395 | 364 | break; | ||
396 | 365 | } | ||
397 | 366 | } | ||
398 | 367 | catch (const std::ofstream::failure &) { | ||
399 | 368 | //TODO: use exception mask to find out what happened | ||
400 | 369 | //TODO: there should be a messagebox to tell the user. | ||
401 | 370 | log("Failed to write to record file. Recording deactivated.\n"); | ||
402 | 371 | stop_recording(); | ||
403 | 372 | throw Journalfile_error(m_recordname); | ||
404 | 373 | } | ||
405 | 374 | } | ||
406 | 375 | |||
407 | 376 | /** | ||
408 | 377 | * Get an event from the playback file. This entails creating an empty | ||
409 | 378 | * event with sensible default values (not all parameters get recorded) | ||
410 | 379 | * and deserializing the event record. | ||
411 | 380 | * | ||
412 | 381 | * \param e The event being returned | ||
413 | 382 | */ | ||
414 | 383 | bool Journal::read_event(SDL_Event & e) | ||
415 | 384 | { | ||
416 | 385 | if (!m_playback) | ||
417 | 386 | return false; | ||
418 | 387 | |||
419 | 388 | bool haveevent = false; | ||
420 | 389 | |||
421 | 390 | try { | ||
422 | 391 | uint8_t recordtype; | ||
423 | 392 | read(recordtype); | ||
424 | 393 | switch (recordtype) { | ||
425 | 394 | case RFC_EVENT: | ||
426 | 395 | uint8_t eventtype; | ||
427 | 396 | read(eventtype); | ||
428 | 397 | switch (eventtype) { | ||
429 | 398 | case RFC_KEYDOWN: | ||
430 | 399 | e.type = SDL_KEYDOWN; | ||
431 | 400 | read(e.key.keysym.mod); | ||
432 | 401 | read(e.key.keysym.sym); | ||
433 | 402 | read(e.key.keysym.unicode); | ||
434 | 403 | break; | ||
435 | 404 | case RFC_KEYUP: | ||
436 | 405 | e.type = SDL_KEYUP; | ||
437 | 406 | read(e.key.keysym.mod); | ||
438 | 407 | read(e.key.keysym.sym); | ||
439 | 408 | read(e.key.keysym.unicode); | ||
440 | 409 | break; | ||
441 | 410 | case RFC_MOUSEBUTTONDOWN: | ||
442 | 411 | e.type = SDL_MOUSEBUTTONDOWN; | ||
443 | 412 | read(e.button.button); | ||
444 | 413 | read(e.button.x); | ||
445 | 414 | read(e.button.y); | ||
446 | 415 | read(e.button.state); | ||
447 | 416 | break; | ||
448 | 417 | case RFC_MOUSEBUTTONUP: | ||
449 | 418 | e.type = SDL_MOUSEBUTTONUP; | ||
450 | 419 | read(e.button.button); | ||
451 | 420 | read(e.button.x); | ||
452 | 421 | read(e.button.y); | ||
453 | 422 | read(e.button.state); | ||
454 | 423 | break; | ||
455 | 424 | case RFC_MOUSEMOTION: | ||
456 | 425 | e.type = SDL_MOUSEMOTION; | ||
457 | 426 | read(e.motion.state); | ||
458 | 427 | read(e.motion.x); | ||
459 | 428 | read(e.motion.y); | ||
460 | 429 | read(e.motion.xrel); | ||
461 | 430 | read(e.motion.yrel); | ||
462 | 431 | break; | ||
463 | 432 | case RFC_QUIT: | ||
464 | 433 | e.type = SDL_QUIT; | ||
465 | 434 | break; | ||
466 | 435 | default: | ||
467 | 436 | throw BadEvent_error(m_playbackname, eventtype); | ||
468 | 437 | } | ||
469 | 438 | |||
470 | 439 | haveevent = true; | ||
471 | 440 | break; | ||
472 | 441 | case RFC_ENDEVENTS: | ||
473 | 442 | //Do nothing | ||
474 | 443 | break; | ||
475 | 444 | default: | ||
476 | 445 | throw BadRecord_error(m_playbackname, recordtype, RFC_INVALID); | ||
477 | 446 | break; | ||
478 | 447 | } | ||
479 | 448 | } catch (const std::ifstream::failure &) { | ||
480 | 449 | //TODO: use exception mask to find out what happened | ||
481 | 450 | //TODO: there should be a messagebox to tell the user. | ||
482 | 451 | log("Failed to read from journal file. Playback deactivated.\n"); | ||
483 | 452 | stop_playback(); | ||
484 | 453 | throw Journalfile_error(m_playbackname); | ||
485 | 454 | } | ||
486 | 455 | |||
487 | 456 | return haveevent; | ||
488 | 457 | } | ||
489 | 458 | |||
490 | 459 | /** | ||
491 | 460 | * Do the right thing with timestamps. | ||
492 | 461 | * All timestamps handled with \ref WLApplication::get_time() pass through here. | ||
493 | 462 | * If necessary, they will be recorded. On playback, they will be modified to | ||
494 | 463 | * show the recorded time instead of the current time. | ||
495 | 464 | */ | ||
496 | 465 | void Journal::timestamp_handler(uint32_t & stamp) | ||
497 | 466 | { | ||
498 | 467 | if (m_record) { | ||
499 | 468 | write(static_cast<uint8_t>(RFC_GETTIME)); | ||
500 | 469 | write(stamp); | ||
501 | 470 | } | ||
502 | 471 | |||
503 | 472 | if (m_playback) { | ||
504 | 473 | ensure_code(static_cast<uint8_t>(RFC_GETTIME)); | ||
505 | 474 | read(stamp); | ||
506 | 475 | } | ||
507 | 476 | } | ||
508 | 477 | |||
509 | 478 | /** | ||
510 | 479 | * \todo document me | ||
511 | 480 | */ | ||
512 | 481 | void Journal::set_idle_mark() | ||
513 | 482 | { | ||
514 | 483 | write(static_cast<uint8_t>(RFC_ENDEVENTS)); | ||
515 | 484 | } | ||
516 | 485 | 0 | ||
517 | === removed file 'src/journal.h' | |||
518 | --- src/journal.h 2013-07-26 19:16:51 +0000 | |||
519 | +++ src/journal.h 1970-01-01 00:00:00 +0000 | |||
520 | @@ -1,137 +0,0 @@ | |||
521 | 1 | /* | ||
522 | 2 | * Copyright (C) 2006-2009 by the Widelands Development Team | ||
523 | 3 | * | ||
524 | 4 | * This program is free software; you can redistribute it and/or | ||
525 | 5 | * modify it under the terms of the GNU General Public License | ||
526 | 6 | * as published by the Free Software Foundation; either version 2 | ||
527 | 7 | * of the License, or (at your option) any later version. | ||
528 | 8 | * | ||
529 | 9 | * This program is distributed in the hope that it will be useful, | ||
530 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
531 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
532 | 12 | * GNU General Public License for more details. | ||
533 | 13 | * | ||
534 | 14 | * You should have received a copy of the GNU General Public License | ||
535 | 15 | * along with this program; if not, write to the Free Software | ||
536 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
537 | 17 | * | ||
538 | 18 | */ | ||
539 | 19 | |||
540 | 20 | #ifndef JOURNAL_H | ||
541 | 21 | #define JOURNAL_H | ||
542 | 22 | |||
543 | 23 | #include <cstring> | ||
544 | 24 | #include <fstream> | ||
545 | 25 | #include <string> | ||
546 | 26 | |||
547 | 27 | #include <SDL_events.h> | ||
548 | 28 | |||
549 | 29 | #include "journal_exceptions.h" | ||
550 | 30 | |||
551 | 31 | /** | ||
552 | 32 | * Journal encapsulates all operations that are necessary for recording and | ||
553 | 33 | * playing back a session. On it's interface, it deals with SDL_Events that | ||
554 | 34 | * might (or might not) be recorded/played back. Whether a recording / playback | ||
555 | 35 | * is actually being performed is internal to Journal. | ||
556 | 36 | * | ||
557 | 37 | * \note If you are hacking this class, throw a Journalfile_exception only | ||
558 | 38 | * and always if there is a nonrecoverable error and you have already dealt with | ||
559 | 39 | * it. | ||
560 | 40 | * | ||
561 | 41 | * \todo The idea of writing enums into a file is bad: enums are int32_t and | ||
562 | 42 | * int32_t varies in size (typ. 32/64bit). Our own codes only need 8bit, so we | ||
563 | 43 | * force IO down to this value. The same happens with keyboard events at | ||
564 | 44 | * 32 bits. Cutting off bits is not a good solution, but in this case it'll do | ||
565 | 45 | * until a better way comes along. | ||
566 | 46 | */ | ||
567 | 47 | struct Journal { | ||
568 | 48 | /// change this and I will ensure your death will be a most unpleasant one | ||
569 | 49 | static uint32_t const RFC_MAGIC = 0x0ACAD100; | ||
570 | 50 | |||
571 | 51 | /** | ||
572 | 52 | * Record file codes | ||
573 | 53 | * It should be possible to use record files across different platforms. | ||
574 | 54 | * However, 64 bit platforms are currently not supported. | ||
575 | 55 | */ | ||
576 | 56 | enum rfccode { | ||
577 | 57 | RFC_GETTIME = 0x01, | ||
578 | 58 | RFC_EVENT = 0x02, | ||
579 | 59 | RFC_ENDEVENTS = 0x03, | ||
580 | 60 | |||
581 | 61 | RFC_KEYDOWN = 0x10, | ||
582 | 62 | RFC_KEYUP = 0x11, | ||
583 | 63 | RFC_MOUSEBUTTONDOWN = 0x12, | ||
584 | 64 | RFC_MOUSEBUTTONUP = 0x13, | ||
585 | 65 | RFC_MOUSEMOTION = 0x14, | ||
586 | 66 | RFC_QUIT = 0x15, | ||
587 | 67 | RFC_INVALID = 0xff | ||
588 | 68 | }; | ||
589 | 69 | |||
590 | 70 | public: | ||
591 | 71 | Journal(); | ||
592 | 72 | ~Journal(); | ||
593 | 73 | |||
594 | 74 | void start_recording(const std::string & filename = "widelands.jnl"); | ||
595 | 75 | void stop_recording(); | ||
596 | 76 | ///True if events are being recorded | ||
597 | 77 | bool is_recording() const {return m_record;} | ||
598 | 78 | |||
599 | 79 | void start_playback (const std::string & filename = "widelands.jnl"); | ||
600 | 80 | void stop_playback(); | ||
601 | 81 | ///True if events are being played back | ||
602 | 82 | bool is_playingback() const {return m_playback;} | ||
603 | 83 | |||
604 | 84 | void record_event(const SDL_Event &); | ||
605 | 85 | bool read_event(SDL_Event &); | ||
606 | 86 | |||
607 | 87 | void timestamp_handler(uint32_t & stamp); | ||
608 | 88 | void set_idle_mark(); | ||
609 | 89 | |||
610 | 90 | protected: | ||
611 | 91 | /** | ||
612 | 92 | * Returns the position in the playback file | ||
613 | 93 | * \return byte offset into the playback file, used with file reading | ||
614 | 94 | */ | ||
615 | 95 | int32_t get_playback_offset() {return m_playbackstream.tellg();} | ||
616 | 96 | |||
617 | 97 | void write(int8_t); | ||
618 | 98 | void write(uint8_t); | ||
619 | 99 | void write(int16_t); | ||
620 | 100 | void write(uint16_t); | ||
621 | 101 | void write(int32_t); | ||
622 | 102 | void write(uint32_t); | ||
623 | 103 | void write(SDLKey); | ||
624 | 104 | void write(SDLMod); | ||
625 | 105 | |||
626 | 106 | void read(int8_t &); | ||
627 | 107 | void read(uint8_t &); | ||
628 | 108 | void read(int16_t &); | ||
629 | 109 | void read(uint16_t &); | ||
630 | 110 | void read(int32_t &); | ||
631 | 111 | void read(uint32_t &); | ||
632 | 112 | void read(SDLKey &); | ||
633 | 113 | void read(SDLMod &); | ||
634 | 114 | void ensure_code(uint8_t code); | ||
635 | 115 | |||
636 | 116 | ///The recording file's name. | ||
637 | 117 | ///\note This does \e not go through the layered filesystem on purpose! | ||
638 | 118 | std::string m_recordname; | ||
639 | 119 | |||
640 | 120 | ///The playback file's name. | ||
641 | 121 | ///\note This does \e not go through the layered filesystem on purpose! | ||
642 | 122 | std::string m_playbackname; | ||
643 | 123 | |||
644 | 124 | ///The file events are being recorded to | ||
645 | 125 | std::ofstream m_recordstream; | ||
646 | 126 | |||
647 | 127 | ///The file events are being played back from | ||
648 | 128 | std::ifstream m_playbackstream; | ||
649 | 129 | |||
650 | 130 | ///True if events are being recorded | ||
651 | 131 | bool m_record; | ||
652 | 132 | |||
653 | 133 | ///True if events are being played back | ||
654 | 134 | bool m_playback; | ||
655 | 135 | }; | ||
656 | 136 | |||
657 | 137 | #endif | ||
658 | 138 | 0 | ||
659 | === removed file 'src/journal_exceptions.cc' | |||
660 | --- src/journal_exceptions.cc 2013-09-23 18:47:02 +0000 | |||
661 | +++ src/journal_exceptions.cc 1970-01-01 00:00:00 +0000 | |||
662 | @@ -1,59 +0,0 @@ | |||
663 | 1 | /* | ||
664 | 2 | * Copyright (C) 2006, 2008 by the Widelands Development Team | ||
665 | 3 | * | ||
666 | 4 | * This program is free software; you can redistribute it and/or | ||
667 | 5 | * modify it under the terms of the GNU General Public License | ||
668 | 6 | * as published by the Free Software Foundation; either version 2 | ||
669 | 7 | * of the License, or (at your option) any later version. | ||
670 | 8 | * | ||
671 | 9 | * This program is distributed in the hope that it will be useful, | ||
672 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
673 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
674 | 12 | * GNU General Public License for more details. | ||
675 | 13 | * | ||
676 | 14 | * You should have received a copy of the GNU General Public License | ||
677 | 15 | * along with this program; if not, write to the Free Software | ||
678 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
679 | 17 | * | ||
680 | 18 | */ | ||
681 | 19 | |||
682 | 20 | #include "journal_exceptions.h" | ||
683 | 21 | |||
684 | 22 | #include "helper.h" | ||
685 | 23 | |||
686 | 24 | Journalfile_error::Journalfile_error(const std::string & _filename) | ||
687 | 25 | : std::runtime_error("Problem with journal file."), filename(_filename) | ||
688 | 26 | { | ||
689 | 27 | text = "Problem with journal file " + _filename; | ||
690 | 28 | } | ||
691 | 29 | |||
692 | 30 | ///\todo Say _which_ magic number was found and which was expected | ||
693 | 31 | BadMagic_error::BadMagic_error(const std::string & _filename) | ||
694 | 32 | : Journalfile_error(_filename) | ||
695 | 33 | { | ||
696 | 34 | text = "Journal file " + _filename + " starts with bad magic number"; | ||
697 | 35 | } | ||
698 | 36 | |||
699 | 37 | BadRecord_error::BadRecord_error | ||
700 | 38 | (const std::string & _filename, | ||
701 | 39 | uint8_t const _code, | ||
702 | 40 | uint8_t const _expectedcode) | ||
703 | 41 | : Journalfile_error(_filename), offset(0), code(_code), expectedcode(_expectedcode) | ||
704 | 42 | { | ||
705 | 43 | text = "Journal file "; | ||
706 | 44 | text += _filename; | ||
707 | 45 | text += " contains record with type "; | ||
708 | 46 | text += toString(static_cast<int>(_code)); | ||
709 | 47 | text += " instead of the expected type "; | ||
710 | 48 | text += toString(static_cast<int>(_expectedcode)); | ||
711 | 49 | } | ||
712 | 50 | |||
713 | 51 | BadEvent_error::BadEvent_error | ||
714 | 52 | (const std::string & _filename, uint8_t const _type) | ||
715 | 53 | : Journalfile_error(_filename), offset(0), type(_type) | ||
716 | 54 | { | ||
717 | 55 | text = "Journal file '"; | ||
718 | 56 | text += _filename; | ||
719 | 57 | text += "' contains record with unknown event type "; | ||
720 | 58 | text += toString(_type); | ||
721 | 59 | } | ||
722 | 60 | 0 | ||
723 | === removed file 'src/journal_exceptions.h' | |||
724 | --- src/journal_exceptions.h 2014-02-22 18:04:02 +0000 | |||
725 | +++ src/journal_exceptions.h 1970-01-01 00:00:00 +0000 | |||
726 | @@ -1,90 +0,0 @@ | |||
727 | 1 | /* | ||
728 | 2 | * Copyright (C) 2006, 2008-2009 by the Widelands Development Team | ||
729 | 3 | * | ||
730 | 4 | * This program is free software; you can redistribute it and/or | ||
731 | 5 | * modify it under the terms of the GNU General Public License | ||
732 | 6 | * as published by the Free Software Foundation; either version 2 | ||
733 | 7 | * of the License, or (at your option) any later version. | ||
734 | 8 | * | ||
735 | 9 | * This program is distributed in the hope that it will be useful, | ||
736 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
737 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
738 | 12 | * GNU General Public License for more details. | ||
739 | 13 | * | ||
740 | 14 | * You should have received a copy of the GNU General Public License | ||
741 | 15 | * along with this program; if not, write to the Free Software | ||
742 | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
743 | 17 | * | ||
744 | 18 | */ | ||
745 | 19 | |||
746 | 20 | #ifndef JOURNAL_EXCEPTIONS_H | ||
747 | 21 | #define JOURNAL_EXCEPTIONS_H | ||
748 | 22 | |||
749 | 23 | #include <stdexcept> | ||
750 | 24 | #include <string> | ||
751 | 25 | |||
752 | 26 | #include <stdint.h> | ||
753 | 27 | |||
754 | 28 | /// | ||
755 | 29 | /// Thrown for IO-errors occurring with a journal file (unable to open file | ||
756 | 30 | /// for any reason, out of space, etc.) that a) are unrecoverable and b) | ||
757 | 31 | /// have already been dealt with. | ||
758 | 32 | /// | ||
759 | 33 | /// This is a purely informational exception. Do not throw it unless it can | ||
760 | 34 | /// safely be ignored. | ||
761 | 35 | /// | ||
762 | 36 | /// \todo add offset into journal file if applicable | ||
763 | 37 | /// \todo Rework as proposed by Erik, see filesystem_exceptions.h. Before that: | ||
764 | 38 | /// Replace with File*_error where appropriate, migrate from runtime_error to | ||
765 | 39 | /// logic_error (?) | ||
766 | 40 | struct Journalfile_error : public std::runtime_error { | ||
767 | 41 | explicit Journalfile_error(const std::string & filename); | ||
768 | 42 | virtual ~Journalfile_error() throw () {} | ||
769 | 43 | |||
770 | 44 | virtual char const * what() const throw () override {return text.c_str();} | ||
771 | 45 | |||
772 | 46 | std::string text; | ||
773 | 47 | std::string filename; | ||
774 | 48 | }; | ||
775 | 49 | |||
776 | 50 | /** | ||
777 | 51 | * Thrown if the journal file contains a bad magic number | ||
778 | 52 | * \todo add offset into journal file | ||
779 | 53 | */ | ||
780 | 54 | struct BadMagic_error : public Journalfile_error { | ||
781 | 55 | explicit BadMagic_error(const std::string & filename); | ||
782 | 56 | virtual ~BadMagic_error() throw () {} | ||
783 | 57 | }; | ||
784 | 58 | |||
785 | 59 | /** | ||
786 | 60 | * Thrown if the journal file contains a record with an unknown type number | ||
787 | 61 | * \todo add offset into journal file | ||
788 | 62 | */ | ||
789 | 63 | struct BadRecord_error : public Journalfile_error { | ||
790 | 64 | explicit BadRecord_error | ||
791 | 65 | (const std::string & filename, | ||
792 | 66 | const uint8_t code, | ||
793 | 67 | const uint8_t expectedcode) | ||
794 | 68 | ; | ||
795 | 69 | virtual ~BadRecord_error() throw () {} | ||
796 | 70 | |||
797 | 71 | std::streamoff offset; | ||
798 | 72 | uint8_t code; | ||
799 | 73 | uint8_t expectedcode; | ||
800 | 74 | }; | ||
801 | 75 | |||
802 | 76 | /** | ||
803 | 77 | * Thrown if the journal file contains an event record with an unknown | ||
804 | 78 | * event type | ||
805 | 79 | * \todo add offset into journal file | ||
806 | 80 | */ | ||
807 | 81 | struct BadEvent_error : public Journalfile_error { | ||
808 | 82 | explicit BadEvent_error(const std::string & filename, uint8_t const type) | ||
809 | 83 | ; | ||
810 | 84 | virtual ~BadEvent_error() throw () {} | ||
811 | 85 | |||
812 | 86 | std::streamoff offset; | ||
813 | 87 | uint8_t type; | ||
814 | 88 | }; | ||
815 | 89 | |||
816 | 90 | #endif | ||
817 | 91 | 0 | ||
818 | === modified file 'src/wlapplication.cc' | |||
819 | --- src/wlapplication.cc 2014-03-09 10:28:39 +0000 | |||
820 | +++ src/wlapplication.cc 2014-03-11 20:49:20 +0000 | |||
821 | @@ -48,7 +48,6 @@ | |||
822 | 48 | #include "io/dedicated_log.h" | 48 | #include "io/dedicated_log.h" |
823 | 49 | #include "io/filesystem/disk_filesystem.h" | 49 | #include "io/filesystem/disk_filesystem.h" |
824 | 50 | #include "io/filesystem/layered_filesystem.h" | 50 | #include "io/filesystem/layered_filesystem.h" |
825 | 51 | #include "journal.h" | ||
826 | 52 | #include "log.h" | 51 | #include "log.h" |
827 | 53 | #include "logic/game.h" | 52 | #include "logic/game.h" |
828 | 54 | #include "logic/game_data_error.h" | 53 | #include "logic/game_data_error.h" |
829 | @@ -248,7 +247,6 @@ | |||
830 | 248 | WLApplication::WLApplication(int const argc, char const * const * const argv) : | 247 | WLApplication::WLApplication(int const argc, char const * const * const argv) : |
831 | 249 | m_commandline (std::map<std::string, std::string>()), | 248 | m_commandline (std::map<std::string, std::string>()), |
832 | 250 | m_game_type (NONE), | 249 | m_game_type (NONE), |
833 | 251 | journal (nullptr), | ||
834 | 252 | m_mouse_swapped (false), | 250 | m_mouse_swapped (false), |
835 | 253 | m_faking_middle_mouse_button(false), | 251 | m_faking_middle_mouse_button(false), |
836 | 254 | m_mouse_position (0, 0), | 252 | m_mouse_position (0, 0), |
837 | @@ -480,158 +478,53 @@ | |||
838 | 480 | 478 | ||
839 | 481 | /** | 479 | /** |
840 | 482 | * Get an event from the SDL queue, just like SDL_PollEvent. | 480 | * Get an event from the SDL queue, just like SDL_PollEvent. |
841 | 483 | * Perform the meat of playback/record stuff when needed. | ||
842 | 484 | * | ||
843 | 485 | * Throttle is a hack to stop record files from getting extremely huge. | ||
844 | 486 | * If it is set to true, we will idle loop if we can't get an SDL_Event | ||
845 | 487 | * returned immediately if we're recording. If there is no user input, | ||
846 | 488 | * the actual mainloop will be throttled to 100fps. | ||
847 | 489 | * | 481 | * |
848 | 490 | * \param ev the retrieved event will be put here | 482 | * \param ev the retrieved event will be put here |
849 | 491 | * \param throttle Limit recording to 100fps max (not the event loop itself!) | ||
850 | 492 | * | 483 | * |
851 | 493 | * \return true if an event was returned inside ev, false otherwise | 484 | * \return true if an event was returned inside ev, false otherwise |
852 | 494 | * | ||
853 | 495 | * \todo Catch Journalfile_error | ||
854 | 496 | */ | 485 | */ |
940 | 497 | bool WLApplication::poll_event(SDL_Event & ev, bool const throttle) { | 486 | bool WLApplication::poll_event(SDL_Event& ev) { |
941 | 498 | bool haveevent = false; | 487 | if (!SDL_PollEvent(&ev)) { |
942 | 499 | 488 | return false; | |
943 | 500 | restart: | 489 | } |
944 | 501 | //inject synthesized events into the event queue when playing back | 490 | |
945 | 502 | if (journal->is_playingback()) { | 491 | // We edit mouse motion events in here, so that |
946 | 503 | try { | 492 | // differences caused by GrabInput or mouse speed |
947 | 504 | haveevent = journal->read_event(ev); | 493 | // settings are invisible to the rest of the code |
948 | 505 | } catch (const Journalfile_error & e) { | 494 | switch (ev.type) { |
949 | 506 | // An error might occur here when playing back a file that | 495 | case SDL_MOUSEMOTION: |
950 | 507 | // was not finalized due to a crash etc. | 496 | ev.motion.xrel += m_mouse_compensate_warp.x; |
951 | 508 | // Since playbacks are intended precisely for debugging such | 497 | ev.motion.yrel += m_mouse_compensate_warp.y; |
952 | 509 | // crashes, we must ignore the error and continue. | 498 | m_mouse_compensate_warp = Point(0, 0); |
953 | 510 | log("JOURNAL: read error, continue without playback: %s\n", e.what()); | 499 | |
954 | 511 | journal->stop_playback(); | 500 | if (m_mouse_locked) { |
955 | 512 | } | 501 | warp_mouse(m_mouse_position); |
956 | 513 | } else { | 502 | |
957 | 514 | haveevent = SDL_PollEvent(&ev); | 503 | ev.motion.x = m_mouse_position.x; |
958 | 515 | 504 | ev.motion.y = m_mouse_position.y; | |
959 | 516 | if (haveevent) { | 505 | } |
960 | 517 | // We edit mouse motion events in here, so that | 506 | break; |
961 | 518 | // differences caused by GrabInput or mouse speed | 507 | |
962 | 519 | // settings are invisible to the rest of the code | 508 | case SDL_USEREVENT: |
963 | 520 | switch (ev.type) { | 509 | if (ev.user.code == CHANGE_MUSIC) |
964 | 521 | case SDL_MOUSEMOTION: | 510 | g_sound_handler.change_music(); |
965 | 522 | ev.motion.xrel += m_mouse_compensate_warp.x; | 511 | break; |
966 | 523 | ev.motion.yrel += m_mouse_compensate_warp.y; | 512 | |
967 | 524 | m_mouse_compensate_warp = Point(0, 0); | 513 | case SDL_VIDEOEXPOSE: |
968 | 525 | 514 | // log ("SDL Video Window expose event: %i\n", ev.expose.type); | |
969 | 526 | if (m_mouse_locked) { | 515 | g_gr->update_fullscreen(); |
970 | 527 | warp_mouse(m_mouse_position); | 516 | break; |
971 | 528 | 517 | } | |
972 | 529 | ev.motion.x = m_mouse_position.x; | 518 | return true; |
888 | 530 | ev.motion.y = m_mouse_position.y; | ||
889 | 531 | } | ||
890 | 532 | |||
891 | 533 | break; | ||
892 | 534 | case SDL_USEREVENT: | ||
893 | 535 | if (ev.user.code == CHANGE_MUSIC) | ||
894 | 536 | g_sound_handler.change_music(); | ||
895 | 537 | |||
896 | 538 | break; | ||
897 | 539 | case SDL_VIDEOEXPOSE: | ||
898 | 540 | //log ("SDL Video Window expose event: %i\n", ev.expose.type); | ||
899 | 541 | g_gr->update_fullscreen(); | ||
900 | 542 | break; | ||
901 | 543 | default:; | ||
902 | 544 | } | ||
903 | 545 | } | ||
904 | 546 | } | ||
905 | 547 | |||
906 | 548 | // log all events into the journal file | ||
907 | 549 | if (journal->is_recording()) { | ||
908 | 550 | if (haveevent) | ||
909 | 551 | journal->record_event(ev); | ||
910 | 552 | else if (throttle && journal->is_playingback()) { | ||
911 | 553 | // Implement the throttle to avoid very quick inner mainloops when | ||
912 | 554 | // recoding a session | ||
913 | 555 | static int32_t lastthrottle = 0; | ||
914 | 556 | int32_t const time = SDL_GetTicks(); | ||
915 | 557 | |||
916 | 558 | if (time - lastthrottle < 10) | ||
917 | 559 | goto restart; | ||
918 | 560 | |||
919 | 561 | lastthrottle = time; | ||
920 | 562 | } | ||
921 | 563 | |||
922 | 564 | journal->set_idle_mark(); | ||
923 | 565 | } else if (haveevent) { | ||
924 | 566 | // Eliminate any unhandled events to make sure that record and playback | ||
925 | 567 | // are _really_ the same. Yes I know, it's overly paranoid but hey... | ||
926 | 568 | switch (ev.type) { | ||
927 | 569 | case SDL_KEYDOWN: | ||
928 | 570 | case SDL_KEYUP: | ||
929 | 571 | case SDL_MOUSEBUTTONDOWN: | ||
930 | 572 | case SDL_MOUSEBUTTONUP: | ||
931 | 573 | case SDL_MOUSEMOTION: | ||
932 | 574 | case SDL_QUIT: | ||
933 | 575 | break; | ||
934 | 576 | default: | ||
935 | 577 | goto restart; | ||
936 | 578 | } | ||
937 | 579 | } | ||
938 | 580 | |||
939 | 581 | return haveevent; | ||
973 | 582 | } | 519 | } |
974 | 583 | 520 | ||
975 | 584 | |||
976 | 585 | /** | 521 | /** |
977 | 586 | * Pump the event queue, get packets from the network, etc... | 522 | * Pump the event queue, get packets from the network, etc... |
978 | 587 | */ | 523 | */ |
979 | 588 | void WLApplication::handle_input(InputCallback const * cb) | 524 | void WLApplication::handle_input(InputCallback const * cb) |
980 | 589 | { | 525 | { |
1026 | 590 | bool gotevents = false; | 526 | SDL_Event ev; |
1027 | 591 | SDL_Event ev; // Valgrind says: | 527 | while (poll_event(ev)) { |
983 | 592 | // Conditional jump or move depends on uninitialised value(s) | ||
984 | 593 | // at 0x407EEDA: (within /usr/lib/libSDL-1.2.so.0.11.0) | ||
985 | 594 | // by 0x407F78F: (within /usr/lib/libSDL-1.2.so.0.11.0) | ||
986 | 595 | // by 0x404FB12: SDL_PumpEvents (in /usr/lib/libSDL-1.2.so.0.11.0) | ||
987 | 596 | // by 0x404FFC3: SDL_PollEvent (in /usr/lib/libSDL-1.2.so.0.11.0) | ||
988 | 597 | // by 0x8252545: WLApplication::poll_event(SDL_Event*, bool) | ||
989 | 598 | // (wlapplication.cc:309) | ||
990 | 599 | // by 0x8252EB6: WLApplication::handle_input(InputCallback const*) | ||
991 | 600 | // (wlapplication.cc:459) by 0x828B56E: UI::Panel::run() (ui_panel.cc:148) | ||
992 | 601 | // by 0x8252FAB: WLApplication::run() (wlapplication.cc:212) | ||
993 | 602 | // by 0x81427A6: main (main.cc:39) | ||
994 | 603 | |||
995 | 604 | // We need to empty the SDL message queue always, even in playback mode | ||
996 | 605 | // In playback mode, only F10 for premature exiting works | ||
997 | 606 | if (journal->is_playingback()) { | ||
998 | 607 | while (SDL_PollEvent(&ev)) { | ||
999 | 608 | switch (ev.type) { | ||
1000 | 609 | case SDL_KEYDOWN: | ||
1001 | 610 | // get out of here quickly, overriding playback; | ||
1002 | 611 | // since this is the only key event that works, we don't guard | ||
1003 | 612 | // it by requiring Ctrl to be pressed. | ||
1004 | 613 | if (ev.key.keysym.sym == SDLK_F10) | ||
1005 | 614 | m_should_die = true; | ||
1006 | 615 | break; | ||
1007 | 616 | case SDL_QUIT: | ||
1008 | 617 | m_should_die = true; | ||
1009 | 618 | break; | ||
1010 | 619 | default:; | ||
1011 | 620 | } | ||
1012 | 621 | } | ||
1013 | 622 | } | ||
1014 | 623 | |||
1015 | 624 | // Usual event queue | ||
1016 | 625 | while (poll_event(ev, !gotevents)) { | ||
1017 | 626 | |||
1018 | 627 | gotevents = true; | ||
1019 | 628 | |||
1020 | 629 | // CAREFUL: Record files do not save the entire SDL_Event structure. | ||
1021 | 630 | // Therefore, playbacks are incomplete. When you change the following | ||
1022 | 631 | // code so that it uses previously unused fields in SDL_Event, | ||
1023 | 632 | // please also take a look at Journal::read_event and | ||
1024 | 633 | // Journal::record_event | ||
1025 | 634 | |||
1028 | 635 | switch (ev.type) { | 528 | switch (ev.type) { |
1029 | 636 | case SDL_KEYDOWN: | 529 | case SDL_KEYDOWN: |
1030 | 637 | case SDL_KEYUP: | 530 | case SDL_KEYUP: |
1031 | @@ -747,9 +640,6 @@ | |||
1032 | 747 | int32_t WLApplication::get_time() { | 640 | int32_t WLApplication::get_time() { |
1033 | 748 | uint32_t time = SDL_GetTicks(); | 641 | uint32_t time = SDL_GetTicks(); |
1034 | 749 | 642 | ||
1035 | 750 | // might change the time when playing back! | ||
1036 | 751 | journal->timestamp_handler(time); | ||
1037 | 752 | |||
1038 | 753 | return time; | 643 | return time; |
1039 | 754 | } | 644 | } |
1040 | 755 | 645 | ||
1041 | @@ -758,20 +648,17 @@ | |||
1042 | 758 | /// SDL_WarpMouse() *will* create a mousemotion event, which we do not want. As | 648 | /// SDL_WarpMouse() *will* create a mousemotion event, which we do not want. As |
1043 | 759 | /// a workaround, we store the delta in m_mouse_compensate_warp and use that to | 649 | /// a workaround, we store the delta in m_mouse_compensate_warp and use that to |
1044 | 760 | /// eliminate the motion event in poll_event() | 650 | /// eliminate the motion event in poll_event() |
1045 | 761 | /// \todo Should this method have to care about playback at all??? | ||
1046 | 762 | /// | 651 | /// |
1047 | 763 | /// \param position The new mouse position | 652 | /// \param position The new mouse position |
1048 | 764 | void WLApplication::warp_mouse(const Point position) | 653 | void WLApplication::warp_mouse(const Point position) |
1049 | 765 | { | 654 | { |
1050 | 766 | m_mouse_position = position; | 655 | m_mouse_position = position; |
1051 | 767 | 656 | ||
1059 | 768 | if (not journal->is_playingback()) { // don't warp anything during playback | 657 | Point cur_position; |
1060 | 769 | Point cur_position; | 658 | SDL_GetMouseState(&cur_position.x, &cur_position.y); |
1061 | 770 | SDL_GetMouseState(&cur_position.x, &cur_position.y); | 659 | if (cur_position != position) { |
1062 | 771 | if (cur_position != position) { | 660 | m_mouse_compensate_warp += cur_position - position; |
1063 | 772 | m_mouse_compensate_warp += cur_position - position; | 661 | SDL_WarpMouse(position.x, position.y); |
1057 | 773 | SDL_WarpMouse(position.x, position.y); | ||
1058 | 774 | } | ||
1064 | 775 | } | 662 | } |
1065 | 776 | } | 663 | } |
1066 | 777 | 664 | ||
1067 | @@ -786,9 +673,6 @@ | |||
1068 | 786 | */ | 673 | */ |
1069 | 787 | void WLApplication::set_input_grab(bool grab) | 674 | void WLApplication::set_input_grab(bool grab) |
1070 | 788 | { | 675 | { |
1071 | 789 | if (journal->is_playingback()) | ||
1072 | 790 | return; // ignore in playback mode | ||
1073 | 791 | |||
1074 | 792 | if (grab) { | 676 | if (grab) { |
1075 | 793 | SDL_WM_GrabInput(SDL_GRAB_ON); | 677 | SDL_WM_GrabInput(SDL_GRAB_ON); |
1076 | 794 | } else { | 678 | } else { |
1077 | @@ -842,10 +726,6 @@ | |||
1078 | 842 | */ | 726 | */ |
1079 | 843 | bool WLApplication::init_settings() { | 727 | bool WLApplication::init_settings() { |
1080 | 844 | 728 | ||
1081 | 845 | //create a journal so that handle_commandline_parameters can open the | ||
1082 | 846 | //journal files | ||
1083 | 847 | journal = new Journal(); | ||
1084 | 848 | |||
1085 | 849 | //read in the configuration file | 729 | //read in the configuration file |
1086 | 850 | g_options.read("config", "global"); | 730 | g_options.read("config", "global"); |
1087 | 851 | Section & s = g_options.pull_section("global"); | 731 | Section & s = g_options.pull_section("global"); |
1088 | @@ -927,10 +807,6 @@ | |||
1089 | 927 | } catch (...) { | 807 | } catch (...) { |
1090 | 928 | log("WARNING: could not save configuration"); | 808 | log("WARNING: could not save configuration"); |
1091 | 929 | } | 809 | } |
1092 | 930 | |||
1093 | 931 | assert(journal); | ||
1094 | 932 | delete journal; | ||
1095 | 933 | journal = nullptr; | ||
1096 | 934 | } | 810 | } |
1097 | 935 | 811 | ||
1098 | 936 | /** | 812 | /** |
1099 | @@ -1280,34 +1156,6 @@ | |||
1100 | 1280 | m_commandline.erase("script"); | 1156 | m_commandline.erase("script"); |
1101 | 1281 | } | 1157 | } |
1102 | 1282 | 1158 | ||
1103 | 1283 | // TODO(sirver): this framework has not been useful in a long time. Kill it. | ||
1104 | 1284 | if (m_commandline.count("record")) { | ||
1105 | 1285 | if (m_commandline["record"].empty()) | ||
1106 | 1286 | throw Parameter_error("ERROR: --record needs a filename!"); | ||
1107 | 1287 | |||
1108 | 1288 | try { | ||
1109 | 1289 | journal->start_recording(m_commandline["record"]); | ||
1110 | 1290 | } catch (Journalfile_error & e) { | ||
1111 | 1291 | wout << "Journal file error: " << e.what() << endl; | ||
1112 | 1292 | } | ||
1113 | 1293 | |||
1114 | 1294 | m_commandline.erase("record"); | ||
1115 | 1295 | } | ||
1116 | 1296 | |||
1117 | 1297 | if (m_commandline.count("playback")) { | ||
1118 | 1298 | if (m_commandline["playback"].empty()) | ||
1119 | 1299 | throw Parameter_error("ERROR: --playback needs a filename!"); | ||
1120 | 1300 | |||
1121 | 1301 | try { | ||
1122 | 1302 | journal->start_playback(m_commandline["playback"]); | ||
1123 | 1303 | } | ||
1124 | 1304 | catch (Journalfile_error & e) { | ||
1125 | 1305 | wout << "Journal file error: " << e.what() << endl; | ||
1126 | 1306 | } | ||
1127 | 1307 | |||
1128 | 1308 | m_commandline.erase("playback"); | ||
1129 | 1309 | } | ||
1130 | 1310 | |||
1131 | 1311 | //If it hasn't been handled yet it's probably an attempt to | 1159 | //If it hasn't been handled yet it's probably an attempt to |
1132 | 1312 | //override a conffile setting | 1160 | //override a conffile setting |
1133 | 1313 | //With typos, this will create invalid config settings. They | 1161 | //With typos, this will create invalid config settings. They |
1134 | @@ -1351,9 +1199,7 @@ | |||
1135 | 1351 | #ifdef __linux__ | 1199 | #ifdef __linux__ |
1136 | 1352 | << _(" Default is ~/.widelands") << "\n" | 1200 | << _(" Default is ~/.widelands") << "\n" |
1137 | 1353 | #endif | 1201 | #endif |
1141 | 1354 | << _(" --record=FILENAME Record all events to the given filename for\n" | 1202 | << "\n" |
1139 | 1355 | " later playback") << "\n" | ||
1140 | 1356 | << _(" --playback=FILENAME Playback given filename (see --record)") << "\n\n" | ||
1142 | 1357 | << _(" --coredump=[yes|no] Generates a core dump on segfaults instead\n" | 1203 | << _(" --coredump=[yes|no] Generates a core dump on segfaults instead\n" |
1143 | 1358 | " of using the SDL") << "\n" | 1204 | " of using the SDL") << "\n" |
1144 | 1359 | << _(" --language=[de_DE|sv_SE|...]\n" | 1205 | << _(" --language=[de_DE|sv_SE|...]\n" |
1145 | 1360 | 1206 | ||
1146 | === modified file 'src/wlapplication.h' | |||
1147 | --- src/wlapplication.h 2014-02-22 18:04:02 +0000 | |||
1148 | +++ src/wlapplication.h 2014-03-11 20:49:20 +0000 | |||
1149 | @@ -38,7 +38,6 @@ | |||
1150 | 38 | 38 | ||
1151 | 39 | 39 | ||
1152 | 40 | namespace Widelands {class Game;} | 40 | namespace Widelands {class Game;} |
1153 | 41 | struct Journal; | ||
1154 | 42 | 41 | ||
1155 | 43 | ///Thrown if a commandline parameter is faulty | 42 | ///Thrown if a commandline parameter is faulty |
1156 | 44 | struct Parameter_error : public std::runtime_error { | 43 | struct Parameter_error : public std::runtime_error { |
1157 | @@ -233,7 +232,7 @@ | |||
1158 | 233 | protected: | 232 | protected: |
1159 | 234 | WLApplication(int argc, char const * const * argv); | 233 | WLApplication(int argc, char const * const * argv); |
1160 | 235 | 234 | ||
1162 | 236 | bool poll_event(SDL_Event &, bool throttle); | 235 | bool poll_event(SDL_Event &); |
1163 | 237 | 236 | ||
1164 | 238 | bool init_settings(); | 237 | bool init_settings(); |
1165 | 239 | void init_language(); | 238 | void init_language(); |
1166 | @@ -271,8 +270,6 @@ | |||
1167 | 271 | std::string m_logfile; | 270 | std::string m_logfile; |
1168 | 272 | 271 | ||
1169 | 273 | GameType m_game_type; | 272 | GameType m_game_type; |
1170 | 274 | ///the event recorder object | ||
1171 | 275 | Journal * journal; | ||
1172 | 276 | 273 | ||
1173 | 277 | ///True if left and right mouse button should be swapped | 274 | ///True if left and right mouse button should be swapped |
1174 | 278 | bool m_mouse_swapped; | 275 | bool m_mouse_swapped; |
looks good to me. I added one revision adressing all the FIXMEs. hjd, if you are happy with my changes we can merge this imho.