static int selection_to_val(const struct settings_list *setting, int selection) { int min = 0, max = 0, step = 1; if (((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) || ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING)) return selection; else if ((setting->flags & F_TABLE_SETTING) == F_TABLE_SETTING) { const struct table_setting *info = setting->table_setting; if (setting->flags&F_ALLOW_ARBITRARY_VALS && table_setting_array_position != -1 && (selection >= table_setting_array_position)) { if (selection == table_setting_array_position) return table_setting_oldval; return info->values[selection-1]; } else return info->values[selection]; } else if ((setting->flags & F_T_SOUND) == F_T_SOUND) { int setting_id = setting->sound_setting->setting; #ifndef ASCENDING_INT_SETTINGS step = sound_steps(setting_id); max = sound_max(setting_id); min = sound_min(setting_id); #else step = -sound_steps(setting_id); min = sound_max(setting_id); max = sound_min(setting_id); #endif } else if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) { const struct int_setting *info = setting->int_setting; #ifndef ASCENDING_INT_SETTINGS min = info->min; max = info->max; step = info->step; #else max = info->min; min = info->max; step = -info->step; #endif } return max- (selection * step); }
void fade(bool fade_in, bool updatewps) { int fp_global_vol = global_settings.volume << 8; int fp_min_vol = sound_min(SOUND_VOLUME) << 8; int fp_step = (fp_global_vol - fp_min_vol) / 10; skin_get_global_state()->is_fading = !fade_in; if (fade_in) { /* fade in */ int fp_volume = fp_min_vol; /* zero out the sound */ sound_set_volume(fp_min_vol >> 8); sleep(HZ/10); /* let audio thread run */ audio_resume(); if (updatewps) update_non_static(); while (fp_volume < fp_global_vol - fp_step) { fp_volume += fp_step; sound_set_volume(fp_volume >> 8); sleep(1); } sound_set_volume(global_settings.volume); } else {
static int volume_limit_callback(int action,const struct menu_item_ex *this_item) { (void)this_item; static struct int_setting volume_limit_int_setting; volume_limit_int_setting.option_callback = NULL; volume_limit_int_setting.unit = UNIT_DB; volume_limit_int_setting.min = sound_min(SOUND_VOLUME); volume_limit_int_setting.max = sound_max(SOUND_VOLUME); volume_limit_int_setting.step = sound_steps(SOUND_VOLUME); volume_limit_int_setting.formatter = NULL; volume_limit_int_setting.get_talk_id = get_dec_talkid; struct settings_list setting; setting.flags = F_BANFROMQS|F_INT_SETTING|F_T_INT|F_NO_WRAP; setting.lang_id = LANG_VOLUME_LIMIT; setting.default_val.int_ = sound_max(SOUND_VOLUME); setting.int_setting = &volume_limit_int_setting; switch (action) { case ACTION_ENTER_MENUITEM: setting.setting = &global_settings.volume_limit; option_screen(&setting, NULL, false, ID2P(LANG_VOLUME_LIMIT)); case ACTION_EXIT_MENUITEM: /* on exit */ setvol(); break; } return action; }
void fade(bool fade_in, bool updatewps) { int fp_global_vol = global_settings.volume << 8; int fp_min_vol = sound_min(SOUND_VOLUME) << 8; int fp_step = (fp_global_vol - fp_min_vol) / 30; int i; skin_get_global_state()->is_fading = !fade_in; if (fade_in) { /* fade in */ int fp_volume = fp_min_vol; /* zero out the sound */ sound_set_volume(fp_min_vol >> 8); sleep(HZ/10); /* let audio thread run */ audio_resume(); while (fp_volume < fp_global_vol - fp_step) { fp_volume += fp_step; sound_set_volume(fp_volume >> 8); if (updatewps) { FOR_NB_SCREENS(i) skin_update(WPS, i, SKIN_REFRESH_NON_STATIC); } sleep(1); } sound_set_volume(global_settings.volume); } else {
void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb) { struct screen *display = gwps->display; struct viewport *vp = 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); } #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 (pb->slider) { struct gui_img *img = 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 (pb->backdrop) { struct gui_img *img = pb->backdrop; #if LCD_DEPTH > 1 if(img->bm.format == FORMAT_MONO) { #endif display->mono_bitmap_part(img->bm.data, 0, 0, img->bm.width, x, y, width, height); #if LCD_DEPTH > 1 } else { display->transparent_bitmap_part((fb_data *)img->bm.data, 0, 0, STRIDE(display->screen_type, img->bm.width, img->bm.height), x, y, width, height); } #endif flags |= DONT_CLEAR_EXCESS; } if (!pb->nobar) { if (pb->image) gui_bitmap_scrollbar_draw(display, &pb->image->bm, x, y, width, height, length, 0, end, flags); else gui_scrollbar_draw(display, x, y, width, height, length, 0, end, flags); } if (pb->slider) { int xoff = 0, yoff = 0; int w = width, h = height; struct gui_img *img = pb->slider; 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; } #if LCD_DEPTH > 1 if(img->bm.format == FORMAT_MONO) { #endif display->mono_bitmap_part(img->bm.data, 0, 0, img->bm.width, x + xoff, y + yoff, w, h); #if LCD_DEPTH > 1 } else { display->transparent_bitmap_part((fb_data *)img->bm.data, 0, 0, STRIDE(display->screen_type, img->bm.width, img->bm.height), x + xoff, y + yoff, w, h); } #endif } 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 } }
/* 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; }
static void val_to_selection(const struct settings_list *setting, int oldvalue, int *nb_items, int *selected, void (**function)(int)) { int var_type = setting->flags&F_T_MASK; /* set the number of items and current selection */ if (var_type == F_T_INT || var_type == F_T_UINT) { if (setting->flags&F_CHOICE_SETTING) { *nb_items = setting->choice_setting->count; *selected = oldvalue; *function = setting->choice_setting->option_callback; } else if (setting->flags&F_TABLE_SETTING) { const struct table_setting *info = setting->table_setting; int i; *nb_items = info->count; *selected = -1; table_setting_array_position = -1; for (i=0;*selected==-1 && i<*nb_items;i++) { if (setting->flags&F_ALLOW_ARBITRARY_VALS && (oldvalue < info->values[i])) { table_setting_oldval = oldvalue; table_setting_array_position = i; *selected = i; (*nb_items)++; } else if (oldvalue == info->values[i]) *selected = i; } *function = info->option_callback; } else if (setting->flags&F_T_SOUND) { int setting_id = setting->sound_setting->setting; int steps = sound_steps(setting_id); int min = sound_min(setting_id); int max = sound_max(setting_id); *nb_items = (max-min)/steps + 1; #ifndef ASCENDING_INT_SETTINGS *selected = (max - oldvalue) / steps; #else *selected = (oldvalue - min) / steps; #endif *function = sound_get_fn(setting_id); } else { const struct int_setting *info = setting->int_setting; int min, max, step; max = info->max; min = info->min; step = info->step; *nb_items = (max-min)/step + 1; #ifndef ASCENDING_INT_SETTINGS *selected = (max - oldvalue) / step; #else *selected = (oldvalue - min) / step; #endif *function = info->option_callback; } } else if (var_type == F_T_BOOL) { *selected = oldvalue; *nb_items = 2; boolfunction = setting->bool_setting->option_callback; if (boolfunction) *function = bool_funcwrapper; } }
/* only the quickscreen and recording trigger needs this */ void option_select_next_val(const struct settings_list *setting, bool previous, bool apply) { int val = 0; int *value = setting->setting; if ((setting->flags & F_BOOL_SETTING) == F_BOOL_SETTING) { *(bool*)value = !*(bool*)value; if (apply && setting->bool_setting->option_callback) setting->bool_setting->option_callback(*(bool*)value); return; } else if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) { struct int_setting *info = (struct int_setting *)setting->int_setting; bool neg_step = (info->step < 0); if (!previous) { val = *value + info->step; if (neg_step ? (val < info->max) : (val > info->max)) val = info->min; } else { val = *value - info->step; if (neg_step ? (val > info->min) : (val < info->min)) val = info->max; } *value = val; if (apply && info->option_callback) info->option_callback(val); } else if ((setting->flags & F_T_SOUND) == F_T_SOUND) { int setting_id = setting->sound_setting->setting; int steps = sound_steps(setting_id); int min = sound_min(setting_id); int max = sound_max(setting_id); if (!previous) { val = *value + steps; if (val >= max) val = min; } else { val = *value - steps; if (val < min) val = max; } *value = val; } else if ((setting->flags & F_CHOICE_SETTING) == F_CHOICE_SETTING) { struct choice_setting *info = (struct choice_setting *)setting->choice_setting; val = *value + 1; if (!previous) { val = *value + 1; if (val >= info->count) val = 0; } else { val = *value - 1; if (val < 0) val = info->count-1; } *value = val; if (apply && info->option_callback) info->option_callback(val); } else if ((setting->flags & F_TABLE_SETTING) == F_TABLE_SETTING) { const struct table_setting *tbl_info = setting->table_setting; int i, add; add = previous?tbl_info->count-1:1; for (i=0; i<tbl_info->count;i++) { if ((*value == tbl_info->values[i]) || (settings->flags&F_ALLOW_ARBITRARY_VALS && *value < tbl_info->values[i])) { val = tbl_info->values[(i+add)%tbl_info->count]; break; } } *value = val; } }
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; } else if (pb->type == SKIN_TOKEN_SETTINGBAR) { int val, count; get_setting_info_for_bar(pb->setting_id, &count, &val); length = count - 1; end = val; } #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); /* account for the sliders width in the progressbar */ if (flags&HORIZONTAL) { width -= img->bm.width; } else { height -= img->bm.height; } } 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, pb->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; } else { h = img->bm.height; yoff = height * end / length; if (flags&INVERTFILL) yoff = height - yoff; } 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 } }
static void set_prescaled_volume(void) { #if defined(TONE_PRESCALER) || !defined(AUDIOHW_HAVE_MONO_VOLUME) const int minvol = sound_value_to_cb(SOUND_VOLUME, sound_min(SOUND_VOLUME)); #endif int volume = sound_prescaler.volume; #if defined(TONE_PRESCALER) int prescale = 0; /* Note: Having Tone + EQ isn't prohibited */ #if defined(AUDIOHW_HAVE_BASS) && defined(AUDIOHW_HAVE_TREBLE) prescale = MAX(sound_prescaler.bass, sound_prescaler.treble); #endif #if defined(AUDIOHW_HAVE_EQ) for (int i = 0; i < AUDIOHW_EQ_BAND_NUM; i++) prescale = MAX(sound_prescaler.eq_gain[i], prescale); #endif if (prescale < 0) prescale = 0; /* no need to prescale if we don't boost bass, treble or eq band */ /* Gain up the analog volume to compensate the prescale gain reduction, * but if this would push the volume over the top, reduce prescaling * instead (might cause clipping). */ const int maxvol = sound_value_to_cb(SOUND_VOLUME, sound_max(SOUND_VOLUME)); if (volume + prescale > maxvol) prescale = maxvol - volume; audiohw_set_prescaler(prescale); if (volume <= minvol) prescale = 0; /* Make sure the audio gets muted */ #ifndef AUDIOHW_HAVE_MONO_VOLUME /* At the moment, such targets have lousy volume resolution and so minute boost won't work how we'd like */ volume += prescale; #endif #endif /* TONE_PRESCALER */ #if defined(AUDIOHW_HAVE_MONO_VOLUME) audiohw_set_volume(volume); #else /* Stereo volume */ int l = volume, r = volume; /* Balance the channels scaled by the current volume and min volume */ int balance = sound_prescaler.balance; /* percent */ if (balance > 0) { l -= (l - minvol) * balance / 100; } else if (balance < 0) { r += (r - minvol) * balance / 100; } audiohw_set_volume(l, r); #endif /* AUDIOHW_HAVE_MONO_VOLUME */ #if defined(AUDIOHW_HAVE_LINEOUT) /* For now, lineout stays at unity */ audiohw_set_lineout_volume(0, 0); #endif /* AUDIOHW_HAVE_LINEOUT */ }
bool set_sound(const char* string, int* variable, int setting) { bool done = false; bool changed = true; int min, max; int val; int numdec; int integer; int dec; const char* unit; char str[32]; int talkunit = UNIT_INT; int steps; int button; unit = sound_unit(setting); numdec = sound_numdecimals(setting); steps = sound_steps(setting); min = sound_min(setting); max = sound_max(setting); if (*unit == 'd') /* crude reconstruction */ talkunit = UNIT_DB; else if (*unit == '%') talkunit = UNIT_PERCENT; else if (*unit == 'H') talkunit = UNIT_HERTZ; #ifdef HAVE_LCD_BITMAP if(global_settings.statusbar) lcd_setmargins(0, STATUSBAR_HEIGHT); else lcd_setmargins(0, 0); #endif lcd_clear_display(); lcd_puts_scroll(0,0,string); while (!done) { if (changed) { val = sound_val2phys(setting, *variable); if(numdec) { integer = val / (10 * numdec); dec = val % (10 * numdec); snprintf(str,sizeof str, fmt[numdec], integer, dec, unit); } else { snprintf(str,sizeof str,"%d %s ", val, unit); } if (global_settings.talk_menu) talk_value(val, talkunit, false); /* speak it */ } lcd_puts(0,1,str); status_draw(true); lcd_update(); changed = false; button = button_get_w_tmo(HZ/2); switch( button ) { case SETTINGS_INC: case SETTINGS_INC | BUTTON_REPEAT: (*variable)+=steps; if(*variable > max ) *variable = max; changed = true; break; case SETTINGS_DEC: case SETTINGS_DEC | BUTTON_REPEAT: (*variable)-=steps; if(*variable < min ) *variable = min; changed = true; break; case SETTINGS_OK: case SETTINGS_CANCEL: #ifdef SETTINGS_OK2 case SETTINGS_OK2: #endif #ifdef SETTINGS_CANCEL2 case SETTINGS_CANCEL2: #endif done = true; break; default: if(default_event_handler(button) == SYS_USB_CONNECTED) return true; break; } if (changed) sound_set(setting, *variable); } lcd_stop_scroll(); return false; }