예제 #1
0
int sb_postproccess(enum screen_type screen, struct wps_data *data)
{
    if (data->wps_loaded)
    {  
        /* hide the sb's default viewport because it has nasty effect with stuff
        * not part of the statusbar,
        * hence .sbs's without any other vps are unsupported*/
        struct skin_viewport *vp = skin_find_item(VP_DEFAULT_LABEL_STRING, SKIN_FIND_VP, data);
        struct skin_element *tree = SKINOFFSETTOPTR(get_skin_buffer(data), data->tree);
        struct skin_element *next_vp = SKINOFFSETTOPTR(get_skin_buffer(data), tree->next);
        
        if (vp)
        {
            if (!next_vp)
            {    /* no second viewport, let parsing fail */
                return 0;
            }
            /* hide this viewport, forever */
            vp->hidden_flags = VP_NEVER_VISIBLE;
        }
        sb_set_info_vp(screen, VP_DEFAULT_LABEL);
        sbs_loaded[screen] = true;
    }
    viewportmanager_theme_undo(screen, false);
    return 1;
}
예제 #2
0
/* Evaluate the conditional that is at *token_index and return whether a skip
   has ocurred. *token_index is updated with the new position.
*/
int evaluate_conditional(struct gui_wps *gwps, int offset, 
                         struct conditional *conditional, int num_options)
{
    if (!gwps)
        return false;

    char result[128];
    const char *value;

    int intval = num_options < 2 ? 2 : num_options;
    /* get_token_value needs to know the number of options in the enum */
    value = get_token_value(gwps, SKINOFFSETTOPTR(get_skin_buffer(gwps->data), conditional->token),
                    offset, result, sizeof(result), &intval);

    /* intval is now the number of the enum option we want to read,
       starting from 1. If intval is -1, we check if value is empty. */
    if (intval == -1)
    {
        if (num_options == 1) /* so %?AA<true> */
            intval = (value && *value) ? 1 : 0; /* returned as 0 for true, -1 for false */
        else
            intval = (value && *value) ? 1 : num_options;
    }
    else if (intval > num_options || intval < 1)
        intval = num_options;

    return intval -1;
}
예제 #3
0
/** Disarms all touchregions. */
void skin_disarm_touchregions(struct wps_data *data)
{
    char* skin_buffer = get_skin_buffer(data);
    struct skin_token_list *regions = SKINOFFSETTOPTR(skin_buffer, data->touchregions);
    while (regions)
    {
        struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, regions->token);
        struct touchregion *region = SKINOFFSETTOPTR(skin_buffer, token->value.data);
        region->armed = false;
        regions = SKINOFFSETTOPTR(skin_buffer, regions->next);
    }
}
예제 #4
0
void wps_display_images(struct gui_wps *gwps, struct viewport* vp)
{
    if(!gwps || !gwps->data || !gwps->display)
        return;
    (void)vp;
    struct wps_data *data = gwps->data;
    struct screen *display = gwps->display;
    struct skin_token_list *list = SKINOFFSETTOPTR(get_skin_buffer(data), data->images);

    while (list)
    {
        struct wps_token *token = SKINOFFSETTOPTR(get_skin_buffer(data), list->token);
        struct gui_img *img = (struct gui_img*)SKINOFFSETTOPTR(get_skin_buffer(data), token->value.data);
        if (img->using_preloaded_icons && img->display >= 0)
        {
            screen_put_icon(display, img->x, img->y, img->display);
        }
        else if (img->loaded)
        {
            if (img->display >= 0)
            {
                wps_draw_image(gwps, img, img->display);
            }
        }
        list = SKINOFFSETTOPTR(get_skin_buffer(data), list->next);
    }
#ifdef HAVE_ALBUMART
    /* now draw the AA */
    struct skin_albumart *aa = SKINOFFSETTOPTR(get_skin_buffer(data), data->albumart);
    if (aa && SKINOFFSETTOPTR(get_skin_buffer(data), aa->vp) == vp
        && aa->draw_handle >= 0)
    {
        draw_album_art(gwps, aa->draw_handle, false);
        aa->draw_handle = -1;
    }
#endif

    display->set_drawmode(DRMODE_SOLID);
}
예제 #5
0
/* Get the touched action.
 * egde_offset is a percentage value for the position of the touch
 * inside the bar for regions which arnt WPS_TOUCHREGION_ACTION type.
 */
