|
|
1.1 root 1: /*
2: Hatari - statusbar.c
3:
1.1.1.8 ! root 4: This file is distributed under the GNU General Public License, version 2
! 5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 6:
7: Code to draw statusbar area, floppy leds etc.
1.1.1.3 root 8:
1.1 root 9: Use like this:
10: - Before screen surface is (re-)created Statusbar_SetHeight()
11: has to be called with the new screen height. Add the returned
12: value to screen height (zero means no statusbar). After this,
13: Statusbar_GetHeight() can be used to retrieve the statusbar size
14: - After screen surface is (re-)created, call Statusbar_Init()
15: to re-initialize / re-draw the statusbar
16: - Call Statusbar_SetFloppyLed() to set floppy drive led ON/OFF,
17: or call Statusbar_EnableHDLed() to enabled HD led for a while
18: - Whenever screen is redrawn, call Statusbar_Update() to draw the
19: updated information to the statusbar (outside of screen locking)
20: - If screen redraws may be partial, Statusbar_OverlayRestore()
21: needs to be called before locking the screen for drawing and
22: Statusbar_OverlayBackup() needs to be called after screen unlocking,
23: but before calling Statusbar_Update(). These are needed for
24: hiding the overlay drive led when drive leds are turned OFF.
25: - If other information shown by Statusbar (TOS version etc) changes,
26: call Statusbar_UpdateInfo()
27:
28: TODO:
29: - re-calculate colors on each update to make sure they're
30: correct in Falcon & TT 8-bit palette modes?
31: - call Statusbar_AddMessage() from log.c?
32: */
1.1.1.3 root 33: const char Statusbar_fileid[] = "Hatari statusbar.c : " __DATE__ " " __TIME__;
1.1 root 34:
35: #include <assert.h>
36: #include "main.h"
37: #include "configuration.h"
38: #include "screenSnapShot.h"
39: #include "sdlgui.h"
40: #include "statusbar.h"
41: #include "tos.h"
1.1.1.5 root 42: #include "screen.h"
1.1 root 43: #include "video.h"
44: #include "wavFormat.h"
45: #include "ymFormat.h"
1.1.1.4 root 46: #include "avi_record.h"
1.1 root 47:
48: #define DEBUG 0
49: #if DEBUG
1.1.1.7 root 50: #include <execinfo.h>
51: # define DEBUGPRINT(x) printf x
1.1 root 52: #else
53: #define DEBUGPRINT(x)
54: #endif
55:
56: #define MAX_DRIVE_LEDS (DRIVE_LED_HD + 1)
57:
58: /* whether drive leds should be ON and their previous shown state */
59: static struct {
1.1.1.8 ! root 60: drive_led_t state;
! 61: drive_led_t oldstate;
1.1 root 62: Uint32 expire; /* when to disable led, valid only if >0 && state=TRUE */
63: int offset; /* led x-pos on screen */
64: } Led[MAX_DRIVE_LEDS];
65:
1.1.1.8 ! root 66:
1.1 root 67: /* drive leds size & y-pos */
68: static SDL_Rect LedRect;
69:
70: /* overlay led size & pos */
71: static SDL_Rect OverlayLedRect;
72:
73: /* screen contents left under overlay led */
74: static SDL_Surface *OverlayUnderside;
75:
76: static enum {
77: OVERLAY_NONE,
78: OVERLAY_DRAWN,
79: OVERLAY_RESTORED
80: } bOverlayState;
81:
82: static SDL_Rect RecLedRect;
83: static bool bOldRecording;
84:
85: /* led colors */
1.1.1.8 ! root 86: static Uint32 LedColor[ MAX_LED_STATE ];
! 87: static Uint32 RecColorOn, RecColorOff;
1.1 root 88: static Uint32 GrayBg, LedColorBg;
89:
90:
1.1.1.8 ! root 91: #define MAX_MESSAGE_LEN 34
1.1 root 92: typedef struct msg_item {
93: struct msg_item *next;
94: char msg[MAX_MESSAGE_LEN+1];
95: Uint32 timeout; /* msecs, zero=no timeout */
96: Uint32 expire; /* when to expire message */
97: bool shown;
98: } msg_item_t;
99:
100: static msg_item_t DefaultMessage;
101: static msg_item_t *MessageList = &DefaultMessage;
102: static SDL_Rect MessageRect;
103:
1.1.1.4 root 104: /* rect for both frame skip value and fast forward indicator */
1.1 root 105: static SDL_Rect FrameSkipsRect;
106: static int nOldFrameSkips;
1.1.1.4 root 107: static int bOldFastForward;
1.1 root 108:
109:
110: /* screen height above statusbar and height of statusbar below screen */
111: static int ScreenHeight;
112: static int StatusbarHeight;
113:
114:
115: /*-----------------------------------------------------------------------*/
116: /**
1.1.1.4 root 117: * Return statusbar height for given width and height
1.1 root 118: */
1.1.1.4 root 119: int Statusbar_GetHeightForSize(int width, int height)
1.1 root 120: {
121: if (ConfigureParams.Screen.bShowStatusbar) {
122: /* Should check the same thing as SDLGui_SetScreen()
123: * does to decide the font size.
124: */
1.1.1.3 root 125: if (width >= 640 && height >= (400-24)) {
1.1.1.7 root 126: DEBUGPRINT(("Statusbar_GetHeightForSize(%d, %d) -> %d\n", width, height, 24));
1.1.1.4 root 127: return 24;
1.1 root 128: } else {
1.1.1.7 root 129: DEBUGPRINT(("Statusbar_GetHeightForSize(%d, %d) -> %d\n", width, height, 12));
1.1.1.4 root 130: return 12;
1.1 root 131: }
132: }
1.1.1.7 root 133: DEBUGPRINT(("Statusbar_GetHeightForSize(%d, %d) -> %d\n", width, height, 0));
1.1.1.4 root 134: return 0;
135: }
136:
137: /*-----------------------------------------------------------------------*/
138: /**
139: * Set screen height used for statusbar height calculation.
140: *
141: * Return height of statusbar that should be added to the screen
142: * height when screen is (re-)created, or zero if statusbar will
143: * not be shown
144: */
145: int Statusbar_SetHeight(int width, int height)
146: {
1.1.1.7 root 147: #if DEBUG
148: /* find out from where the set height is called */
149: void *addr[8];
150: int count = backtrace(addr, sizeof(addr)/sizeof(*addr));
151: backtrace_symbols_fd(addr, count, fileno(stderr));
152: #endif
1.1.1.4 root 153: ScreenHeight = height;
154: StatusbarHeight = Statusbar_GetHeightForSize(width, height);
1.1.1.6 root 155: DEBUGPRINT(("Statusbar_SetHeight(%d, %d) -> %d\n", width, height, StatusbarHeight));
1.1 root 156: return StatusbarHeight;
157: }
158:
159: /*-----------------------------------------------------------------------*/
160: /**
161: * Return height of statusbar set with Statusbar_SetHeight()
162: */
163: int Statusbar_GetHeight(void)
164: {
165: return StatusbarHeight;
166: }
167:
168:
169: /*-----------------------------------------------------------------------*/
170: /**
171: * Enable HD drive led, it will be automatically disabled after a while.
172: */
1.1.1.8 ! root 173: void Statusbar_EnableHDLed(drive_led_t state)
1.1 root 174: {
175: /* leds are shown for 1/2 sec after enabling */
176: Led[DRIVE_LED_HD].expire = SDL_GetTicks() + 1000/2;
1.1.1.8 ! root 177: Led[DRIVE_LED_HD].state = state;
1.1 root 178: }
179:
180: /*-----------------------------------------------------------------------*/
181: /**
182: * Set given floppy drive led state, anything enabling led with this
183: * needs also to take care of disabling it.
184: */
1.1.1.8 ! root 185: void Statusbar_SetFloppyLed(drive_index_t drive, drive_led_t state)
1.1 root 186: {
187: assert(drive == DRIVE_LED_A || drive == DRIVE_LED_B);
188: Led[drive].state = state;
189: }
190:
191:
192: /*-----------------------------------------------------------------------*/
193: /**
194: * Set overlay led size/pos on given screen to internal Rect
195: * and free previous resources.
196: */
197: static void Statusbar_OverlayInit(const SDL_Surface *surf)
198: {
199: int h;
200: /* led size/pos needs to be re-calculated in case screen changed */
201: h = surf->h / 50;
202: OverlayLedRect.w = 2*h;
203: OverlayLedRect.h = h;
204: OverlayLedRect.x = surf->w - 5*h/2;
205: OverlayLedRect.y = h/2;
206: /* free previous restore surface if it's incompatible */
207: if (OverlayUnderside &&
208: OverlayUnderside->w == OverlayLedRect.w &&
209: OverlayUnderside->h == OverlayLedRect.h &&
210: OverlayUnderside->format->BitsPerPixel == surf->format->BitsPerPixel) {
211: SDL_FreeSurface(OverlayUnderside);
212: OverlayUnderside = NULL;
213: }
214: bOverlayState = OVERLAY_NONE;
215: }
216:
217: /*-----------------------------------------------------------------------*/
218: /**
219: * (re-)initialize statusbar internal variables for given screen surface
220: * (sizes&colors may need to be re-calculated for the new SDL surface)
221: * and draw the statusbar background.
222: */
223: void Statusbar_Init(SDL_Surface *surf)
224: {
225: msg_item_t *item;
226: SDL_Rect ledbox, sbarbox;
227: int i, fontw, fonth, offset;
228: const char *text[MAX_DRIVE_LEDS] = { "A:", "B:", "HD:" };
229:
1.1.1.6 root 230: DEBUGPRINT(("Statusbar_Init()\n"));
1.1 root 231: assert(surf);
232:
233: /* dark green and light green for leds themselves */
1.1.1.8 ! root 234: LedColor[ LED_STATE_OFF ] = SDL_MapRGB(surf->format, 0x00, 0x40, 0x00);
! 235: LedColor[ LED_STATE_ON ] = SDL_MapRGB(surf->format, 0x00, 0xc0, 0x00);
! 236: LedColor[ LED_STATE_ON_BUSY ] = SDL_MapRGB(surf->format, 0x00, 0xe0, 0x00);
1.1 root 237: LedColorBg = SDL_MapRGB(surf->format, 0x00, 0x00, 0x00);
238: RecColorOff = SDL_MapRGB(surf->format, 0x40, 0x00, 0x00);
239: RecColorOn = SDL_MapRGB(surf->format, 0xe0, 0x00, 0x00);
240: GrayBg = SDL_MapRGB(surf->format, 0xc0, 0xc0, 0xc0);
241:
242: /* disable leds */
243: for (i = 0; i < MAX_DRIVE_LEDS; i++) {
1.1.1.8 ! root 244: Led[i].state = Led[i].oldstate = LED_STATE_OFF;
1.1 root 245: Led[i].expire = 0;
246: }
247: Statusbar_OverlayInit(surf);
248:
249: /* disable statusbar if it doesn't fit to video mode */
250: if (surf->h < ScreenHeight + StatusbarHeight) {
251: StatusbarHeight = 0;
252: }
253: if (!StatusbarHeight) {
1.1.1.6 root 254: DEBUGPRINT(("Doesn't fit <- Statusbar_Init()\n"));
1.1 root 255: return;
256: }
257:
258: /* prepare fonts */
259: SDLGui_Init();
260: SDLGui_SetScreen(surf);
261: SDLGui_GetFontSize(&fontw, &fonth);
262:
263: /* video mode didn't match, need to recalculate sizes */
264: if (surf->h > ScreenHeight + StatusbarHeight) {
265: StatusbarHeight = fonth + 2;
266: /* actually statusbar vertical offset */
267: ScreenHeight = surf->h - StatusbarHeight;
268: } else {
269: assert(fonth+2 < StatusbarHeight);
270: }
271:
272: /* draw statusbar background gray so that text shows */
273: sbarbox.x = 0;
274: sbarbox.y = surf->h - StatusbarHeight;
275: sbarbox.w = surf->w;
276: sbarbox.h = StatusbarHeight;
277: SDL_FillRect(surf, &sbarbox, GrayBg);
278:
279: /* led size */
1.1.1.4 root 280: LedRect.w = fonth/2;
1.1 root 281: LedRect.h = fonth - 4;
282: LedRect.y = ScreenHeight + StatusbarHeight/2 - LedRect.h/2;
1.1.1.4 root 283:
1.1 root 284: /* black box for the leds */
285: ledbox = LedRect;
286: ledbox.y -= 1;
287: ledbox.w += 2;
288: ledbox.h += 2;
289:
290: offset = fontw;
291: MessageRect.y = LedRect.y - 2;
292: /* draw led texts and boxes + calculate box offsets */
293: for (i = 0; i < MAX_DRIVE_LEDS; i++) {
294: SDLGui_Text(offset, MessageRect.y, text[i]);
295: offset += strlen(text[i]) * fontw;
296: offset += fontw/2;
297:
298: ledbox.x = offset - 1;
299: SDL_FillRect(surf, &ledbox, LedColorBg);
300:
301: LedRect.x = offset;
1.1.1.8 ! root 302: SDL_FillRect(surf, &LedRect, LedColor[ LED_STATE_OFF ]);
1.1 root 303:
304: Led[i].offset = offset;
1.1.1.4 root 305: offset += LedRect.w + fontw;
1.1 root 306: }
307:
308: /* draw frameskip */
309: FrameSkipsRect.x = offset;
310: FrameSkipsRect.y = MessageRect.y;
311: SDLGui_Text(FrameSkipsRect.x, FrameSkipsRect.y, "FS:");
312: FrameSkipsRect.x += 3 * fontw + fontw/2;
1.1.1.4 root 313: FrameSkipsRect.w = 4 * fontw;
1.1 root 314: FrameSkipsRect.h = fonth;
1.1.1.4 root 315:
316: if(ConfigureParams.System.bFastForward) {
317: SDLGui_Text(FrameSkipsRect.x, FrameSkipsRect.y, "0 >>");
318: } else {
319: SDLGui_Text(FrameSkipsRect.x, FrameSkipsRect.y, "0");
320: }
321:
1.1 root 322: nOldFrameSkips = 0;
1.1.1.4 root 323:
1.1 root 324: /* intialize messages */
1.1.1.4 root 325: MessageRect.x = FrameSkipsRect.x + FrameSkipsRect.w + fontw;
1.1 root 326: MessageRect.w = MAX_MESSAGE_LEN * fontw;
327: MessageRect.h = fonth;
328: for (item = MessageList; item; item = item->next) {
1.1.1.3 root 329: item->shown = false;
1.1 root 330: }
331:
332: /* draw recording led box */
333: RecLedRect = LedRect;
334: RecLedRect.x = surf->w - fontw - RecLedRect.w;
335: ledbox.x = RecLedRect.x - 1;
336: SDLGui_Text(ledbox.x - 4*fontw - fontw/2, MessageRect.y, "REC:");
337: SDL_FillRect(surf, &ledbox, LedColorBg);
338: SDL_FillRect(surf, &RecLedRect, RecColorOff);
1.1.1.3 root 339: bOldRecording = false;
1.1 root 340:
341: /* and blit statusbar on screen */
342: SDL_UpdateRects(surf, 1, &sbarbox);
1.1.1.6 root 343: DEBUGPRINT(("Drawn <- Statusbar_Init()\n"));
1.1 root 344: }
345:
346:
347: /*-----------------------------------------------------------------------*/
348: /**
349: * Qeueue new statusbar message 'msg' to be shown for 'msecs' milliseconds
350: */
351: void Statusbar_AddMessage(const char *msg, Uint32 msecs)
352: {
353: msg_item_t *item;
354:
355: if (!ConfigureParams.Screen.bShowStatusbar) {
356: /* no sense in queuing messages that aren't shown */
357: return;
358: }
359: item = calloc(1, sizeof(msg_item_t));
360: assert(item);
361:
362: item->next = MessageList;
363: MessageList = item;
364:
365: strncpy(item->msg, msg, MAX_MESSAGE_LEN);
366: item->msg[MAX_MESSAGE_LEN] = '\0';
367: DEBUGPRINT(("Add message: '%s'\n", item->msg));
368:
369: if (msecs) {
370: item->timeout = msecs;
371: } else {
372: /* show items by default for 2.5 secs */
373: item->timeout = 2500;
374: }
1.1.1.3 root 375: item->shown = false;
1.1 root 376: }
377:
378: /*-----------------------------------------------------------------------*/
379: /**
380: * Write given 'more' string to 'buffer' and return new end of 'buffer'
381: */
382: static char *Statusbar_AddString(char *buffer, const char *more)
383: {
384: while(*more) {
385: *buffer++ = *more++;
386: }
387: return buffer;
388: }
389:
390: /*-----------------------------------------------------------------------*/
391: /**
392: * Retrieve/update default statusbar information
393: */
394: void Statusbar_UpdateInfo(void)
395: {
396: char *end = DefaultMessage.msg;
397:
1.1.1.4 root 398: /* CPU MHz */
399: if (ConfigureParams.System.nCpuFreq > 9) {
400: *end++ = '0' + ConfigureParams.System.nCpuFreq / 10;
401: }
402: *end++ = '0' + ConfigureParams.System.nCpuFreq % 10;
403: end = Statusbar_AddString(end, "MHz/");
404:
405: /* CPU type */
406: if(ConfigureParams.System.nCpuLevel > 0) {
407: *end++ = '0';
408: *end++ = '0' + ConfigureParams.System.nCpuLevel % 10;
409: *end++ = '0';
410: *end++ = '/';
411: }
412:
1.1 root 413: /* amount of memory */
414: if (ConfigureParams.Memory.nMemorySize > 9) {
415: *end++ = '1';
416: *end++ = '0' + ConfigureParams.Memory.nMemorySize % 10;
417: } else {
418: if (ConfigureParams.Memory.nMemorySize) {
419: *end++ = '0' + ConfigureParams.Memory.nMemorySize;
420: } else {
1.1.1.7 root 421: end = Statusbar_AddString(end, "0.5");
1.1 root 422: }
423: }
424: end = Statusbar_AddString(end, "MB ");
1.1.1.4 root 425:
1.1 root 426: /* machine type */
427: switch (ConfigureParams.System.nMachineType) {
428: case MACHINE_ST:
429: end = Statusbar_AddString(end, "ST");
430: break;
431: case MACHINE_STE:
432: end = Statusbar_AddString(end, "STE");
433: break;
1.1.1.5 root 434: case MACHINE_MEGA_STE:
1.1.1.7 root 435: end = Statusbar_AddString(end, "MegaSTE");
1.1.1.5 root 436: break;
1.1 root 437: case MACHINE_TT:
438: end = Statusbar_AddString(end, "TT");
439: break;
440: case MACHINE_FALCON:
441: end = Statusbar_AddString(end, "Falcon");
442: break;
443: default:
444: end = Statusbar_AddString(end, "???");
445: break;
446: }
447:
448: /* TOS type/version */
449: if (bIsEmuTOS) {
450: end = Statusbar_AddString(end, ", EmuTOS");
451: } else {
452: end = Statusbar_AddString(end, ", TOS v");
453: *end++ = '0' + ((TosVersion & 0xf00) >> 8);
454: *end++ = '.';
455: *end++ = '0' + ((TosVersion & 0xf0) >> 4);
456: *end++ = '0' + (TosVersion & 0xf);
457: }
458: *end = '\0';
1.1.1.4 root 459:
1.1 root 460: assert(end - DefaultMessage.msg < MAX_MESSAGE_LEN);
461: DEBUGPRINT(("Set default message: '%s'\n", DefaultMessage.msg));
1.1.1.5 root 462: /* make sure default message gets (re-)drawn when next checked */
1.1.1.3 root 463: DefaultMessage.shown = false;
1.1 root 464: }
465:
466: /*-----------------------------------------------------------------------*/
467: /**
468: * Draw 'msg' centered to the message area
469: */
470: static void Statusbar_DrawMessage(SDL_Surface *surf, const char *msg)
471: {
472: int fontw, fonth, offset;
473: SDL_FillRect(surf, &MessageRect, GrayBg);
474: if (*msg) {
475: SDLGui_GetFontSize(&fontw, &fonth);
476: offset = (MessageRect.w - strlen(msg) * fontw) / 2;
477: SDLGui_Text(MessageRect.x + offset, MessageRect.y, msg);
478: }
479: SDL_UpdateRects(surf, 1, &MessageRect);
480: DEBUGPRINT(("Draw message: '%s'\n", msg));
481: }
482:
483: /*-----------------------------------------------------------------------*/
484: /**
485: * If message's not shown, show it. If message's timed out,
486: * remove it and show next one.
487: */
488: static void Statusbar_ShowMessage(SDL_Surface *surf, Uint32 ticks)
489: {
490: msg_item_t *next;
491:
492: if (MessageList->shown) {
493: if (!MessageList->expire) {
1.1.1.5 root 494: /* last/default message newer expires */
1.1 root 495: return;
496: }
497: if (MessageList->expire > ticks) {
498: /* not timed out yet */
499: return;
500: }
501: assert(MessageList->next); /* last message shouldn't end here */
502: next = MessageList->next;
503: free(MessageList);
504: MessageList = next;
505: /* make sure next message gets shown */
1.1.1.3 root 506: MessageList->shown = false;
1.1 root 507: }
508: if (!MessageList->shown) {
509: /* not shown yet, show */
510: Statusbar_DrawMessage(surf, MessageList->msg);
511: if (MessageList->timeout && !MessageList->expire) {
512: MessageList->expire = ticks + MessageList->timeout;
513: }
1.1.1.3 root 514: MessageList->shown = true;
1.1 root 515: }
516: }
517:
518:
519: /*-----------------------------------------------------------------------*/
520: /**
521: * Save the area that will be left under overlay led
522: */
523: void Statusbar_OverlayBackup(SDL_Surface *surf)
524: {
1.1.1.3 root 525: if ((StatusbarHeight && ConfigureParams.Screen.bShowStatusbar)
526: || !ConfigureParams.Screen.bShowDriveLed) {
1.1 root 527: /* overlay not used with statusbar */
528: return;
529: }
530: assert(surf);
531: if (!OverlayUnderside) {
532: SDL_Surface *bak;
533: SDL_PixelFormat *fmt = surf->format;
534: bak = SDL_CreateRGBSurface(surf->flags,
535: OverlayLedRect.w, OverlayLedRect.h,
536: fmt->BitsPerPixel,
537: fmt->Rmask, fmt->Gmask, fmt->Bmask,
538: fmt->Amask);
539: assert(bak);
540: OverlayUnderside = bak;
541: }
542: SDL_BlitSurface(surf, &OverlayLedRect, OverlayUnderside, NULL);
543: }
544:
545: /*-----------------------------------------------------------------------*/
546: /**
547: * Restore the area left under overlay led
548: */
549: void Statusbar_OverlayRestore(SDL_Surface *surf)
550: {
1.1.1.3 root 551: if ((StatusbarHeight && ConfigureParams.Screen.bShowStatusbar)
552: || !ConfigureParams.Screen.bShowDriveLed) {
1.1 root 553: /* overlay not used with statusbar */
554: return;
555: }
556: if (bOverlayState == OVERLAY_DRAWN && OverlayUnderside) {
557: assert(surf);
558: SDL_BlitSurface(OverlayUnderside, NULL, surf, &OverlayLedRect);
559: /* this will make the draw function to update this the screen */
560: bOverlayState = OVERLAY_RESTORED;
561: }
562: }
563:
564: /*-----------------------------------------------------------------------*/
565: /**
566: * Draw overlay led
567: */
568: static void Statusbar_OverlayDrawLed(SDL_Surface *surf, Uint32 color)
569: {
570: SDL_Rect rect;
571: if (bOverlayState == OVERLAY_DRAWN) {
572: /* some led already drawn */
573: return;
574: }
575: bOverlayState = OVERLAY_DRAWN;
576:
577: /* enabled led with border */
578: rect = OverlayLedRect;
579: rect.x += 1;
580: rect.y += 1;
581: rect.w -= 2;
582: rect.h -= 2;
583: SDL_FillRect(surf, &OverlayLedRect, LedColorBg);
584: SDL_FillRect(surf, &rect, color);
585: }
586:
587: /*-----------------------------------------------------------------------*/
588: /**
589: * Draw overlay led onto screen surface if any drives are enabled.
590: */
591: static void Statusbar_OverlayDraw(SDL_Surface *surf)
592: {
593: Uint32 currentticks = SDL_GetTicks();
594: int i;
595:
596: assert(surf);
1.1.1.4 root 597: if (bRecordingYM || bRecordingWav || bRecordingAvi) {
1.1 root 598: Statusbar_OverlayDrawLed(surf, RecColorOn);
599: }
600: for (i = 0; i < MAX_DRIVE_LEDS; i++) {
601: if (Led[i].state) {
602: if (Led[i].expire && Led[i].expire < currentticks) {
1.1.1.8 ! root 603: Led[i].state = LED_STATE_OFF;
1.1 root 604: continue;
605: }
1.1.1.8 ! root 606: Statusbar_OverlayDrawLed(surf, LedColor[ Led[i].state ]);
1.1 root 607: break;
608: }
609: }
610: /* possible state transitions:
611: * NONE -> DRAWN -> RESTORED -> DRAWN -> RESTORED -> NONE
612: * Other than NONE state needs to be updated on screen
613: */
614: switch (bOverlayState) {
615: case OVERLAY_RESTORED:
616: bOverlayState = OVERLAY_NONE;
617: case OVERLAY_DRAWN:
618: SDL_UpdateRects(surf, 1, &OverlayLedRect);
619: DEBUGPRINT(("Overlay LED = %s\n", bOverlayState==OVERLAY_DRAWN?"ON":"OFF"));
620: break;
621: case OVERLAY_NONE:
622: break;
623: }
624: }
625:
626:
627: /*-----------------------------------------------------------------------*/
628: /**
629: * Update statusbar information (leds etc) if/when needed.
630: *
631: * May not be called when screen is locked (SDL limitation).
632: */
633: void Statusbar_Update(SDL_Surface *surf)
634: {
635: Uint32 color, currentticks;
636: SDL_Rect rect;
637: int i;
638:
639: if (!(StatusbarHeight && ConfigureParams.Screen.bShowStatusbar)) {
640: /* not enabled (anymore), show overlay led instead? */
641: if (ConfigureParams.Screen.bShowDriveLed) {
642: Statusbar_OverlayDraw(surf);
643: }
644: return;
645: }
646: assert(surf);
647: /* Statusbar_Init() not called before this? */
1.1.1.6 root 648: #if DEBUG
649: if (surf->h != ScreenHeight + StatusbarHeight) {
650: printf("%d != %d + %d\n", surf->h, ScreenHeight, StatusbarHeight);
651: }
652: #endif
1.1 root 653: assert(surf->h == ScreenHeight + StatusbarHeight);
654:
655: rect = LedRect;
656: currentticks = SDL_GetTicks();
657: for (i = 0; i < MAX_DRIVE_LEDS; i++) {
658: if (Led[i].expire && Led[i].expire < currentticks) {
1.1.1.8 ! root 659: Led[i].state = LED_STATE_OFF;
1.1 root 660: }
661: if (Led[i].state == Led[i].oldstate) {
662: continue;
663: }
664: Led[i].oldstate = Led[i].state;
1.1.1.8 ! root 665: color = LedColor[ Led[i].state ];
1.1 root 666: rect.x = Led[i].offset;
667: SDL_FillRect(surf, &rect, color);
668: SDL_UpdateRects(surf, 1, &rect);
1.1.1.8 ! root 669: DEBUGPRINT(("LED[%d] = %d\n", i, Led[i].state));
1.1 root 670: }
1.1.1.4 root 671:
1.1 root 672: Statusbar_ShowMessage(surf, currentticks);
673:
1.1.1.4 root 674: if (nOldFrameSkips != nFrameSkips ||
675: bOldFastForward != ConfigureParams.System.bFastForward) {
676: char fscount[5];
677: int end = 2;
678:
1.1.1.3 root 679: if (nFrameSkips < 10)
680: fscount[0] = '0' + nFrameSkips;
681: else
682: fscount[0] = 'X';
1.1.1.4 root 683: fscount[1] = ' ';
684: if(ConfigureParams.System.bFastForward) {
685: fscount[2] = '>';
686: fscount[3] = '>';
687: end = 4;
688: }
689: fscount[end] = '\0';
690:
1.1 root 691: SDL_FillRect(surf, &FrameSkipsRect, GrayBg);
692: SDLGui_Text(FrameSkipsRect.x, FrameSkipsRect.y, fscount);
693: SDL_UpdateRects(surf, 1, &FrameSkipsRect);
694: DEBUGPRINT(("FS = %s\n", fscount));
695: nOldFrameSkips = nFrameSkips;
1.1.1.4 root 696: bOldFastForward = ConfigureParams.System.bFastForward;
1.1 root 697: }
698:
1.1.1.4 root 699: if ((bRecordingYM || bRecordingWav || bRecordingAvi)
1.1 root 700: != bOldRecording) {
701: bOldRecording = !bOldRecording;
702: if (bOldRecording) {
703: color = RecColorOn;
704: } else {
705: color = RecColorOff;
706: }
707: SDL_FillRect(surf, &RecLedRect, color);
708: SDL_UpdateRects(surf, 1, &RecLedRect);
709: DEBUGPRINT(("REC = ON\n"));
710: }
711: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.