Beispiel #1
0
void skin_statusbar_changed(struct gui_wps *skin)
{
    if (!skin)
        return;
    struct wps_data *data = skin->data;
    const struct screen *display = skin->display;
    const int   screen = display->screen_type;
    struct skin_viewport *svp = skin_find_item(VP_DEFAULT_LABEL, SKIN_FIND_VP, data);

    struct viewport *vp = &svp->vp;
    viewport_set_defaults(vp, screen);

    if (data->wps_sb_tag)
    {   /* fix up the default viewport */
        if (data->show_sb_on_wps)
        {
            if (statusbar_position(screen) != STATUSBAR_OFF)
                return;     /* vp is fixed already */

            vp->y       = STATUSBAR_HEIGHT;
            vp->height  = display->lcdheight - STATUSBAR_HEIGHT;
        }
        else
        {
            if (statusbar_position(screen) == STATUSBAR_OFF)
                return;     /* vp is fixed already */
            vp->y       = vp->x = 0;
            vp->height  = display->lcdheight;
            vp->width   = display->lcdwidth;
        }
    }
}
Beispiel #2
0
static int parse_statusbar_tags(struct skin_element* element,
                                struct wps_token *token,
                                struct wps_data *wps_data)
{
    (void)element;
    if (token->type == SKIN_TOKEN_DRAW_INBUILTBAR)
    {
        token->value.data = (void*)&curr_vp->vp;
    }
    else
    {
        struct skin_element *def_vp = wps_data->tree;
        struct skin_viewport *default_vp = def_vp->data;
        if (def_vp->params_count == 0)
        {
            wps_data->wps_sb_tag = true;
            wps_data->show_sb_on_wps = (token->type == SKIN_TOKEN_ENABLE_THEME);
        }
        if (wps_data->show_sb_on_wps)
        {
            viewport_set_defaults(&default_vp->vp, curr_screen);
        }
        else
        {
            viewport_set_fullscreen(&default_vp->vp, curr_screen);
        }
#ifdef HAVE_REMOTE_LCD
        /* viewport_set_defaults() sets the font to FONT_UI+curr_screen.
         * This parser requires font 1 to always be the UI font, 
         * so force it back to FONT_UI and handle the screen number at the end */
        default_vp->vp.font = FONT_UI;
#endif
    }
    return 0;
}
Beispiel #3
0
int time_screen(void* ignored)
{
    (void)ignored;
    int nb_lines, font_h, ret;
    menu_was_pressed = false;

    push_current_activity(ACTIVITY_TIMEDATESCREEN);

    FOR_NB_SCREENS(i)
    {
        viewport_set_defaults(&clock_vps[i], i);
#ifdef HAVE_BUTTONBAR
        if (global_settings.buttonbar)
        {
            clock_vps[i].height -= BUTTONBAR_HEIGHT;
        }
#endif
        nb_lines = viewport_get_nb_lines(&clock_vps[i]);

        gui_synclist_set_viewport_defaults(&menu[i], i);
        /* force time to be drawn centered */
        clock_vps[i].flags |= VP_FLAG_ALIGN_CENTER;

        font_h = font_get(clock_vps[i].font)->height;
        nb_lines -= 2; /* at least 2 lines for menu */
        if (nb_lines > 4)
            nb_lines = 4;
        if (nb_lines >= 2)
            clock_vps[i].height = nb_lines*font_h;
        else /* disable the clock_vps drawing */
            clock_vps[i].height = 0;
        menu[i].y += clock_vps[i].height;
        menu[i].height -= clock_vps[i].height;
        draw_timedate(&clock_vps[i], &screens[i]);
    }

#ifdef SAMSUNG_YH820
    /* some hardware revisions of the yh820 have a rtc problem: if you try to set
       the time/date it will leave the player in an absolute unresponsive state
       which can only be reverted by removing the battery. Setting time/date
       should be prohibited on this targets. Fortunately we can autodetect these,
       because they always report "02:02:02" as time.
    */
    struct tm *tm = get_time();
    if (tm->tm_year==102 && tm->tm_hour==2 && tm->tm_min==2 && tm->tm_sec==2) {
        splash(4*HZ, "Can't set time/date due to hardware issues!");
        return 0;
    }
#endif

    ret = do_menu(&time_menu, NULL, menu, false);
    pop_current_activity();
    /* see comments above in the button callback */
    if (!menu_was_pressed && ret == GO_TO_PREVIOUS)
        return 0;
    return ret;
}
void gui_buttonbar_init(struct gui_buttonbar * buttonbar)
{
    int i;
    gui_buttonbar_unset(buttonbar);
    FOR_NB_SCREENS(i)
    {
        viewport_set_defaults(&bb_vp[i], i);
        bb_vp[i].font = FONT_SYSFIXED;
        bb_vp[i].y = screens[i].lcdheight - BUTTONBAR_HEIGHT;
        bb_vp[i].height = BUTTONBAR_HEIGHT;
        bb_vp[i].drawmode = DRMODE_COMPLEMENT;
    }
}
Beispiel #5
0
static void draw_slider(void)
{
    int i;
    FOR_NB_SCREENS(i)
    {
        struct viewport vp;
        int slider_height = 2*screens[i].getcharheight();
        viewport_set_defaults(&vp, i);
        screens[i].set_viewport(&vp);
        show_busy_slider(&screens[i], 1, vp.height - slider_height,
                         vp.width-2, slider_height-1);
        screens[i].update_viewport();
        screens[i].set_viewport(NULL);
    }
}
Beispiel #6
0
static void usb_screen_fix_viewports(struct screen *screen,
        struct usb_screen_vps_t *usb_screen_vps)
{
    bool disable = true;
    int logo_width, logo_height;
    struct viewport *parent = &usb_screen_vps->parent;
    struct viewport *logo = &usb_screen_vps->logo;

#ifdef HAVE_REMOTE_LCD
    if (screen->screen_type == SCREEN_REMOTE)
    {
        logo_width = BMPWIDTH_remote_usblogo;
        logo_height = BMPHEIGHT_remote_usblogo;
    }
    else
#endif
    {
        logo_width = BMPWIDTH_usblogo;
        logo_height = BMPHEIGHT_usblogo;
    }

    viewport_set_defaults(parent, screen->screen_type);
    disable = (parent->width < logo_width || parent->height < logo_height);
    viewportmanager_theme_enable(screen->screen_type, !disable, parent);