int skin_get_touchaction(struct wps_data *data, int* edge_offset,
                         struct touchregion **retregion)
{
    int returncode = ACTION_NONE;
    short x,y;
    short vx, vy;
    int type = action_get_touchscreen_press(&x, &y);
    struct skin_viewport *wvp;
    struct touchregion *r, *temp = NULL;
    char* skin_buffer = get_skin_buffer(data);
    bool repeated = (type == BUTTON_REPEAT);
    bool released = (type == BUTTON_REL);
    bool pressed = (type == BUTTON_TOUCHSCREEN);
    struct skin_token_list *regions = SKINOFFSETTOPTR(skin_buffer, data->touchregions);
    bool needs_repeat;

    while (regions)
    {
        struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, regions->token);
        r = SKINOFFSETTOPTR(skin_buffer, token->value.data);
        wvp = SKINOFFSETTOPTR(skin_buffer, r->wvp);
        /* make sure this region's viewport is visible */
        if (wvp->hidden_flags&VP_DRAW_HIDDEN)
        {
            regions = SKINOFFSETTOPTR(skin_buffer, regions->next);
            continue;
        }
        if (data->touchscreen_locked && 
            (r->action != ACTION_TOUCH_SOFTLOCK && !r->allow_while_locked))
        {
            regions = SKINOFFSETTOPTR(skin_buffer, regions->next);
            continue;
        }
        needs_repeat = r->press_length != PRESS;
        /* check if it's inside this viewport */
        if (viewport_point_within_vp(&(wvp->vp), x, y))
        {   /* reposition the touch inside the viewport since touchregions
             * are relative to a preceding viewport */
            vx = x - wvp->vp.x;
            vy = y - wvp->vp.y;
            /* now see if the point is inside this region */
            if (vx >= r->x && vx < r->x+r->width &&
                vy >= r->y && vy < r->y+r->height)
            {
                /* reposition the touch within the area */
                vx -= r->x;
                vy -= r->y;

                switch(r->action)
                {
                    case ACTION_TOUCH_SCROLLBAR:
                    case ACTION_TOUCH_VOLUME:
                    case ACTION_TOUCH_SETTING:
                        if (edge_offset)
                        {
                            struct progressbar *bar =
                                    SKINOFFSETTOPTR(skin_buffer, r->bar);
                            if(r->width > r->height)
                                *edge_offset = vx*100/r->width;
                            else
                                *edge_offset = vy*100/r->height;
                            if (r->reverse_bar || (bar && bar->invert_fill_direction))
                                *edge_offset = 100 - *edge_offset;
                        }
                        temp = r;
                        returncode = r->action;
                        r->last_press = current_tick;
                        break;
                    default:
                        if (r->armed && ((repeated && needs_repeat) || 
                            (released && !needs_repeat)))
                        {
                            returncode = r->action;
                            temp = r;
                        }
                        if (pressed)
                        {
                            r->armed = true;
                            r->last_press = current_tick;
                        }
                        break;
                }
            }
        }
        regions = SKINOFFSETTOPTR(skin_buffer, regions->next);
    }

    /* On release, all regions are disarmed. */
    if (released)
        skin_disarm_touchregions(data);
    if (retregion && temp)
        *retregion = temp;
    if (temp && temp->press_length == LONG_PRESS)
        temp->armed = false;
    
    if (returncode != ACTION_NONE)
    {
        if (global_settings.party_mode)
        {
            switch (returncode)
            {
                case ACTION_WPS_PLAY:
                case ACTION_WPS_SKIPPREV:
                case ACTION_WPS_SKIPNEXT:
                case ACTION_WPS_STOP:
                    returncode = ACTION_NONE;
                    break;
                default:
                    break;
            }
        }
        switch (returncode)
        {
            case ACTION_TOUCH_SOFTLOCK:
                data->touchscreen_locked = !data->touchscreen_locked;
                returncode = ACTION_NONE;
                break;
            case ACTION_WPS_PLAY:
                if (!audio_status())
                {
                    if ( global_status.resume_index != -1 )
                    {
                        if (playlist_resume() != -1)
                        {
                            playlist_start(global_status.resume_index,
                                global_status.resume_offset);
                        }
                    }
                    else
                    {
                        splash(HZ*2, ID2P(LANG_NOTHING_TO_RESUME));
                    }
                }
                else
                {
                    wps_do_playpause(false);
                }
                returncode = ACTION_REDRAW;
                break;
            case ACTION_WPS_SKIPPREV:
                audio_prev();
                returncode = ACTION_REDRAW;
                break;
            case ACTION_WPS_SKIPNEXT:
                audio_next();
                returncode = ACTION_REDRAW;
                break;
            case ACTION_WPS_STOP:
                audio_stop();
                returncode = ACTION_REDRAW;
                break;
            case ACTION_SETTINGS_INC:
            case ACTION_SETTINGS_DEC:
            {
                const struct settings_list *setting = 
                                            temp->setting_data.setting;
                option_select_next_val(setting, 
                                       returncode == ACTION_SETTINGS_DEC,
                                       true);
                returncode = ACTION_REDRAW;
            }
            break;
            case ACTION_SETTINGS_SET:
            {
                struct touchsetting *data = &temp->setting_data;
                const struct settings_list *s = data->setting;
                void (*f)(int) = NULL;
                switch (s->flags&F_T_MASK)
                {
                    case F_T_CUSTOM:
                        s->custom_setting
                            ->load_from_cfg(s->setting, SKINOFFSETTOPTR(skin_buffer, data->value.text));
                        break;                          
                    case F_T_INT:
                    case F_T_UINT:
                        *(int*)s->setting = data->value.number;
                        if ((s->flags & F_T_SOUND) == F_T_SOUND)
                            sound_set(s->sound_setting->setting, data->value.number);
                        else if (s->flags&F_CHOICE_SETTING)
                            f = s->choice_setting->option_callback;
                        else if (s->flags&F_TABLE_SETTING)
                            f = s->table_setting->option_callback;
                        else
                            f = s->int_setting->option_callback;

                        if (f)
                            f(data->value.number);
                        break;
                    case F_T_BOOL:
                        *(bool*)s->setting = data->value.number ? true : false;
                        if (s->bool_setting->option_callback)
                            s->bool_setting
                                ->option_callback(data->value.number ? true : false);
                        break;
                }
                returncode = ACTION_REDRAW;
            }
            break;
            case ACTION_TOUCH_MUTE:
            {
                const int min_vol = sound_min(SOUND_VOLUME);
                if (global_settings.volume == min_vol)
                    global_settings.volume = temp->value;
                else
                {
                    temp->value = global_settings.volume;
                    global_settings.volume = min_vol;
                }
                setvol();
                returncode = ACTION_REDRAW;
            }
            break;
            case ACTION_TOUCH_SHUFFLE: /* toggle shuffle mode */
            {
                global_settings.playlist_shuffle = 
                                            !global_settings.playlist_shuffle;
                replaygain_update();
                if (global_settings.playlist_shuffle)
                    playlist_randomise(NULL, current_tick, true);
                else
                    playlist_sort(NULL, true);
                returncode = ACTION_REDRAW;
            }
            break;
            case ACTION_TOUCH_REPMODE: /* cycle the repeat mode setting */
            {
                const struct settings_list *rep_setting = 
                                find_setting(&global_settings.repeat_mode, NULL);
                option_select_next_val(rep_setting, false, true);
                audio_flush_and_reload_tracks();
                returncode = ACTION_REDRAW;
            }
            break;
            case ACTION_TOUCH_SETTING:
            {                
                struct progressbar *bar =
                        SKINOFFSETTOPTR(skin_buffer, temp->bar);
                if (bar && edge_offset)
                {                    
                    int val, count;
                    get_setting_info_for_bar(bar->setting_id, &count, &val);
                    val = *edge_offset * count / 100;
                    update_setting_value_from_touch(bar->setting_id, val);
                }
            }
            break;
        }
        return returncode;
    }

    return ACTION_TOUCHSCREEN;
}
예제 #6
0
void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb)
{
    struct screen *display = gwps->display;
    struct viewport *vp = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->vp);
    struct wps_state *state = skin_get_global_state();
    struct mp3entry *id3 = state->id3;
    int x = pb->x, y = pb->y, width = pb->width, height = pb->height;
    unsigned long length, end;
    int flags = HORIZONTAL;
    
    if (height < 0)
        height = font_get(vp->font)->height;

    if (y < 0)
    {
        int line_height = font_get(vp->font)->height;
        /* center the pb in the line, but only if the line is higher than the pb */
        int center = (line_height-height)/2;
        /* if Y was not set calculate by font height,Y is -line_number-1 */
        y = line*line_height + (0 > center ? 0 : center);
    }

    if (pb->type == SKIN_TOKEN_VOLUMEBAR)
    {
        int minvol = sound_min(SOUND_VOLUME);
        int maxvol = sound_max(SOUND_VOLUME);
        length = maxvol-minvol;
        end = global_settings.volume-minvol;
    }
    else if (pb->type == SKIN_TOKEN_BATTERY_PERCENTBAR)
    {
        length = 100;
        end = battery_level();
    }
    else if (pb->type == SKIN_TOKEN_PEAKMETER_LEFTBAR ||
             pb->type == SKIN_TOKEN_PEAKMETER_RIGHTBAR)
    {
        int left, right, val;
        peak_meter_current_vals(&left, &right);
        val = pb->type == SKIN_TOKEN_PEAKMETER_LEFTBAR ? left : right;
        length = MAX_PEAK;
        end = peak_meter_scale_value(val, length);
    }
    else if (pb->type == SKIN_TOKEN_LIST_SCROLLBAR)
    {
        int val, min, max;
        skinlist_get_scrollbar(&val, &min, &max);
        end = val - min;
        length = max - min;
    }
