/*************************************************************************** * Copyright (c) 2003-2006, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: $ * $brcm_Revision: $ * $brcm_Date: $ * * Module Description: * * Revision History: * * $brcm_Log: $ * ***************************************************************************/ #include "bapp.h" #include "bapp_palette.h" #include "bapp_util.h" #include "bgfx.h" #include "chan_mgr.h" #include "ts_psi.h" #include "ts_scte_18.h" #include "bapp_str_table.h" BDBG_MODULE(bscreen); /* Register software module with debug interface */ /* DIG defines 7 characters as max but for PSI channel scan it is useful to have more. */ #define MAX_NAME_CHARS 14 /* local function declarations */ static void banner_null_draw(void *v_app, void *v_screen); #define SCREEN_MIN(a,b) ((a)<(b) ? (a) : (b)) /* min macro */ /* Local definitions */ #ifndef CONFIG_CHINESE_FONTS_RAM static char * s_str_table[eTEXT_MAX] = { /*eTEXT_ONE_MOMENT, */"One Moment Please", /*eTEXT_TROUBLE_ERROR_1, */"Your service has been temporarily interrupted.", /*eTEXT_TROUBLE_ERROR_2, */"It should be restored momentarily.", /*eTEXT_TROUBLE_ERROR_3, */"", /*eTEXT_MUTE_TITLE, */"Mute", /*eTEXT_PENDING_1, */"We've detected an interruption in your service.", /*eTEXT_PENDING_2, */"Please contact Comcast at 1-800-COMCAST", /*eTEXT_PENDING_3, */"(1-800-266-2278) to restore service.", /*eTEXT_PENDING_4, */"We're sorry for the inconvenience.", #ifdef BDBG_DEBUG_BUILD /*eTEXT_SYS_INFO, */"Press INFO to exit Vol- or Vol+ to change page", #else /*eTEXT_SYS_INFO, */"Press INFO to exit Press CH- or CH+ to change page", #endif /*eTEXT_VENDOR, */DEF_VENDOR_NAME, /*eTEXT_MUTE, */"Mute", /*eTEXT_VOLUME, */"Volume", /*eTEXT_DL_1, */"Please give us a moment to prepare your", /*eTEXT_DL_2, */"adapter for new software - delivered", /*eTEXT_DL_3, */"exclusively from Comcast.", /*eTEXT_DL_4, */"This typically takes less than 20 minutes", /*eTEXT_DL_5, */"but it'll be worth the wait. Your adapter may", /*eTEXT_DL_6, */"automatically reset during this process.", /*eTEXT_HUNT_TITLE, */"We're searching for cable services in your area.", /*eTEXT_HUNT_PROGRESS, */"Total Progress: ", }; #else static char * s_str_table[eTEXT_MAX] = { /*eTEXT_ONE_MOMENT, */"c7ebc9d4baf20000", /*eTEXT_TROUBLE_ERROR_1, */"ced2c3c7d4ddcab1d6d0b6cfc4fab5c4b7fecef1a1a30000", /*eTEXT_TROUBLE_ERROR_2, */"ced2c3c7c9d4baf2bdabbbd6b8b4c4fab5c4b7fe0000", /*eTEXT_TROUBLE_ERROR_3, */"cef1a1a30000", /*eTEXT_MUTE_TITLE, */"cffbd2f40000", /*eTEXT_PENDING_1, */"c7ebb5e7b8e60031002e003800300030002e0043004f004d00430041005300540000", /*eTEXT_PENDING_2, */"d2d4bbd6b8b4c4fab5c4b7fecef1a1a30000", /*eTEXT_PENDING_3, */"d2d4bbd6b8b4c4fab5c4b7fecef1a1a30000", /*eTEXT_PENDING_4, */"d2d4bbd6b8b4c4fab5c4b7fecef1a1a30000", #ifdef BDBG_DEBUG_BUILD /*eTEXT_SYS_INFO, */"b0b40049004e0046004fbcfccdcbb3f60020002000200020b0b40056004f004c002dbbf20056004f004c002bbcfcd2d4bbbbd2b30000", #else /*eTEXT_SYS_INFO, */"b0b40049004e0046004fbcfccdcbb3f60020002000200020b0b400430048002dbbf200430048002bbcfcd2d4bbbbd2b30000", #endif /*eTEXT_VENDOR, */DEF_VENDOR_NAME, /*eTEXT_MUTE, */"cffbd2f40000", /*eTEXT_VOLUME, */"d2f4c1bf0000" }; #endif screensaver_state_t g_screensaver_state = { 0 }; banner_state_t g_banner_state = { { 0, 0, 0, 0}, 0, false, eLS_BANNER_OFF, { eS_EVENT_MAX, 0, 0}, 0, 0, 0, 0, 0 }; /* Summary: copy string and remove spaces. . */ void strncpy_no_spaces(char* dst_str, char* src_str,int len) { int idx = 0; int dst_idx = 0; while (src_str[idx] && (idx < len)) { if (src_str[idx] != ' ') { dst_str[dst_idx++] = src_str[idx]; } idx++; } dst_str[dst_idx] = 0; } #define eEAS_TEXT_X (eSCREEN_ACTION_SAFE_X + 110) #define eEAS_TEXT_Y (eSCREEN_ACTION_SAFE_Y + 120) #define eEAS_TEXT_WIDTH (eSCREEN_ACTION_SAFE_WIDTH - eEAS_TEXT_X) #define eEAS_TEXT_HEIGHT (eSCREEN_ACTION_SAFE_HEIGHT - eEAS_TEXT_Y - 60) #define eEAS_ROW_HEIGHT (25) #define MAX_EAS_TEXT 128 #define EAS_TEXT_LINE_MAX 4 /* 4 lines, including EAS event, one empty line and two text lines */ #define MAX_TSTR_LINE 40 /* letters per line */ #define EAS_BANNER_POPPED 0x8000 /* flag indicates that EAS text scrolling banner has been launched */ typedef struct eas_pkt_info_t { unsigned char *p_eas; /* pointer to eas packet buffer */ unsigned char eas_text[MAX_EAS_TEXT]; /* pinter to eas text to display */ unsigned int eas_text_len; /* eas test lenght */ unsigned int eas_current; /* current offset to display */ TS_SCTE_18_header header; /* header structure */ } eas_pkt_into_t; static struct eas_pkt_info_t s_eas_text_scrolling_info = { NULL, "", 0, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; /* Summary: process the MSS string Returns non-zero on failure. */ int eas_process_mss(bapp_t *p_app, /* [in] pointer to p_app */ PSIP_MSS_string p_mss, /* [in] Pointer to MSS */ unsigned char *mss_buf, /* [out] string buffer */ unsigned int mss_len) /* [out] string buffer length */ { int str_idx,lsize; char *p_code; BERR_Code retcode; int num_str; if (!p_mss || !mss_buf || !mss_len) return BERR_INVALID_PARAMETER; num_str = PSIP_MSS_getNumStrings(p_mss); memset(mss_buf,0,mss_len); for (str_idx = 0; str_idx < num_str; ++str_idx) { if ((retcode = PSIP_MSS_getCode(p_mss,str_idx, &p_code)) != BERR_SUCCESS) { BDBG_WRN(("PSIP_MSS_getCode:%d failed %d",__LINE__,retcode)); memset(mss_buf,0,mss_len); continue; } /* to match language of string, TODO handle other language */ if (eLANG_ENGLISH == p_app->lang && (*p_code == 'e' && *(p_code + 1) == 'n')) goto LANG_CHECKED; if (eLANG_FRENCH == p_app->lang && (*p_code == 'f' && *(p_code + 1) == 'r')) goto LANG_CHECKED; if (eLANG_SPANISH == p_app->lang && ((*p_code == 'e' && *(p_code + 1) == 's') || (*p_code == 'e' && *(p_code + 1) == 'p'))) goto LANG_CHECKED; else { memset(mss_buf,0,mss_len); continue; } LANG_CHECKED: lsize = mss_len; if ((retcode = PSIP_MSS_getString(p_mss,str_idx,&lsize,(char*)mss_buf)) != BERR_SUCCESS) { BDBG_ERR(("MSS invalid %d",retcode)); return retcode; } BDBG_MSG(("%s:%d idx = %d, %d/%d-%s",__FUNCTION__,__LINE__,str_idx,lsize,mss_len,mss_buf)); return 0; } /* in case no valid language exists just use first string */ if (num_str > 0) { lsize = mss_len; if ((retcode = PSIP_MSS_getString(p_mss,0,&lsize, (char*)mss_buf)) == BERR_SUCCESS) { BDBG_WRN(("No language match using default")); return 0; } else { BDBG_WRN(("PSIP_MSS_getString failed %d",retcode)); } } BDBG_WRN(("%s:%d no valid string found, num_str = %d",__FUNCTION__,__LINE__,num_str)); return BERR_NOT_SUPPORTED; } /* Summary: set EAS packet information Return: 0 if sucess error code if failed */ int bscreen_eas_text_scrolling_info(bapp_t *p_app, unsigned char *eas_pkt, unsigned int size) { if (!eas_pkt) { BDBG_WRN(("%s NULL pkt pointer",__FUNCTION__)); return BERR_INVALID_PARAMETER; } else { unsigned char *p_mss = NULL; unsigned int len; if (TS_SCTE_18_getSectionHeader(eas_pkt, size, &s_eas_text_scrolling_info.header) != 0) { goto FAILED; } if (s_eas_text_scrolling_info.header.alert_text_length) { p_mss = TS_SCTE_18_getAlrtTextOffset((const unsigned char *)eas_pkt, &len); } if (!p_mss) { goto FAILED; } /* we get EAS text if we are here */ if (eas_process_mss(p_app, p_mss, s_eas_text_scrolling_info.eas_text, len)) { goto FAILED; } s_eas_text_scrolling_info.p_eas = eas_pkt; s_eas_text_scrolling_info.eas_current = 0; /* set EAS Alert Text read pointer to beginning */ s_eas_text_scrolling_info.eas_text_len = strlen((const char*)s_eas_text_scrolling_info.eas_text); return BERR_SUCCESS; } FAILED: s_eas_text_scrolling_info.p_eas = NULL; s_eas_text_scrolling_info.eas_text_len = 0; BDBG_ERR(("#### get EAS Alert Text failed ####")); return BERR_INVALID_PARAMETER; } static const unsigned char *get_eas_text_line(void) { static char ts_str[MAX_TSTR_LINE + 1]; if (!s_eas_text_scrolling_info.p_eas || s_eas_text_scrolling_info.eas_current >= s_eas_text_scrolling_info.eas_text_len) { /* empty or no more text */ ts_str[0] = '\0'; } else { int i, cur; cur = s_eas_text_scrolling_info.eas_current; if ((cur + MAX_TSTR_LINE) < s_eas_text_scrolling_info.eas_text_len) { memcpy(ts_str, &s_eas_text_scrolling_info.eas_text[cur], MAX_TSTR_LINE); ts_str[MAX_TSTR_LINE] = '\0'; /* now back scan to find a place with white space, TODO unicode handling */ for (i = strlen(ts_str); i > 0; i--) { if ((0x20 == ts_str[i] || '\t' == ts_str[i])) { ts_str[i] = '\0'; break; } } } else { memcpy(ts_str, &s_eas_text_scrolling_info.eas_text[cur], s_eas_text_scrolling_info.eas_text_len - cur); ts_str[s_eas_text_scrolling_info.eas_text_len - cur] = '\0'; } s_eas_text_scrolling_info.eas_current += strlen(ts_str); } return (const unsigned char *)ts_str; } static void get_line_str(bapp_t *p_app, int line, /* line number */ unsigned int *p_uni_str, /* Buffer to put UNI string into */ unsigned int *str_len) /* On input the max length in words on output the actual size in characters. */ { static char ts_str[MAX_EAS_TEXT + 1]; if (!s_eas_text_scrolling_info.p_eas) { *str_len = 0; return; } switch (line) { default: case 0: case 1: *str_len = 0; break; break; case 2: *str_len = snprintf(ts_str,MAX_EAS_TEXT,"%s", get_eas_text_line()); break; case 3: /* scrolling position */ *str_len = snprintf(ts_str,MAX_EAS_TEXT,"%s", get_eas_text_line()); break; } if (*str_len) { *str_len = c_to_uni_str((unsigned char*)ts_str,p_uni_str,*str_len); } } /* Summary: EAS alert text drawing function. */ void bscreen_eas_text_scrolling_info_draw(void *v_app, void *v_screen) { bapp_t *p_app = (bapp_t*)v_app; uint16_t x,y,y_off; unsigned int num_chars = 0; int i = 0,size; x = eEAS_TEXT_X; y = eEAS_TEXT_Y; bgfx_fill_rect(&p_app->surf,x,y,eEAS_TEXT_WIDTH,eEAS_TEXT_HEIGHT,eCOLOR_BLACK); y += eEAS_ROW_HEIGHT; while (i < EAS_TEXT_LINE_MAX) { y_off = y + (i * eEAS_ROW_HEIGHT); if ((y_off + eEAS_ROW_HEIGHT) >= eHEIGHT) { BDBG_WRN(("%s too many rows %d, y = %d",__FUNCTION__,i,y_off)); break; } bgfx_fill_rect(&p_app->surf,x,y_off,eEAS_TEXT_WIDTH,eEAS_ROW_HEIGHT,eCOLOR_BLACK); num_chars = SCREEN_MAX_STR_WIDTH; if (0 == i) { char *p = NULL, event[30]; if (s_eas_text_scrolling_info.header.nature_of_activation_text_length) { p = (char *)TS_SCTE_18_getActivationTextOffset((const unsigned char *)s_eas_text_scrolling_info.p_eas,(size_t*) &size); if (p) { if (eas_process_mss(p_app, (unsigned char*)p, (unsigned char*)event, sizeof(event) - 1)) { p = NULL; } } else { BDBG_WRN(("TS_SCTE_18_getActivationTextOffset failed")); } } if (!p) { strcpy(event, "EAS Alert\n"); } num_chars = c_to_uni_str((unsigned char*)event, p_app->tmp_str, strlen(event)); text_box(&p_app->surf, p_app->p_font[eLANG_ENGLISH][eFONT_SIZE_SMALL], x + 10, y_off, eEAS_TEXT_WIDTH - 10, eEAS_ROW_HEIGHT, p_app->tmp_str, num_chars, eCOLOR_DK_YELLOW, 0); } else { num_chars = SCREEN_MAX_STR_WIDTH; get_line_str(p_app,i,p_app->tmp_str,&num_chars); if (num_chars) { text_box(&p_app->surf, p_app->p_font[eLANG_ENGLISH][eFONT_SIZE_SMALL], x + 10, y_off, eEAS_TEXT_WIDTH - 10, eEAS_ROW_HEIGHT, p_app->tmp_str, num_chars, eCOLOR_WHITE,0); } } i++; } } /* Summary: Use the this function to get a UNI string. */ void bscreen_get_string( bapp_lang_t e_lang, /* Language enum */ btext_id_t e_text_id, /* Text enum */ unsigned int *p_uni_str, /* Buffer to put UNI string into */ unsigned int *str_len /* On input the max length in words on output the actual size in characters. */ ) { char *p_str; if ((e_text_id >= eTEXT_MAX) || (e_lang >= eLANG_MAX)) { BDBG_ERR(("bscreen_get_string(%d,%d)(%d,%d) failed\n", e_lang, e_text_id,eTEXT_MAX,eLANG_MAX)); *str_len = 0; return; } p_str = (char*)s_str_table[e_text_id]; #if 0 BDBG_ERR(("get text id: %d - %s\n", e_text_id, p_str)); #endif *str_len = c_to_uni_str((unsigned char*)p_str,p_uni_str,*str_len); } /* Summary: Default screen idle handler Description: Default screen idle handler. . */ int bscreen_default_idle(void *v_app, void *v_screen) { bapp_t *p_app = (bapp_t*)v_app; bscreen_t *p_screen = (bscreen_t*)v_screen; uint32_t current_tick = bapp_task_getticks(); bool show_screensaver = false; /* check for screen timeout when 'no signal' popup is displayed */ if (current_tick >= (p_app->last_keypress_tick + MS_TO_TICKS(SCREEN_DEFAULT_TIMEOUT))) { if (p_app->screen_id == eSCREEN_BANNER) { banner_state_t *p_bs = (banner_state_t*)p_screen->local_state; if ( p_bs->mode == eLS_BANNER_INFO ) { show_screensaver = true; } } else if (p_app->screen_id != eSCREEN_SCREENSAVER) { show_screensaver = true; } } #ifndef CONFIG_SCREENSAVER if (show_screensaver) { return 0; /* don't cause screen redraw */ } #else if (show_screensaver) { bapp_set_current_screen(p_app, eSCREEN_SCREENSAVER, eSCREEN_MAX); p_app->last_keypress_tick = current_tick; BDBG_WRN(("#### %s:%d 0x%08x ####\n",__FUNCTION__,__LINE__,TICKS_TO_MS(p_app->last_keypress_tick))); return 1; /* cause screen redraw */ } #endif return 0; } #ifdef BDBG_DEBUG_BUILD #define bscreen_set_banner_state(app,screen,mode) bscreen_set_banner_state_dbg(app,screen,mode,__FUNCTION__,__LINE__) static int bscreen_set_banner_state_dbg(void *v_app, void *v_screen, banner_mode_t new_mode, const char* func, int line) #else static int bscreen_set_banner_state(void *v_app, void *v_screen, banner_mode_t new_mode) #endif { bapp_t *p_app = (bapp_t*)v_app; bscreen_t *p_screen = (bscreen_t*)v_screen; banner_state_t *p_bs = (banner_state_t*)p_screen->local_state; BDBG_ASSERT(p_bs); if (p_app->screen_id != eSCREEN_BANNER) return 0; /* Allow closed caption to pass through when we get a banner i.e. PIG */ bapp_enable_cc(p_app, 1); p_bs->mode = new_mode; switch (p_bs->mode) { case eLS_BANNER_SMALL: p_bs->timeout = bapp_task_getticks() + MS_TO_TICKS(BANNER_SMALL_TIMEOUT); banner_null_draw(v_app,v_screen); break; case eLS_BANNER_VOLUME: p_bs->timeout = bapp_task_getticks() + MS_TO_TICKS(BANNER_VOLUME_TIMEOUT); banner_null_draw(v_app,v_screen); break; case eLS_BANNER_SAP: p_bs->timeout = bapp_task_getticks() + MS_TO_TICKS(BANNER_SAP_TIMEOUT); banner_null_draw(v_app,v_screen); break; case eLS_BANNER_INFO: p_bs->timeout = bapp_task_getticks() + MS_TO_TICKS(SCREEN_DEFAULT_TIMEOUT); banner_null_draw(v_app,v_screen); break; case eLS_BANNER_EAS_TEXT_SCROLLING: p_bs->timeout = bapp_task_getticks() + MS_TO_TICKS(SCREEN_DEFAULT_TIMEOUT); banner_null_draw(v_app,v_screen); break; default: break; } #ifdef BDBG_DEBUG_BUILD BDBG_WRN(("banner state new mode %d called from %s:%d(%d)\n",new_mode, func,line,p_bs->timeout)); #endif return 1; } static void reset_10_key_timeout(bscreen_t *p_screen) { banner_state_t *p_bs = (banner_state_t*)p_screen->local_state; if (p_bs->majorChIndex > 0) { p_bs->ten_key_timeout = bapp_task_getticks() + MS_TO_TICKS(BANNER_10_KEY_TIMEOUT); p_bs->timeout = bapp_task_getticks() + MS_TO_TICKS(BANNER_SMALL_TIMEOUT); } else p_bs->ten_key_timeout = 0; } static void reset_10_key(bscreen_t *p_screen) { banner_state_t *p_bs = (banner_state_t*)p_screen->local_state; BDBG_ASSERT(p_bs); memset(p_bs->majorCh, 0, sizeof(p_bs->majorCh)); p_bs->majorChIndex = 0; p_bs->enter = false; reset_10_key_timeout(p_screen); } static int my_atoi(const char *s) { int i=0; while ((*s >= '0') && (*s <='9')) i = i*10 + *(s++) - '0'; return i; } /* Summary: Banner screen event handler Description: Banner screen event handler. . */ int screen_banner_event(void *v_app, void *v_screen, bscreen_event_t *p_event) { bapp_t *p_app = (bapp_t*)v_app; bscreen_t *p_screen = (bscreen_t*)v_screen; banner_state_t *p_bs; int result = 0; bool muted; static int last_mode = -1; p_bs = (banner_state_t*)p_screen->local_state; BDBG_ASSERT(p_bs); switch (p_event->type) { case eS_EVENT_REDRAW: result = 1; break; case eS_EVENT_SETUP: { result = 1; /* always handle event */ /* if showing banner because of 10key, do not reset value */ if (!((p_event->id >= eIR_0) && (p_event->id <= eIR_9))) reset_10_key(p_screen); /* reset key repeat timeout */ p_bs->repeat_rate = 1; p_bs->repeat_timeout = bapp_task_getticks() + DEFAULT_REPEAT_TIMEOUT/p_bs->repeat_rate; reset_10_key_timeout(p_screen); } break; case eS_EVENT_SETUP_DONE: if (p_app->state == eAPP_STATE_NORMAL) result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); else if ((p_app->state == eAPP_STATE_PENDING) || (p_app->state == eAPP_STATE_DOWNLOAD) || (p_app->state == eAPP_STATE_HUNT)) result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_INFO); else result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_OFF); break; case eS_EVENT_IDLE: { uint32_t current_tick = bapp_task_getticks(); /* Check for change in the applications state */ switch (p_app->state) { case eAPP_STATE_NORMAL: /* determine whether banner needs to be brought up or torn down */ /* based on signal status */ if (bapp_get_signal_status(p_app)) { /* if signal present */ if (p_bs->mode == eLS_BANNER_INFO) { /* if banner is currently up */ result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_OFF); /* take it down */ p_bs->timeout = 0; /* clear time out just in case */ } } else { /* if no signal present */ if (p_bs->mode == eLS_BANNER_OFF) { /* if on video */ result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_INFO); /* put up banner */ p_app->last_keypress_tick = current_tick; /* reset timer for screensaver entry */ p_bs->timeout = 0; /* this screen doesn't time out */ } } break; case eAPP_STATE_HUNT: case eAPP_STATE_PENDING: case eAPP_STATE_DOWNLOAD: { static chm_cmd_t last_cmd_id = eCHM_CANCEL; p_bs->event.type = eS_EVENT_MAX; /* Prevent repeat key when not in normal state */ if ((p_bs->mode != eLS_BANNER_INFO) || (p_bs->timeout == 0) || (last_cmd_id != p_app->chm.cmd)) { last_cmd_id = p_app->chm.cmd; result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_INFO); } if (p_app->state == eAPP_STATE_HUNT) { static int s_local_progress = 0; int progress = chm_get_hunt_progress(&p_app->chm); result = (s_local_progress != progress) ? 1 : result; s_local_progress = progress; } else if (p_app->state == eAPP_STATE_PENDING) { static unsigned short s_local_num_vch = 0; static bool s_local_activated = false; unsigned short num_vch, num_st; unsigned char num_freq ; ch_map_get_counts(bapp_cur_ch_map(p_app),&num_vch,&num_st,&num_freq); if ((s_local_activated != p_app->settings.activated) || (num_vch != s_local_num_vch)) { result = 1; } s_local_activated = p_app->settings.activated; s_local_num_vch = num_vch; } } break; default: break; } if (p_bs->mode == eLS_BANNER_INFO) { if ((p_app->state == eAPP_STATE_NORMAL) && bapp_get_signal_status(p_app)) { result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); } } /* if eas alert is fired */ if (p_app->eas_text && p_app->eas_timeout) { if (eAPP_STATE_NORMAL == p_app->state) { static int cnt = 0; /* to bring up EAS text scrolling if not yet */ if (eLS_BANNER_EAS_TEXT_SCROLLING != p_bs->mode && !(p_app->eas_text & EAS_BANNER_POPPED)) { cnt = 0; result = bscreen_set_banner_state(v_app, v_screen, eLS_BANNER_EAS_TEXT_SCROLLING); p_app->eas_text |= EAS_BANNER_POPPED; } if (eLS_BANNER_EAS_TEXT_SCROLLING == p_bs->mode) { if (cnt++ == 50) { cnt = 0; /* if no more text to draw, redraw from beginning */ if (s_eas_text_scrolling_info.eas_current >= s_eas_text_scrolling_info.eas_text_len) s_eas_text_scrolling_info.eas_current = 0; result = 1; } } } } /* Handle repeating when key is held down */ if (p_bs->repeat_timeout < current_tick) { /* BDBG_MSG(("%s repeat %d\n",__FUNCTION__,p_bs->event.id)); */ if (p_bs->event.type == eS_EVENT_IR) { switch (p_bs->event.id) { case eIR_UP: case eIR_CH_UP: bapp_change_channel(p_app,1,1); result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); break; case eIR_DOWN: case eIR_CH_DOWN: bapp_change_channel(p_app,0,1); result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); break; case eIR_VOL_UP: bapp_set_audio_volume(p_app, p_app->audio_vol - VOLUME_INCREMENT); result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_VOLUME); break; case eIR_VOL_DOWN: bapp_set_audio_volume(p_app, p_app->audio_vol + VOLUME_INCREMENT); result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_VOLUME); break; default: break; } } if (p_bs->repeat_rate < MAX_REPEAT_ACCEL) { p_bs->repeat_rate += REPEAT_INC; } p_bs->repeat_timeout = current_tick + (DEFAULT_REPEAT_TIMEOUT/p_bs->repeat_rate); } /* handle timeout */ if (p_bs->timeout && (current_tick >= p_bs->timeout)) { BDBG_WRN(("banner timeout %d >= %d\n",current_tick,p_bs->timeout)); p_bs->timeout = 0; if (p_app->eas_text && p_app->eas_timeout) { result = bscreen_set_banner_state(v_app, v_screen, eLS_BANNER_EAS_TEXT_SCROLLING); } else result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_OFF); } /* handle 10key timeout */ if ((p_bs->ten_key_timeout) && (current_tick >= p_bs->ten_key_timeout)) { /* user has entered some 10key so attempt tune */ /* force drawing of last digit indicator */ p_bs->enter = true; bapp_set_channel(p_app, my_atoi(p_bs->majorCh)); reset_10_key(p_screen); result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); } result |= bscreen_default_idle(v_app, v_screen); if (last_mode != p_bs->mode) { result = 1; last_mode = p_bs->mode; } } break; case eS_EVENT_IR: { /* cancel partial 10key entry if user presses any invalid key */ if ((p_bs->majorChIndex > 0) && ((p_event->id & KEY_UP) == 0)) { if ((p_event->id != eIR_0) && (p_event->id != eIR_1) && (p_event->id != eIR_2) && (p_event->id != eIR_3) && (p_event->id != eIR_4) && (p_event->id != eIR_5) && (p_event->id != eIR_6) && (p_event->id != eIR_7) && (p_event->id != eIR_8) && (p_event->id != eIR_9) && (p_event->id != eIR_DOT) && (p_event->id != eIR_SELECT) && (p_event->id != eIR_ENTER)) { reset_10_key(p_screen); result = 1; } } switch (p_event->id) { case eIR_VOL_UP: muted = p_app->is_muted; if (muted) { p_app->audio_mute = !p_app->audio_mute; bapp_audio_mute(p_app, p_app->audio_mute); /* reset screensaver timeout if we will show mute popup */ result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_VOLUME); } else { p_app->audio_mute = 0; bapp_set_audio_volume(p_app, p_app->audio_vol - VOLUME_INCREMENT); result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_VOLUME); if (muted && !result) result = 1; } break; case eIR_VOL_DOWN: muted = p_app->is_muted; if (muted) { p_app->audio_mute = !p_app->audio_mute; bapp_audio_mute(p_app, p_app->audio_mute); /* reset screensaver timeout if we will show mute popup */ result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_VOLUME); } else { p_app->audio_mute = 0; bapp_set_audio_volume(p_app, p_app->audio_vol + VOLUME_INCREMENT); result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_VOLUME); if (muted && !result) result = 1; } break; case eIR_VOL_OPT: muted = p_app->is_muted; p_app->audio_mute = 0; /* umute audio */ /* set volume to max */ bapp_set_audio_volume(p_app, DEFAULT_VOLUME_LEVEL); /* wlh, CR 0811-0621 - don't put up the volume banner */ if ( muted ) result = 1; break; case eIR_LEFT: break; case eIR_MENU: break; case eIR_INFO: result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); break; case eIR_GUIDE: break; case eIR_UP: case eIR_CH_UP: bapp_change_channel(p_app,1,1); result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); break; case eIR_DOWN: case eIR_CH_DOWN: bapp_change_channel(p_app,0,1); result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); break; case eIR_DOT: break; case eIR_0: case eIR_1: case eIR_2: case eIR_3: case eIR_4: case eIR_5: case eIR_6: case eIR_7: case eIR_8: case eIR_9: if (p_bs->majorChIndex >= MAJOR_CH_CHARS) { /* max number of major channel digits have been entered so skip to minor channel digit entry */ p_bs->enter = true; } if (!p_bs->enter) { /* major channel number digit entered */ p_bs->majorCh[p_bs->majorChIndex] = '0' + (p_event->id - eIR_0); p_bs->majorChIndex++; reset_10_key_timeout(p_screen); } result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); if (p_bs->majorChIndex < MAJOR_CH_CHARS) break; case eIR_ENTER: if (p_bs->majorChIndex > 0) { /* force drawing of channel without '_' */ p_bs->enter = true; bapp_set_channel(p_app, my_atoi(p_bs->majorCh)); reset_10_key(p_screen); } result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); break; /* Avoid doing previous channel on key down to handle diag screen entry on prech > 5sec */ case (eIR_PRECH | KEY_UP): { bapp_tune_prev(p_app); result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); } break; case eIR_MUTE: p_app->audio_mute = !p_app->audio_mute; bapp_audio_mute(p_app, p_app->audio_mute); /* reset screensaver timeout if we will show mute popup */ result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_VOLUME); break; case eIR_SELECT: if (p_bs->majorChIndex > 0) { /* force drawing of channel without '_' */ p_bs->enter = true; bapp_set_channel(p_app, my_atoi(p_bs->majorCh)); reset_10_key(p_screen); result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SMALL); } else { if (p_bs->mode == eLS_BANNER_SAP) { bapp_rotate_audio_sap(p_app); } /* reset screensaver timeout since we will show SAP popup */ result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SAP); } break; case eIR_LANG: if ( ( p_bs->mode == eLS_BANNER_SAP ) || ( p_bs->mode == eLS_BANNER_OFF) ) { bapp_rotate_audio_sap(p_app); } /* reset screensaver timeout since we will show SAP popup */ result = bscreen_set_banner_state(v_app, v_screen,eLS_BANNER_SAP); break; } } p_bs->event = *p_event; /* reset key repeat timeout */ p_bs->repeat_rate = 1; p_bs->repeat_timeout = bapp_task_getticks() + (DEFAULT_REPEAT_TIMEOUT/p_bs->repeat_rate); /* Since the tuning time can be greater than the repeat timeout increase it to handle these cases */ switch (p_event->id) { case eIR_UP: case eIR_CH_UP: case eIR_DOWN: case eIR_CH_DOWN: p_bs->repeat_timeout += (DEFAULT_REPEAT_TIMEOUT/p_bs->repeat_rate); break; default: break; } break; default: case eS_EVENT_SELECTED: case eS_EVENT_CHECKED: { result = bscreen_default_event(v_app,v_screen,p_event); } break; } return result; } /* Summary: screensaver screen event handler Description: screensaver screen event handler. . */ int screen_screensaver_event(void *v_app, void *v_screen, bscreen_event_t *p_event) { bapp_t *p_app = (bapp_t*)v_app; bscreen_t *p_screen = (bscreen_t*)v_screen; int result = 0; screensaver_state_t *p_ss = (screensaver_state_t*)p_screen->local_state; BDBG_ASSERT(p_ss); switch (p_event->type) { case eS_EVENT_IDLE: if (bapp_task_getticks() >= p_ss->image_swap_timeout) { /* redraw window */ result = 1; p_ss->image_swap_timeout = bapp_task_getticks() + MS_TO_TICKS(SCREENSAVER_IMAGE_TIMEOUT); } if (!result) result = bscreen_default_idle(v_app, v_screen); if ((p_screen->last_screen_id == eSCREEN_BANNER) && bapp_get_signal_status(p_app)) { bapp_goto_last_screen(p_app); } break; case eS_EVENT_SETUP: { p_ss->image_swap_timeout = bapp_task_getticks() + MS_TO_TICKS(SCREENSAVER_IMAGE_TIMEOUT); bapp_set_palette(p_app, ePALETTE_SCREENSAVER); } break; case eS_EVENT_IR: if ((p_event->id & KEY_UP) == 0) { screen_null_draw(v_app, v_screen); bapp_goto_last_screen(p_app); /* recheck ratings block status which may have changed while in screensaver */ result = 1; } break; default: break; } return result; /* always handle event */ } /* Summary: Power off screen event handler Description: Power off screen event handler. . */ int screen_power_off_event(void *v_app, void *v_screen, bscreen_event_t *p_event) { #ifdef CONFIG_SCREENSAVER bapp_t *p_app = (bapp_t*)v_app; #endif int result = 0; switch (p_event->type) { case eS_EVENT_SETUP: #ifdef CONFIG_SCREENSAVER p_app->last_keypress_tick = bapp_task_getticks(); BDBG_WRN(("#### %s:%d 0x%08x ####\n",__FUNCTION__,__LINE__,TICKS_TO_MS(p_app->last_keypress_tick))); bapp_enable_cc(p_app, 0); #endif result = 1; break; default: break; } return result; /* always handle event */ } /* Summary: Screensaver screen event handler . */ int bscreen_screensaver_event(void *v_app, void *v_screen, bscreen_event_t *p_event) { int result = 0; bapp_t *p_app = (bapp_t*)v_app; switch (p_event->type) { case eS_EVENT_SETUP: bapp_enable_cc(p_app, 0); result = 1; break; default: result = bscreen_default_event(v_app,v_screen,p_event); } return result; } /* Summary: Default screen event handler Description: Default screen event handler. . */ int bscreen_default_event(void *v_app, void *v_screen, bscreen_event_t *p_event) { bapp_t *p_app = (bapp_t*)v_app; bscreen_t *p_screen = (bscreen_t*)v_screen; int result = 0; switch (p_event->type) { default: case eS_EVENT_IDLE: result = bscreen_default_idle(v_app,v_screen); break; case eS_EVENT_REDRAW: result = 1; break; case eS_EVENT_SETUP: bscreen_default_setup(v_app,v_screen); result = 1; break; case eS_EVENT_SELECTED: result = (p_screen->button_selection == p_event->id) ? 1 : 0; break; case eS_EVENT_CHECKED: result = (p_screen->button_checked == p_event->id) ? 1 : 0; break; case eS_EVENT_IR: switch (p_event->id) { case eIR_INFO: break; case eIR_LEFT: case eIR_MENU: break; case eIR_RIGHT: case eIR_SELECT: break; case eIR_UP: break; case eIR_DOWN: break; case eIR_1: case eIR_2: case eIR_3: case eIR_4: case eIR_5: case eIR_6: case eIR_7: case eIR_8: case eIR_9: if ((p_event->id - 1) < p_screen->num_buttons) { bscreen_event_t event; p_screen->button_selection = p_event->id - 1; event.id = eIR_SELECT; event.type = eS_EVENT_IR; result = p_screen->handle_event(p_app,p_screen,&event); } break; default: /* Do nothing */ break; } break; } return result; /* always handle event */ } /* Summary: NULL screen drawing function Description: NULL screen drawing function. . */ void screen_null_draw(void *v_app, void *v_screen) { bapp_t *p_app = (bapp_t*)v_app; bgfx_fill_rect(&p_app->surf,0,0,eWIDTH,eHEIGHT,eCOLOR_CLEAR); } /* Summary: NULL screen drawing function for banner Description: NULL screen drawing function for banner . */ static void banner_null_draw(void *v_app, void *v_screen) { bapp_t *p_app = (bapp_t*)v_app; bgfx_fill_rect(&p_app->surf,0,0,eWIDTH,eHEIGHT,eCOLOR_CLEAR); } /* Summary: Default screen setup function Description: Default screen setup function used to set initial state before drawing. */ void bscreen_default_setup(void *v_app, void *v_screen) { bscreen_t *p_screen = (bscreen_t*)v_screen; if ((p_screen->button_selection + 1) > p_screen->num_buttons) p_screen->button_selection = 0; p_screen->button_checked = 0; } /* Summary: Default screen drawing function Description: Default screen drawing function. . */ void bscreen_default_draw(void *v_app, void *v_screen) { bapp_t *p_app = (bapp_t*)v_app; bgfx_fill_rect(&p_app->surf,0,0,eWIDTH,eHEIGHT,eCOLOR_BLACK); } /* Summary: Channel Banner Draw. */ #define TMP_BUF_CHAR_MAX 16 static void bscreen_ch_banner_draw(void *v_app, void *v_screen) { bapp_t *p_app = (bapp_t*)v_app; bscreen_t *p_screen = (bscreen_t*)v_screen; unsigned int num_chars; unsigned char *p_str; int i; char tmp_buf[TMP_BUF_CHAR_MAX]; banner_state_t *p_bs = (banner_state_t*)p_screen->local_state; vch_t vch; st_t st; freq_t freq; /* draw small banner with semi-transparent background */ bgfx_fill_rect(&p_app->surf,eBANNER_X,eBANNER_Y, eBANNER_WIDTH,eBANNER_HEIGHT,eCOLOR_BLACK); for (i = 0; i < 4; i++) { bgfx_h_draw_line(&p_app->surf,eBANNER_X+i,eBANNER_X+eBANNER_WIDTH-i, eBANNER_Y+i,eCOLOR_BLACK); bgfx_h_draw_line(&p_app->surf,eBANNER_X+i,eBANNER_X+eBANNER_WIDTH-i, eBANNER_Y+eBANNER_HEIGHT-1-i,eCOLOR_BLACK); } if (!ch_map_get_current(bapp_cur_ch_map(p_app),&vch,&st,&freq)) { BDBG_MSG(("Invalid current channel or map.\n")); return; } /* draw channel num */ num_chars = SCREEN_MAX_STR_WIDTH; if (p_bs->enter) { /* user has finish 10keying in a new channel num */ snprintf(tmp_buf,9,"%s",p_bs->majorCh); } else if (p_bs->majorChIndex > 0) { snprintf(tmp_buf,9,"%s", p_bs->majorCh); } else { /* display current channel */ snprintf(tmp_buf,9,"%d", vch.ch_num); } num_chars = c_to_uni_str((unsigned char*)tmp_buf,p_app->tmp_str,num_chars); text_box_shadow(&p_app->surf, p_app->p_font[p_app->lang][eFONT_SIZE_MED], eBANNER_CH_NUM_X, eBANNER_CH_NUM_Y, eBANNER_CH_NUM_WIDTH, eBANNER_CH_NUM_HEIGHT, p_app->tmp_str, num_chars, eCOLOR_LT_BLUE,eCOLOR_BLACK, eMENU_TEXT_DROPSHADOW ,0); /* draw channel name */ if (p_bs->enter) { /* user has finished 10keying in a new channel num */ p_str = (unsigned char*)st.name; } else if (p_bs->majorChIndex > 0) { p_str = (unsigned char*)" "; } else { /* display current channel name */ p_str = (unsigned char*)st.name; } if (p_str) { num_chars = c_to_uni_str(p_str,p_app->tmp_str,SCREEN_MAX_STR_WIDTH); if (num_chars > 0) { if (num_chars > MAX_NAME_CHARS) num_chars = MAX_NAME_CHARS; text_box_shadow(&p_app->surf, p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], eBANNER_TITLE_X, eBANNER_TITLE_Y, eBANNER_TITLE_WIDTH, eBANNER_TITLE_HEIGHT, p_app->tmp_str, num_chars, eCOLOR_WHITE,eCOLOR_BLACK, eMENU_TEXT_DROPSHADOW ,100); } } } /* Summary: Volume Banner Draw. */ extern const int s_volume_num; static void bscreen_vol_banner_draw(void *v_app, void *v_screen) { bapp_t *p_app = (bapp_t*)v_app; unsigned int num_chars; int i,w,h; int x; static int last_vol = 0; static int vol_minimized = 0; /* erase last language text */ /* Creates Volume Black Box */ bgfx_fill_rect(&p_app->surf,eBANNER_POPUP_VOL_X,eBANNER_POPUP_VOL_Y, eBANNER_POPUP_VOL_WIDTH, eBANNER_POPUP_VOL_HEIGHT, eCOLOR_BLACK); /* Highlights Top & Bottom of Box */ for (i = 0; i < 4; i++) { bgfx_h_draw_line(&p_app->surf,eBANNER_POPUP_VOL_X+i,eBANNER_POPUP_VOL_X+eBANNER_POPUP_VOL_WIDTH-i, eBANNER_POPUP_VOL_Y+i,eCOLOR_BLACK); bgfx_h_draw_line(&p_app->surf,eBANNER_POPUP_VOL_X+i,eBANNER_POPUP_VOL_X+eBANNER_POPUP_VOL_WIDTH-i, eBANNER_POPUP_VOL_Y+eBANNER_POPUP_VOL_HEIGHT-1-i,eCOLOR_BLACK); } /* Paints either Volume or Mute on screen */ num_chars = SCREEN_MAX_STR_WIDTH; if (p_app->audio_mute) bscreen_get_string(p_app->lang,eTEXT_MUTE, p_app->tmp_str, &num_chars); else bscreen_get_string(p_app->lang,eTEXT_VOLUME, p_app->tmp_str, &num_chars); bgfx_string_info(p_app->p_font[p_app->lang][eFONT_SIZE_SMALL],(const unsigned long *)p_app->tmp_str,num_chars,&w,&h); text_box_shadow(&p_app->surf, p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], eBANNER_POPUP_VOL_TITLE_X, eBANNER_POPUP_VOL_TITLE_Y, eBANNER_POPUP_VOL_WIDTH, eBANNER_POPUP_VOL_HEIGHT, p_app->tmp_str, num_chars, eCOLOR_WHITE,eCOLOR_BLACK, eMENU_TEXT_DROPSHADOW ,0); if ((last_vol == 31) && (p_app->audio_vol==31)) { vol_minimized = 1;/*tells the drawing routine to show no bars */ } last_vol = p_app->audio_vol; if ((vol_minimized == 1) && (p_app->audio_vol == 30)) { vol_minimized = 0;/*exit the minimized state */ p_app->audio_vol = 31;/*revert to 31 to illuminate one bar */ } for (x=s_volume_num, i = 0; i < eBANNER_POPUP_VOL_BAR_WIDTH; i += (eBANNER_POPUP_VOL_TICK_WIDTH * 2), x--) { /* bgfx_pixel color = eCOLOR_BLUE_TICK; */ bgfx_pixel color = eCOLOR_DIM_BLUE; /* else if ((i >= (((s_volume_num - p_app->audio_vol - 1) * eBANNER_POPUP_VOL_BAR_WIDTH)/s_volume_num))) */ if (x > p_app->audio_vol) /* color = eCOLOR_DIM_BLUE; */ color = eCOLOR_BLUE_TICK; if (vol_minimized == 1) { color = eCOLOR_DIM_BLUE; } if (p_app->audio_vol == 0) { color = eCOLOR_BLUE_TICK; } /* last, check for mute and change the volume bar to red if muted */ if (p_app->audio_mute) color = eCOLOR_RED_TICK; BDBG_MSG(("tick(%d,%d,%d,%d- %d,%d %d %d %d)\n", eBANNER_POPUP_VOL_TICK_X + i, eBANNER_POPUP_VOL_TICK_Y, eBANNER_POPUP_VOL_TICK_WIDTH, eBANNER_POPUP_VOL_TICK_HEIGHT, i, (((s_volume_num - p_app->audio_vol - 1) * eBANNER_POPUP_VOL_BAR_WIDTH)/s_volume_num), s_volume_num, p_app->audio_vol, x )); bgfx_fill_rect( &p_app->surf, eBANNER_POPUP_VOL_TICK_X + i, eBANNER_POPUP_VOL_TICK_Y, eBANNER_POPUP_VOL_TICK_WIDTH, eBANNER_POPUP_VOL_TICK_HEIGHT, color ); } } /* Summary: Volume Banner Draw. */ static bool languages_match(char *lang1,char *lang2) { return (memcmp(lang1,lang2,3) == 0) ? true : false; } /* Summary: Determine language name and create on if some match or there is none. */ static void get_lang_name(vch_t *p_vch, char *buf, int idx) { if (p_vch->audio_lang[idx][0] == 0) { snprintf(buf,TMP_BUF_CHAR_MAX,"LANG-%2d",idx+1); return; } snprintf(buf,TMP_BUF_CHAR_MAX,"%c%c%c",p_vch->audio_lang[idx][0], p_vch->audio_lang[idx][1], p_vch->audio_lang[idx][2]); switch (idx) { case 0: if (languages_match(p_vch->audio_lang[idx],p_vch->audio_lang[1]) || languages_match(p_vch->audio_lang[idx],p_vch->audio_lang[2])) { snprintf(buf,TMP_BUF_CHAR_MAX,"%c%c%c-1",p_vch->audio_lang[idx][0], p_vch->audio_lang[idx][1], p_vch->audio_lang[idx][2]); } break; case 1: if (languages_match(p_vch->audio_lang[idx],p_vch->audio_lang[0])) { snprintf(buf,TMP_BUF_CHAR_MAX,"%c%c%c-2",p_vch->audio_lang[idx][0], p_vch->audio_lang[idx][1], p_vch->audio_lang[idx][2]); } else if (languages_match(p_vch->audio_lang[idx],p_vch->audio_lang[2])) { snprintf(buf,TMP_BUF_CHAR_MAX,"%c%c%c-1",p_vch->audio_lang[idx][0], p_vch->audio_lang[idx][1], p_vch->audio_lang[idx][2]); } break; case 2: if (languages_match(p_vch->audio_lang[idx],p_vch->audio_lang[0]) && languages_match(p_vch->audio_lang[idx],p_vch->audio_lang[1])) { snprintf(buf,TMP_BUF_CHAR_MAX,"%c%c%c-3",p_vch->audio_lang[idx][0], p_vch->audio_lang[idx][1], p_vch->audio_lang[idx][2]); } else if (languages_match(p_vch->audio_lang[idx],p_vch->audio_lang[1])) { snprintf(buf,TMP_BUF_CHAR_MAX,"%c%c%c-2",p_vch->audio_lang[idx][0], p_vch->audio_lang[idx][1], p_vch->audio_lang[idx][2]); } break; } } /* Summary: Volume Banner Draw. */ static void bscreen_sap_banner_draw(void *v_app, void *v_screen) { bapp_t *p_app = (bapp_t*)v_app; unsigned int num_chars; int i,w,h; char tmp_buf[TMP_BUF_CHAR_MAX]; vch_t vch; st_t st; freq_t freq; if (!ch_map_get_current(bapp_cur_ch_map(p_app),&vch,&st,&freq)) { BDBG_MSG(("Invalid current channel or map.\n")); return; } get_lang_name(&vch,tmp_buf,vch.cur_audio); num_chars = c_to_uni_str((unsigned char*)tmp_buf, p_app->tmp_str, strlen(tmp_buf)); /* erase last language text */ bgfx_fill_rect(&p_app->surf,eBANNER_POPUP_SAP_X,eBANNER_POPUP_SAP_Y, eBANNER_POPUP_SAP_WIDTH, eBANNER_POPUP_SAP_HEIGHT, eCOLOR_BLACK); for (i = 0; i < 4; i++) { bgfx_h_draw_line(&p_app->surf,eBANNER_POPUP_SAP_X+i,eBANNER_POPUP_SAP_X+eBANNER_POPUP_SAP_WIDTH-i, eBANNER_POPUP_SAP_Y+i,eCOLOR_BLACK); bgfx_h_draw_line(&p_app->surf,eBANNER_POPUP_SAP_X+i,eBANNER_POPUP_SAP_X+eBANNER_POPUP_SAP_WIDTH-i, eBANNER_POPUP_SAP_Y+eBANNER_POPUP_SAP_HEIGHT-1-i,eCOLOR_BLACK); } bgfx_string_info(p_app->p_font[p_app->lang][eFONT_SIZE_SMALL],(const unsigned long *)p_app->tmp_str,num_chars,&w,&h); text_box_shadow(&p_app->surf, p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], eBANNER_POPUP_SAP_WIDTH - w - eBANNER_POPUP_SAP_TITLE_MARGIN, eBANNER_POPUP_SAP_Y + (eBANNER_POPUP_SAP_HEIGHT - h)/2, eBANNER_POPUP_SAP_WIDTH - w, eBANNER_POPUP_SAP_HEIGHT, p_app->tmp_str, num_chars, eCOLOR_WHITE,eCOLOR_BLACK, eMENU_TEXT_DROPSHADOW ,0); } /* Summary: Info Banner Draw. */ static void bscreen_calc_box(bapp_t *p_app, btext_id_t *titles, int num_titles, bapp_lang_t lang, bapp_font_size_t font_size, int line_space, int margin_h, int margin_v, int *x, int *y, int *w, int *h) { int i,str_w,str_h; unsigned int num_chars; *x = 0; *y = 0; *w = 0; *h = 0; for (i = 0; i < num_titles; ++i) { num_chars = SCREEN_MAX_STR_WIDTH; bscreen_get_string(p_app->lang,titles[i], p_app->tmp_str, &num_chars); bgfx_string_info(p_app->p_font[lang][font_size], (const unsigned long *)p_app->tmp_str,num_chars,&str_w,&str_h); if (str_w > *w) *w = str_w; *h += str_h; if ((i + 1) < num_titles) *h += line_space; } *h += margin_v * 2; *w += margin_h * 2; *x = (eWIDTH - *w)/2; if (*x < 0) *x = eSCREEN_ACTION_SAFE_X; *y = (eHEIGHT - *h)/2; if (*y < 0) *y = eSCREEN_ACTION_SAFE_Y; } /* Summary: Draw progress bar */ static void bscreen_progress_bar_draw(bapp_t *p_app, int start_x, int start_y, int width, int height, int percent) { int x; BDBG_ASSERT(p_app); BDBG_ASSERT(width); BDBG_ASSERT(height); for (x = 0; x < width; x += 2 * eBANNER_POPUP_VOL_TICK_WIDTH ) { bgfx_pixel color = eCOLOR_BLUE_TICK; if ((x * 100)/width > percent) color = eCOLOR_DIM_BLUE; bgfx_fill_rect( &p_app->surf, start_x + x, start_y, eBANNER_POPUP_VOL_TICK_WIDTH, height, color ); } } /* Summary: Info Banner Draw. */ #define MAX_PROGRESS_STR_LEN 64 static char s_progress_str[MAX_PROGRESS_STR_LEN]; static void bscreen_info_banner_draw(void *v_app, void *v_screen) { bapp_t *p_app = (bapp_t*)v_app; unsigned int num_chars; int w,h,y, box_x,box_y,box_width,box_height,num_titles; btext_id_t title[6]; unsigned short num_vch, num_st; unsigned char num_freq ; int pct_offset = 0; ch_map_get_counts(bapp_cur_ch_map(p_app),&num_vch,&num_st,&num_freq); title[0] = eTEXT_ONE_MOMENT; title[1] = eTEXT_TROUBLE_ERROR_1; title[2] = eTEXT_TROUBLE_ERROR_2; #ifndef CONFIG_CHINESE_FONTS_RAM num_titles = 3; #else title[3] = eTEXT_TROUBLE_ERROR_3; num_titles = 4; #endif BDBG_WRN(("%s (%d)\n",__FUNCTION__,p_app->state)); switch (p_app->state) { case eAPP_STATE_HUNT: title[0] = eTEXT_HUNT_TITLE; title[1] = eTEXT_HUNT_PROGRESS; num_titles = 2; break; case eAPP_STATE_PENDING: if (p_app->settings.deactivated) { title[0] = eTEXT_PENDING_1; title[1] = eTEXT_PENDING_2; title[2] = eTEXT_PENDING_3; title[3] = eTEXT_PENDING_4; num_titles = 4; } break; case eAPP_STATE_NORMAL: break; case eAPP_STATE_DOWNLOAD: title[0] = eTEXT_DL_1; title[1] = eTEXT_DL_2; title[2] = eTEXT_DL_3; title[3] = eTEXT_DL_4; title[4] = eTEXT_DL_5; title[5] = eTEXT_DL_6; num_titles = 6; default: break; } bscreen_calc_box(p_app,title, num_titles,p_app->lang,eFONT_SIZE_SMALL, eMENU_TEXT_SPACING, 14, 14, &box_x, &box_y, &box_width, &box_height); /* add extra space for title line */ box_height += 8; /* Add space for progress bar */ if (p_app->state == eAPP_STATE_HUNT) { box_height += ((eBANNER_POPUP_VOL_TICK_HEIGHT + eMENU_TEXT_SPACING) * 2); pct_offset = 14; } /* draw popup background and border*/ bgfx_fill_rect(&p_app->surf,box_x,box_y, box_width,box_height,eCOLOR_BORDER_BLUE); bgfx_fill_rect(&p_app->surf,box_x + 4,box_y + 4, box_width-8,box_height-8,eCOLOR_BLACK); box_y += 14; num_chars = SCREEN_MAX_STR_WIDTH; bscreen_get_string(p_app->lang,title[0], p_app->tmp_str, &num_chars); bgfx_string_info(p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], (const unsigned long *)p_app->tmp_str,num_chars,&w,&h); text_box(&p_app->surf, p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], box_x + (box_width - w)/2, box_y, box_width, h, p_app->tmp_str, num_chars, eCOLOR_WHITE ,eMENU_TEXT_SPACING); y = box_y + h + eMENU_TEXT_SPACING; if (p_app->state != eAPP_STATE_DOWNLOAD) y += 8; /* draw popup text */ num_chars = SCREEN_MAX_STR_WIDTH; bscreen_get_string(p_app->lang,title[1], p_app->tmp_str, &num_chars); bgfx_string_info(p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], (const unsigned long *)p_app->tmp_str,num_chars,&w,&h); text_box(&p_app->surf, p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], box_x - pct_offset + (box_width - w)/2, y, box_width, h, p_app->tmp_str, num_chars, eCOLOR_WHITE ,eMENU_TEXT_SPACING); /* In hunt mode draw a progress bar */ if (p_app->state == eAPP_STATE_HUNT) { int progress = chm_get_hunt_progress(&p_app->chm); int prog_width = 50 * eBANNER_POPUP_VOL_TICK_WIDTH; int prog_x = box_x + (box_width - prog_width)/2; int prev_w = w; num_chars = snprintf((char*)s_progress_str,MAX_PROGRESS_STR_LEN,"%d",progress); num_chars = bapp_util_strlen(s_progress_str); s_progress_str[num_chars] = '%'; num_chars += 1; s_progress_str[num_chars] = 0; num_chars = c_to_uni_str((unsigned char*)s_progress_str,p_app->tmp_str,num_chars); bgfx_string_info(p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], (const unsigned long *)p_app->tmp_str,num_chars,&w,&h); text_box(&p_app->surf, p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], box_x - pct_offset + (box_width - prev_w)/2 + prev_w, y, 2*w, h, p_app->tmp_str, num_chars, eCOLOR_BLUE_TICK ,eMENU_TEXT_SPACING); y += h + eMENU_TEXT_SPACING; bscreen_progress_bar_draw(p_app, prog_x, y,prog_width, eBANNER_POPUP_VOL_TICK_HEIGHT, progress); return; } y += h + eMENU_TEXT_SPACING; num_chars = SCREEN_MAX_STR_WIDTH; bscreen_get_string(p_app->lang,title[2], p_app->tmp_str, &num_chars); bgfx_string_info(p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], (const unsigned long *)p_app->tmp_str,num_chars,&w,&h); text_box(&p_app->surf, p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], box_x + (box_width - w)/2, y, box_width, h, p_app->tmp_str, num_chars, eCOLOR_WHITE ,eMENU_TEXT_SPACING); if (num_titles < 4) return; if (p_app->state == eAPP_STATE_DOWNLOAD) y += 8; y += h + eMENU_TEXT_SPACING; num_chars = SCREEN_MAX_STR_WIDTH; bscreen_get_string(p_app->lang,title[3], p_app->tmp_str, &num_chars); bgfx_string_info(p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], (const unsigned long *)p_app->tmp_str,num_chars,&w,&h); text_box(&p_app->surf, p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], box_x + (box_width - w)/2, y, box_width, h, p_app->tmp_str, num_chars, eCOLOR_WHITE ,eMENU_TEXT_SPACING); if (num_titles < 5) return; y += h + eMENU_TEXT_SPACING; num_chars = SCREEN_MAX_STR_WIDTH; bscreen_get_string(p_app->lang,title[4], p_app->tmp_str, &num_chars); bgfx_string_info(p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], (const unsigned long *)p_app->tmp_str,num_chars,&w,&h); text_box(&p_app->surf, p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], box_x + (box_width - w)/2, y, box_width, h, p_app->tmp_str, num_chars, eCOLOR_WHITE ,eMENU_TEXT_SPACING); if (num_titles < 6) return; y += h + eMENU_TEXT_SPACING; num_chars = SCREEN_MAX_STR_WIDTH; bscreen_get_string(p_app->lang,title[5], p_app->tmp_str, &num_chars); bgfx_string_info(p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], (const unsigned long *)p_app->tmp_str,num_chars,&w,&h); text_box(&p_app->surf, p_app->p_font[p_app->lang][eFONT_SIZE_SMALL], box_x + (box_width - w)/2, y, box_width, h, p_app->tmp_str, num_chars, eCOLOR_WHITE ,eMENU_TEXT_SPACING); } /* Summary: Banner screen drawing function Description: Banner screen drawing function. . */ void bscreen_banner_draw(void *v_app, void *v_screen) { bscreen_t *p_screen = (bscreen_t*)v_screen; int i; banner_state_t *p_bs = (banner_state_t*)p_screen->local_state; BDBG_ASSERT(p_bs); BDBG_MSG(("%s:%d, mode = %d\n",__FUNCTION__,__LINE__,p_bs->mode)); i = 0; banner_null_draw(v_app,v_screen); switch (p_bs->mode) { default: case eLS_BANNER_OFF: break; case eLS_BANNER_SMALL: bscreen_ch_banner_draw(v_app,v_screen); break; case eLS_BANNER_SAP: bscreen_sap_banner_draw(v_app,v_screen); break; case eLS_BANNER_VOLUME: bscreen_vol_banner_draw(v_app,v_screen); break; case eLS_BANNER_INFO: bscreen_info_banner_draw(v_app,v_screen); break; case eLS_BANNER_EAS_TEXT_SCROLLING: bscreen_eas_text_scrolling_info_draw(v_app,v_screen); break; } } /* Summary: Screensaver screen drawing function Description: Screensaver screen drawing function. */ void bscreen_screensaver_draw(void *v_app, void *v_screen) { #ifndef CONFIG_SCREENSAVER BDBG_ERR(("NO SCREENSAVER.\n")); #else bapp_t *p_app = (bapp_t*)v_app; if (g_p_dsp->ui_comp.logo) { bin_read_t br; bcm_raw_8_t *p_header = (bcm_raw_8_t*)g_p_dsp->ui_comp.logo; br.cnt = 0; br.data = (void*)g_p_dsp->ui_comp.logo; br.size = g_p_dsp->ui_comp.logo_size; screen_null_draw(v_app, v_screen); bgfx_render_file(&p_app->surf, eSCREEN_ACTION_SAFE_X + RAND_INT(eSCREEN_ACTION_SAFE_WIDTH-p_header->width), eSCREEN_ACTION_SAFE_Y + RAND_INT(eSCREEN_ACTION_SAFE_HEIGHT-p_header->height), &br, 0); } else { unsigned int num_chars; int w,h; num_chars = SCREEN_MAX_STR_WIDTH; bgfx_fill_rect(&p_app->surf,0,0,eWIDTH,eHEIGHT,eCOLOR_BLACK); bscreen_get_string(p_app->lang, eTEXT_VENDOR, p_app->tmp_str, &num_chars); bgfx_string_info(p_app->p_font[p_app->lang][eFONT_SIZE_MED], (const unsigned long *)p_app->tmp_str,num_chars,&w,&h); w += 16; text_box(&p_app->surf, p_app->p_font[eLANG_ENGLISH][eFONT_SIZE_MED], eSCREEN_ACTION_SAFE_X + RAND_INT(eSCREEN_ACTION_SAFE_WIDTH - w), eSCREEN_ACTION_SAFE_Y + RAND_INT(eSCREEN_ACTION_SAFE_HEIGHT - h), w, h, p_app->tmp_str, num_chars, eCOLOR_WHITE,0); } #endif } /* Summary: Power off screen drawing function Description: Power off screen drawing function. */ void bscreen_power_off_draw(void *v_app, void *v_screen) { screen_null_draw(v_app, v_screen); }