    *logo = *parent;
    logo->x = parent->x + parent->width - logo_width;
    logo->y = parent->y + (parent->height - logo_height) / 2;
    logo->width = logo_width;
    logo->height = logo_height;

#ifdef USB_ENABLE_HID
    if (usb_hid)
    {
        struct viewport *title = &usb_screen_vps->title;
        int char_height = font_get(parent->font)->height;
        *title = *parent;
        title->y = logo->y + logo->height + char_height;
        title->height = char_height;
        /* try to fit logo and title to parent */
        if (parent->y + parent->height < title->y + title->height)
        {
            logo->y = parent->y;
            title->y = parent->y + logo->height;
        }
    }
#endif
}
Beispiel #7
0
int time_screen(void* ignored)
{
    (void)ignored;
    int nb_lines, font_h, ret;
    menu_was_pressed = false;

    push_current_activity(ACTIVITY_TIMEDATESCREEN);

    FOR_NB_SCREENS(i)
    {
        viewport_set_defaults(&clock_vps[i], i);
#ifdef HAVE_BUTTONBAR
        if (global_settings.buttonbar)
        {
            clock_vps[i].height -= BUTTONBAR_HEIGHT;
        }
#endif
        nb_lines = viewport_get_nb_lines(&clock_vps[i]);

        gui_synclist_set_viewport_defaults(&menu[i], i);
        /* force time to be drawn centered */
        clock_vps[i].flags |= VP_FLAG_ALIGN_CENTER;

        font_h = font_get(clock_vps[i].font)->height;
        nb_lines -= 2; /* at least 2 lines for menu */
        if (nb_lines > 4)
            nb_lines = 4;
        if (nb_lines >= 2)
            clock_vps[i].height = nb_lines*font_h;
        else /* disable the clock_vps drawing */
            clock_vps[i].height = 0;
        menu[i].y += clock_vps[i].height;
        menu[i].height -= clock_vps[i].height;
        draw_timedate(&clock_vps[i], &screens[i]);
    }

    ret = do_menu(&time_menu, NULL, menu, false);
    pop_current_activity();
    /* see comments above in the button callback */
    if (!menu_was_pressed && ret == GO_TO_PREVIOUS)
        return 0;
    return ret;
}
Beispiel #8
0
void gui_usb_screen_run(bool early_usb)
{
    (void) early_usb;
    struct usb_screen_vps_t usb_screen_vps_ar[NB_SCREENS];
#if defined HAVE_TOUCHSCREEN
    enum touchscreen_mode old_mode = touchscreen_get_mode();

    /* TODO: Paint buttons on screens OR switch to point mode and use
     * touchscreen as a touchpad to move the host's mouse cursor */
    touchscreen_set_mode(TOUCHSCREEN_BUTTON);
#endif

    push_current_activity(ACTIVITY_USBSCREEN);

#ifdef USB_ENABLE_HID
    usb_hid = global_settings.usb_hid;
    usb_keypad_mode = global_settings.usb_keypad_mode;
#endif

    FOR_NB_SCREENS(i)
    {
        struct screen *screen = &screens[i];

        screen->set_viewport(NULL);
#ifdef HAVE_LCD_CHARCELLS
        /* Quick fix. Viewports should really be enabled proper for charcell */
        viewport_set_defaults(&usb_screen_vps_ar[i].parent, i);
#else
        usb_screen_fix_viewports(screen, &usb_screen_vps_ar[i]);
#endif
    }

    /* update the UI before disabling fonts, this maximizes the propability
     * that font cache lookups succeed during USB */
    send_event(GUI_EVENT_ACTIONUPDATE, NULL);
#ifdef HAVE_LCD_BITMAP
    if(!early_usb)
    {
        /* The font system leaves the .fnt fd's open, so we need for force close them all */
        font_disable_all();
    }
#endif

    usb_acknowledge(SYS_USB_CONNECTED_ACK);

    while (1)
    {
        usb_screens_draw(usb_screen_vps_ar);
#ifdef SIMULATOR
        if (button_get_w_tmo(HZ/2))
            break;
        send_event(GUI_EVENT_ACTIONUPDATE, NULL);
#else
        if (handle_usb_events())
            break;
#endif /* SIMULATOR */
    }

    FOR_NB_SCREENS(i)
    {
        const struct viewport* vp = NULL;

#if defined(HAVE_LCD_BITMAP) && defined(USB_ENABLE_HID)
        vp = usb_hid ? &usb_screen_vps_ar[i].title : NULL;
#elif !defined(HAVE_LCD_BITMAP)
        vp = &usb_screen_vps_ar[i].parent;
#endif
        if (vp)
            screens[i].scroll_stop_viewport(vp);
    }
#ifdef USB_ENABLE_HID
    if (global_settings.usb_keypad_mode != usb_keypad_mode)
    {
        global_settings.usb_keypad_mode = usb_keypad_mode;
        settings_save();
    }
#endif

#ifdef HAVE_TOUCHSCREEN
    touchscreen_set_mode(old_mode);
#endif

#ifdef HAVE_LCD_CHARCELLS
    status_set_usb(false);
#endif /* HAVE_LCD_CHARCELLS */

#ifdef HAVE_LCD_BITMAP
    if(!early_usb)
    {
        font_enable_all();
        /* Not pretty, reload all settings so fonts are loaded again correctly */
        settings_apply(true);
        /* Reload playlist */
        playlist_resume();
    }
#endif

    FOR_NB_SCREENS(i)
    {
        screens[i].backlight_on();
        viewportmanager_theme_undo(i, false);
    }

    pop_current_activity();
}
Beispiel #9
0
bool alarm_screen(void)
{
    int h, m;
    bool done = false;
    struct tm *tm;
    int togo;
    int button;
    bool update = true;
    bool hour_wrapped = false;
    struct viewport vp[NB_SCREENS];

    rtc_get_alarm(&h, &m);

    /* After a battery change the RTC values are out of range */
    if (m > 60 || h > 24) {
        m = 0;
        h = 12;
    } else {
        m = m / 5 * 5; /* 5 min accuracy should be enough */
    }
    FOR_NB_SCREENS(i)
    {
        viewport_set_defaults(&vp[i], i);
    }

    while(!done) {
        if(update)
        {
            FOR_NB_SCREENS(i)
            {
                screens[i].set_viewport(&vp[i]);
                screens[i].clear_viewport();
                screens[i].puts(0, 4, str(LANG_ALARM_MOD_KEYS));
            }
            /* Talk when entering the wakeup screen */
            speak_time(h, m, true, true);
            update = false;
        }

        FOR_NB_SCREENS(i)
        {
            screens[i].set_viewport(&vp[i]);
            screens[i].putsf(0, 1, str(LANG_ALARM_MOD_TIME));
            screens[i].putsf(0, 2, "%02d:%02d", h, m);
            screens[i].update_viewport();
            screens[i].set_viewport(NULL);
        }
        button = get_action(CONTEXT_SETTINGS,HZ);

        switch(button) {
            case ACTION_STD_OK:
            /* prevent that an alarm occurs in the shutdown procedure */
            /* accept alarms only if they are in 2 minutes or more */
            tm = get_time();
            togo = (m + h * 60 - tm->tm_min - tm->tm_hour * 60 + 1440) % 1440;

            if (togo > 1) {
                rtc_init();
                rtc_set_alarm(h,m);
                rtc_enable_alarm(true);
                if (global_settings.talk_menu)
                {
                    talk_id(LANG_ALARM_MOD_TIME_TO_GO, true);
                    talk_value(togo / 60, UNIT_HOUR, true);
                    talk_value(togo % 60, UNIT_MIN, true);
                    talk_force_enqueue_next();
                }
                splashf(HZ*2, str(LANG_ALARM_MOD_TIME_TO_GO),
                               togo / 60, togo % 60);
                done = true;
            } else {
                splash(HZ, ID2P(LANG_ALARM_MOD_ERROR));
                update = true;
            }
            break;

         /* inc(m) */
        case ACTION_SETTINGS_INC:
        case ACTION_SETTINGS_INCREPEAT:
            m += 5;
            if (m == 60) {
                h += 1;
                m = 0;
                hour_wrapped = true;
            }
            if (h == 24)
                h = 0;

            speak_time(h, m, hour_wrapped, false);
            break;

         /* dec(m) */
        case ACTION_SETTINGS_DEC:
        case ACTION_SETTINGS_DECREPEAT:
             m -= 5;
             if (m == -5) {
                 h -= 1;
                 m = 55;
                 hour_wrapped = true;
             }
             if (h == -1)
                 h = 23;

             speak_time(h, m, hour_wrapped, false);
             break;

         /* inc(h) */
         case ACTION_STD_NEXT:
         case ACTION_STD_NEXTREPEAT:
             h = (h+1) % 24;

             if (global_settings.talk_menu)
                 talk_value(h, UNIT_HOUR, false);
             break;

         /* dec(h) */
        case ACTION_STD_PREV:
        case ACTION_STD_PREVREPEAT:
             h = (h+23) % 24;
             
             if (global_settings.talk_menu)
                 talk_value(h, UNIT_HOUR, false);
             break;

        case ACTION_STD_CANCEL:
            rtc_enable_alarm(false);
            splash(HZ*2, ID2P(LANG_ALARM_MOD_DISABLE));
            done = true;
            break;

        case ACTION_NONE:
            hour_wrapped = false;
            break;

        default:
            if(default_event_handler(button) == SYS_USB_CONNECTED)
            {
                rtc_enable_alarm(false);
                return true;
            }
            break;
        }
    }
    return false;
}
enum yesno_res gui_syncyesno_run(const struct text_message * main_message,
                                 const struct text_message * yes_message,
                                 const struct text_message * no_message)
{
    int button;
    int result=-1;
    bool result_displayed;
    struct gui_yesno yn[NB_SCREENS];
    struct viewport vp[NB_SCREENS];
    long talked_tick = 0;
    FOR_NB_SCREENS(i)
    {
        yn[i].main_message=main_message;
        yn[i].result_message[YESNO_YES]=yes_message;
        yn[i].result_message[YESNO_NO]=no_message;
        yn[i].display=&screens[i];
        yn[i].vp = &vp[i];
#ifdef HAVE_LCD_CHARCELLS
        /* Quick fix. Viewports should really be enabled proper for charcell */
        viewport_set_defaults(yn[i].vp, i);
#else
        viewportmanager_theme_enable(i, true, yn[i].vp);
#endif
        screens[i].stop_scroll();
        gui_yesno_draw(&(yn[i]));
    }
    /* make sure to eat any extranous keypresses */
    while (get_action(CONTEXT_STD+99, TIMEOUT_NOBLOCK))
        action_wait_for_release();
    while (result==-1)
    {
        /* Repeat the question every 5secs (more or less) */
        if (global_settings.talk_menu
                && (talked_tick==0 || TIME_AFTER(current_tick, talked_tick+HZ*5)))
        {
            talked_tick = current_tick;
            talk_text_message(main_message, false);
        }
        button = get_action(CONTEXT_YESNOSCREEN, HZ*5);
        switch (button)
        {
#ifdef HAVE_TOUCHSCREEN
        case ACTION_TOUCHSCREEN:
        {
            short int x, y;
            if (action_get_touchscreen_press_in_vp(&x, &y, yn[0].vp) == BUTTON_TOUCHSCREEN)
            {
                if (y > yn[0].vp->height/2)
                {
                    if (x <= yn[0].vp->width/2)
                        result = YESNO_YES;
                    else
                        result = YESNO_NO;
                }
            }
        }
        break;
#endif
        case ACTION_YESNO_ACCEPT:
            result=YESNO_YES;
            break;
        case ACTION_NONE:
        case SYS_CHARGER_DISCONNECTED:
        case SYS_BATTERY_UPDATE:
            /* ignore some SYS events that can happen */
            continue;
        default:
            if(default_event_handler(button) == SYS_USB_CONNECTED)
                return(YESNO_USB);
            result = YESNO_NO;
        }
    }

    FOR_NB_SCREENS(i)
    result_displayed=gui_yesno_draw_result(&(yn[i]), result);

    if (global_settings.talk_menu)
    {
        talk_text_message((result == YESNO_YES) ? yes_message
                          : no_message, false);
        talk_force_enqueue_next();
    }
    if(result_displayed)
        sleep(HZ);

    FOR_NB_SCREENS(i)
    {
        screens[i].scroll_stop(yn[i].vp);
        viewportmanager_theme_undo(i, true);
    }
    return(result);
}
Beispiel #11
0
static bool gui_syncquickscreen_run(struct gui_quickscreen * qs, int button_enter)
{
    int button, i, j;
    struct viewport parent[NB_SCREENS];
    struct viewport vps[NB_SCREENS][QUICKSCREEN_ITEM_COUNT];
    struct viewport vp_icons[NB_SCREENS];
    bool changed = false;
    /* To quit we need either :
     *  - a second press on the button that made us enter
     *  - an action taken while pressing the enter button,
     *    then release the enter button*/
    bool can_quit = false;
    FOR_NB_SCREENS(i)
    {
        screens[i].set_viewport(NULL);
        screens[i].stop_scroll();
        viewport_set_defaults(&parent[i], i);
        quickscreen_fix_viewports(qs, &screens[i], &parent[i], vps[i], &vp_icons[i]);
        gui_quickscreen_draw(qs, &screens[i], &parent[i], vps[i], &vp_icons[i]);
    }
    /* Announce current selection on entering this screen. This is all
       queued up, but can be interrupted as soon as a setting is
       changed. */
    cond_talk_ids(VOICE_QUICKSCREEN);
    talk_qs_option(qs->items[QUICKSCREEN_TOP], true);
    talk_qs_option(qs->items[QUICKSCREEN_LEFT], true);
    talk_qs_option(qs->items[QUICKSCREEN_BOTTOM], true);
    talk_qs_option(qs->items[QUICKSCREEN_RIGHT], true);
    while (true) {
        button = get_action(CONTEXT_QUICKSCREEN, HZ/5);
#ifdef HAVE_TOUCHSCREEN
        if (button == ACTION_TOUCHSCREEN)
            button = quickscreen_touchscreen_button(vps[SCREEN_MAIN]);
#endif
        if (default_event_handler(button) == SYS_USB_CONNECTED)
            return(true);
        if (gui_quickscreen_do_button(qs, button))
        {
            changed = true;
            can_quit = true;
            FOR_NB_SCREENS(i)
                gui_quickscreen_draw(qs, &screens[i], &parent[i],
                                     vps[i], &vp_icons[i]);
            if (qs->callback)
                qs->callback(qs);
        }
        else if (button == button_enter)
            can_quit = true;
            
        if ((button == button_enter) && can_quit)
            break;
            
        if (button == ACTION_STD_CANCEL)
            break;
    }
    /* Notify that we're exiting this screen */
    cond_talk_ids_fq(VOICE_OK);
    FOR_NB_SCREENS(i)
    {   /* stop scrolling before exiting */
        for (j = 0; j < QUICKSCREEN_ITEM_COUNT; j++)
            screens[i].scroll_stop(&vps[i][j]);
    }
    
    return changed;
}
static int touchscreen_slider(struct screen *display,
                                struct rgb_pick *rgb,
                                int *selected_slider)
{
    short     x, y;
    int       char_height, line_height;
    int       max_label_width;
    int       text_top, slider_x, slider_width;
    bool      display_three_rows;
    int       button;
    int       pressed_slider;
    struct viewport vp;

    viewport_set_defaults(&vp, display->screen_type);
    display->set_viewport(&vp);

    button = action_get_touchscreen_press_in_vp(&x, &y, &vp);
    if (button == ACTION_UNKNOWN || button == BUTTON_NONE)
        return ACTION_NONE;
    /* Get slider positions and top starting position
     * need vp.y here, because of the statusbar, since touchscreen
     * coordinates are absolute */
    max_label_width = label_get_max_width(display);
    char_height  = display->getcharheight();
    text_top     = MARGIN_TOP + char_height +
                   TITLE_MARGIN_BOTTOM + SELECTOR_TB_MARGIN;
    slider_x     = SELECTOR_WIDTH + max_label_width + SLIDER_TEXT_MARGIN;
    slider_width = vp.width - slider_x*2 - max_label_width;
    line_height  = char_height + 2*SELECTOR_TB_MARGIN;

    /* same logic as in draw_screen */
    /* Find out if there's enough room for three sliders or just
       enough to display the selected slider - calculate total height
       of display with three sliders present */
    display_three_rows =
        vp.height >=
            text_top + line_height*3  + /* Title + 3 sliders     */
            SWATCH_TOP_MARGIN         + /* at least 2 lines      */
            char_height*2             + /*  + margins for bottom */
            MARGIN_BOTTOM;              /* colored rectangle     */

    display->set_viewport(NULL);

    if (y < text_top)
    {
        if (button == BUTTON_REL)
            return ACTION_STD_CANCEL;
        else
            return ACTION_NONE;
    }

    if (y >= text_top + line_height * (display_three_rows ? 3:1))
    {   /* touching the color area means accept */
        if (button == BUTTON_REL)
            return ACTION_STD_OK;
        else
            return ACTION_NONE;
    }
    /* y is relative to the original viewport */
    pressed_slider = (y - text_top)/line_height;
    if (pressed_slider != *selected_slider)
        *selected_slider = pressed_slider;
    /* add max_label_width to overcome integer division limits,
     * cap value later since that may lead to an overflow */
    if (x < slider_x + (slider_width+max_label_width) && x > slider_x)
    {
        char computed_val;
        x -= slider_x;
        computed_val = (x*rgb_max[pressed_slider]/(slider_width));
        rgb->rgb_val[pressed_slider] =
                        MIN(computed_val,rgb_max[pressed_slider]);
        pack_rgb(rgb);
    }
    return ACTION_NONE;
}
static void draw_screen(struct screen *display, char *title,
                        struct rgb_pick *rgb, int row)
{
    unsigned  text_color       = LCD_BLACK;
    unsigned  background_color = LCD_WHITE;
    char      buf[32];
    int       i, char_height, line_height;
    int       max_label_width;
    int       text_x, text_top;
    int       slider_x, slider_width;
    bool      display_three_rows;
    struct viewport vp;