#if CONFIG_TUNER
    else if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF))
    {
#ifdef HAVE_RADIO_RSSI
        if (pb->type == SKIN_TOKEN_TUNER_RSSI_BAR)
        {
            int val = tuner_get(RADIO_RSSI);
            int min = tuner_get(RADIO_RSSI_MIN);
            int max = tuner_get(RADIO_RSSI_MAX);
            end = val - min;
            length = max - min;
        }
        else
#endif
        {
            int min = fm_region_data[global_settings.fm_region].freq_min;
            end = radio_current_frequency() - min;
            length = fm_region_data[global_settings.fm_region].freq_max - min;
        }
    }
#endif
    else if (id3 && id3->length)
    {
        length = id3->length;
        end = id3->elapsed + state->ff_rewind_count;
    }
    else
    {
        length = 1;
        end = 0;
    }
    
    if (!pb->horizontal)
    {
        /* we want to fill upwards which is technically inverted. */
        flags = INVERTFILL;
    }
    
    if (pb->invert_fill_direction)
    {
        flags ^= INVERTFILL;
    }

    if (pb->nofill)
    {
        flags |= INNER_NOFILL;
    }

    if (SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider))
    {
        struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider);
        /* clear the slider */
        screen_clear_area(display, x, y, width, height);

        /* shrink the bar so the slider is inside bounds */
        if (flags&HORIZONTAL)
        {
            width -= img->bm.width;
            x += img->bm.width / 2;
        }
        else
        {
            height -= img->bm.height;
            y += img->bm.height / 2;
        }
    }
    
    if (SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->backdrop))
    {
        struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->backdrop);
        img->bm.data = core_get_data(img->buflib_handle);
        display->bmp_part(&img->bm, 0, 0, x, y, width, height);
        flags |= DONT_CLEAR_EXCESS;
    }
    
    if (!pb->nobar)
    {
        struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->image);
        if (img)
        {
            char *img_data = core_get_data(img->buflib_handle);
            img->bm.data = img_data;
            gui_bitmap_scrollbar_draw(display, &img->bm,
                                    x, y, width, height,
                                    length, 0, end, flags);
        }
        else
            gui_scrollbar_draw(display, x, y, width, height,
                               length, 0, end, flags);
    }

    if (SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider))
    {
        int xoff = 0, yoff = 0;
        int w = width, h = height;
        struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider);
        img->bm.data = core_get_data(img->buflib_handle);

        if (flags&HORIZONTAL)
        {
            w = img->bm.width;
            xoff = width * end / length;
            if (flags&INVERTFILL)
                xoff = width - xoff;
            xoff -= w / 2;
        }
        else
        {
            h = img->bm.height;
            yoff = height * end / length;
            if (flags&INVERTFILL)
                yoff = height - yoff;
            yoff -= h / 2;
        }
        display->bmp_part(&img->bm, 0, 0, x + xoff, y + yoff, w, h);
    }

    if (pb->type == SKIN_TOKEN_PROGRESSBAR)
    {
        if (id3 && id3->length)
        {
#ifdef AB_REPEAT_ENABLE
            if (ab_repeat_mode_enabled())
                ab_draw_markers(display, id3->length, x, y, width, height);
#endif

            if (id3->cuesheet)
                cue_draw_markers(display, id3->cuesheet, id3->length,
                                 x, y+1, width, height-2);
        }
#if 0 /* disable for now CONFIG_TUNER */
        else if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF))
        {
            presets_draw_markers(display, x, y, width, height);
        }
#endif
    }
}
예제 #7
0
bool skinlist_draw(struct screen *display, struct gui_synclist *list)
{
    int cur_line, display_lines;
    const int screen = display->screen_type;
    struct viewport *parent = (list->parent[screen]);
    char* label = NULL;
    const int list_start_item = list->start_item[screen];
    struct gui_wps wps;
    if (!skinlist_is_configured(screen, list))
        return false;

    current_list = list;
    wps.display = display;
    wps.data = listcfg[screen]->data;
    display_lines = skinlist_get_line_count(screen, list);
    label = (char *)SKINOFFSETTOPTR(get_skin_buffer(wps.data), listcfg[screen]->label);
    display->set_viewport(parent);
    display->clear_viewport();
    current_item = list->selected_item;
    current_nbitems = list->nb_items;
    needs_scrollbar[screen] = list->nb_items > display_lines;

    for (cur_line = 0; cur_line < display_lines; cur_line++)
    {
        struct skin_element* viewport;
        struct skin_viewport* skin_viewport = NULL;
        if (list_start_item+cur_line+1 > list->nb_items)
            break;
        current_drawing_line = list_start_item+cur_line;
        is_selected = list->show_selection_marker &&
                list_start_item+cur_line == list->selected_item;

        for (viewport = SKINOFFSETTOPTR(get_skin_buffer(wps.data), listcfg[screen]->data->tree);
             viewport;
             viewport = SKINOFFSETTOPTR(get_skin_buffer(wps.data), viewport->next))
        {
            int original_x, original_y;
            skin_viewport = SKINOFFSETTOPTR(get_skin_buffer(wps.data), viewport->data);
            char *viewport_label = SKINOFFSETTOPTR(get_skin_buffer(wps.data), skin_viewport->label);
            if (viewport->children == 0 || !viewport_label ||
                (skin_viewport->label && strcmp(label, viewport_label))
                )
                continue;
            if (is_selected)
            {
                memcpy(&listcfg[screen]->selected_item_vp, skin_viewport, sizeof(struct skin_viewport));
                skin_viewport = &listcfg[screen]->selected_item_vp;
            }
            original_x = skin_viewport->vp.x;
            original_y = skin_viewport->vp.y;
            if (listcfg[screen]->tile)
            {
                int cols = (parent->width / listcfg[screen]->width);
                current_column = (cur_line)%cols;
                current_row = (cur_line)/cols;
                
                skin_viewport->vp.x = parent->x + listcfg[screen]->width*current_column + original_x;
                skin_viewport->vp.y = parent->y + listcfg[screen]->height*current_row + original_y;
            }
            else
            {
                current_column = 1;
                current_row = cur_line;
                skin_viewport->vp.x = parent->x + original_x;
                skin_viewport->vp.y = parent->y + original_y +
                                   (listcfg[screen]->height*cur_line);
            }
            display->set_viewport(&skin_viewport->vp);
#ifdef HAVE_LCD_BITMAP
            /* Set images to not to be displayed */
            struct skin_token_list *imglist = SKINOFFSETTOPTR(get_skin_buffer(wps.data), wps.data->images);
            while (imglist)
            {
                struct wps_token *token = SKINOFFSETTOPTR(get_skin_buffer(wps.data), imglist->token);
                struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(wps.data), token->value.data);
                img->display = -1;
                imglist = SKINOFFSETTOPTR(get_skin_buffer(wps.data), imglist->next);
            }
#endif
            struct skin_element** children = SKINOFFSETTOPTR(get_skin_buffer(wps.data), viewport->children);
            skin_render_viewport(SKINOFFSETTOPTR(get_skin_buffer(wps.data), (intptr_t)children[0]),
                                 &wps, skin_viewport, SKIN_REFRESH_ALL);
#ifdef HAVE_LCD_BITMAP
            wps_display_images(&wps, &skin_viewport->vp);
#endif
            /* force disableing scroll because it breaks later */
            if (!is_selected)
            {
                display->scroll_stop_viewport(&skin_viewport->vp);
                skin_viewport->vp.x = original_x;
                skin_viewport->vp.y = original_y;
            }
        }
    }
    current_column = -1;
    current_row = -1;
    display->set_viewport(parent);
    display->update_viewport();
    current_drawing_line = list->selected_item;
    return true;
}
예제 #8
0
/* Draw the album art bitmap from the given handle ID onto the given WPS.
   Call with clear = true to clear the bitmap instead of drawing it. */
