From 239b70fad38be55075dd14ea8e3c0f6f54a1f35b Mon Sep 17 00:00:00 2001 From: Jörg Hohensohn Date: Fri, 19 Mar 2004 22:15:52 +0000 Subject: patch #908634 applied git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4413 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/vu_meter.c | 391 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 348 insertions(+), 43 deletions(-) diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c index 685d2f65d8..a9d74da794 100644 --- a/apps/plugins/vu_meter.c +++ b/apps/plugins/vu_meter.c @@ -15,20 +15,30 @@ * KIND, either express or implied. * **************************************************************************/ + + /****************************************************** + * Quick note: throughout this code you'll see + * comments like this one, inside of a box. They are + * used to indicate new functions, not because I + * think you're blind. Only here to help. + ******************************************************/ + #include "plugin.h" -#ifndef SIMULATOR #ifdef HAVE_LCD_BITMAP static struct plugin_api* rb; /* This table is used to define x positions on a logarithmic (dBfs) scale. - The formula I used to figure these out was log(x+1)*31.89293, + There are 112 of them, one for each pixel. + The formula I used to figure these out was log(x)*32.09, where x was the original x position. */ -static unsigned char db_scale[] = {0,9.6,15.2,19.2,22.3,24.8,27,28.8,30.4,31.9,33.2,34.4,35.5,36.6,37.5,38.4, - 39.2,40,40.8,41.5,52.2,42.8,43.4,44,44.6,45.1,45.7,46.2,46.6,47.1,47.6,48, - 48.4,48.8,49.2,49.6,50,50.4,50.7,51.1,51.4,51.8,52.1,52.4,52.7,53,53.3,53.6, - 53.9,54.2,54.5,54.7,55,55.3,55.5,55.8,56}; +static unsigned char db_scale[] = {0,0,10,15,19,22,25,27,29,31,32,33,35,36,37,38,39,39,40,41,42,42, + 43,44,44,45,45,46,46,47,47,48,48,49,49,50,50,50,51,51,51,52,52, + 52,53,53,53,54,54,54,55,55,55,55,56,56,56,56,56,66, 71,75,78,81, + 83,85,87,88,89,91,92,93,94,95,95,96,97,98,98,99,100,100,101,101, + 102,102,103,103,104,104,105,105,106,106,106,107,107,107,108,108, + 108,109,109,109,110,110,110,111,111,111,111,112,112,112}; /* Define's y positions, and makes it look like an arch, like a real needle would. */ static unsigned char y_values[] = {32,31,30,29,28,27,26,25,24,24,23,22,22,21,21,20,19,19,18,18,18,18,18,17,17,17,17,17, @@ -36,81 +46,328 @@ static unsigned char y_values[] = {32,31,30,29,28,27,26,25,24,24,23,22,22,21,21, 32,31,30,29,28,27,26,25,24,24,23,22,22,21,21,20,19,19,18,18,18,18,18,17,17,17,17,17, 17,17,17,17,17,18,18,18,18,18,19,19,20,21,21,22,22,23,24,24,25,26,27,28,29,30,31,32}; +/*************************************************** + * LCD Bitmaps/Icons + ***************************************************/ + /* Linear mode bitmap icon. */ -static unsigned char mode_linear[] = {0xDF,0x10,0xD0,0x00,0xDF,0x00,0xDF,0x02,0xC4,0x08,0xDF, - 0x00,0xDF,0x15,0xD1,0x00,0xDE,0x05,0xDE,0x00,0xDF,0x05, - 0xDA}; +unsigned char mode_linear[] = {0xDF,0x10,0xD0,0x00,0xDF,0x00,0xDF,0x02,0xC4,0x08,0xDF, + 0x00,0xDF,0x15,0xD1,0x00,0xDE,0x05,0xDE,0x00,0xDF,0x05, + 0xDA}; /* Logarithmic (dBfs) mode bitmap icon. */ -static unsigned char mode_dbfs[] = {0xC8,0x14,0x14,0x1F,0x00,0xDF,0x15,0x15,0x0A,0xC0,0x1E, - 0x05,0x05,0xC0,0x16,0x15,0xD5,0x09,0xC0,0x00,0xF0,0x00, - 0xFE}; +unsigned char mode_dbfs[] = {0xC8,0x14,0x14,0x1F,0x00,0xDF,0x15,0x15,0x0A,0xC0,0x1E, + 0x05,0x05,0xC0,0x16,0x15,0xD5,0x09,0xC0,0x00,0xF0,0x00, + 0xFE}; + +/* Channel indicator - no level [4x8] */ +static unsigned char sound_speaker[] = {0x18,0x24,0x42,0xFF}; + +/* Channel indicator - low level [2x8] */ +static unsigned char sound_low_level[] = {0x24,0x18}; + +/* Channel indicator - medium level [2x8] */ +static unsigned char sound_med_level[] = {0x42,0x3C}; + +/* Channel indicator - high level [2x8] */ +static unsigned char sound_high_level[] = {0x81,0x7E}; + +/* Channel indicator - maxed out [3x8] */ +static unsigned char sound_max_level[] = {0x0E,0xDF,0x0E}; + +/* Volume level icon [4x7] */ +static unsigned char volume_indicator[] = {0x1C,0x1C,0x22,0x7F}; +/* RIGHT ARROW icon (from icons.c) [7x8] */ +static unsigned char right_arrow[] = {0x7F,0x3E,0x1C,0x7F,0x3E,0x1C,0x08}; +/* LEFT ARROW icon (from icons.c) [7x8] */ +static unsigned char left_arrow[] = {0x08,0x1C,0x3E,0x7F,0x1C,0x3E,0x7F}; + +/************************* + * DEFINES + *************************/ #define MAX_PEAK 0x7FFF #define NEEDLE_BOTTOM_Y 54 +/****************************** + * LEFT NEEDLE ints + ******************************/ #define LEFT_NEEDLE_BOTTOM_X 28 int left_needle_top_y; int left_needle_top_x; int old_left_needle_top_x = 0; int left_needle_top_x_no_log; +/******************************* + * RIGHT NEEDLE ints + *******************************/ #define RIGHT_NEEDLE_BOTTOM_X 84 int right_needle_top_y; int right_needle_top_x; int old_right_needle_top_x = 56; int right_needle_top_x_no_log; -bool show_arch = true; +/********************* + * LEFT MINIMETER ints + *********************/ +int mini_left_low; +int mini_left_med; +int mini_left_high; +int mini_left_clip; + +/********************** + * RIGHT MINIMETER ints + **********************/ +int mini_right_low; +int mini_right_med; +int mini_right_high; +int mini_right_clip; + +/************************ + * GENERAL ints + ************************/ +char curr_vol[3]; /* CURRENT VOLUME */ +int vol; /* CURENNT VOLUME int */ +int on = 1; /* MINIMETER OPTIONS int */ +int needle_cover_mode = 1; /* NEEDLE COVER int (defaults to "rounded") */ +int arch = 1; /* ARCH int (defaults to "solid") */ +int decay = 3; /* DECAY int (defaults to "medium") */ + +/************************* + * GENERAL bools + *************************/ +bool quit = false; bool use_log_scale = true; -int needle_cover_mode = 1; +bool use_minimeters = true; + +/******************************************** + * Change the volume - derived from VIDEO.C + ********************************************/ +void ChangeVolume(int delta) +{ + vol = rb->global_settings->volume + delta; -/* This draws everthing but the needles, needle covers, and the visible arch. */ + if (vol > 100) vol = 100; + else if (vol < 0) vol = 0; + if (vol != rb->global_settings->volume) + { + rb->mpeg_sound_set(SOUND_VOLUME, vol); + rb->global_settings->volume = vol; + rb->snprintf(curr_vol, sizeof(curr_vol), "%d", vol); + } +} + +/***************************************************** + * Draw the status bar + *****************************************************/ void draw_status_bar(void) { rb->lcd_setfont(FONT_SYSFIXED); - rb->lcd_clear_display(); - rb->lcd_drawline(0, 10, 111, 10); + rb->lcd_drawline(0, 10, 112, 10); rb->lcd_putsxy(1, 1, "VU Meter"); + rb->lcd_drawline(52, 1, 52, 8); + rb->lcd_bitmap(volume_indicator, 60, 1, 4, 7, true); + rb->lcd_putsxy(65, 1, curr_vol); + rb->lcd_drawline(85, 1, 85, 8); if(use_log_scale) rb->lcd_bitmap(mode_dbfs, 88, 1, 23, 8, true); else rb->lcd_bitmap(mode_linear, 88, 1, 23, 8, true); - rb->lcd_putsxy(25, 56, "L"); - rb->lcd_putsxy(81, 56, "R"); - /* The last line under the needle covers. */ rb->lcd_drawline(0, 54, 111, 54); - rb->lcd_update(); + rb->lcd_update_rect(0, 0, 112, 10); +} + +/****************************** + * DRAW left MiniMeters + ******************************/ + +void draw_left_minimeters(void) +{ + rb->lcd_bitmap(sound_speaker, 22, 56, 4, 8, true); + + if(5lcd_bitmap(sound_low_level, 27, 56, 2, 8, false); + if(12lcd_bitmap(sound_med_level, 30, 56, 2, 8, false); + if(24lcd_bitmap(sound_high_level, 33, 56, 2, 8, false); + if(40lcd_bitmap(sound_max_level, 36, 56, 3, 8, false); +} + +/******************************* + * DRAW right MiniMeters + *******************************/ +void draw_right_minimeters(void) +{ + rb->lcd_bitmap(sound_speaker, 79, 56, 4, 8, true); + + if(5<(right_needle_top_x_no_log-56)) + rb->lcd_bitmap(sound_low_level, 84, 56, 2, 8, false); + if(12<(right_needle_top_x_no_log-56)) + rb->lcd_bitmap(sound_med_level, 87, 56, 2, 8, false); + if(24<(right_needle_top_x_no_log-56)) + rb->lcd_bitmap(sound_high_level, 90, 56, 2, 8, false); + if(40<(right_needle_top_x_no_log-56)) + rb->lcd_bitmap(sound_max_level, 93, 56, 3, 8, false); +} + +/*************************************** + * GENERAL SETTINGS - F1 + ***************************************/ +void general_settings(void) +{ + char buf[15]; + int w, h; + + while(!quit) + { + rb->lcd_clear_display(); + + /* Left hand side (needle covers) */ + rb->lcd_putsxy(0, 15, "Needle"); + rb->lcd_putsxy(0, 23, "Covers:"); + if(needle_cover_mode == 1) + rb->lcd_putsxy(0, 32, "Rounded"); + else + rb->lcd_putsxy(0, 32, "Pyramid"); + rb->lcd_bitmap(left_arrow, 43, 23, 7, 8, true); + + /* Right hand side (visible arch) */ + rb->snprintf(buf, sizeof(buf), "Visible"); + rb->lcd_getstringsize(buf, &w, &h); + rb->lcd_putsxy(LCD_WIDTH-w, 15, buf); + rb->snprintf(buf, sizeof(buf), "Arch:"); + rb->lcd_getstringsize(buf, &w, &h); + rb->lcd_putsxy(LCD_WIDTH-w, 23, buf); + rb->lcd_bitmap(right_arrow, 62, 23, 7, 8, true); + if(arch == 1) + { + rb->snprintf(buf, sizeof(buf), "Solid"); + rb->lcd_getstringsize(buf, &w, &h); + rb->lcd_putsxy(LCD_WIDTH-w, 32, buf); + } + else if(arch == 2) + { + rb->snprintf(buf, sizeof(buf), "Dotted"); + rb->lcd_getstringsize(buf, &w, &h); + rb->lcd_putsxy(LCD_WIDTH-w, 32, buf); + } + else + { + rb->snprintf(buf, sizeof(buf), "Off"); + rb->lcd_getstringsize(buf, &w, &h); + rb->lcd_putsxy(LCD_WIDTH-w, 32, buf); + } + + rb->lcd_update(); + + switch(rb->button_get_w_tmo(HZ/4)) + { + case BUTTON_F1: + case BUTTON_OFF: + quit = true; + break; + + case BUTTON_RIGHT: + arch==3 ? arch=1 : arch++; + break; + + case BUTTON_LEFT: + needle_cover_mode==2 ? needle_cover_mode=1 : needle_cover_mode++; + break; + } + } } +/***************************** + * User Decay settings + *****************************/ +void user_decay_settings(void) +{ + while(!quit) + { + rb->lcd_clear_display(); + + rb->lcd_putsxy(2, 0, "User Decay Options"); + rb->lcd_putsxy(5, 15, "Release Speed:"); + + switch(decay) + { + case 0: rb->lcd_putsxy(5, 23, "No Decay"); break; + case 1: rb->lcd_putsxy(5, 23, "Very Fast"); break; + case 2: rb->lcd_putsxy(5, 23, "Fast"); break; + case 3: rb->lcd_putsxy(5, 23, "Medium"); break; + case 4: rb->lcd_putsxy(5, 23, "Medium-Slow"); break; + case 5: rb->lcd_putsxy(5, 23, "Slow"); break; + case 6: rb->lcd_putsxy(5, 23, "Very Slow"); break; + default: break; + } + + rb->lcd_putsxy(2, 48, "UP/DOWN: Change"); + rb->lcd_putsxy(2, 56, "OFF/F2: Back to VU"); + + rb->lcd_update(); + + switch(rb->button_get_w_tmo(HZ/4)) + { + case BUTTON_F2: + case BUTTON_OFF: + quit = true; + break; + + case BUTTON_DOWN: + decay == 6 ? decay = 0 : decay++; + break; + + case BUTTON_UP: + decay == 0 ? decay = 6 : decay--; + break; + } + } +} + +/*********************************************************************** + * PLUGIN STARTS HERE + ***********************************************************************/ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { TEST_PLUGIN_API(api); (void) parameter; rb = api; - draw_status_bar(); + /* Calculate the volume right away */ + vol = rb->global_settings->volume; + rb->snprintf(curr_vol, sizeof(curr_vol), "%d", vol); + rb->splash(HZ*2, true, "Press [ON] for help"); while (!PLUGIN_OK) { + quit = false; + + #ifdef SIMULATOR + left_needle_top_x_no_log = rb->rand()%56; + right_needle_top_x_no_log = (rb->rand()%56)+56; + #else left_needle_top_x_no_log = (rb->mas_codec_readreg(0xC) * 56 / MAX_PEAK); right_needle_top_x_no_log = (rb->mas_codec_readreg(0xD) * 56 / MAX_PEAK) + 56; + #endif rb->lcd_clear_display(); if (use_log_scale) { left_needle_top_x = db_scale[left_needle_top_x_no_log]; - right_needle_top_x = db_scale[right_needle_top_x_no_log-56]+56; + right_needle_top_x = db_scale[right_needle_top_x_no_log]; } else @@ -119,9 +376,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) right_needle_top_x = right_needle_top_x_no_log; } - /* Makes a decay on the needle. Todo: Make a user custom decay. */ - left_needle_top_x = (left_needle_top_x+old_left_needle_top_x*2)/3; - right_needle_top_x = (right_needle_top_x+old_right_needle_top_x*2)/3; + /* Makes a decay on the needle (Custom Decay is at F2) */ + left_needle_top_x = (left_needle_top_x+old_left_needle_top_x*decay)/(decay+1); + right_needle_top_x = (right_needle_top_x+old_right_needle_top_x*decay)/(decay+1); old_left_needle_top_x = left_needle_top_x; old_right_needle_top_x = right_needle_top_x; @@ -136,6 +393,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) rb->lcd_drawline(RIGHT_NEEDLE_BOTTOM_X, NEEDLE_BOTTOM_Y, right_needle_top_x, right_needle_top_y); + /* We've got four needle cover modes... */ if(needle_cover_mode == 1) /* Rounded needle cover. */ { /* Left needle cover, top to bottom */ @@ -170,47 +428,95 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) rb->lcd_drawline(80, 53, 88, 53); } - if(show_arch) + if(arch == 1) /* Solid */ { int i; - for(i=0;i<=112;i++) + for(i=0; i<=112; i++) rb->lcd_drawpixel(i, (y_values[i])-2 ); } + else if(arch == 2) /* Dotted */ + { + int i; + for(i=0; i<=112; i+=2) + rb->lcd_drawpixel(i, y_values[i]); + } + + if(use_minimeters) + { + draw_left_minimeters(); + draw_right_minimeters(); + } - rb->lcd_update_rect(0,15,112,39); + draw_status_bar(); - switch (rb->button_get_w_tmo(1)) + rb->lcd_update(); + + /* Using a faster timeout like "1" makes the + * minimeters flicker, HZ/35 looks good. */ + switch (rb->button_get_w_tmo(HZ/35)) { + /* EXIT */ case BUTTON_OFF: return PLUGIN_OK; break; + /* INFO */ case BUTTON_ON: rb->lcd_clear_display(); - rb->lcd_putsxy(1, 1, "Information:"); - rb->lcd_putsxy(2, 15, "OFF: Exit"); - rb->lcd_putsxy(2, 25, "ON: This Info"); - rb->lcd_putsxy(2, 35, "PLAY: Change Scale"); - rb->lcd_putsxy(2, 45, "F1: Needle Covers"); - rb->lcd_putsxy(2, 55, "F2: Visible Arch"); - rb->lcd_update(); - rb->sleep(HZ*3); - draw_status_bar(); + while(!quit) + { + rb->lcd_puts(0, 0, "OFF: Exit Plugin"); + rb->lcd_puts(0, 1, "PLAY: Change Scale"); + rb->lcd_puts(0, 2, "F1: Settings"); + rb->lcd_puts(0, 3, "F2: Custom Decay"); + rb->lcd_puts(0, 4, "F3: Mini-Meters"); + rb->lcd_puts(0, 5, "UP/DOWN: Volume"); + rb->lcd_puts(0, 7, "ON to exit..."); + + rb->lcd_update(); + + switch(rb->button_get_w_tmo(HZ/4)) + { + case BUTTON_ON: + quit = true; + break; + } + } break; + /* SCALE switch */ case BUTTON_PLAY: use_log_scale = !use_log_scale; - draw_status_bar(); break; + /* GENERAL SETTINGS screen */ case BUTTON_F1: - needle_cover_mode==2 ? needle_cover_mode=1 : needle_cover_mode++; + general_settings(); break; + /* DECAY SETTINGS screen */ case BUTTON_F2: - show_arch = !show_arch; + user_decay_settings(); + break; + + /* MINIMETER SETTINGS screen */ + case BUTTON_F3: + use_minimeters = !use_minimeters; + break; + + /* VOLUME UP */ + case BUTTON_UP: + case BUTTON_UP | BUTTON_REPEAT: + ChangeVolume(1); + break; + + /* VOLUME DOWN */ + case BUTTON_DOWN: + case BUTTON_DOWN | BUTTON_REPEAT: + ChangeVolume(-1); break; + /* USB CONNECTED */ case SYS_USB_CONNECTED: rb->usb_screen(); return PLUGIN_USB_CONNECTED; @@ -219,4 +525,3 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) } } #endif /* #ifdef HAVE_LCD_BITMAP */ -#endif /* #ifndef SIMULATOR */ -- cgit v1.2.3