    viewport_set_defaults(&vp, display->screen_type);
    display->set_viewport(&vp);

    display->clear_viewport();

    if (display->depth > 1)
    {
        text_color       = display->get_foreground();
        background_color = display->get_background();
    }

    /* Draw title string */
    set_drawinfo(display, DRMODE_SOLID, text_color, background_color);
    vp.flags |= VP_FLAG_ALIGN_CENTER;
    display->putsxy(0, MARGIN_TOP, title);

    /* Get slider positions and top starting position */
    max_label_width = label_get_max_width(display);
    char_height  = display->getcharheight();
    text_top     = MARGIN_TOP + char_height +
                   TITLE_MARGIN_BOTTOM + SELECTOR_TB_MARGIN;
    text_x       = SELECTOR_WIDTH;
    slider_x     = text_x + max_label_width + SLIDER_TEXT_MARGIN;
    slider_width = vp.width - slider_x*2 - max_label_width;
    line_height  = char_height + 2*SELECTOR_TB_MARGIN;

    /* Find out if there's enough room for three sliders or just
       enough to display the selected slider - calculate total height
       of display with three sliders present */
    display_three_rows =
        vp.height >=
            text_top + line_height*3  + /* Title + 3 sliders     */
            SWATCH_TOP_MARGIN         + /* at least 2 lines      */
            char_height*2             + /*  + margins for bottom */
            MARGIN_BOTTOM;              /* colored rectangle     */

