api refactor
- handles power related input and state - handles battery and settings rendering
This commit is contained in:
parent
eb676cd833
commit
1145988066
5 changed files with 360 additions and 272 deletions
257
src/common/api.c
257
src/common/api.c
|
|
@ -113,6 +113,7 @@ struct owlfb_mem_info {
|
|||
///////////////////////////////
|
||||
|
||||
static struct GFX_Context {
|
||||
int mode;
|
||||
int fb;
|
||||
int pitch;
|
||||
int buffer;
|
||||
|
|
@ -153,11 +154,13 @@ GFX_Fonts font;
|
|||
|
||||
///////////////////////////////
|
||||
|
||||
SDL_Surface* GFX_init(void) {
|
||||
SDL_Surface* GFX_init(int mode) {
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
SDL_ShowCursor(0);
|
||||
TTF_Init();
|
||||
|
||||
|
||||
gfx.mode = mode;
|
||||
|
||||
// we're drawing to the (triple-buffered) framebuffer directly
|
||||
// but we still need to set video mode to initialize input events
|
||||
SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_DEPTH, SDL_HWSURFACE);
|
||||
|
|
@ -246,6 +249,10 @@ void GFX_quit(void) {
|
|||
TTF_CloseFont(font.tiny);
|
||||
|
||||
SDL_FreeSurface(gfx.assets);
|
||||
#ifdef GFX_ENABLE_VSYNC
|
||||
int arg = 1;
|
||||
ioctl(gfx.fb, OWLFB_WAITFORVSYNC, &arg);
|
||||
#endif
|
||||
GFX_clearAll();
|
||||
munmap(gfx.map, gfx.map_size);
|
||||
close(gfx.fb);
|
||||
|
|
@ -403,63 +410,123 @@ void GFX_blitButton(char* hint, char*button, SDL_Surface* dst, SDL_Rect* dst_rec
|
|||
SDL_BlitSurface(text, NULL, dst, &(SDL_Rect){ox+dst_rect->x,dst_rect->y+(SCALE1(BUTTON_SIZE)-text->h)/2,text->w,text->h});
|
||||
SDL_FreeSurface(text);
|
||||
}
|
||||
|
||||
void GFX_blitABButtons(char* a, char* b, SDL_Surface* dst) {
|
||||
int ox;
|
||||
int oy;
|
||||
int ow;
|
||||
char* hint;
|
||||
char* button;
|
||||
|
||||
struct Hint {
|
||||
char* hint;
|
||||
char* button;
|
||||
int ow;
|
||||
} hints[3];
|
||||
int w = 0; // individual button dimension
|
||||
int h = 0; // hints index
|
||||
ow = 0; // full pill width
|
||||
ox = SCREEN_WIDTH - SCALE1(PADDING);
|
||||
oy = SCREEN_HEIGHT - SCALE1(PADDING + PILL_SIZE);
|
||||
|
||||
if (b) {
|
||||
hint = b;
|
||||
button = "B";
|
||||
w = GFX_getButtonWidth(hint, button);
|
||||
hints[h].hint = hint;
|
||||
hints[h].button = button;
|
||||
hints[h].ow = w;
|
||||
h += 1;
|
||||
ow += SCALE1(BUTTON_MARGIN) + w;
|
||||
void GFX_blitMessage(char* msg, SDL_Surface* dst, SDL_Rect* dst_rect) {
|
||||
if (dst_rect==NULL) {
|
||||
dst_rect = &(SDL_Rect){0,0,SCREEN_WIDTH,SCREEN_HEIGHT};
|
||||
}
|
||||
|
||||
|
||||
hint = a;
|
||||
button = "A";
|
||||
w = GFX_getButtonWidth(hint, button);
|
||||
hints[h].hint = hint;
|
||||
hints[h].button = button;
|
||||
hints[h].ow = w;
|
||||
h += 1;
|
||||
ow += SCALE1(BUTTON_MARGIN) + w;
|
||||
|
||||
ow += SCALE1(BUTTON_MARGIN);
|
||||
ox -= ow;
|
||||
GFX_blitPill(ASSET_DARK_GRAY_PILL, dst, &(SDL_Rect){
|
||||
ox,
|
||||
oy,
|
||||
ow,
|
||||
SCALE1(PILL_SIZE)
|
||||
});
|
||||
|
||||
ox += SCALE1(BUTTON_MARGIN);
|
||||
oy += SCALE1(BUTTON_MARGIN);
|
||||
for (int i=0; i<h; i++) {
|
||||
GFX_blitButton(hints[i].hint, hints[i].button, dst, &(SDL_Rect){ox,oy});
|
||||
ox += hints[i].ow + SCALE1(BUTTON_MARGIN);
|
||||
SDL_Surface* text;
|
||||
#define TEXT_BOX_MAX_ROWS 16
|
||||
#define LINE_HEIGHT 24
|
||||
char* rows[TEXT_BOX_MAX_ROWS];
|
||||
int row_count = 0;
|
||||
|
||||
char* tmp;
|
||||
rows[row_count++] = msg;
|
||||
while ((tmp=strchr(rows[row_count-1], '\n'))!=NULL) {
|
||||
if (row_count+1>=TEXT_BOX_MAX_ROWS) return; // TODO: bail
|
||||
rows[row_count++] = tmp+1;
|
||||
}
|
||||
|
||||
int rendered_height = SCALE1(LINE_HEIGHT) * row_count;
|
||||
int y = dst_rect->y;
|
||||
y += (dst_rect->h - rendered_height) / 2;
|
||||
|
||||
char line[256];
|
||||
for (int i=0; i<row_count; i++) {
|
||||
int len;
|
||||
if (i+1<row_count) {
|
||||
len = rows[i+1]-rows[i]-1;
|
||||
if (len) strncpy(line, rows[i], len);
|
||||
line[len] = '\0';
|
||||
}
|
||||
else {
|
||||
len = strlen(rows[i]);
|
||||
strcpy(line, rows[i]);
|
||||
}
|
||||
|
||||
|
||||
if (len) {
|
||||
text = TTF_RenderUTF8_Blended(font.large, line, COLOR_WHITE);
|
||||
int x = dst_rect->x;
|
||||
x += (dst_rect->w - text->w) / 2;
|
||||
SDL_BlitSurface(text, NULL, dst, &(SDL_Rect){x,y});
|
||||
SDL_FreeSurface(text);
|
||||
}
|
||||
y += SCALE1(LINE_HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
int GFX_blitHardwareGroup(SDL_Surface* dst, int show_setting) {
|
||||
int ox;
|
||||
int oy;
|
||||
int ow = 0;
|
||||
|
||||
int setting_value;
|
||||
int setting_min;
|
||||
int setting_max;
|
||||
|
||||
if (show_setting) {
|
||||
ow = SCALE1(PILL_SIZE + SETTINGS_WIDTH + PADDING + 4);
|
||||
ox = SCREEN_WIDTH - SCALE1(PADDING) - ow;
|
||||
oy = SCALE1(PADDING);
|
||||
GFX_blitPill(gfx.mode==MODE_MAIN ? ASSET_DARK_GRAY_PILL : ASSET_BLACK_PILL, dst, &(SDL_Rect){
|
||||
ox,
|
||||
oy,
|
||||
ow,
|
||||
SCALE1(PILL_SIZE)
|
||||
});
|
||||
|
||||
if (show_setting==1) {
|
||||
setting_value = GetBrightness();
|
||||
setting_min = BRIGHTNESS_MIN;
|
||||
setting_max = BRIGHTNESS_MAX;
|
||||
}
|
||||
else {
|
||||
setting_value = GetVolume();
|
||||
setting_min = VOLUME_MIN;
|
||||
setting_max = VOLUME_MAX;
|
||||
}
|
||||
|
||||
int asset = show_setting==1?ASSET_BRIGHTNESS:(setting_value>0?ASSET_VOLUME:ASSET_VOLUME_MUTE);
|
||||
int ax = ox + (show_setting==1 ? SCALE1(6) : SCALE1(8));
|
||||
int ay = oy + (show_setting==1 ? SCALE1(5) : SCALE1(7));
|
||||
GFX_blitAsset(asset, NULL, dst, &(SDL_Rect){ax,ay});
|
||||
|
||||
ox += SCALE1(PILL_SIZE);
|
||||
oy += SCALE1((PILL_SIZE - SETTINGS_SIZE) / 2);
|
||||
GFX_blitPill(ASSET_BAR_BG, dst, &(SDL_Rect){
|
||||
ox,
|
||||
oy,
|
||||
SCALE1(SETTINGS_WIDTH),
|
||||
SCALE1(SETTINGS_SIZE)
|
||||
});
|
||||
|
||||
float percent = ((float)(setting_value-setting_min) / (setting_max-setting_min));
|
||||
if (show_setting==1 || setting_value>0) {
|
||||
GFX_blitPill(ASSET_BAR, dst, &(SDL_Rect){
|
||||
ox,
|
||||
oy,
|
||||
SCALE1(SETTINGS_WIDTH) * percent,
|
||||
SCALE1(SETTINGS_SIZE)
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
ow = SCALE1(PILL_SIZE);
|
||||
ox = SCREEN_WIDTH - SCALE1(PADDING) - ow;
|
||||
oy = SCALE1(PADDING);
|
||||
GFX_blitPill(gfx.mode==MODE_MAIN ? ASSET_DARK_GRAY_PILL : ASSET_BLACK_PILL, dst, &(SDL_Rect){
|
||||
ox,
|
||||
oy,
|
||||
ow,
|
||||
SCALE1(PILL_SIZE)
|
||||
});
|
||||
GFX_blitBattery(dst, &(SDL_Rect){ox,oy});
|
||||
}
|
||||
|
||||
return ow;
|
||||
}
|
||||
int GFX_blitButtonGroup(char** pairs, SDL_Surface* dst, int align_right) {
|
||||
int ox;
|
||||
int oy;
|
||||
|
|
@ -493,7 +560,7 @@ int GFX_blitButtonGroup(char** pairs, SDL_Surface* dst, int align_right) {
|
|||
|
||||
ow += SCALE1(BUTTON_MARGIN);
|
||||
if (align_right) ox -= ow;
|
||||
GFX_blitPill(ASSET_DARK_GRAY_PILL, dst, &(SDL_Rect){
|
||||
GFX_blitPill(gfx.mode==MODE_MAIN ? ASSET_DARK_GRAY_PILL : ASSET_BLACK_PILL, dst, &(SDL_Rect){
|
||||
ox,
|
||||
oy,
|
||||
ow,
|
||||
|
|
@ -753,6 +820,79 @@ int PAD_justRepeated(int btn) { return pad.just_repeated & btn; }
|
|||
|
||||
///////////////////////////////
|
||||
|
||||
// TODO: separate settings/battery and power management?
|
||||
void POW_update(int* _dirty, int* _show_setting, POW_callback_t before_sleep, POW_callback_t after_sleep) {
|
||||
int dirty = _dirty ? *_dirty : 0;
|
||||
int show_setting = _show_setting ? *_show_setting : 0;
|
||||
|
||||
static unsigned long cancel_start = 0;
|
||||
static unsigned long power_start = 0;
|
||||
|
||||
static unsigned long setting_start = 0;
|
||||
static unsigned long charge_start = 0;
|
||||
static int was_charging = -1;
|
||||
if (was_charging==-1) was_charging = POW_isCharging();
|
||||
|
||||
unsigned long now = SDL_GetTicks();
|
||||
if (cancel_start==0) cancel_start = now;
|
||||
if (charge_start==0) charge_start = now;
|
||||
|
||||
if (PAD_anyPressed()) cancel_start = now;
|
||||
|
||||
#define CHARGE_DELAY 1000
|
||||
if (dirty || now-charge_start>=CHARGE_DELAY) {
|
||||
int is_charging = POW_isCharging();
|
||||
if (was_charging!=is_charging) {
|
||||
was_charging = is_charging;
|
||||
dirty = 1;
|
||||
}
|
||||
charge_start = now;
|
||||
}
|
||||
|
||||
if (power_start && now-power_start>=1000) {
|
||||
if (before_sleep) before_sleep();
|
||||
POW_powerOff();
|
||||
}
|
||||
if (PAD_justPressed(BTN_SLEEP)) {
|
||||
power_start = now;
|
||||
}
|
||||
|
||||
#define SLEEP_DELAY 30000
|
||||
if (now-cancel_start>=SLEEP_DELAY && POW_preventAutosleep()) cancel_start = now;
|
||||
|
||||
if (now-cancel_start>=SLEEP_DELAY || PAD_justReleased(BTN_SLEEP)) {
|
||||
if (before_sleep) before_sleep();
|
||||
POW_fauxSleep();
|
||||
if (after_sleep) after_sleep();
|
||||
|
||||
cancel_start = SDL_GetTicks();
|
||||
power_start = 0;
|
||||
dirty = 1;
|
||||
}
|
||||
|
||||
int was_dirty = dirty; // dirty list (not including settings/battery)
|
||||
|
||||
#define SETTING_DELAY 500
|
||||
if (show_setting && now-setting_start>=SETTING_DELAY && !PAD_isPressed(BTN_MENU)) {
|
||||
show_setting = 0;
|
||||
dirty = 1;
|
||||
}
|
||||
|
||||
if (PAD_justRepeated(BTN_VOL_UP) || PAD_justRepeated(BTN_VOL_DN) || PAD_justPressed(BTN_MENU)) {
|
||||
setting_start = now;
|
||||
if (PAD_isPressed(BTN_MENU)) {
|
||||
show_setting = 1;
|
||||
}
|
||||
else {
|
||||
show_setting = 2;
|
||||
}
|
||||
}
|
||||
if (show_setting) dirty = 1; // shm is slow or keymon is catching input on the next frame
|
||||
|
||||
if (_dirty) *_dirty = dirty;
|
||||
if (_show_setting) *_show_setting = show_setting;
|
||||
}
|
||||
|
||||
static int can_poweroff = 1;
|
||||
void POW_disablePowerOff(void) {
|
||||
can_poweroff = 0;
|
||||
|
|
@ -760,6 +900,13 @@ void POW_disablePowerOff(void) {
|
|||
|
||||
void POW_powerOff(void) {
|
||||
if (can_poweroff) {
|
||||
char* msg = exists(AUTO_RESUME_PATH) ? "Quicksave created,\npowering off" : "Powering off";
|
||||
GFX_clear(gfx.screen);
|
||||
GFX_blitMessage(msg, gfx.screen, NULL);
|
||||
GFX_flip(gfx.screen);
|
||||
sleep(2);
|
||||
|
||||
// actual shutdown
|
||||
system("echo u > /proc/sysrq-trigger");
|
||||
system("echo s > /proc/sysrq-trigger");
|
||||
system("echo o > /proc/sysrq-trigger");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue