Esempio n. 1
0
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;
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
LVAL xlc_snd_max(void)
{
    LVAL arg1 = xlgetarg();
    long arg2 = getfixnum(xlgafixnum());
    double result;

    xllastarg();
    result = sound_max(arg1, arg2);
    return cvflonum(result);
}
Esempio n. 4
0
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
    }
}
Esempio n. 5
0
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;
    }
}
Esempio n. 6
0
   /* 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;
    }
}
Esempio n. 7
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;
    }
    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
    }
}
Esempio n. 8
0
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 */
}
Esempio n. 9
0
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;
}