    for (i = 0; i < 3; i++)
    {
        unsigned sb_flags = HORIZONTAL;
        int      mode     = DRMODE_SOLID;
        unsigned fg       = text_color;
        unsigned bg       = background_color;

        if (i == row)
        {
            set_drawinfo(display, DRMODE_SOLID, text_color, background_color);

            if (global_settings.cursor_style != 0)
            {
                /* Draw solid bar selection bar */
                display->fillrect(0,
                                  text_top - SELECTOR_TB_MARGIN,
                                  vp.width,
                                  char_height + SELECTOR_TB_MARGIN*2);

                if (display->depth < 16)
                {
                    sb_flags |= FOREGROUND | INNER_FILL;
                    mode     |= DRMODE_INVERSEVID;
                }
            }
            else if (display_three_rows)
            {
                /* Draw ">    <" around sliders */
                int top = text_top + (char_height - SELECTOR_HEIGHT) / 2;
                screen_put_iconxy(display, 0, top, Icon_Cursor);
                screen_put_iconxy(display,
                                  vp.width - SELECTOR_WIDTH,
                                  top, Icon_Cursor);
            }

            if (display->depth >= 16)
            {
                sb_flags |= FOREGROUND | INNER_BGFILL;
                mode      = DRMODE_FG;
                fg        = prim_rgb[SB_PRIM][i];
                bg        = prim_rgb[SB_FILL][i];
            }
        }
        else if (!display_three_rows)
            continue;

        set_drawinfo(display, mode, fg, bg);

        /* Draw label */
        buf[0] = str(LANG_COLOR_RGB_LABELS)[i];
        buf[1] = '\0';
        vp.flags &= ~VP_FLAG_ALIGNMENT_MASK;
        display->putsxy(text_x, text_top, buf);
        /* Draw color value */
        snprintf(buf, 3, "%02d", rgb->rgb_val[i]);
        vp.flags |= VP_FLAG_ALIGN_RIGHT;
        display->putsxy(text_x, text_top, buf);

        /* Draw scrollbar */
        gui_scrollbar_draw(display,                     /* screen */
                           slider_x,                    /* x */
                           text_top + char_height / 4,  /* y */
                           slider_width,                /* width */
                           char_height / 2,             /* height */
                           rgb_max[i],                  /* items */
                           0,                           /* min_shown */
                           rgb->rgb_val[i],             /* max_shown */
                           sb_flags);                   /* flags */

        /* Advance to next line */
        text_top += line_height;
    } /* end for */

