static int scrollbar_scroll(struct gui_synclist * gui_list, int y) { const int screen = screens[SCREEN_MAIN].screen_type; const int nb_lines = viewport_get_nb_lines(&list_text[screen]); if (nb_lines < gui_list->nb_items) { /* scrollbar scrolling is still line based */ y_offset = 0; int scrollbar_size = nb_lines* font_get(gui_list->parent[screen]->font)->height; int actual_y = y - list_text[screen].y; int new_selection = (actual_y * gui_list->nb_items) / scrollbar_size; int start_item = new_selection - nb_lines/2; if(start_item < 0) start_item = 0; else if(start_item > gui_list->nb_items - nb_lines) start_item = gui_list->nb_items - nb_lines; gui_list->start_item[screen] = start_item; return ACTION_REDRAW; } return ACTION_NONE; }
/* * Draws the yesno * - yn : the yesno structure */ static void gui_yesno_draw(struct gui_yesno * yn) { struct screen * display=yn->display; struct viewport *vp = yn->vp; int nb_lines, vp_lines, line_shift=0; display->set_viewport(vp); display->clear_viewport(); nb_lines = yn->main_message->nb_lines; vp_lines = viewport_get_nb_lines(vp); if(nb_lines+3< vp_lines) line_shift=1; line_shift += put_message(display, yn->main_message, line_shift, vp_lines); /* Space remaining for yes / no text ? */ if(line_shift+2 <= vp_lines) { if(line_shift+3 <= vp_lines) line_shift++; display->puts(0, line_shift, str(LANG_CONFIRM_WITH_BUTTON)); #ifdef HAVE_LCD_BITMAP display->puts(0, line_shift+1, str(LANG_CANCEL_WITH_ANY)); #endif } display->update_viewport(); display->set_viewport(NULL); }
static void gui_quickscreen_draw(const struct gui_quickscreen *qs, struct screen *display, struct viewport *parent, struct viewport vps[QUICKSCREEN_ITEM_COUNT], struct viewport *vp_icons) { int i; char buf[MAX_PATH]; unsigned const char *title, *value; void *setting; int temp; display->set_viewport(parent); display->clear_viewport(); for (i = 0; i < QUICKSCREEN_ITEM_COUNT; i++) { struct viewport *vp = &vps[i]; if (!qs->items[i]) continue; display->set_viewport(vp); display->scroll_stop(vp); title = P2STR(ID2P(qs->items[i]->lang_id)); setting = qs->items[i]->setting; temp = option_value_as_int(qs->items[i]); value = option_get_valuestring(qs->items[i], buf, MAX_PATH, temp); if (viewport_get_nb_lines(vp) < 2) { char text[MAX_PATH]; snprintf(text, MAX_PATH, "%s: %s", title, value); display->puts_scroll(0, 0, text); } else { display->puts_scroll(0, 0, title); display->puts_scroll(0, 1, value); } display->update_viewport(); } /* draw the icons */ display->set_viewport(vp_icons); display->mono_bitmap(bitmap_icons_7x8[Icon_UpArrow], (vp_icons->width/2) - 4, 0, 7, 8); display->mono_bitmap(bitmap_icons_7x8[Icon_FastForward], vp_icons->width - 8, (vp_icons->height/2) - 4, 7, 8); display->mono_bitmap(bitmap_icons_7x8[Icon_FastBackward], 0, (vp_icons->height/2) - 4, 7, 8); display->mono_bitmap(bitmap_icons_7x8[Icon_DownArrow], (vp_icons->width/2) - 4, vp_icons->height - 8, 7, 8); display->set_viewport(parent); display->update_viewport(); display->set_viewport(NULL); }
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; }
/* * Draws the yesno result * - yn : the yesno structure * - result : the result tha must be displayed : * YESNO_NO if no * YESNO_YES if yes */ static bool gui_yesno_draw_result(struct gui_yesno * yn, enum yesno_res result) { const struct text_message * message=yn->result_message[result]; struct viewport *vp = yn->vp; struct screen * display=yn->display; if(message==NULL) return false; display->set_viewport(vp); display->clear_viewport(); put_message(yn->display, message, 0, viewport_get_nb_lines(vp)); display->update_viewport(); display->set_viewport(NULL); return(true); }
/* * Draws the yesno * - yn : the yesno structure */ static void gui_yesno_draw(struct gui_yesno * yn) { struct screen * display=yn->display; struct viewport *vp = yn->vp; int nb_lines, vp_lines, line_shift=0; display->set_viewport(vp); display->clear_viewport(); nb_lines = yn->main_message->nb_lines; vp_lines = viewport_get_nb_lines(vp); if(nb_lines+3< vp_lines) line_shift=1; line_shift += put_message(display, yn->main_message, line_shift, vp_lines); #ifdef HAVE_TOUCHSCREEN if (display->screen_type == SCREEN_MAIN) { int w,h; int rect_w = vp->width/2, rect_h = vp->height/2; int old_pattern = vp->fg_pattern; vp->fg_pattern = LCD_RGBPACK(0,255,0); display->drawrect(0, rect_h, rect_w, rect_h); display->getstringsize(str(LANG_SET_BOOL_YES), &w, &h); display->putsxy((rect_w-w)/2, rect_h+(rect_h-h)/2, str(LANG_SET_BOOL_YES)); vp->fg_pattern = LCD_RGBPACK(255,0,0); display->drawrect(rect_w, rect_h, rect_w, rect_h); display->getstringsize(str(LANG_SET_BOOL_NO), &w, &h); display->putsxy(rect_w + (rect_w-w)/2, rect_h+(rect_h-h)/2, str(LANG_SET_BOOL_NO)); vp->fg_pattern = old_pattern; } #else /* Space remaining for yes / no text ? */ if(line_shift+2 <= vp_lines) { if(line_shift+3 <= vp_lines) line_shift++; display->puts(0, line_shift, str(LANG_CONFIRM_WITH_BUTTON)); #ifdef HAVE_LCD_BITMAP display->puts(0, line_shift+1, str(LANG_CANCEL_WITH_ANY)); #endif } #endif display->update_viewport(); display->set_viewport(NULL); }
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; }
static void draw_timedate(struct viewport *vp, struct screen *display) { struct tm *tm = get_time(); int line; char time[16], date[16]; const char *t = time, *d = date; if (vp->height == 0) return; display->set_viewport(vp); display->clear_viewport(); if (viewport_get_nb_lines(vp) >= 4) line = 1; else line = 0; if (valid_time(tm)) { snprintf(time, sizeof(time), "%02d:%02d:%02d%s", global_settings.timeformat == 0 ? tm->tm_hour : ((tm->tm_hour + 11) % 12) + 1, tm->tm_min, tm->tm_sec, global_settings.timeformat == 0 ? "" : tm->tm_hour>11 ? " P" : " A"); snprintf(date, sizeof(date), "%s %d %d", str(LANG_MONTH_JANUARY + tm->tm_mon), tm->tm_mday, tm->tm_year+1900); } else { t = "--:--:--"; d = str(LANG_UNKNOWN); } display->puts(0, line++, t); display->puts(0, line, d); display->update_viewport(); display->set_viewport(NULL); }
static bool swipe_scroll(struct gui_synclist * gui_list, int line_height, int difference) { /* fixme */ const enum screen_type screen = screens[SCREEN_MAIN].screen_type; const int nb_lines = viewport_get_nb_lines(&list_text[screen]); if (UNLIKELY(scroll_begin_threshold == 0)) scroll_begin_threshold = touchscreen_get_scroll_threshold(); /* make selecting items easier */ threshold_accumulation += abs(difference); if (threshold_accumulation < scroll_begin_threshold && scroll_mode == SCROLL_NONE) return false; threshold_accumulation = 0; /* does the list even scroll? if no, return but still show * the caller that we would scroll */ if (nb_lines >= gui_list->nb_items) return true; const int old_start = gui_list->start_item[screen]; int new_start_item = -1; int line_diff = 0; /* don't scroll at the edges of the list */ if ((old_start == 0 && difference > 0) || (old_start == (gui_list->nb_items - nb_lines) && difference < 0)) { y_offset = 0; gui_list->start_item[screen] = old_start; return scroll_mode != SCROLL_KINETIC; /* stop kinetic at the edges */ } /* add up y_offset over time and translate to lines * if scrolled enough */ y_offset += difference; if (abs(y_offset) > line_height) { line_diff = y_offset/line_height; y_offset -= line_diff * line_height; } if(line_diff != 0) { int selection_offset = gui_list->selected_item - old_start; new_start_item = old_start - line_diff; /* check if new_start_item is bigger than list item count */ if(new_start_item > gui_list->nb_items - nb_lines) new_start_item = gui_list->nb_items - nb_lines; /* set new_start_item to 0 if it's negative */ if(new_start_item < 0) new_start_item = 0; gui_list->start_item[screen] = new_start_item; /* keep selected item in sync */ gui_list->selected_item = new_start_item + selection_offset; } return true; }
void list_draw(struct screen *display, struct gui_synclist *list) { struct viewport list_icons; int start, end, line_height, style, i; const int screen = display->screen_type; const int list_start_item = list->start_item[screen]; const int icon_width = get_icon_width(screen) + ICON_PADDING; const bool scrollbar_in_left = (global_settings.scrollbar == SCROLLBAR_LEFT); const bool show_cursor = !global_settings.cursor_style && list->show_selection_marker; struct viewport *parent = (list->parent[screen]); #ifdef HAVE_LCD_COLOR unsigned char cur_line = 0; #endif int item_offset; bool show_title; struct viewport *list_text_vp = &list_text[screen]; line_height = font_get(parent->font)->height; display->set_viewport(parent); display->clear_viewport(); display->scroll_stop(list_text_vp); *list_text_vp = *parent; if ((show_title = draw_title(display, list))) { list_text_vp->y += line_height; list_text_vp->height -= line_height; } const int nb_lines = viewport_get_nb_lines(list_text_vp); start = list_start_item; end = start + nb_lines; #ifdef HAVE_TOUCHSCREEN if (list->selected_item == 0 || (list->nb_items < nb_lines)) y_offset = 0; /* reset in case it's a new list */ int draw_offset = y_offset; /* draw some extra items to not have empty lines at the top and bottom */ if (y_offset > 0) { /* make it negative for more consistent apparence when switching * directions */ draw_offset -= line_height; if (start > 0) start--; } else if (y_offset < 0) end++; #else #define draw_offset 0 #endif /* draw the scrollbar if its needed */ if (global_settings.scrollbar && nb_lines < list->nb_items) { struct viewport vp = *list_text_vp; vp.width = SCROLLBAR_WIDTH; vp.height = line_height * nb_lines; vp.x = parent->x; list_text_vp->width -= SCROLLBAR_WIDTH; if (scrollbar_in_left) list_text_vp->x += SCROLLBAR_WIDTH; else vp.x += list_text_vp->width; display->set_viewport(&vp); gui_scrollbar_draw(display, (scrollbar_in_left? 0: 1), 0, SCROLLBAR_WIDTH-1, vp.height, list->nb_items, list_start_item, list_start_item + nb_lines, VERTICAL); } else if (show_title) { /* shift everything a bit in relation to the title... */ if (!VP_IS_RTL(list_text_vp) && scrollbar_in_left) { list_text_vp->width -= SCROLLBAR_WIDTH; list_text_vp->x += SCROLLBAR_WIDTH; } else if (VP_IS_RTL(list_text_vp) && !scrollbar_in_left) { list_text_vp->width -= SCROLLBAR_WIDTH; } } /* setup icon placement */ list_icons = *list_text_vp; int icon_count = (list->callback_get_item_icon != NULL) ? 1 : 0; if (show_cursor) icon_count++; if (icon_count) { list_icons.width = icon_width * icon_count; list_text_vp->width -= list_icons.width + ICON_PADDING; if (VP_IS_RTL(&list_icons)) list_icons.x += list_text_vp->width + ICON_PADDING; else list_text_vp->x += list_icons.width + ICON_PADDING; } for (i=start; i<end && i<list->nb_items; i++) { /* do the text */ unsigned const char *s; char entry_buffer[MAX_PATH]; unsigned char *entry_name; int text_pos = 0; int line = i - start; s = list->callback_get_item_name(i, list->data, entry_buffer, sizeof(entry_buffer)); entry_name = P2STR(s); display->set_viewport(list_text_vp); style = STYLE_DEFAULT; /* position the string at the correct offset place */ int item_width,h; display->getstringsize(entry_name, &item_width, &h); item_offset = gui_list_get_item_offset(list, item_width, text_pos, display, list_text_vp); #ifdef HAVE_LCD_COLOR /* if the list has a color callback */ if (list->callback_get_item_color) { int color = list->callback_get_item_color(i, list->data); /* if color selected */ if (color >= 0) { style |= STYLE_COLORED|color; } } #endif /* draw the selected line */ if( #ifdef HAVE_TOUCHSCREEN /* don't draw it during scrolling */ scroll_mode == SCROLL_NONE && #endif i >= list->selected_item && i < list->selected_item + list->selected_size && list->show_selection_marker) {/* The selected item must be displayed scrolling */ if (global_settings.cursor_style == 1 #ifdef HAVE_REMOTE_LCD /* the global_settings.cursor_style check is here to make * sure if they want the cursor instead of bar it will work */ || (display->depth < 16 && global_settings.cursor_style) #endif ) { /* Display inverted-line-style */ style = STYLE_INVERT; } #ifdef HAVE_LCD_COLOR else if (global_settings.cursor_style == 2) { /* Display colour line selector */ style = STYLE_COLORBAR; } else if (global_settings.cursor_style == 3) { /* Display gradient line selector */ style = STYLE_GRADIENT; /* Make the lcd driver know how many lines the gradient should cover and current line number */ /* number of selected lines */ style |= NUMLN_PACK(list->selected_size); /* current line number, zero based */ style |= CURLN_PACK(cur_line); cur_line++; } #endif /* if the text is smaller than the viewport size */ if (item_offset> item_width - (list_text_vp->width - text_pos)) { /* don't scroll */ display->puts_style_xyoffset(0, line, entry_name, style, item_offset, draw_offset); } else { display->puts_scroll_style_xyoffset(0, line, entry_name, style, item_offset, draw_offset); } } else { if (list->scroll_all) display->puts_scroll_style_xyoffset(0, line, entry_name, style, item_offset, draw_offset); else display->puts_style_xyoffset(0, line, entry_name, style, item_offset, draw_offset); } /* do the icon */ display->set_viewport(&list_icons); if (list->callback_get_item_icon != NULL) { screen_put_icon_with_offset(display, show_cursor?1:0, (line),show_cursor?ICON_PADDING:0,draw_offset, list->callback_get_item_icon(i, list->data)); } if (show_cursor && i >= list->selected_item && i < list->selected_item + list->selected_size) { screen_put_icon_with_offset(display, 0, line, 0, draw_offset, Icon_Cursor); } } display->set_viewport(parent); display->update_viewport(); display->set_viewport(NULL); }
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; }
static void quickscreen_fix_viewports(struct gui_quickscreen *qs, struct screen *display, struct viewport *parent, struct viewport vps[QUICKSCREEN_ITEM_COUNT], struct viewport *vp_icons) { int char_height, width, pad = 0; int left_width = 0, right_width = 0, vert_lines; unsigned char *s; int nb_lines = viewport_get_nb_lines(parent); /* nb_lines only returns the number of fully visible lines, small screens or really large fonts could cause problems with the calculation below. */ if (nb_lines == 0) nb_lines++; char_height = parent->height/nb_lines; /* center the icons VP first */ *vp_icons = *parent; vp_icons->width = CENTER_ICONAREA_SIZE; /* abosulte smallest allowed */ vp_icons->x = parent->x; vp_icons->x += (parent->width-CENTER_ICONAREA_SIZE)/2; vps[QUICKSCREEN_BOTTOM] = *parent; vps[QUICKSCREEN_TOP] = *parent; /* depending on the space the top/buttom items use 1 or 2 lines */ if (nb_lines < MIN_LINES) vert_lines = 1; else vert_lines = 2; vps[QUICKSCREEN_TOP].y = parent->y; vps[QUICKSCREEN_TOP].height = vps[QUICKSCREEN_BOTTOM].height = vert_lines*char_height; vps[QUICKSCREEN_BOTTOM].y = parent->y + parent->height - vps[QUICKSCREEN_BOTTOM].height; /* enough space vertically, so put a nice margin */ if (nb_lines >= MAX_NEEDED_LINES) { vps[QUICKSCREEN_TOP].y += MARGIN; vps[QUICKSCREEN_BOTTOM].y -= MARGIN; } vp_icons->y = vps[QUICKSCREEN_TOP].y + vps[QUICKSCREEN_TOP].height; vp_icons->height = vps[QUICKSCREEN_BOTTOM].y - vp_icons->y; /* adjust the left/right items widths to fit the screen nicely */ if (qs->items[QUICKSCREEN_LEFT]) { s = P2STR(ID2P(qs->items[QUICKSCREEN_LEFT]->lang_id)); left_width = display->getstringsize(s, NULL, NULL); } if (qs->items[QUICKSCREEN_RIGHT]) { s = P2STR(ID2P(qs->items[QUICKSCREEN_RIGHT]->lang_id)); right_width = display->getstringsize(s, NULL, NULL); } width = MAX(left_width, right_width); if (width*2 + vp_icons->width > parent->width) { /* crop text viewports */ width = (parent->width - vp_icons->width)/2; } else { /* add more gap in icons vp */ int excess = parent->width - vp_icons->width - width*2; if (excess > MARGIN*4) { pad = MARGIN; excess -= MARGIN*2; } vp_icons->x -= excess/2; vp_icons->width += excess; } vps[QUICKSCREEN_LEFT] = *parent; vps[QUICKSCREEN_LEFT].x = parent->x + pad; vps[QUICKSCREEN_LEFT].width = width; vps[QUICKSCREEN_RIGHT] = *parent; vps[QUICKSCREEN_RIGHT].x = parent->x + parent->width - width - pad; vps[QUICKSCREEN_RIGHT].width = width; vps[QUICKSCREEN_LEFT].height = vps[QUICKSCREEN_RIGHT].height = 2*char_height; vps[QUICKSCREEN_LEFT].y = vps[QUICKSCREEN_RIGHT].y = parent->y + (parent->height/2) - char_height; /* shrink the icons vp by a few pixels if there is room so the arrows aren't drawn right next to the text */ if (vp_icons->width > CENTER_ICONAREA_SIZE*2) { vp_icons->width -= CENTER_ICONAREA_SIZE*2/3; vp_icons->x += CENTER_ICONAREA_SIZE*2/6; } if (vp_icons->height > CENTER_ICONAREA_SIZE*2) { vp_icons->height -= CENTER_ICONAREA_SIZE*2/3; vp_icons->y += CENTER_ICONAREA_SIZE*2/6; } /* text alignment */ vps[QUICKSCREEN_LEFT].flags &= ~VP_FLAG_ALIGNMENT_MASK; /* left-aligned */ vps[QUICKSCREEN_TOP].flags |= VP_FLAG_ALIGN_CENTER; /* centered */ vps[QUICKSCREEN_BOTTOM].flags |= VP_FLAG_ALIGN_CENTER; /* centered */ vps[QUICKSCREEN_RIGHT].flags &= ~VP_FLAG_ALIGNMENT_MASK;/* right aligned*/ vps[QUICKSCREEN_RIGHT].flags |= VP_FLAG_ALIGN_RIGHT; }
static void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps, struct skin_viewport* skin_viewport, unsigned long refresh_type) { struct screen *display = gwps->display; char linebuf[MAX_LINE]; skin_render_func func = skin_render_line; struct skin_element* line = viewport; struct skin_draw_info info = { .gwps = gwps, .buf = linebuf, .buf_size = sizeof(linebuf), .line_number = 0, .no_line_break = false, .line_scrolls = false, .refresh_type = refresh_type, .skin_vp = skin_viewport, .offset = 0 }; struct align_pos * align = &info.align; bool needs_update; #ifdef HAVE_LCD_BITMAP /* Set images to not to be displayed */ struct skin_token_list *imglist = gwps->data->images; while (imglist) { struct gui_img *img = (struct gui_img *)imglist->token->value.data; img->display = -1; imglist = imglist->next; } #endif while (line) { linebuf[0] = '\0'; info.no_line_break = false; info.line_scrolls = false; info.force_redraw = false; info.cur_align_start = info.buf; align->left = info.buf; align->center = NULL; align->right = NULL; if (line->type == LINE_ALTERNATOR) func = skin_render_alternator; else if (line->type == LINE) func = skin_render_line; needs_update = func(line, &info); #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) if (skin_viewport->vp.fg_pattern != skin_viewport->start_fgcolour || skin_viewport->vp.bg_pattern != skin_viewport->start_bgcolour) { /* 2bit lcd drivers need lcd_set_viewport() to be called to change * the colour, 16bit doesnt. But doing this makes static text * get the new colour also */ needs_update = true; display->set_viewport(&skin_viewport->vp); } #endif /* only update if the line needs to be, and there is something to write */ if (refresh_type && needs_update) { if (info.line_scrolls) { /* if the line is a scrolling one we don't want to update too often, so that it has the time to scroll */ if ((refresh_type & SKIN_REFRESH_SCROLL) || info.force_redraw) write_line(display, align, info.line_number, true); } else write_line(display, align, info.line_number, false); } if (!info.no_line_break) info.line_number++; line = line->next; } #ifdef HAVE_LCD_BITMAP wps_display_images(gwps, &skin_viewport->vp); #endif } void skin_render(struct gui_wps *gwps, unsigned refresh_mode) { struct wps_data *data = gwps->data; struct screen *display = gwps->display; struct skin_element* viewport = data->tree; struct skin_viewport* skin_viewport; int old_refresh_mode = refresh_mode; #ifdef HAVE_LCD_CHARCELLS int i; for (i = 0; i < 8; i++) { if (data->wps_progress_pat[i] == 0) data->wps_progress_pat[i] = display->get_locked_pattern(); } #endif viewport = data->tree; skin_viewport = (struct skin_viewport *)viewport->data; if (skin_viewport->label && viewport->next && !strcmp(skin_viewport->label,VP_DEFAULT_LABEL)) refresh_mode = 0; for (viewport = data->tree; viewport; viewport = viewport->next) { /* SETUP */ skin_viewport = (struct skin_viewport*)viewport->data; unsigned vp_refresh_mode = refresh_mode; #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) skin_viewport->vp.fg_pattern = skin_viewport->start_fgcolour; skin_viewport->vp.bg_pattern = skin_viewport->start_bgcolour; #endif /* dont redraw the viewport if its disabled */ if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE) { /* don't draw anything into this one */ vp_refresh_mode = 0; } else if ((skin_viewport->hidden_flags&VP_DRAW_HIDDEN)) { skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN; continue; } else if (((skin_viewport->hidden_flags& (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE)) == (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE))) { vp_refresh_mode = SKIN_REFRESH_ALL; skin_viewport->hidden_flags = VP_DRAW_HIDEABLE; } display->set_viewport(&skin_viewport->vp); if ((vp_refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL) { display->clear_viewport(); } /* render */ if (viewport->children_count) skin_render_viewport(viewport->children[0], gwps, skin_viewport, vp_refresh_mode); refresh_mode = old_refresh_mode; } /* Restore the default viewport */ display->set_viewport(NULL); display->update(); } #ifdef HAVE_LCD_BITMAP static __attribute__((noinline)) void skin_render_playlistviewer(struct playlistviewer* viewer, struct gui_wps *gwps, struct skin_viewport* skin_viewport, unsigned long refresh_type) { struct screen *display = gwps->display; char linebuf[MAX_LINE]; skin_render_func func = skin_render_line; struct skin_element* line; struct skin_draw_info info = { .gwps = gwps, .buf = linebuf, .buf_size = sizeof(linebuf), .line_number = 0, .no_line_break = false, .line_scrolls = false, .refresh_type = refresh_type, .skin_vp = skin_viewport, .offset = viewer->start_offset }; struct align_pos * align = &info.align; bool needs_update; int cur_pos, start_item, max; int nb_lines = viewport_get_nb_lines(viewer->vp); #if CONFIG_TUNER if (current_screen() == GO_TO_FM) { cur_pos = radio_current_preset(); start_item = cur_pos + viewer->start_offset; max = start_item+radio_preset_count(); } else #endif { struct cuesheet *cue = skin_get_global_state()->id3 ? skin_get_global_state()->id3->cuesheet : NULL; cur_pos = playlist_get_display_index(); max = playlist_amount()+1; if (cue) max += cue->track_count; start_item = MAX(0, cur_pos + viewer->start_offset); } if (max-start_item > nb_lines) max = start_item + nb_lines; line = viewer->line; while (start_item < max) { linebuf[0] = '\0'; info.no_line_break = false; info.line_scrolls = false; info.force_redraw = false; info.cur_align_start = info.buf; align->left = info.buf; align->center = NULL; align->right = NULL; if (line->type == LINE_ALTERNATOR) func = skin_render_alternator; else if (line->type == LINE) func = skin_render_line; needs_update = func(line, &info); /* only update if the line needs to be, and there is something to write */ if (refresh_type && needs_update) { if (info.line_scrolls) { /* if the line is a scrolling one we don't want to update too often, so that it has the time to scroll */ if ((refresh_type & SKIN_REFRESH_SCROLL) || info.force_redraw) write_line(display, align, info.line_number, true); } else write_line(display, align, info.line_number, false); } info.line_number++; info.offset++; start_item++; } }