]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/framework/EventLoop.cpp
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / framework / EventLoop.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31
32 idCVar idEventLoop::com_journal( "com_journal", "0", CVAR_INIT|CVAR_SYSTEM, "1 = record journal, 2 = play back journal", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
33
34 idEventLoop eventLoopLocal;
35 idEventLoop *eventLoop = &eventLoopLocal;
36
37
38 /*
39 =================
40 idEventLoop::idEventLoop
41 =================
42 */
43 idEventLoop::idEventLoop( void ) {
44         com_journalFile = NULL;
45         com_journalDataFile = NULL;
46         initialTimeOffset = 0;
47 }
48
49 /*
50 =================
51 idEventLoop::~idEventLoop
52 =================
53 */
54 idEventLoop::~idEventLoop( void ) {
55 }
56
57 /*
58 =================
59 idEventLoop::GetRealEvent
60 =================
61 */
62 sysEvent_t      idEventLoop::GetRealEvent( void ) {
63         int                     r;
64         sysEvent_t      ev;
65
66         // either get an event from the system or the journal file
67         if ( com_journal.GetInteger() == 2 ) {
68                 r = com_journalFile->Read( &ev, sizeof(ev) );
69                 if ( r != sizeof(ev) ) {
70                         common->FatalError( "Error reading from journal file" );
71                 }
72                 if ( ev.evPtrLength ) {
73                         ev.evPtr = Mem_ClearedAlloc( ev.evPtrLength );
74                         r = com_journalFile->Read( ev.evPtr, ev.evPtrLength );
75                         if ( r != ev.evPtrLength ) {
76                                 common->FatalError( "Error reading from journal file" );
77                         }
78                 }
79         } else {
80                 ev = Sys_GetEvent();
81
82                 // write the journal value out if needed
83                 if ( com_journal.GetInteger() == 1 ) {
84                         r = com_journalFile->Write( &ev, sizeof(ev) );
85                         if ( r != sizeof(ev) ) {
86                                 common->FatalError( "Error writing to journal file" );
87                         }
88                         if ( ev.evPtrLength ) {
89                                 r = com_journalFile->Write( ev.evPtr, ev.evPtrLength );
90                                 if ( r != ev.evPtrLength ) {
91                                         common->FatalError( "Error writing to journal file" );
92                                 }
93                         }
94                 }
95         }
96
97         return ev;
98 }
99
100 /*
101 =================
102 idEventLoop::PushEvent
103 =================
104 */
105 void idEventLoop::PushEvent( sysEvent_t *event ) {
106         sysEvent_t              *ev;
107         static                  bool printedWarning;
108
109         ev = &com_pushedEvents[ com_pushedEventsHead & (MAX_PUSHED_EVENTS-1) ];
110
111         if ( com_pushedEventsHead - com_pushedEventsTail >= MAX_PUSHED_EVENTS ) {
112
113                 // don't print the warning constantly, or it can give time for more...
114                 if ( !printedWarning ) {
115                         printedWarning = true;
116                         common->Printf( "WARNING: Com_PushEvent overflow\n" );
117                 }
118
119                 if ( ev->evPtr ) {
120                         Mem_Free( ev->evPtr );
121                 }
122                 com_pushedEventsTail++;
123         } else {
124                 printedWarning = false;
125         }
126
127         *ev = *event;
128         com_pushedEventsHead++;
129 }
130
131 /*
132 =================
133 idEventLoop::GetEvent
134 =================
135 */
136 sysEvent_t idEventLoop::GetEvent( void ) {
137         if ( com_pushedEventsHead > com_pushedEventsTail ) {
138                 com_pushedEventsTail++;
139                 return com_pushedEvents[ (com_pushedEventsTail-1) & (MAX_PUSHED_EVENTS-1) ];
140         }
141         return GetRealEvent();
142 }
143
144 /*
145 =================
146 idEventLoop::ProcessEvent
147 =================
148 */
149 void idEventLoop::ProcessEvent( sysEvent_t ev ) {
150         // track key up / down states
151         if ( ev.evType == SE_KEY ) {
152                 idKeyInput::PreliminaryKeyEvent( ev.evValue, ( ev.evValue2 != 0 ) );
153         }
154
155         if ( ev.evType == SE_CONSOLE ) {
156                 // from a text console outside the game window
157                 cmdSystem->BufferCommandText( CMD_EXEC_APPEND, (char *)ev.evPtr );
158                 cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "\n" );
159         } else {
160                 session->ProcessEvent( &ev );
161         }
162
163         // free any block data
164         if ( ev.evPtr ) {
165                 Mem_Free( ev.evPtr );
166         }
167 }
168
169 /*
170 ===============
171 idEventLoop::RunEventLoop
172 ===============
173 */
174 int idEventLoop::RunEventLoop( bool commandExecution ) {
175         sysEvent_t      ev;
176
177         while ( 1 ) {
178
179                 if ( commandExecution ) {
180                         // execute any bound commands before processing another event
181                         cmdSystem->ExecuteCommandBuffer();
182                 }
183
184                 ev = GetEvent();
185
186                 // if no more events are available
187                 if ( ev.evType == SE_NONE ) {
188                         return 0;
189                 }
190                 ProcessEvent( ev );
191         }
192
193         return 0;       // never reached
194 }
195
196 /*
197 =============
198 idEventLoop::Init
199 =============
200 */
201 void idEventLoop::Init( void ) {
202
203         initialTimeOffset = Sys_Milliseconds();
204
205         common->StartupVariable( "journal", false );
206
207         if ( com_journal.GetInteger() == 1 ) {
208                 common->Printf( "Journaling events\n" );
209                 com_journalFile = fileSystem->OpenFileWrite( "journal.dat" );
210                 com_journalDataFile = fileSystem->OpenFileWrite( "journaldata.dat" );
211         } else if ( com_journal.GetInteger() == 2 ) {
212                 common->Printf( "Replaying journaled events\n" );
213                 com_journalFile = fileSystem->OpenFileRead( "journal.dat" );
214                 com_journalDataFile = fileSystem->OpenFileRead( "journaldata.dat" );
215         }
216
217         if ( !com_journalFile || !com_journalDataFile ) {
218                 com_journal.SetInteger( 0 );
219                 com_journalFile = 0;
220                 com_journalDataFile = 0;
221                 common->Printf( "Couldn't open journal files\n" );
222         }
223 }
224
225 /*
226 =============
227 idEventLoop::Shutdown
228 =============
229 */
230 void idEventLoop::Shutdown( void ) {
231         if ( com_journalFile ) {
232                 fileSystem->CloseFile( com_journalFile );
233                 com_journalFile = NULL;
234         }
235         if ( com_journalDataFile ) {
236                 fileSystem->CloseFile( com_journalDataFile );
237                 com_journalDataFile = NULL;
238         }
239 }
240
241 /*
242 ================
243 idEventLoop::Milliseconds
244
245 Can be used for profiling, but will be journaled accurately
246 ================
247 */
248 int idEventLoop::Milliseconds( void ) {
249 #if 1   // FIXME!
250         return Sys_Milliseconds() - initialTimeOffset;
251 #else
252         sysEvent_t      ev;
253
254         // get events and push them until we get a null event with the current time
255         do {
256
257                 ev = Com_GetRealEvent();
258                 if ( ev.evType != SE_NONE ) {
259                         Com_PushEvent( &ev );
260                 }
261         } while ( ev.evType != SE_NONE );
262         
263         return ev.evTime;
264 #endif
265 }
266
267 /*
268 ================
269 idEventLoop::JournalLevel
270 ================
271 */
272 int idEventLoop::JournalLevel( void ) const {
273         return com_journal.GetInteger();
274 }