    /* Format RGB: #rrggbb */
    snprintf(buf, sizeof(buf), str(LANG_COLOR_RGB_VALUE),
                               rgb->red, rgb->green, rgb->blue);
    vp.flags |= VP_FLAG_ALIGN_CENTER;
    if (display->depth >= 16)
    {
        /* Display color swatch on color screens only */
        int top    = text_top + SWATCH_TOP_MARGIN;
        int width  = vp.width - text_x*2;
        int height = vp.height - top - MARGIN_BOTTOM;

        /* Only draw if room */
        if (height >= char_height + 2)
        {
            /* draw the big rectangle */
            display->set_foreground(rgb->color);
            display->fillrect(text_x, top, width, height);

            /* Draw RGB: #rrggbb in middle of swatch */
            set_drawinfo(display, DRMODE_FG, get_black_or_white(rgb),
                         background_color);

            display->putsxy(0, top + (height - char_height) / 2, buf);

            /* Draw border around the rect */
            set_drawinfo(display, DRMODE_SOLID, text_color, background_color);
            display->drawrect(text_x, top, width, height);
        }
    }
    else
    {
        /* Display RGB value only centered on remaining display if room */
        int top = text_top + SWATCH_TOP_MARGIN;
        int height = vp.height - top - MARGIN_BOTTOM;

        if (height >= char_height)
        {
            set_drawinfo(display, DRMODE_SOLID, text_color, background_color);
            display->putsxy(0, top + (height - char_height) / 2, buf);
        }
    }