void draw_album_art(struct gui_wps *gwps, int handle_id, bool clear)
{
    if (!gwps || !gwps->data || !gwps->display || handle_id < 0)
        return;

    struct wps_data *data = gwps->data;
    struct skin_albumart *aa = SKINOFFSETTOPTR(get_skin_buffer(data), data->albumart);

    if (!aa)
        return;
        
    struct bitmap *bmp;
    if (bufgetdata(handle_id, 0, (void *)&bmp) <= 0)
        return;

    short x = aa->x;
    short y = aa->y;
    short width = bmp->width;
    short height = bmp->height;

    if (aa->width > 0)
    {
        /* Crop if the bitmap is too wide */
        width = MIN(bmp->width, aa->width);

        /* Align */
        if (aa->xalign & WPS_ALBUMART_ALIGN_RIGHT)
            x += aa->width - width;
        else if (aa->xalign & WPS_ALBUMART_ALIGN_CENTER)
            x += (aa->width - width) / 2;
    }

    if (aa->height > 0)
    {
        /* Crop if the bitmap is too high */
        height = MIN(bmp->height, aa->height);

        /* Align */
        if (aa->yalign & WPS_ALBUMART_ALIGN_BOTTOM)
            y += aa->height - height;
        else if (aa->yalign & WPS_ALBUMART_ALIGN_CENTER)
            y += (aa->height - height) / 2;
    }

    if (!clear)
    {
        /* Draw the bitmap */
        gwps->display->bitmap_part((fb_data*)bmp->data, 0, 0, 
                                    STRIDE(gwps->display->screen_type, 
                                        bmp->width, bmp->height),
                                   x, y, width, height);
#ifdef HAVE_LCD_INVERT
        if (global_settings.invert) {
            gwps->display->set_drawmode(DRMODE_COMPLEMENT);
            gwps->display->fillrect(x, y, width, height);
            gwps->display->set_drawmode(DRMODE_SOLID);
        }
#endif
    }
    else
    {
        /* Clear the bitmap */
        gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
        gwps->display->fillrect(x, y, width, height);
        gwps->display->set_drawmode(DRMODE_SOLID);
    }
}