summaryrefslogtreecommitdiff
path: root/apps/plugins/lib/pluginlib_exit.h
blob: 8170cf71e92eb5ef5a6e7eb65919a0852cd110e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/***************************************************************************
*             __________               __   ___.
*   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
*   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
*   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
*   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
*                     \/            \/     \/    \/            \/
* $Id$
*
* Copyright (C) 2009 by Maurus Cuelenaere
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/

#ifndef __PLUGINLIB_EXIT_H__
#define __PLUGINLIB_EXIT_H__

/* make sure we are in sync with the real definitions, especially on
 * hosted systems */
#include <stdlib.h>
#include "gcc_extensions.h"

/* these are actually implemented in plugin_crt0.c which all plugins link
 *
 * the cygwin/mingw shared library stub also defines atexit, so give our
 * implementation a prefix */
#define atexit rb_atexit
extern int rb_atexit(void (*func)(void));
extern void exit(int status) NORETURN_ATTR;
/* these don't call the exit handlers */
extern void _exit(int status) NORETURN_ATTR;
/* C99 version */
#define _Exit _exit

#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#endif

/**
 * helper function to handle USB connected events coming from
 * button_get()
 *
 * it will exit the plugin if usb is detected, but it will call the atexit func
 * before actually showing the usb screen
 *
 * it additionally handles power off as well, with the same behavior
 */
extern void exit_on_usb(int button);

#endif /*  __PLUGINLIB_EXIT_H__ */
>202 203 204 205 206 207 208 209 210 211 212
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id: jackpot.c 14034 2007-07-28 05:42:55Z kevin $
 *
 * Copyright (C) 2007 Copyright Kévin Ferrare based on Zakk Roberts's work
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/

#include "clock.h"
#include "clock_bitmaps.h"
#include "clock_draw.h"
#include "clock_settings.h"
#include "lib/picture.h"

static int max_skin[]={
    [ANALOG]=2,
    [BINARY]=3,
    [DIGITAL]=2,
};

enum message{
    MESSAGE_LOADING,
    MESSAGE_LOADED,
    MESSAGE_ERRLOAD,
    MESSAGE_SAVING,
    MESSAGE_SAVED,
    MESSAGE_ERRSAVE
};

enum settings_file_status{
    LOADED, ERRLOAD,
    SAVED, ERRSAVE
};

struct clock_settings clock_settings;

/* The settings as they exist on the hard disk, so that 
 * we can know at saving time if changes have been made */
struct clock_settings hdd_clock_settings;

bool settings_needs_saving(struct clock_settings* settings){
    return(rb->memcmp(settings, &hdd_clock_settings, sizeof(*settings)));
}

void clock_settings_reset(struct clock_settings* settings){
    settings->mode = ANALOG;
    int i;
    for(i=0;i<NB_CLOCK_MODES;i++){
        settings->skin[i]=0;
    }
    settings->general.hour_format = H12;
    settings->general.date_format = EUROPEAN;
    settings->general.show_counter = true;
    settings->general.save_settings = true;
    settings->general.idle_poweroff=true;
    settings->general.backlight = ROCKBOX_SETTING;

    settings->analog.show_date = false;
    settings->analog.show_seconds = true;
    settings->analog.show_border = true;

    settings->digital.show_seconds = true;
    settings->digital.blinkcolon = false;
    apply_backlight_setting(settings->general.backlight);
}

void apply_backlight_setting(int backlight_setting)
{
    if(backlight_setting == ALWAS_OFF)
        rb->backlight_set_timeout(-1);
    else if(backlight_setting == ROCKBOX_SETTING)
        rb->backlight_set_timeout(rb->global_settings->backlight_timeout);
    else if(backlight_setting == ALWAYS_ON)
        rb->backlight_set_timeout(0);
}

void clock_settings_skin_next(struct clock_settings* settings){
    settings->skin[settings->mode]++;
    if(settings->skin[settings->mode]>=max_skin[settings->mode])
        settings->skin[settings->mode]=0;
}

void clock_settings_skin_previous(struct clock_settings* settings){
    settings->skin[settings->mode]--;
    if(settings->skin[settings->mode]<0)
        settings->skin[settings->mode]=max_skin[settings->mode]-1;
}

enum settings_file_status clock_settings_load(struct clock_settings* settings,
                                              char* filename){
    int fd = rb->open(filename, O_RDONLY);
    if(fd >= 0){ /* does file exist? */
        /* basic consistency check */
        if(rb->filesize(fd) == sizeof(*settings)){
            rb->read(fd, settings, sizeof(*settings));
            rb->close(fd);
            apply_backlight_setting(settings->general.backlight);
            rb->memcpy(&hdd_clock_settings, settings, sizeof(*settings));
            return(LOADED);
        }
    }
    /* Initializes the settings with default values at least */
    clock_settings_reset(settings);
    return(ERRLOAD);
}

enum settings_file_status clock_settings_save(struct clock_settings* settings,
                                              char* filename){
    int fd = rb->creat(filename);
    if(fd >= 0){ /* does file exist? */
        rb->write (fd, settings, sizeof(*settings));
        rb->close(fd);
        return(SAVED);
    }
    return(ERRSAVE);
}

void draw_logo(struct screen* display){
#ifdef HAVE_LCD_COLOR
    if(display->is_color){
        display->set_foreground(LCD_BLACK);
        display->set_background(LCD_RGBPACK(180,200,230));
    }
#endif

    const struct picture* logo = &(logos[display->screen_type]);
    display->clear_display();
    picture_draw(display, logo, 0, 0);
}

void draw_message(struct screen* display, int msg, int y){
    const struct picture* message = &(messages[display->screen_type]);
    display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
    display->fillrect(0, display->getheight()-message->height,
                      display->getwidth(), message->height);
    display->set_drawmode(DRMODE_SOLID);
    vertical_picture_draw_sprite(display, message, msg,
                                 0, display->getheight()-(message->height*y));
}

void load_settings(void){
    int i;
    struct screen* display;
    FOR_NB_SCREENS(i){
        display=rb->screens[i];
        display->clear_display();
        draw_logo(display);
        draw_message(display, MESSAGE_LOADING, 1);
        display->update();
    }

    enum settings_file_status load_status=
        clock_settings_load(&clock_settings, settings_filename);

    FOR_NB_SCREENS(i){
        display=rb->screens[i];
        if(load_status==LOADED)
            draw_message(display, MESSAGE_LOADED, 1);
        else
            draw_message(display, MESSAGE_ERRLOAD, 1);
        display->update();
    }
    rb->storage_sleep();
    rb->sleep(HZ);
}

void save_settings(void){
    int i;
    struct screen* display;
    if(!settings_needs_saving(&clock_settings))
        return;

    FOR_NB_SCREENS(i){
        display=rb->screens[i];
        display->clear_display();
        draw_logo(display);

        draw_message(display, MESSAGE_SAVING, 1);

        display->update();
    }
    enum settings_file_status load_status=
        clock_settings_save(&clock_settings, settings_filename);

    FOR_NB_SCREENS(i){
        display=rb->screens[i];

        if(load_status==SAVED)
            draw_message(display, MESSAGE_SAVED, 1);
        else
            draw_message(display, MESSAGE_ERRSAVE, 1);
        display->update();
    }
    rb->sleep(HZ);
}

void save_settings_wo_gui(void){
    clock_settings_save(&clock_settings, settings_filename);
}