    display->update_viewport();
    display->set_viewport(NULL);
}
Beispiel #14
0
void gui_usb_screen_run(void)
{
    int i;
    struct usb_screen_vps_t usb_screen_vps_ar[NB_SCREENS];
#if defined HAVE_TOUCHSCREEN
    enum touchscreen_mode old_mode = touchscreen_get_mode();

    /* TODO: Paint buttons on screens OR switch to point mode and use
     * touchscreen as a touchpad to move the host's mouse cursor */
    touchscreen_set_mode(TOUCHSCREEN_BUTTON);
#endif

#ifndef SIMULATOR
    usb_acknowledge(SYS_USB_CONNECTED_ACK);
#endif

#ifdef USB_ENABLE_HID
    usb_hid = global_settings.usb_hid;
    usb_keypad_mode = global_settings.usb_keypad_mode;
#endif

    FOR_NB_SCREENS(i)
    {
        struct screen *screen = &screens[i];

        screen->set_viewport(NULL);
#ifdef HAVE_LCD_CHARCELLS
        /* Quick fix. Viewports should really be enabled proper for charcell */
        viewport_set_defaults(&usb_screen_vps_ar[i].parent, i);
#else
        usb_screen_fix_viewports(screen, &usb_screen_vps_ar[i]);
#endif
    }

    while (1)
    {
        usb_screens_draw(usb_screen_vps_ar);
#ifdef SIMULATOR
        if (button_get_w_tmo(HZ/2))
            break;
        send_event(GUI_EVENT_ACTIONUPDATE, NULL);
#else
        if (handle_usb_events())
            break;
#endif /* SIMULATOR */
    }

    FOR_NB_SCREENS(i)
    {
        const struct viewport* vp = NULL;

#if defined(HAVE_LCD_BITMAP) && defined(USB_ENABLE_HID)
        vp = usb_hid ? &usb_screen_vps_ar[i].title : NULL;
#elif !defined(HAVE_LCD_BITMAP)
        vp = &usb_screen_vps_ar[i].parent;
#endif
        if (vp)
            screens[i].scroll_stop(vp);
    }
#ifdef USB_ENABLE_HID
    if (global_settings.usb_keypad_mode != usb_keypad_mode)
    {
        global_settings.usb_keypad_mode = usb_keypad_mode;
        settings_save();
    }
#endif

#ifdef HAVE_TOUCHSCREEN
    touchscreen_set_mode(old_mode);
#endif

#ifdef HAVE_LCD_CHARCELLS
    status_set_usb(false);
#endif /* HAVE_LCD_CHARCELLS */
    FOR_NB_SCREENS(i)
    {
        screens[i].backlight_on();
        viewportmanager_theme_undo(i, false);
    }

}
Beispiel #15
0
enum yesno_res gui_syncyesno_run(const struct text_message * main_message,
                                 const struct text_message * yes_message,
                                 const struct text_message * no_message)
{
    int i;
    int button;
    int result=-1;
    bool result_displayed;
    struct gui_yesno yn[NB_SCREENS];
    struct viewport vp[NB_SCREENS];
    long talked_tick = 0;
    FOR_NB_SCREENS(i)
    {
        yn[i].main_message=main_message;
        yn[i].result_message[YESNO_YES]=yes_message;
        yn[i].result_message[YESNO_NO]=no_message;
        yn[i].display=&screens[i];
        yn[i].vp = &vp[i];
        viewport_set_defaults(yn[i].vp, i);
        screens[i].stop_scroll();
        gui_yesno_draw(&(yn[i]));
    }
    while (result==-1)
    {
        /* Repeat the question every 5secs (more or less) */
        if (global_settings.talk_menu
            && (talked_tick==0 || TIME_AFTER(current_tick, talked_tick+HZ*5)))
        {
            talked_tick = current_tick;
            talk_text_message(main_message, false);
        }
        button = get_action(CONTEXT_YESNOSCREEN, HZ*5);
        switch (button)
        {
            case ACTION_YESNO_ACCEPT:
                result=YESNO_YES;
                break;
            case ACTION_NONE:
            case SYS_CHARGER_DISCONNECTED:
                /* ignore some SYS events that can happen */
                continue;
            default:
                if(default_event_handler(button) == SYS_USB_CONNECTED)
                    return(YESNO_USB);
                result = YESNO_NO;
        }
    }

    FOR_NB_SCREENS(i)
        result_displayed=gui_yesno_draw_result(&(yn[i]), result);

    if (global_settings.talk_menu)
    {
        talk_text_message((result == YESNO_YES) ? yes_message 
                          : no_message, false);
        talk_force_enqueue_next();
    }
    if(result_displayed)
        sleep(HZ);

    FOR_NB_SCREENS(i) /* stop scrolling before getting out */
        screens[i].scroll_stop(yn[i].vp);
    return(result);
}
Beispiel #16
0
static void splash_internal(struct screen * screen, const char *fmt, va_list ap)
{
    char splash_buf[MAXBUFFER];
    char *lines[MAXLINES];

    char *next;
    char *lastbreak = NULL;
    char *store = NULL;
    int line = 0;
    int x = 0;
    int y, i;
    int space_w, w, h;
    struct viewport vp;
#ifdef HAVE_LCD_BITMAP
    int width, height;
    int maxw = 0;

    viewport_set_defaults(&vp, screen->screen_type);
    screen->set_viewport(&vp);
    
    screen->getstringsize(" ", &space_w, &h);
#else /* HAVE_LCD_CHARCELLS */
    vp.width = screen->lcdwidth;
    vp.height = screen->lcdheight;

    space_w = h = 1;
    screen->double_height (false);
#endif
    y = h;

    vsnprintf(splash_buf, sizeof(splash_buf), fmt, ap);
    va_end(ap);

    /* break splash string into display lines, doing proper word wrap */

    next = strtok_r(splash_buf, " ", &store);
    if (!next)
        goto end; /* nothing to display */

    lines[0] = next;
    while (true)
    {
#ifdef HAVE_LCD_BITMAP
        screen->getstringsize(next, &w, NULL);
#else
        w = utf8length(next);
#endif
        if (lastbreak)
        {
            if (x + (next - lastbreak) * space_w + w
                    > vp.width - RECT_SPACING*2)
            {   /* too wide, wrap */
#ifdef HAVE_LCD_BITMAP
                if (x > maxw)
                    maxw = x;
#endif
                if ((y + h > vp.height) || (line >= (MAXLINES-1)))
                    break;  /* screen full or out of lines */
                x = 0;
                y += h;
                lines[++line] = next;
            }
            else
            {
                /*  restore & calculate spacing */
                *lastbreak = ' ';
                x += (next - lastbreak) * space_w;
            }
        }
        x += w;
        lastbreak = next + strlen(next);
        next = strtok_r(NULL, " ", &store);
        if (!next)
        {   /* no more words */
#ifdef HAVE_LCD_BITMAP
            if (x > maxw)
                maxw = x;
#endif
            break;
        }
    }

    /* prepare viewport
     * First boundaries, then the grey filling, then the black border and finally
     * the text*/

    screen->scroll_stop();

#ifdef HAVE_LCD_BITMAP

    width = maxw + 2*RECT_SPACING;
    height = y + 2*RECT_SPACING;

    if (width > vp.width)
        width = vp.width;
    if (height > vp.height)
        height = vp.height;

    vp.x += (vp.width - width) / 2;
    vp.y += (vp.height - height) / 2;
    vp.width = width;
    vp.height = height;
    
    vp.flags |=  VP_FLAG_ALIGN_CENTER;
#if LCD_DEPTH > 1
    if (screen->depth > 1)
    {
        vp.drawmode = DRMODE_FG;
        /* can't do vp.fg_pattern here, since set_foreground does a bit more on
         * greyscale */
        screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_LIGHTGRAY));
    }
    else
#endif
        vp.drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID);

    screen->fill_viewport();

#if LCD_DEPTH > 1
    if (screen->depth > 1)
        /* can't do vp.fg_pattern here, since set_foreground does a bit more on
         * greyscale */
        screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_BLACK));
    else
#endif
        vp.drawmode = DRMODE_SOLID;

    screen->draw_border_viewport();

    /* prepare putting the text */
    y = RECT_SPACING;
#else /* HAVE_LCD_CHARCELLS */
    y = 0;    /* vertical centering on 2 lines would be silly */
    screen->clear_display();
#endif

    /* print the message to screen */
    for (i = 0; i <= line; i++, y+=h)
    {
#ifdef HAVE_LCD_BITMAP
        screen->putsxy(0, y, lines[i]);
#else
        screen->puts(0, y, lines[i]);
#endif
    }
    screen->update_viewport();
end:
    screen->set_viewport(NULL);
}
Beispiel #17
0
int gui_syncpitchscreen_run(void)
{
    int button, i;
    int32_t pitch = sound_get_pitch();
    int32_t semitone;

    int32_t new_pitch;
    int32_t pitch_delta;
    bool nudged = false;
    bool exit = false;
    /* should maybe be passed per parameter later, not needed for now */
    struct viewport parent[NB_SCREENS];
    struct viewport pitch_viewports[NB_SCREENS][PITCH_ITEM_COUNT];
    int max_lines[NB_SCREENS];

#if CONFIG_CODEC == SWCODEC
    int32_t new_speed = 0, new_stretch;

    /* the speed variable holds the apparent speed of the playback */
    int32_t speed;
    if (dsp_timestretch_available())
    {
        speed = GET_SPEED(pitch, dsp_get_timestretch());
    }
    else
    {
        speed = pitch;
    }

    /* Figure out whether to be in timestretch mode */
    if (global_settings.pitch_mode_timestretch && !dsp_timestretch_available())
    {
        global_settings.pitch_mode_timestretch = false;
        settings_save();
    }
#endif

    /* set the semitone index based on the current pitch */
    semitone = get_semitone_from_pitch(pitch);

    /* initialize pitchscreen vps */
    FOR_NB_SCREENS(i)
    {
        viewport_set_defaults(&parent[i], i);
        max_lines[i] = viewport_get_nb_lines(&parent[i]);
        pitchscreen_fix_viewports(&parent[i], pitch_viewports[i]);
        screens[i].set_viewport(&parent[i]);
        screens[i].clear_viewport();

        /* also, draw the icons now, it's only needed once */
        pitchscreen_draw_icons(&screens[i], &parent[i]);
    }
#if CONFIG_CODEC == SWCODEC
    pcmbuf_set_low_latency(true);
#endif

    while (!exit)
    {
        FOR_NB_SCREENS(i)
            pitchscreen_draw(&screens[i], max_lines[i],
                              pitch_viewports[i], pitch, semitone
#if CONFIG_CODEC == SWCODEC
                              , speed
#endif
                              );
        pitch_delta = 0;
#if CONFIG_CODEC == SWCODEC
        new_speed = 0;
#endif
        button = get_action(CONTEXT_PITCHSCREEN, HZ);
        
#ifdef HAVE_TOUCHSCREEN
        if (button == ACTION_TOUCHSCREEN)
        {
            FOR_NB_SCREENS(i)
                button = pitchscreen_do_touchscreen(pitch_viewports[i]);
        }
#endif
        switch (button)
        {
            case ACTION_PS_INC_SMALL:
                if(global_settings.pitch_mode_semitone)
                    pitch_delta = SEMITONE_SMALL_DELTA;
                else 
                    pitch_delta = PITCH_SMALL_DELTA;
                break;

            case ACTION_PS_INC_BIG:
                if(global_settings.pitch_mode_semitone)
                    pitch_delta = SEMITONE_BIG_DELTA;
                else 
                    pitch_delta = PITCH_BIG_DELTA;
                break;

            case ACTION_PS_DEC_SMALL:
                if(global_settings.pitch_mode_semitone)
                    pitch_delta = -SEMITONE_SMALL_DELTA;
                else 
                    pitch_delta = -PITCH_SMALL_DELTA;
                break;

            case ACTION_PS_DEC_BIG:
                if(global_settings.pitch_mode_semitone)
                    pitch_delta = -SEMITONE_BIG_DELTA;
                else 
                    pitch_delta = -PITCH_BIG_DELTA;
                break;

            case ACTION_PS_NUDGE_RIGHT:
#if CONFIG_CODEC == SWCODEC
                if (!global_settings.pitch_mode_timestretch)
                {
#endif
                    new_pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false
#if CONFIG_CODEC == SWCODEC
                                               , speed
#endif                            
                        );
                    nudged = (new_pitch != pitch);
                    pitch = new_pitch;
                    semitone = get_semitone_from_pitch(pitch);
#if CONFIG_CODEC == SWCODEC
                    speed = pitch;
#endif
                    break;
#if CONFIG_CODEC == SWCODEC
                }
                else
                {
                    new_speed = speed + SPEED_SMALL_DELTA;
                    at_limit = false;
                }
                break;

            case ACTION_PS_FASTER:
                if (global_settings.pitch_mode_timestretch)
                {
                    new_speed = speed + SPEED_BIG_DELTA;
                    /* snap to whole numbers */
                    if(new_speed % PITCH_SPEED_PRECISION != 0)
                        new_speed -= new_speed % PITCH_SPEED_PRECISION;
                    at_limit = false;
                }
                break;
#endif

            case ACTION_PS_NUDGE_RIGHTOFF:
                if (nudged)
                {
                    pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false
#if CONFIG_CODEC == SWCODEC
                                           , speed
#endif                            
                        );
#if CONFIG_CODEC == SWCODEC
                    speed = pitch;
#endif
                    semitone = get_semitone_from_pitch(pitch);
                    nudged = false;
                }
                break;

            case ACTION_PS_NUDGE_LEFT:
#if CONFIG_CODEC == SWCODEC
                if (!global_settings.pitch_mode_timestretch)
                {
#endif
                    new_pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false
#if CONFIG_CODEC == SWCODEC
                                               , speed
#endif                            
                        );
                    nudged = (new_pitch != pitch);
                    pitch = new_pitch;
                    semitone = get_semitone_from_pitch(pitch);
#if CONFIG_CODEC == SWCODEC
                    speed = pitch;
#endif
                    break;
#if CONFIG_CODEC == SWCODEC
                }
                else
                {
                    new_speed = speed - SPEED_SMALL_DELTA;
                    at_limit = false;
                }
                break;

            case ACTION_PS_SLOWER:
                if (global_settings.pitch_mode_timestretch)
                {
                    new_speed = speed - SPEED_BIG_DELTA;
                    /* snap to whole numbers */
                    if(new_speed % PITCH_SPEED_PRECISION != 0)
                        new_speed += PITCH_SPEED_PRECISION - speed % PITCH_SPEED_PRECISION;
                    at_limit = false;
                }
                break;
#endif

            case ACTION_PS_NUDGE_LEFTOFF:
                if (nudged)
                {
                    pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false
#if CONFIG_CODEC == SWCODEC
                                           , speed
#endif                            
                        );
#if CONFIG_CODEC == SWCODEC
                    speed = pitch;
#endif
                    semitone = get_semitone_from_pitch(pitch);
                    nudged = false;
                }
                break;

            case ACTION_PS_RESET:
                pitch = PITCH_SPEED_100;
                sound_set_pitch(pitch);
#if CONFIG_CODEC == SWCODEC
                speed = PITCH_SPEED_100;
                if (dsp_timestretch_available())
                {
                    dsp_set_timestretch(PITCH_SPEED_100);
                    at_limit = false;
                }
#endif
                semitone = get_semitone_from_pitch(pitch);
                break;

            case ACTION_PS_TOGGLE_MODE:
                global_settings.pitch_mode_semitone = !global_settings.pitch_mode_semitone;
#if CONFIG_CODEC == SWCODEC

                if (dsp_timestretch_available() && !global_settings.pitch_mode_semitone)
                {
                    global_settings.pitch_mode_timestretch = !global_settings.pitch_mode_timestretch;
                    if(!global_settings.pitch_mode_timestretch)
                    {
                        /* no longer in timestretch mode.  Reset speed */
                        speed = pitch;
                        dsp_set_timestretch(PITCH_SPEED_100);
                    }
                }
                settings_save();
#endif
                break;

            case ACTION_PS_EXIT:
                exit = true;
                break;

            default:
                if (default_event_handler(button) == SYS_USB_CONNECTED)
                    return 1;
                break;
        }
        if (pitch_delta)
        {
            if (global_settings.pitch_mode_semitone)
            {
                semitone = pitch_increase_semitone(pitch, semitone, pitch_delta
#if CONFIG_CODEC == SWCODEC
                                                , speed
#endif                            
                );
                pitch = get_pitch_from_semitone(semitone);
            }
            else
            {
                pitch = pitch_increase(pitch, pitch_delta, true
#if CONFIG_CODEC == SWCODEC
                                       , speed
#endif                            
                );
                semitone = get_semitone_from_pitch(pitch);
            }
#if CONFIG_CODEC == SWCODEC
            if (global_settings.pitch_mode_timestretch)
            {
                /* do this to make sure we properly obey the stretch limits */
                new_speed = speed;
            }
            else
            {
                speed = pitch;
            }
#endif
        }

#if CONFIG_CODEC == SWCODEC
        if(new_speed)
        {
            new_stretch = GET_STRETCH(pitch, new_speed);

            /* limit the amount of stretch */
            if(new_stretch > STRETCH_MAX)
            {
                new_stretch = STRETCH_MAX;
                new_speed = GET_SPEED(pitch, new_stretch);
            }
            else if(new_stretch < STRETCH_MIN)
            {
                new_stretch = STRETCH_MIN;
                new_speed = GET_SPEED(pitch, new_stretch);
            }

            new_stretch = GET_STRETCH(pitch, new_speed);
            if(new_stretch >= STRETCH_MAX || 
               new_stretch <= STRETCH_MIN)
            {
                at_limit = true;
            }

            /* set the amount of stretch */
            dsp_set_timestretch(new_stretch);

            /* update the speed variable with the new speed */
            speed = new_speed;

            /* Reset new_speed so we only call dsp_set_timestretch */
            /* when needed                                         */
            new_speed = 0;
        }
#endif
    }
#if CONFIG_CODEC == SWCODEC
    pcmbuf_set_low_latency(false);
#endif
    return 0;
}
Beispiel #18
0
        /* finally, assign the font_id to the viewport */
        vp->font = font->id;
    }
    return success;
}

#endif /* HAVE_LCD_BITMAP */
static int convert_viewport(struct wps_data *data, struct skin_element* element)
{
    struct skin_viewport *skin_vp = 
        (struct skin_viewport *)skin_buffer_alloc(sizeof(struct skin_viewport));
    struct screen *display = &screens[curr_screen];
    
    if (!skin_vp)
        return CALLBACK_ERROR;
        
    skin_vp->hidden_flags = 0;
    skin_vp->label = NULL;
    skin_vp->is_infovp = false;
    element->data = skin_vp;
    curr_vp = skin_vp;
    curr_viewport_element = element;
    
    viewport_set_defaults(&skin_vp->vp, curr_screen);
#ifdef HAVE_REMOTE_LCD
    /* viewport_set_defaults() sets the font to FONT_UI+curr_screen.
     * This parser requires font 1 to always be the UI font, 
     * so force it back to FONT_UI and handle the screen number at the end */
    skin_vp->vp.font = FONT_UI;
#endif
    
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
    skin_vp->start_fgcolour = skin_vp->vp.fg_pattern;
    skin_vp->start_bgcolour = skin_vp->vp.bg_pattern;
#endif
    

    struct skin_tag_parameter *param = element->params;
    if (element->params_count == 0) /* default viewport */
    {
        if (!data->tree) /* first viewport in the skin */
            data->tree = element;
        skin_vp->label = VP_DEFAULT_LABEL;
        return CALLBACK_OK;
    }
    
    if (element->params_count == 6)
    {
        if (element->tag->type == SKIN_TOKEN_UIVIEWPORT_LOAD)
        {
            skin_vp->is_infovp = true;
            if (isdefault(param))
            {
                skin_vp->hidden_flags = VP_NEVER_VISIBLE;
                skin_vp->label = VP_DEFAULT_LABEL;
            }
            else
            {
                skin_vp->hidden_flags = VP_NEVER_VISIBLE;
                skin_vp->label = param->data.text;
            }
        }
        else
        {
                skin_vp->hidden_flags = VP_DRAW_HIDEABLE|VP_DRAW_HIDDEN;
                skin_vp->label = param->data.text;
        }
        param++;
    }
    /* x */
    if (!isdefault(param))
    {
        skin_vp->vp.x = param->data.number;
        if (param->data.number < 0)
            skin_vp->vp.x += display->lcdwidth;
    }
    param++;
    /* y */
    if (!isdefault(param))
    {
        skin_vp->vp.y = param->data.number;
        if (param->data.number < 0)
            skin_vp->vp.y += display->lcdheight;
    }
    param++;
    /* width */
    if (!isdefault(param))
    {
        skin_vp->vp.width = param->data.number;
        if (param->data.number < 0)
            skin_vp->vp.width = (skin_vp->vp.width + display->lcdwidth) - skin_vp->vp.x;
    }
    else
    {
        skin_vp->vp.width = display->lcdwidth - skin_vp->vp.x;
    }
    param++;
    /* height */
    if (!isdefault(param))
    {
        skin_vp->vp.height = param->data.number;
        if (param->data.number < 0)
            skin_vp->vp.height = (skin_vp->vp.height + display->lcdheight) - skin_vp->vp.y;
    }
    else
    {
        skin_vp->vp.height = display->lcdheight - skin_vp->vp.y;
    }
    param++;
#ifdef HAVE_LCD_BITMAP
    /* font */
    if (!isdefault(param))
    {
        skin_vp->vp.font = param->data.number;
    }
#endif
    if ((unsigned) skin_vp->vp.x >= (unsigned) display->lcdwidth ||
        skin_vp->vp.width + skin_vp->vp.x > display->lcdwidth ||
        (unsigned) skin_vp->vp.y >= (unsigned) display->lcdheight ||
        skin_vp->vp.height + skin_vp->vp.y > display->lcdheight)
        return CALLBACK_ERROR;

    return CALLBACK_OK;
}