/*************************************************************************** * 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 "bgfx.h" #include "bstd.h" #include "bos.h" #include "ministd.h" #include "cache_util.h" #include "bapp_palette.h" #include "bsettop_graphics.h" static void bapp_first_pts_callback(void); static void bapp_seq_hdr_callback(void); #include "bapp_settings.h" #ifdef CONFIG_SCREENSAVER #include "logo.c" #endif #include "psip_descriptor.h" #include "bavc.h" /* dolby logo support */ #ifdef CONFIG_STANDBY #include "birw.h" #endif BDBG_MODULE(bapp); /* Register software module with debug interface */ #define OLD_INFO_KEY_PROCESSING #define BAPP_MAX_VOLUME 32 #define BAPP_VCHIP_TIMEOUT (7000) /* Milliseconds */ #define BAPP_RATINGS_EVAL_DELAY (500) /* Milliseconds */ #define BAPP_DIAG_TIMEOUT 3 /* Seconds */ #define BAPP_SAVE_TIMEOUT 3 /* Seconds */ #define BAPP_RF_TIMEOUT 2 /* Seconds */ /* switch to audio only screen timeout check */ #define BAPP_AUDIO_CHANNEL_SWITCH_TIMEOUT 5 /* Seconds */ /* check audio only screen timeout condition if no keypress for given timeout */ #define BAPP_AUDIO_CHANNEL_KEYPRESS_CHECK_TIMEOUT 2 /* Seconds */ #define BAPP_VCHIP_MSG BDBG_WRN #define TIME_APP_DRAWING static bgfx_font_t s_font[eFONT_SIZE_MAX]; static void bapp_eval_state(bapp_t *p_app,bapp_state_t new_state); static int bapp_channel_hunt(bapp_t *p_app); static void bapp_standby(bapp_t *p_app, bool power); static void bapp_new_screen(bapp_t *p_app); #ifdef CONFIG_8BIT_FONT extern unsigned int g_FrancophilB_20_aa_size; extern const unsigned char g_FrancophilB_20_aa[]; extern unsigned int g_FrancophilB_22_aa_size; extern const unsigned char g_FrancophilB_22_aa[]; extern unsigned int g_FrancophilB_28_aa_size; extern const unsigned char g_FrancophilB_28_aa[]; #else extern unsigned int g_FrancophilB_22_mono_size; extern const unsigned char g_FrancophilB_22_mono[]; extern unsigned int g_FrancophilB_28_mono_size; extern const unsigned char g_FrancophilB_28_mono[]; extern unsigned int g_FrancophilB_40_mono_size; extern const unsigned char g_FrancophilB_40_mono[]; #endif extern int bscreen_eas_text_scrolling_info(bapp_t *p_app, unsigned char *eas_pkt, unsigned int size); #ifndef NO_VCHIP #define BAPP_CAD_TIMEOUT 10 /* in seconds */ /* TODO add Mexico rating system support */ typedef enum rsys_t { eRS_MPA, eRS_US, eRS_MPA_OLD, eRS_CANADIAN_ENGLISH, eRS_CANADIAN_FRENCH, eRS_RESERVED_0, eRS_RESERVED_1 }rsys_t; const static char *s_rsys_name[] = { "MPA", "TV", "MPA", "CE", "CF", "R0", "R1" }; /* * Maps value in remote strap registers to bsettop_user_io.c remote type */ const static unsigned int s_remote_type_map[] = { 5, 4, 6, 0 }; #define BAPP_TV_RATING_STR_NUM 8 static const char *bapp_tv_rating_str[BAPP_TV_RATING_STR_NUM] = { "", /* unrated */ "TV-Y", "TV-Y7", "TV-G", "TV-PG", "TV-14", "TV-MA", "" /* unrated */ }; /* LUT used to translate from user defined tv limit to canadian equivalent */ static unsigned char tv_to_can_eng[8] = { 0, 1, 2, 3, 4, 5, 6, 0}; static unsigned char tv_to_can_fra[8] = { 0, 2, 2, 2, 3, 4, 5, 0}; #define BAPP_MPAA_RATING_STR_NUM 8 static const char *bapp_mpa_rating_str[] = { "", /* unrated */ "G", "PG", "PG-13", "R", "NC-17", "X", "NR" /* Not Rated */ }; #define BAPP_CE_RATING_STR_NUM 8 static const char *bapp_ce_rating_str[] = { "E", "C", "C8+", "G", "PG", "14+", "18+" "", /* invalid */ }; #define BAPP_CF_RATING_STR_NUM 8 static const char *bapp_cf_rating_str[] = { "E", "G", "8ans+", "13ans+", "16ans+", "18ans+", "", /* invalid */ "", /* invalid */ }; #endif /* * Global app reference used by a couple callbacks to reference the application. */ bapp_t *s_p_app = NULL; static bscreen_t g_screens[] = { /* title_text_id desc_text_id help_text_id top_banner_height num_buttons idle_timeout p_button_array (* draw)() (* handle_event)() local_state */ { eTEXT_MAX, eTEXT_MAX, eTEXT_MENU_HELP1, 0, 0, 0, 0, 0, eSCREEN_NULL, 0, bscreen_banner_draw, screen_banner_event, (uint32_t)&g_banner_state}, { eTEXT_MAIN_MENU, eTEXT_MAX, eTEXT_MENU_HELP1, eMENU_TITLE_AREA_HEIGHT_0_LINE, 0, 0, g_buttons_main_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_main, bscreen_default_draw, bscreen_default_event, 0}, { eTEXT_PICTURE_MENU, eTEXT_PICTURE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_sd_output_options_config_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_sd_output_options_config, bscreen_default_draw, screen_sd_output_options_config_event, 0}, { eTEXT_SOUND_MENU, eTEXT_SOUND_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_sound_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_AV, g_buttons_sound, bscreen_default_draw, screen_sound_event, 0}, { eTEXT_AV_MENU, eTEXT_AV_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_av_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_av, bscreen_default_draw, bscreen_default_event, 0}, { eTEXT_ANTENNA_MENU, eTEXT_ANTENNA_MENU_DESC, eTEXT_MENU_HELP6, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_antenna_draw, screen_antenna_event, 0}, { eTEXT_CAPTIONS_MENU, eTEXT_CAPTIONS_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_captions_advanced_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_advanced, bscreen_default_draw, screen_captions_advanced_event, 0}, { eTEXT_CAPTIONS_FONT_OPTIONS_MENU,eTEXT_CAPTIONS_FONT_OPTIONS_MENU_DESC,eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_font_options_num,SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font_options,bscreen_default_draw, screen_captions_font_options_event, 0}, { eTEXT_CAPTIONS_BACK_OPTIONS_MENU,eTEXT_CAPTIONS_BACK_OPTIONS_MENU_DESC,eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_back_options_num,SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_back_options,bscreen_default_draw, screen_captions_back_options_event, 0}, { eTEXT_CAPTIONS_FONT_MENU, eTEXT_CAPTIONS_FONT_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_font_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font, bscreen_default_draw, screen_captions_font_event, 0}, { eTEXT_CAPTIONS_FONT_SIZE_MENU, eTEXT_CAPTIONS_FONT_SIZE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_font_size_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font_size, bscreen_default_draw, screen_captions_font_size_event, 0}, { eTEXT_CAPTIONS_FONT_STYLE_MENU, eTEXT_CAPTIONS_FONT_STYLE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_font_style_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font_style, bscreen_default_draw, screen_captions_font_style_event, 0}, { eTEXT_CAPTIONS_FONT_COLOR_MENU, eTEXT_CAPTIONS_FONT_COLOR_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_font_color_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font_color, bscreen_default_draw, screen_captions_font_color_event, 0}, { eTEXT_CAPTIONS_FONT_OPACITY_MENU,eTEXT_CAPTIONS_FONT_OPACITY_MENU_DESC,eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_opacity_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_font_opacity,bscreen_default_draw, screen_captions_font_opacity_event, 0}, { eTEXT_CAPTIONS_BACK_COLOR_MENU, eTEXT_CAPTIONS_BACK_COLOR_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_color_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_color, bscreen_default_draw, screen_captions_back_color_event, 0}, { eTEXT_CAPTIONS_BACK_OPACITY_MENU,eTEXT_CAPTIONS_BACK_OPACITY_MENU_DESC,eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_opacity_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_back_opacity,bscreen_default_draw, screen_captions_back_opacity_event, 0}, { eTEXT_CAPTIONS_EDGE_COLOR_MENU ,eTEXT_CAPTIONS_EDGE_COLOR_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_edge_color_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_edge_color, bscreen_default_draw, screen_captions_edge_color_event, 0}, { eTEXT_CAPTIONS_EDGE_TYPE_MENU ,eTEXT_CAPTIONS_EDGE_TYPE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_edge_type_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_edge_type, bscreen_default_draw, screen_captions_edge_type_event, 0}, { eTEXT_CAPTIONS_RESET_MENU, eTEXT_CAPTIONS_RESET_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_reset_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_reset, bscreen_default_draw, screen_captions_reset_event, 0}, { eTEXT_LANGUAGE_MENU, eTEXT_LANGUAGE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_language_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_language, bscreen_default_draw, screen_language_event, 0}, #ifdef CONFIG_EIA_708 { eTEXT_SETUP_MENU, eTEXT_SETUP_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE-4, 0, 0, g_buttons_setup_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_setup, bscreen_default_draw, screen_setup_event, 0}, #else { eTEXT_SETUP_MENU, eTEXT_SETUP_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_setup_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_setup, bscreen_default_draw, screen_setup_event, 0}, #endif { eTEXT_WIZ_CH_SCAN_MENU, eTEXT_WIZ_CH_SCAN_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_3_LINE, 0, 0, g_buttons_ch_scan_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ch_scan, bscreen_wiz_ch_scan_draw, screen_ch_scan_event, 0}, { eTEXT_CH_SCAN_PROGRESS_MENU, eTEXT_CH_SCAN_PROGRESS_MENU_DESC, eTEXT_MENU_HELP4, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_ch_scan_progress_draw, screen_ch_scan_progress_event, 0}, { eTEXT_RESET_MENU, eTEXT_RESET_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_reset_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_reset, bscreen_default_draw, screen_reset_event, 0}, { eTEXT_WIZ_WELCOME_MENU, eTEXT_WIZ_WELCOME_MENU_DESC, eTEXT_MENU_HELP3, eMENU_TITLE_AREA_HEIGHT_3_LINE, 0, 0, g_buttons_wiz_welcome_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wiz_welcome, bscreen_wiz_welcome_draw, screen_wiz_welcome_event, 0}, { eTEXT_WIZ_LANGUAGE_MENU, eTEXT_LANGUAGE_MENU_DESC, eTEXT_MENU_HELP8, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_wiz_language_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wiz_language, bscreen_default_draw, screen_wiz_language_event, 0}, { eTEXT_WIZ_CH_SCAN_MENU, eTEXT_WIZ_CH_SCAN_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_3_LINE, 0, 0, g_buttons_wiz_ch_scan_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wiz_ch_scan, bscreen_wiz_ch_scan_draw, screen_wiz_ch_scan_event, 0}, { eTEXT_WIZ_PIN_NEW_MENU, eTEXT_WIZ_PIN_NEW_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_4_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_PIN_CONFIRM_MENU, eTEXT_PIN_CONFIRM_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_MISMATCHED_PINS_MENU, eTEXT_MISMATCHED_PINS_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_wiz_mismatched_pins_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wiz_mismatched_pins, bscreen_default_draw, screen_wrong_pin_event, 0}, { eTEXT_WIZ_DONE_MENU, eTEXT_WIZ_DONE_MENU_DESC, eTEXT_MENU_HELP6, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_wiz_done_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wiz_done, bscreen_wiz_done_draw, screen_wiz_done_event, 0}, { eTEXT_AUTO_POWER_MENU, eTEXT_AUTO_POWER_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_auto_power_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_auto_power, bscreen_auto_power_draw, screen_auto_power_event, 0}, { eTEXT_RATINGS_MENU, eTEXT_RATINGS_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_ratings_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings, bscreen_default_draw, screen_ratings_event, 0}, { eTEXT_RATINGS_LOCK_MENU, eTEXT_RATINGS_LOCK_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_ratings_lock_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_lock, bscreen_default_draw, screen_ratings_lock_event, 0}, { eTEXT_RATINGS_LIMITS_MENU, eTEXT_RATINGS_LIMITS_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, g_buttons_ratings_limits_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_limits, bscreen_default_draw, screen_ratings_limits_event, 0}, { eTEXT_RATINGS_TV_MENU, eTEXT_RATINGS_TV_MENU_DESC, eTEXT_MENU_HELP2,eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_ratings_tv_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_tv, bscreen_default_draw, screen_ratings_tv_event, 0}, { eTEXT_RATINGS_MOVIES_MENU, eTEXT_RATINGS_MOVIES_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_ratings_movies_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_movies, bscreen_default_draw, screen_ratings_movies_event, 0}, { eTEXT_RATINGS_RRT_DIM_MENU, eTEXT_RATINGS_RRT_DIM_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, MAX_RRT_DIM_BUTTONS, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_rrt_dim, bscreen_rrt_dim_draw, screen_ratings_rrt_dim_event, 0}, { eTEXT_RATINGS_RRT_VAL_MENU, eTEXT_RATINGS_RRT_VAL_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, MAX_RRT_VAL_BUTTONS, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_rrt_val, bscreen_rrt_val_draw, screen_ratings_rrt_val_event, 0}, { eTEXT_RATINGS_RRT_UPDATE_MENU, eTEXT_RATINGS_RRT_UPDATE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_ratings_rrt_update_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_ratings_rrt_update, bscreen_default_draw, screen_ratings_rrt_update_event, 0}, { eTEXT_PIN_ENTER_MENU, eTEXT_PIN_ENTER_MENU_DESC, eTEXT_MENU_HELP9, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_PIN_ENTER_MENU, eTEXT_PIN_ENTER_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_PIN_ENTER_MENU, eTEXT_PIN_ENTER_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_PIN_NEW_MENU, eTEXT_PIN_NEW_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_2_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_PIN_CONFIRM_MENU, eTEXT_PIN_CONFIRM_MENU_DESC, eTEXT_MENU_HELP7, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_pin_draw, screen_pin_event, 0}, { eTEXT_WRONG_PIN_LIVE_MENU, eTEXT_WRONG_PIN_LIVE_MENU_DESC, eTEXT_MENU_HELP8, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_wrong_pin_live_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wrong_pin_live, bscreen_default_draw, screen_wrong_pin_event, 0}, { eTEXT_WRONG_PIN_MENU_MENU, eTEXT_WRONG_PIN_MENU_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_wrong_pin_ratings_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wrong_pin_ratings, bscreen_default_draw, screen_wrong_pin_event, 0}, { eTEXT_WRONG_PIN_MENU_MENU, eTEXT_WRONG_PIN_MENU_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_wrong_pin_reset_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_wrong_pin_reset, bscreen_default_draw, screen_wrong_pin_event, 0}, { eTEXT_MISMATCHED_PINS_MENU, eTEXT_MISMATCHED_PINS_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_mismatched_pins_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_mismatched_pins, bscreen_default_draw, screen_wrong_pin_event, 0}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, BANNER_SMALL_TIMEOUT, eSCREEN_NULL, 0, bscreen_banner_draw, screen_banner_event, (uint32_t)&g_banner_state}, { eTEXT_GUIDE_TITLE, eTEXT_MAX, eTEXT_MENU_HELP5,eMENU_TITLE_AREA_HEIGHT_0_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_guide_draw, screen_guide_event, (uint32_t)&g_guide_state}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, 0, eSCREEN_NULL, 0, bscreen_screensaver_draw, screen_screensaver_event, (uint32_t)&g_screensaver_state}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, 0, eSCREEN_NULL, 0, bscreen_power_off_draw, screen_power_off_event, 0}, { eTEXT_TIMEZONE_MENU, eTEXT_TIMEZONE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_timezone_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_timezone, bscreen_default_draw, bscreen_timezone_event, 0}, { eTEXT_MAX, /* status */ eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_status_draw, bscreen_status_event, 0 }, { eTEXT_MAX, /* diag */ eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_diag_menu_draw, bscreen_diag_menu_event, 0 }, { eTEXT_MAX, /* sys info */ eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_sys_info_draw, bscreen_sys_info_event, 0 }, { eTEXT_MAX, /* tuner status */ eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_tuner_status_draw, bscreen_tuner_status_event, 0 }, { eTEXT_MAX, /* channel status */ eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_ch_status_draw, bscreen_ch_status_event, 0 }, { eTEXT_MAX, /* decoder status */ eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_decoder_status_draw, bscreen_decoder_status_event, 0 }, { eTEXT_SD_CONFIG_OPTIONS_BUTTON, /* SD output options */ eTEXT_SD_CONFIG_OPTIONS, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_sd_output_options_config_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_PICTURE, g_buttons_sd_output_options_config, bscreen_default_draw, screen_sd_output_options_config_event, 0 }, { eTEXT_RFM_CONFIG_OPTIONS, /* RFM */ eTEXT_RFM_CONFIG_OPTIONS_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_rfm_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_AV, g_buttons_rfm, bscreen_default_draw, screen_rfm_event, 0 }, #ifdef CONFIG_FACTORY_TEST { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, factory_draw, factory_handle_event, 0 }, #endif { eTEXT_CAPTIONS_DIGITAL, /* digital captioning */ eTEXT_CAPTIONS_DIGITAL_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_digital_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_CAPTIONS_ADVANCED, g_buttons_captions_digital, bscreen_default_draw, screen_digital_captioning_event, 0 }, { eTEXT_TIMEZONE_MENU, eTEXT_TIMEZONE_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_timezone_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_timezone, bscreen_default_draw, bscreen_wiz_timezone_event, 0 }, { eTEXT_DETAILED_GUIDE, eTEXT_MAX, eTEXT_MENU_HELP10, eMENU_TITLE_AREA_HEIGHT_0_LINE, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_detailed_guide_draw, screen_detailed_guide_event, (uint32_t)&g_detailed_guide_state }, { eTEXT_MAX, /* frequency configure */ eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_frequency_draw, screen_frequency_event, 0 }, /* support for Music Channel draw */ { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, 0, eSCREEN_NULL, 0, bscreen_audio_channel_draw, screen_audio_channel_event, 0 }, }; const unsigned char g_screens_num = sizeof(g_screens)/sizeof(g_screens[0]); void bl_write(void) { } static bgfx_io_t s_io = { bin_read, bin_tell, bin_set }; #if defined(CONFIG_GFX_ARGB32) && !defined(SIMULATOR) static bgfx_hw_t s_gfx_hw = {(BGFX_HW_FILL)bsurface_fill, (BGFX_HW_BLIT)bsurface_blit_surface, (BGFX_HW_SURFACE_CREATE)bsurface_create_surface}; static bgfx_hw_t *s_p_gfx_hw = &s_gfx_hw; #else static bgfx_hw_t *s_p_gfx_hw = NULL; #endif //#ifdef BCM_DEBUG #if 0 static const char *s_chm_evt_str[] = { "CHM_EVT_CANCEL", "CHM_EVT_DONE", "CHM_EVT_REDRAW", "CHM_EVT_PROGRESS", "CHM_EVT_SIGNAL", "CHM_EVT_EAS", "CHM_EVT_STATUS", "CHM_EVT_AV_MUTE", "CHM_EVT_SAVE", "CHM_EVT_TIME", "eCHM_EVT_RRT", "eCHM_EVT_CAD", "eCHM_EVT_BLOCK", "eCHM_EVT_SET_SCREEN", "eCHM_EVT_SNR", "eCHM_EVT_RESET", "eCHM_EVT_MAX", }; #endif #ifdef ACB612 void aov_setAVL_target() { int target, lowbound, fixedboost; bapp_get_avl_settings(&target, &lowbound, &fixedboost); target = -11; bapp_set_avl_settings(target, lowbound, fixedboost); return; } #endif /* Summary: set video related configuration if default are not match */ void bapp_set_video_configuration(bapp_t *p_app) { bdisplay_settings s; bdisplay_get(p_app->display,&s); if (s.sd_options != p_app->settings.sd_options) { s.sd_options = p_app->settings.sd_options; bdisplay_set(p_app->display,&s); } } /* Summary: Set the LED mode based on the state and settings. */ void bapp_led_set_mode(bapp_t *p_app) { enum led_mode_t mode = led_off_mode; if (!p_app->power) { mode = led_off_mode; } else { switch (p_app->state) { case eAPP_STATE_HUNT: mode = led_hunt_mode; break; case eAPP_STATE_NORMAL: mode = led_on_mode; break; case eAPP_STATE_FACTORY: case eAPP_STATE_DEFAULT: case eAPP_STATE_DONE: break; } } if (mode == p_app->led_mode) { return; } p_app->led_mode = mode; led_set_mode(mode); } /* * Flush cache */ void bapp_flush_screen(bapp_t *p_app) { #ifndef CONFIG_GFX_ARGB32 unsigned int *palette; int width,height,pitch; #endif if (p_app->settings.av_mute && (p_app->screen_id != eSCREEN_POWER_OFF)) { BDBG_WRN(("%s av_mute = %d, screen = %d\n",__FUNCTION__,p_app->settings.av_mute,p_app->screen_id )); return; } if (bgraphics_sync(p_app->graphics, false) == berr_timeout) { BDBG_WRN(("bgraphics_sync timeout, try again.\n" )); if (bgraphics_sync(p_app->graphics, false) == berr_timeout) { BDBG_ERR(("bgraphics_sync timeouted out again.\n" )); } } #ifndef CONFIG_GFX_ARGB32 bgraphics_get_framebuffer(p_app->graphics,(void**)&p_app->osd_mem,(unsigned int **)&palette,&width,&height,&pitch); p_app->osd_mem_size = pitch * height; p_app->width = width; p_app->height = height; p_app->surf.surface.buf = p_app->osd_mem; #endif } /* * flush SD or HD or both graphics */ void bapp_flush_screen_partial(bapp_t *p_app, int id) { #ifdef CONFIG_GFX_ARGB32 if (bgraphics_sync_partial(p_app->graphics, id, false) == berr_timeout) { BDBG_WRN(("bgraphics_sync_hd timeout, try again")); if (bgraphics_sync_partial(p_app->graphics, id, false) == berr_timeout) { BDBG_ERR(("bgraphics_sync timeout again.")); } } #else bapp_flush_screen(p_app); #endif } #ifndef NO_VCHIP /* * Determine ratings system */ static rsys_t bapp_get_rsys(unsigned char c1, unsigned char c2) { if ((c1 & 0x18) == 0x18) /* eRS_CANADIAN_ENGLISH - eRS_RESERVED_1 */ { if (c1 & 0x20) /* eRS_CANADIAN_FRENCH or eRS_RESERVED_1 */ { if (c2 & 0x08) return eRS_RESERVED_1; else return eRS_CANADIAN_FRENCH; } else { if (c2 & 0x08) return eRS_RESERVED_0; else return eRS_CANADIAN_ENGLISH; } } else /* eRS_MPA - eRS_MPA_OLD */ { if (c1 & 0x10) return eRS_MPA_OLD; else if (c1 & 0x08) return eRS_US; else return eRS_MPA; } return eRS_US; } /* * Return 1 if MPA rating is exceeded * Return 0 if MPA rating is not exceeded * Return -1 on invalid rating or error */ static int bapp_mpa_block( unsigned char mpa_level, /* MPA level 0 - 7 */ unsigned char c1 /* xds 1 character */ ) { c1 &= 0x7; /* update rating string */ if (c1 < BAPP_MPAA_RATING_STR_NUM) strcpy(s_p_app->prog_rating_str, bapp_mpa_rating_str[c1]); if (c1 == 0) return -1; /* level 0 rating not applicable */ return(c1 >= mpa_level) ? 1 : 0; } /* * Return 1 if Canadian English rating is exceeded * Return 0 if MPA rating is not exceeded * Return -1 on invalid rating or error */ static int bapp_CE_block( unsigned char CE_level, /* Canadian English level 0 - 7 */ unsigned char c2 /* xds 2 character */ ) { c2 &= 0x7; if (c2 == 7) return -1; /* level 7 rating is invalid */ /* update rating string */ if (c2 < BAPP_CE_RATING_STR_NUM) strcpy(s_p_app->prog_rating_str, bapp_ce_rating_str[c2]); if (c2 == 0) return -1; return(c2 >= CE_level) ? 1 : 0; } /* * Return 1 if Canadian French rating is exceeded * Return 0 if MPA rating is not exceeded * Return -1 on invalid rating or error */ static int bapp_CF_block( unsigned char CF_level, /* Canadian French level 0 - 7 */ unsigned char c2 /* xds 2 character */ ) { c2 &= 0x7; if ((c2 == 6) || (c2 == 7)) return -1; /* level 6 or 7 rating is invalid */ /* update rating string */ if (c2 < BAPP_CF_RATING_STR_NUM) strcpy(s_p_app->prog_rating_str, bapp_cf_rating_str[c2]); if (c2 == 0) return -1; return(c2 >= CF_level) ? 1 : 0; } /* * Return 1 if US rating is exceeded * Return 0 if MPA rating is not exceeded * Return -1 on invalid rating or error */ static int bapp_US_block( unsigned char US_level, /* US level 0 - 7 */ unsigned char mask, /* VSLD modifier mask */ unsigned char c1, /* xds 1 character */ unsigned char c2 /* xds 2 character */ ) { unsigned char tmp_c2 = c2 & 0x7; unsigned char c1_mask,c2_mask; int slen; c2_mask = (mask & 0xE) << 2; c1_mask = (mask & 0x1) << 5; /* update rating string */ if (tmp_c2 < BAPP_TV_RATING_STR_NUM) strcpy(s_p_app->prog_rating_str, bapp_tv_rating_str[tmp_c2]); else s_p_app->prog_rating_str[0] = 0; switch (tmp_c2) { case 2: if (c2 & 0x20) { slen = strlen(s_p_app->prog_rating_str); s_p_app->prog_rating_str[slen] = 'F'; s_p_app->prog_rating_str[slen + 1] = 'V'; s_p_app->prog_rating_str[slen + 2] = 0; } break; case 4: case 5: case 6: if (c2 & 0x20) { slen = strlen(s_p_app->prog_rating_str); s_p_app->prog_rating_str[slen] = 'V'; s_p_app->prog_rating_str[slen + 1] = 0; } if (c2 & 0x08) { slen = strlen(s_p_app->prog_rating_str); s_p_app->prog_rating_str[slen] = 'L'; s_p_app->prog_rating_str[slen + 1] = 0; } if (c2 & 0x10) { slen = strlen(s_p_app->prog_rating_str); s_p_app->prog_rating_str[slen] = 'S'; s_p_app->prog_rating_str[slen + 1] = 0; } if (tmp_c2 != 6) { if (c1 & 0x20) { slen = strlen(s_p_app->prog_rating_str); s_p_app->prog_rating_str[slen] = 'D'; s_p_app->prog_rating_str[slen + 1] = 0; } } break; default: break; } BDBG_MSG(("Level - %d, LIMIT - %d, mask = 0x%02x(c1m 0x%02x, c2m 0x%02x)\n",tmp_c2,US_level,mask,c1_mask,c2_mask )); if ((tmp_c2 == 0) || (tmp_c2 == 0x7)) return -1; /* level 0 and 7 ratings not applicable */ switch (US_level) { case 0: return 0; case 3: case 1:return(tmp_c2 > US_level) ? 1 : 0; case 2: { if (tmp_c2 > US_level) return 1; else if ((tmp_c2 == US_level) && /* handle case where xds rating has no vsld modifier */ ((s_p_app->settings.ratings.ratings_tv >> screen_ratings_tv_xds2pos(US_level)) & (0 | (0x1)))) return 1; else if ((tmp_c2 == US_level) && (c2 & (0x20 & c1_mask))) /* FV restriction */ return 1; } break; case 4: case 5: { if (tmp_c2 > US_level) return 1; else if ((tmp_c2 == US_level) && /* handle case where xds rating has no vsld modifier */ ((s_p_app->settings.ratings.ratings_tv >> screen_ratings_tv_xds2pos(US_level)) & (0 | (0x1)))) return 1; else if ((tmp_c2 == US_level) && ((c2 & (0x38 & c2_mask)) || (c1 & (0x20 & c1_mask)))) /* VSLD restriction */ return 1; } break; case 6: { if (tmp_c2 > US_level) return 1; else if ((tmp_c2 == US_level) && /* handle case where xds rating has no vsld modifier */ ((s_p_app->settings.ratings.ratings_tv >> screen_ratings_tv_xds2pos(US_level)) & (0 | (0x1)))) return 1; else if ((tmp_c2 == US_level) && (c2 & (0x38 & c2_mask))) /* VSL restriction */ return 1; } break; } return 0; } /* * Return 1 if rating is enabled and exceeded * Return 0 if rating is disabled or not exceeded * Returns -1 on invalid rating or error */ static int bapp_block( bapp_t *p_app, unsigned char c1, /* xds 1 character */ unsigned char c2 /* xds 2 character */ ) { rsys_t rsys; unsigned char mask = 0; int blocked = 0; rsys = bapp_get_rsys(c1,c2); BAPP_VCHIP_MSG(("%s-0x%02x,0x%02x\n",s_rsys_name[rsys],c1,c2)); switch (rsys) { default: case eRS_MPA_OLD: case eRS_MPA: { unsigned char rat = 0; /* determine most restrictive user selected movie rating and convert to xds equivalent. */ if ((p_app->settings.ratings.ratings_movies >> 0) & (0 | (0x1))) rat = 1; else if ((p_app->settings.ratings.ratings_movies >> 1) & (0 | (0x1))) rat = 2; else if ((p_app->settings.ratings.ratings_movies >> 2) & (0 | (0x1))) rat = 3; else if ((p_app->settings.ratings.ratings_movies >> 3) & (0 | (0x1))) rat = 4; else if ((p_app->settings.ratings.ratings_movies >> 4) & (0 | (0x1))) rat = 5; else if ((p_app->settings.ratings.ratings_movies >> 5) & (0 | (0x1))) rat = 6; else if ((p_app->settings.ratings.ratings_movies >> 6) & (0 | (0x1))) rat = 7; else rat = 0; BAPP_VCHIP_MSG(("@@@ ratings_movie:%x rat:%d\n", p_app->settings.ratings.ratings_movies, rat)); blocked = bapp_mpa_block(rat, c1); break; } case eRS_US: { unsigned char tmp_c2 = c2 & 0x7; unsigned char d = 0; unsigned char l = 0; unsigned char s = 0; unsigned char v = 0; unsigned char fv = 0; unsigned char rat = 0; switch (tmp_c2) { case 1: mask = 0; break; case 2: /* build tv-y7 content ratings mask */ fv = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_Y7_FV) & (0 | (0x1))); mask = (fv << 3); break; case 3: mask = 0; break; case 4: /* build tv-pg and tv-14 content ratings mask */ d = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_PG_D) & (0 | (0x1))); l = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_PG_L) & (0 | (0x1))); s = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_PG_S) & (0 | (0x1))); v = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_PG_V) & (0 | (0x1))); mask = ((v << 3) | (s << 2) | (l << 1) | (d << 0)); break; case 5: d = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_14_D) & (0 | (0x1))); l = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_14_L) & (0 | (0x1))); s = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_14_S) & (0 | (0x1))); v = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_14_V) & (0 | (0x1))); mask = ((v << 3) | (s << 2) | (l << 1) | (d << 0)); break; case 6: /* build tv-ma content ratings mask */ d = 0; l = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_MA_L) & (0 | (0x1))); s = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_MA_S) & (0 | (0x1))); v = ((p_app->settings.ratings.ratings_tv >> ePOS_TV_MA_V) & (0 | (0x1))); mask = ((v << 3) | (s << 2) | (l << 1) | (d << 0)); break; default: mask = 0; break; } /* determine most restrictive user selected tv rating and convert to xds equivalent. */ if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_Y) & (0 | (0x1))) rat = 1; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_Y7) & (0 | (0x3))) rat = 2; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_G) & (0 | (0x1))) rat = 3; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_PG) & (0 | (0x1F))) rat = 4; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_14) & (0 | (0x1F))) rat = 5; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_MA) & (0 | (0x1F))) rat = 6; else rat = 0; BAPP_VCHIP_MSG(("@@@ ratings_tv:%x rat:%d\n", p_app->settings.ratings.ratings_tv, rat)); blocked = bapp_US_block(rat,mask,c1,c2); } break; case eRS_CANADIAN_ENGLISH: { unsigned char rat = 0; /* determine most restrictive user selected tv rating and convert to xds equivalent. */ if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_Y) & (0 | (0x1))) rat = 1; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_Y7) & (0 | (0x3))) rat = 2; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_G) & (0 | (0x1))) rat = 3; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_PG) & (0 | (0x1F))) rat = 4; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_14) & (0 | (0x1F))) rat = 5; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_MA) & (0 | (0x1F))) rat = 6; else rat = 0; blocked = bapp_CE_block(tv_to_can_eng[rat], c2); } break; case eRS_CANADIAN_FRENCH: { unsigned char rat = 0; /* determine most restrictive user selected tv rating and convert to xds equivalent. */ if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_Y) & (0 | (0x1))) rat = 1; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_Y7) & (0 | (0x3))) rat = 2; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_G) & (0 | (0x1))) rat = 3; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_PG) & (0 | (0x1F))) rat = 4; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_14) & (0 | (0x1F))) rat = 5; else if ((p_app->settings.ratings.ratings_tv >> ePOS_TV_MA) & (0 | (0x1F))) rat = 6; else rat = 0; blocked = bapp_CF_block(tv_to_can_fra[rat], c2); } break; } /* we go thru ratings evaluation so we can always display current rating whether we are currently enforcing it or not */ if (p_app->settings.ratings.ratings_lock == 0) blocked = 0; BDBG_MSG(("%s:%d (%d %s)\n", __FUNCTION__,__LINE__,blocked,p_app->prog_rating_str)); { static chm_event_t rating_evt; rating_evt.type = eCHM_EVT_REDRAW; rating_evt.id = blocked; rating_evt.ticks = bos_getticks(); bos_post_event(p_app->msg_queue, (b_event_t *)&rating_evt); } return blocked; } /* * Callback to process XDS data (V-CHIP) */ static void bapp_xds_callback( int xds_class, /* the class (0 - current, used for vchip) */ int xds_type, /* the xds type (5 - vchip) */ unsigned char* data, /* the data buffer, containing data_len valid bytes */ int data_len /* the number of valid bytes in data */ ) { if (data_len != 2) return; if (xds_class == 0) { /* Current class */ if (xds_type == 5) { static chm_event_t chm_evt; int block = 0; b_timeval tv; unsigned int current_ticks = bos_getticks(); /* ignore rating if ratings was received while tuned to a different channel. */ if (current_ticks < (s_p_app->last_tune_tick + MS_TO_TICKS(BAPP_RATINGS_EVAL_DELAY))) return; GETTIMEOFDAY(&tv); s_p_app->last_xds = tv.tv_sec; /* VCHIP processing */ block = bapp_block(s_p_app,data[0],data[1]); BDBG_WRN(("bapp_block(0x%02x,0x%02x) - %d, 0x%08x\n",data[0],data[1],block,current_ticks)); if (block != -1) { s_p_app->last_rating_tick = current_ticks; if (block != s_p_app->last_rating_block_status) { chm_evt.type = eCHM_EVT_BLOCK; chm_evt.id = block; chm_evt.ticks = current_ticks; bos_post_event(s_p_app->msg_queue,(b_event_t*)&chm_evt); } s_p_app->last_rating_block_status = block; } } } else if (xds_class == 3) { /* Miscellaneous class */ if (xds_type == 1) { /* time of day */ } else if (xds_type == 4) { #if 0 /* JPF XDS time is unreliable in current BA broadcasts */ /* local time zone */ BDBG_WRN(("### UTC OFFSET = %d(s) ###\n", data[0] & 0x1F,(data[0] & 0x20) ? "DST" : "STD")); g_xds_time_offset = data[0] & 0x1F; g_xds_dst = (data[0] & 0x20) ? 1 : 0; #endif } } } #endif /* Summary: Set volume level Description: Set Volume level (range 0(full) - s_volume_num) */ void bapp_set_audio_volume(bapp_t *p_app, uint8_t level) { baudio_decode_config config; if (p_app->system_mute) return; if (level == p_app->audio_vol) return; if (level > BAPP_MAX_VOLUME) level = BAPP_MAX_VOLUME; baudio_decode_get_config(p_app->audio, &config); config.left_volume = config.right_volume = level; baudio_decode_set_config(p_app->audio, &config); p_app->audio_vol = level; p_app->settings_dirty |= DIRTY_CHANNEL;/*janzy@20121101,save and apply audio_volume*/ } /* Summary: Mute audio Description: Mute audio when enable is non-zero. */ void bapp_audio_mute(bapp_t *p_app, int mute) { baudio_decode_config config; if (p_app->system_mute) return; if ((mute && p_app->is_muted) || (!mute && !p_app->is_muted) || p_app->settings.av_mute || (p_app->audio_mute && p_app->is_muted)) return; baudio_decode_get_config(p_app->audio, &config); config.mute = (mute == 0) ? false : true; if (baudio_decode_set_config(p_app->audio, &config) != b_ok) { BDBG_WRN(("%s baudio_decode_set_config mute = %d failed\n",__FUNCTION__,config.mute)); } else p_app->is_muted = mute; } /*janzy@20121108,add DolbyDrc mode function*/ void bapp_audio_SetDolbyDrc_mode(bapp_t *p_app, baudio_dolby_drc_mode mode) { baudio_decode_config config; baudio_decode_get_config(p_app->audio, &config); config.dolby.drc_mode = mode; if (baudio_decode_set_config(p_app->audio, &config) != b_ok) { BDBG_WRN(("%s baudio_decode_set_config mute = %d failed\n",__FUNCTION__,config.dolby.drc_mode)); } return; } /*janzy@20121108,add DolbyDrc mode function*/ void bapp_audio_GetDolbyDrc_mode(bapp_t *p_app, baudio_dolby_drc_mode mode) { baudio_decode_config config; baudio_decode_get_config(p_app->audio, &config); mode = config.dolby.drc_mode; return; } /* Summary: Mute video Description: Mute video only */ void bapp_video_mute(bapp_t *p_app, int mute) { bdecode_config cfg; bdecode_get_config(p_app->decode,&cfg); if (mute) cfg.mute = 1; else cfg.mute = 0; bdecode_set_config(p_app->decode,&cfg); } /* Summary: Mute both audio and video. Description: Mute both audio and video when enable is non-zero. */ void bapp_av_mute(bapp_t *p_app, int mute) { bapp_audio_mute(p_app,mute); bapp_video_mute(p_app,mute); if (mute) { bapp_sync(p_app); bgfx_fill_rect(&p_app->surf,0,0,eWIDTH,eHEIGHT,eCOLOR_CLEAR); bapp_flush_screen(p_app); } /* 'reset' feature will invoke setup wizard. it shouldn't mute graphics. see screen_reset_event */ p_app->settings.av_mute = (mute==1)?mute:0; p_app->settings_dirty |= DIRTY_MISC; } /* Summary: Configure the video output mode. Description: Configure the video output mode. */ void bapp_output_mode(bapp_t *p_app, int widescreen) { #if 0 /* JPF TODO SET OUTPUT MODE- extend to HD */ bdecode_config cfg; bdecode_get_config(p_app->decode,&cfg); if (widescreen) { BDBG_WRN(("Widescreen (%d)\n", widescreen)); cfg.widescreen = widescreen; } else { BDBG_WRN(("Full Screen...\n")); cfg.widescreen = 0; } bdecode_set_config(p_app->decode,&cfg); #endif } /* Summary: Apply the current settings. Description: Apply the current settings. Restart decode. */ static void bapp_apply_settings(bapp_t *p_app) { p_app->audio_vol = p_app->settings.audio_vol; bapp_set_audio_volume(p_app, p_app->audio_vol); } #ifdef HAS_HDMI /* Summary: Reset the Video output to the default values. */ void bapp_reset_hd_config_settings(bapp_t *p_app) { p_app->settings.hd_config.output_format = bdisplay_format_auto; p_app->settings.hd_config.hd_options = bdisplay_hd_output_options_auto; p_app->settings.hd_config.sharpness = 0; /* soft */ } #endif /* Summary: Reset the closed captioning settings to the default values. */ void bapp_reset_cc_config_settings(bapp_t *p_app) { #ifdef CONFIG_EIA_708 p_app->captions_basic = 0; p_app->settings.dcc.captions_basic = 0; /* disable digital captioning */ p_app->settings.dcc.captions_font = 0; /* auto */ p_app->settings.dcc.captions_font_size = 0; /* auto */ p_app->settings.dcc.captions_font_style = 0; /* normal */ p_app->settings.dcc.captions_font_color = 0; /* default */ p_app->settings.dcc.captions_font_opacity = 0; p_app->settings.dcc.captions_back_color = 0; p_app->settings.dcc.captions_back_opacity = 0; p_app->settings.dcc.captions_edge_color = 0; p_app->settings.dcc.captions_edge_type = 0; p_app->settings.dcc.captions_analog = 1; /* disable analog captioning */ p_app->settings.dcc.captions_digital = 0; /* we use captions_basic instead this variable for CSx switch */ p_app->settings_dirty |= DIRTY_DCC; #endif } /* Summary: Reset the current user settings Description: Reset the current user settings. Note this does not change them in flash. */ void bapp_reset_settings(bapp_t *p_app) { memset(&p_app->settings, 0, sizeof(p_app->settings)); bdisplay_settings s; //ch_map_init(&(p_app->settings.ch_map),&(p_app->ch_map_mutex)); /* this will make sure volume is reset to default from UI */ p_app->audio_mute = false; //audio mute release p_app->settings.audio_vol = BAPP_MAX_VOLUME; p_app->audio_vol = BAPP_MAX_VOLUME; p_app->settings.rrt_settings.pin = DEFAULT_PIN; p_app->settings.psi_scan = 1; #ifdef ACB612/*janzy@20121115,fixed factory function(Key 9) to reset default*/ p_app->settings.wiz_completed = 0; #else p_app->settings.wiz_completed = 1; #endif #ifdef ACB612 p_app->settings.language = eLANG_SPANISH; #endif #ifdef HAS_HDMI bapp_reset_hd_config_settings(p_app); #endif //widescreen default AR / bscreen / p_app->settings.sd_options = bdisplay_sd_output_options_widescreen; s.sd_options = bdisplay_sd_output_options_widescreen; bdisplay_set(p_app->display,&s); /* need to reset it for consistency of DCC option */ p_app->captions_basic = 0; //alternate audio default p_app->settings.sound = 1; p_app->settings.dcc.captions_analog = 1; p_app->settings.rfm=0; p_app->settings.dst=0; //When STB reset,daylight init. p_app->chm.local_dst_obs = p_app->settings.dst; brfm_set_ch3(p_app->p_rfm, p_app->settings.rfm); } /* Summary: Load current settings from NVM */ static void bapp_load_settings(bapp_t *p_app) { int result = 0; memset(&p_app->settings.ch, 0, sizeof(p_app->settings.ch)); p_app->settings_dirty = 0; if (bos_acquire_mutex(&p_app->ch_map_mutex, 45) == b_ok) { if (bos_acquire_mutex(&(s_p_app->flash_mutex), 250) == b_ok) { result = bast_channel_read(p_app); if (0 == result || 3 == result) { result = bast_misc_read(p_app); if (0 == result || 3 == result) { result = bast_channel_map_read(p_app); if (0 == result || 3 == result) { result = bast_screen_read(p_app); if (0 == result) { result = bast_eas_read(p_app); } } else { p_app->settings.num_channels = p_app->cur_ch_num = 0; } } } bos_release_mutex(&(s_p_app->flash_mutex)); } else { BDBG_WRN(("%s:%d mutex timeout", __FUNCTION__, __LINE__)); } bos_release_mutex(&p_app->ch_map_mutex); if (0 == result) { //ch_output(bapp_cur_ch_map(p_app)); } else { BDBG_WRN(("Error loading settings, resetting to default.")); bapp_reset_settings(p_app); p_app->audio_vol = p_app->settings.audio_vol; p_app->settings_dirty = DIRTY_CHANNEL | DIRTY_MISC | DIRTY_EAS | DIRTY_CHANNEL_MAP | DIRTY_SCREEN; bapp_save_settings(p_app); } } return; } /* Summary: Save current settings to NVM Description: Save current settings to NVM */ void bapp_save_settings(bapp_t *p_app) { if (bos_acquire_mutex(&(s_p_app->flash_mutex), 250) != b_ok) { BDBG_WRN(("%s:%d mutex timeout\n", __FUNCTION__, __LINE__)); return; } if (0 != (p_app->settings_dirty & DIRTY_CHANNEL)) { /* update unsaved settings */ p_app->settings.audio_vol = p_app->audio_vol; bast_channel_save(p_app); p_app->settings_dirty &= ~DIRTY_CHANNEL; } /* use MISC instead of having its own DB */ if (p_app->settings_dirty & DIRTY_HD_CONFIG) { bdisplay_settings s; bdisplay_get(p_app->display,&s); #ifdef HAS_HDMI p_app->settings.hd_config.output_format = s.format; p_app->settings.hd_config.hd_options = s.hd_options; p_app->settings.hd_config.sharpness = s.sharpness; p_app->settings_dirty &= ~DIRTY_HD_CONFIG; #endif p_app->settings.sd_options = s.sd_options; p_app->settings_dirty |= DIRTY_MISC; } if (p_app->settings_dirty & DIRTY_DEBUG_CONFIG) { p_app->settings_dirty &= ~DIRTY_DEBUG_CONFIG; p_app->settings_dirty |= DIRTY_MISC; } if (0 != (p_app->settings_dirty & DIRTY_MISC)) { bast_misc_save(p_app); p_app->settings_dirty &= ~DIRTY_MISC; } if (0 != (p_app->settings_dirty & DIRTY_EAS)) { bast_eas_save(p_app); p_app->settings_dirty &= ~DIRTY_EAS; } if (0 != (p_app->settings_dirty & DIRTY_SCREEN)) { bast_screen_save(p_app); p_app->settings_dirty &= ~DIRTY_SCREEN; } if (bos_acquire_mutex(&p_app->ch_map_mutex,45) == b_ok) { if (0 != (p_app->settings_dirty & DIRTY_CHANNEL_MAP)) { bast_channel_map_save(p_app); p_app->settings_dirty &= ~DIRTY_CHANNEL_MAP; } bos_release_mutex(&p_app->ch_map_mutex); } else { BDBG_WRN(("%s:%d mutex timeout", __FUNCTION__, __LINE__)); } bos_release_mutex(&(s_p_app->flash_mutex)); } /* Summary: Power down audio DAC and power off */ void bapp_do_poweroff(bapp_t *p_app) { bapp_standby(p_app, false); } /* Summary: Initialize the main app structure. Description: Do necessary configuration of main app structure. Assumes p_app is allocated and p_surf and palette are initialized. */ void bapp_init(bapp_t *p_app) { bapp_lang_t e_lang; bgraphics_settings graphics_settings; bresult rc; unsigned int *palette; /* [out] address of palette */ int width; /* [out] width of the OSD surface */ int height; /* [out] height of the OSD surface */ int pitch; /* [out] pitch of the OSD surface */ bdecode_config cfg; #ifdef ACB612 static int ntimeout; int ngetkey; #endif bool isBootUpFromPowerPlugIn = false; BDBG_MSG(("%s:%d\n",__FUNCTION__,__LINE__)); #if(AOV_MODEL == ALCO) printf("\nMODEL = ALCO\n"); #elif (AOV_MODEL == ZINWELL) printf("\nMODEL = ZINWELL\n"); #else printf("\nMODEL = %d\n",AOV_MODEL); #endif #if(USERIO_ID == 5) printf("\nRemote = RCA\n"); #elif (USERIO_ID == 4) printf("\nRemote = ARC-008\n"); #elif (USERIO_ID == 10) printf("\nRemote = MK-35\n"); #elif (USERIO_ID == 11) printf("\nRemote = ZRC-4502\n"); #elif(USERIO_ID == 12)/*janzy@20121030,add remote Skyworth_01*/ printf("\nRemote = Skyworth_01\n"); #else printf("\nRemote = %d\n",USERIO_ID); #endif memset(p_app,0,sizeof(bapp_t)); s_p_app = p_app; p_app->last_key_down = (bIR_codes_t)0xFFF; p_app->last_screen_id = eSCREEN_MAX; bsettop_init(0); #ifdef ACB612/*janzy@20121106,enable pass through before entering standby*/ #ifdef MERGE_20121115 isBootUpFromPowerPlugIn = ((b_GetKBD1_KBD_PAT0() == 0)?true:false); #endif #endif GETTIMEOFDAY(&p_app->timeout_tv); p_app->user_io = buser_input_open(B_ID(USERIO_ID)); bast_init(p_app); #ifdef ACB612/*ChengYu@20120809: for XModem firmware upgrade*/ p_app->factory_test = false; ngetkey = AOV_buser_input_GetButtonfactory(); if(ngetkey== eButton_D00) { /*RLQ*/ void fupdate(void); fupdate(); } else if(ngetkey == eButton_0U0) { p_app->factory_test = true; /*RLQ*/ #if 0 printf("\n\n\n%15s@%5d:%25s Factory Enable\n\n",strrchr(__FILE__,'/')? strrchr(__FILE__,'/')+1 : __FILE__,__LINE__,__FUNCTION__); printf("\n\n\n%15s@%5d:%25s Factory Enable\n\n",strrchr(__FILE__,'/')? strrchr(__FILE__,'/')+1 : __FILE__,__LINE__,__FUNCTION__); printf("\n\n\n%15s@%5d:%25s Factory Enable\n\n",strrchr(__FILE__,'/')? strrchr(__FILE__,'/')+1 : __FILE__,__LINE__,__FUNCTION__); #endif } #endif bgraphics_get(&graphics_settings); graphics_settings.format = bgraphics_pixel_format_palette4; bgraphics_set(&graphics_settings); if(!isBootUpFromPowerPlugIn) { BDBG_WRN(("Open display...\n")); p_app->display = bdisplay_open(B_ID(0)); BDBG_WRN(("Display opened %d\n",p_app->display)); } BDBG_WRN(("Open decoder...\n")); p_app->decode = bdecode_open(0); BDBG_ASSERT(p_app->decode); BDBG_WRN(("Decoder opened 0x%08x\n",p_app->decode)); smessage_init(NULL); if(!isBootUpFromPowerPlugIn) { p_app->window[0] = bdecode_window_open(0, p_app->display); p_app->window[1] = bdecode_window_open(1, p_app->display); } p_app->audio = baudio_decode_open(B_ID(0)); if (!p_app->audio) { BDBG_WRN(("baudio_decode_open failed\n")); } p_app->audio_mute = 0; #if HAS_HDMI rc = bsettop_hdmi_open(&(p_app->hdmi),p_app->display,p_app->audio, NULL /* no hdcp authentication callback needed*/); BDBG_ASSERT(rc == b_ok); #endif #if (BCHP_VER>=BCHP_VER_B0) p_app->p_rfm = brfm_open(0); #endif if(!isBootUpFromPowerPlugIn) { /* turn on green LED */ buser_AOV_input_LED(p_app->p_rfm, eLED_Status_G); } bos_create_queue(&p_app->msg_queue, p_app->msg_event, MAX_MSG_EVENT); BDBG_ASSERT(p_app->msg_queue); rc = bos_create_mutex(&p_app->ch_map_mutex); BDBG_ASSERT(rc == b_ok); rc = bos_create_mutex(&p_app->flash_mutex); BDBG_ASSERT(rc == b_ok); //ch_map_init(&(p_app->settings.ch_map),&(p_app->ch_map_mutex)); #ifdef CONFIG_SCREENSAVER p_app->logo = (unsigned char *)s_logo; p_app->logo_size = s_logo_size; #endif #ifdef DOLBY_LOGO_NO_D /* defined in dolby_logo_no_D.c */ extern unsigned int g_dolby_logo_no_D_size; extern const unsigned char g_dolby_logo_no_D[]; /* dolby logo to show in the banner screen */ p_app->dolby_logo = (unsigned char *)g_dolby_logo_no_D; p_app->dolby_logo_size = g_dolby_logo_no_D_size; #else extern unsigned int g_dolby_logo_240_size; extern const unsigned char g_dolby_logo_240[]; /* dolby logo to show in the banner screen */ p_app->dolby_logo = (unsigned char *)g_dolby_logo_240; p_app->dolby_logo_size = g_dolby_logo_240_size; #endif //12-02 splash screen added extern unsigned int g_dst_logoSize; extern const unsigned char g_dst_logo[]; p_app->dst_logo = (unsigned char *)g_dst_logo; p_app->dst_logoSize = g_dst_logoSize; if(!isBootUpFromPowerPlugIn) { p_app->graphics = bgraphics_open(B_ID(0),p_app->display); } /* should after bgraphics_open, since bgraphics_open will overwrite some BVN TOP registers, e.g. AMOL */ chm_init(&p_app->chm,p_app); /*janzy@20121106,enable pass through before entering standby*/ if(isBootUpFromPowerPlugIn) { BDBG_ERR(("######## Turn OFF ########\n")); #ifdef CONFIG_NXP_TDA182I4 #ifdef MERGE_20121115 NXP_TDA182I4_SetLoopThrough(true);/*janzy@20121108,add NXP_TDA182I4_SetLoopThrough*/ #endif NXP_TDA182I4_SetStandby(); #endif #ifdef CONFIG_STANDBY bos_sleep(200); b_s3_standby(USERIO_ID); #endif p_app->power = false; while(1) { bos_sleep(200); } } p_app->yield_ms = APP_DEFAULT_YIELD; p_app->lang = eLANG_ENGLISH; bgraphics_get_framebuffer(p_app->graphics,(void**)&p_app->osd_mem,(unsigned int **)&palette,&width,&height,&pitch); bapp_set_palette(p_app,ePALETTE_DEFAULT); bgraphics_load_palette(p_app->graphics); p_app->osd_mem_size = pitch * height; p_app->width = width; p_app->height = height; BDBG_MSG(("%s:%d - Width = %d, Height = %d, Pitch = %d.\n",__FUNCTION__,__LINE__,width,height,pitch)); BDBG_MSG(("%s:%d - Initialize screens.\n",__FUNCTION__,__LINE__)); /* Default to NULL (empty) screen (TODO: goto factory test then setup wizard.) */ p_app->screen_id = eSCREEN_BANNER; p_app->p_screens = g_screens; p_app->num_screens = g_screens_num; BDBG_MSG(("%s:%d - Initialize bgfx.\n",__FUNCTION__,__LINE__)); /* initialize bgfx */ bgfx_init(&s_io,NULL,s_p_gfx_hw); #ifdef CONFIG_GFX_ARGB32 bgraphics_get_osd_params(p_app->graphics,(bsettop_surf_t*)&(p_app->surf.surface.surf),(void**)&(p_app->osd_mem),NULL,NULL); if (bgfx_create(&p_app->surf,p_app->width,p_app->height,(uint8_t*)p_app->osd_mem, pitch,NULL,BGFX_SURF_BPP(32)|BGFX_SURF_RGB|BGFX_SURF_GRC) != 0) { BDBG_ASSERT(0); } #else /* Create the OSD surface to use for all drawing */ if (bgfx_create(&p_app->surf,p_app->width,p_app->height,(uint8_t*)p_app->osd_mem, pitch,&p_app->palette, BGFX_SURF_PRIMARY | BGFX_SURF_BPP(4)) != 0) { BDBG_ASSERT(0); } #endif bgfx_fill_rect(&p_app->surf,0,0,p_app->width,p_app->height,eCOLOR_CLEAR); //----------------------- splash image p_app->br.cnt = 0; p_app->br.data = (void*)p_app->dst_logo; p_app->br.size = p_app->dst_logoSize; bgfx_render_file(&p_app->surf, 0, 0, &p_app->br, 0); bapp_flush_screen(p_app); bos_sleep(3000); bgfx_fill_rect(&p_app->surf,0,0,p_app->width,p_app->height,eCOLOR_CLEAR); //----------------------- BDBG_MSG(("%s:%d - Load fonts.\n",__FUNCTION__,__LINE__)); memset(&s_font[eFONT_SIZE_SMALL],0,sizeof(bgfx_font_t) * 3); p_app->br.cnt = 0; #ifdef CONFIG_8BIT_FONT p_app->br.data = (unsigned char*)g_FrancophilB_20_aa; p_app->br.size = g_FrancophilB_22_aa_size; #else p_app->br.data = (unsigned char*)g_FrancophilB_22_mono; p_app->br.size = g_FrancophilB_22_mono_size; #endif if (bgfx_load_font(&(s_font[eFONT_SIZE_SMALL]),&p_app->br) != 0) { BDBG_ASSERT(0); } p_app->br.cnt = 0; #ifdef CONFIG_8BIT_FONT p_app->br.data = (unsigned char*)g_FrancophilB_22_aa; p_app->br.size = g_FrancophilB_28_aa_size; #else p_app->br.data = (unsigned char*)g_FrancophilB_28_mono; p_app->br.size = g_FrancophilB_28_mono_size; #endif if (bgfx_load_font(&(s_font[eFONT_SIZE_MED]),&p_app->br) != 0) { BDBG_ASSERT(0); } p_app->br.cnt = 0; #ifdef CONFIG_8BIT_FONT p_app->br.data = (unsigned char*)g_FrancophilB_28_aa; p_app->br.size = g_FrancophilB_28_aa_size; #else p_app->br.data = (unsigned char*)g_FrancophilB_40_mono; p_app->br.size = g_FrancophilB_40_mono_size; #endif if (bgfx_load_font(&(s_font[eFONT_SIZE_LARGE]), &p_app->br) != 0) { BDBG_ASSERT(0); } for (e_lang = eLANG_ENGLISH; e_lang < eLANG_MAX; ++e_lang) { p_app->p_font[e_lang][eFONT_SIZE_SMALL] = &s_font[eFONT_SIZE_SMALL]; p_app->p_font[e_lang][eFONT_SIZE_MED] = &s_font[eFONT_SIZE_MED]; p_app->p_font[e_lang][eFONT_SIZE_LARGE] = &s_font[eFONT_SIZE_LARGE]; } bapp_load_settings(p_app); /* set current language */ p_app->lang = p_app->settings.language; p_app->captions_basic = p_app->settings.dcc.captions_basic; #if (BCHP_VER>=BCHP_VER_B0) /* if not default CH3, then set to CH4 */ if (p_app->settings.rfm) brfm_set_ch3(p_app->p_rfm, p_app->settings.rfm); #endif bapp_set_video_configuration(p_app); #if(AOV_MODEL == ZINWELL) /* will make AVL configurable */ bapp_P_enable_avl(p_app, false);/*janzy@20121108,Disable AVL*/ #else /* will make AVL configurable */ bapp_P_enable_avl(p_app, false); #endif #ifdef ACB612 aov_setAVL_target(); #endif #ifndef NO_VCHIP p_app->ratings_override = false; /* reset so ratings will be re-evaluated when returned to full tv */ p_app->last_rating_block_status = -1; /* assume psip unblock */ p_app->last_psip_rating_block_status = 0; #endif bapp_apply_settings(p_app); BDBG_WRN(("%s:%d - av_mute = %d\n",__FUNCTION__,__LINE__,p_app->settings.av_mute)); BDBG_WRN(("%s:%d - prev_state = %d\n",__FUNCTION__,__LINE__,p_app->settings.state)); #ifdef CONFIG_EIA_708 p_app->eia708 = bapp_eia708_open(p_app); BAPP_ASSERT(p_app->eia708); bdecode_get_config(p_app->decode, &cfg); cfg.cc_callback = bapp_eia708_cb; #ifndef NO_VCHIP cfg.xds_callback = bapp_xds_callback; #endif bdecode_set_config(p_app->decode, &cfg); #endif #if(AOV_MODEL == ZINWELL) /*janzy@20121108,set DolbyDrc = baudio_dolby_drc_mode_line*/ bapp_audio_SetDolbyDrc_mode(p_app, baudio_dolby_drc_mode_line); #else bapp_audio_SetDolbyDrc_mode(p_app, baudio_dolby_drc_mode_rf); #endif bapp_av_mute(p_app,0); /*janzy@20121101,save and apply audio_volume begin*/ unsigned char vol_temp; vol_temp = p_app->settings.audio_vol; p_app->audio_vol = 0; bapp_set_audio_volume(p_app, vol_temp); /*end*/ bapp_flush_screen(p_app); if (p_app->settings.num_channels > 0) { bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX); } else { if (!p_app->settings.wiz_completed) { /* first time to run, launch welcome screen */ memset(&p_app->settings, 0, sizeof(p_app->settings)); if (0 == p_app->settings.audio_vol) { p_app->settings.audio_vol = BAPP_MAX_VOLUME; bapp_apply_settings(p_app); p_app->audio_vol = BAPP_MAX_VOLUME; } p_app->settings.rrt_settings.pin = DEFAULT_PIN; #ifdef ACB612 p_app->settings.language = eLANG_SPANISH; #endif bapp_set_current_screen(p_app, eSCREEN_WIZ_WELCOME, eSCREEN_MAX); } else { bapp_set_current_screen(p_app, eSCREEN_MAIN, eSCREEN_MAX); } p_app->settings.sound = 1; p_app->settings.sd_options = bdisplay_sd_output_options_widescreen; p_app->settings.dcc.captions_analog = 1; } /* enable CC */ bapp_enable_cc(p_app, true); bapp_new_screen(p_app); p_app->power = 1; /* Always enter pending state on hard power up. */ #ifdef CONFIG_DTA_CABLE_TESTING p_app->settings.psi_scan = 1; bapp_eval_state(p_app,eAPP_STATE_NORMAL); #else p_app->settings.psi_scan = 1; if (p_app->settings.psi_scan) bapp_eval_state(p_app,eAPP_STATE_NORMAL); else bapp_eval_state(p_app,eAPP_STATE_HUNT); #endif #ifdef ACB612/*janzy@20120803*/ if(p_app->factory_test == true) { ntimeout = 0; bapp_channel_hunt(p_app); while(!chm_GetScanStatusFinish()) { bos_sleep(100); ntimeout++; if(ntimeout > 1000) break; } p_app->state = eAPP_STATE_FACTORY; bapp_set_current_screen(p_app, eSCREEN_STATUS, eSCREEN_MAX); bapp_new_screen(p_app); } #endif /* in case no signal in the bootup */ p_app->last_keypress_tick = bos_getticks(); /* initialize it in case there is no any key press after bootup */ p_app->power_saver_tick = bos_getticks(); #ifdef BCM_DEBUG BDBG_SetModuleLevel("bscreen",BDBG_eWrn); timing_profile_init(); p_app->ptp_tune = timing_profile_get("Tune"); /* start tune to first pts */ p_app->ptp_psi = timing_profile_get("PSI"); /* profile psi (PAT/PMT) */ p_app->ptp_first_pts = timing_profile_get("PTS"); /* profile start decode to first PTS */ p_app->ptp_decode = timing_profile_get("Decode"); /* start tuner to first pts */ bdecode_get_config(p_app->decode,&cfg); cfg.first_pts_callback = bapp_first_pts_callback; cfg.seq_hdr_callback = bapp_seq_hdr_callback; bdecode_set_config(p_app->decode,&cfg); #endif } /* Summary: Main app event handler. Description: Main application event handler. */ void bapp_handle_event(bapp_t *p_app, bscreen_event_t *p_event) { if (p_event && (p_event->type == eS_EVENT_IR) && (p_event->id >= eIR_CHMAP)) { BDBG_WRN(("%s:%d - event_id = 0x%08x",__FUNCTION__,__LINE__,p_event->id)); switch (p_event->id) { case eIR_CHMAP: /* Output channel map on UART */ //ch_output(bapp_cur_ch_map(p_app)); break; case eIR_SCAN: /* Perform channel scan */ p_app->state = eAPP_STATE_NORMAL; if (p_app->settings.psi_scan) { } bapp_eval_state(p_app,eAPP_STATE_HUNT); break; case eIR_SETUP: /* Perform default setup */ p_app->state = eAPP_STATE_NORMAL; //bapp_eval_state(p_app,eAPP_STATE_DOWNLOAD); BDBG_WRN(("%s:%d - eIR_SETUP\n",__FUNCTION__,__LINE__)); break; case eIR_EXIT: /* Exit to banner menu */ bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX); if (p_app->system_mute) { bapp_audio_do_mute(p_app, false); bapp_video_mute(p_app, false); } break; default: if ((p_event->id & eIR_SETCH) == eIR_SETCH) { /* TODO Tune to channel number */ bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX); } break; } } } /* Summary: Main app idle time handler. Description: Main application idle time handler. */ void bapp_idle(bapp_t *p_app) { b_timeval end_tv; unsigned int delta_hrs; static b_timeval last_tv = { 0, 0}; #ifndef NO_VCHIP bool rating_timeout = false; static chm_event_t chm_evt; uint32_t current_ticks = bos_getticks(); #endif GETTIMEOFDAY(&end_tv); /* PVT Monitor */ if (end_tv.tv_sec > (last_tv.tv_sec + 2)) { bsettop_pvt(); last_tv = end_tv; } delta_hrs = (end_tv.tv_sec - p_app->timeout_tv.tv_sec)/(60 * 60); if ((delta_hrs > 0) && (((int)p_app->settings.timeout_cnt) > 0)) { p_app->settings.timeout_cnt--; BDBG_WRN(("%s decriment timeout counter %d\n",__FUNCTION__,p_app->settings.timeout_cnt)); p_app->timeout_tv = end_tv; } #ifndef NO_VCHIP /* check if last psip rating has timed out */ if ((p_app->last_cad + BAPP_CAD_TIMEOUT) < end_tv.tv_sec) { if (p_app->last_psip_rating_block_status == 1) { BDBG_WRN(("clear PSIP rating to unrated - timed out! %d\n",end_tv.tv_sec)); p_app->last_psip_rating_block_status = 0; /* clear ratings string */ rating_timeout = true; } p_app->psip_rating_str[0] = 0; } /* check if last xds rating has timed out */ if ((p_app->last_rating_tick + MS_TO_TICKS(BAPP_VCHIP_TIMEOUT)) < current_ticks) { if (p_app->last_rating_block_status == 1) { BDBG_WRN(("clear XDS rating to unrated - timed out! (0x%08x)\n",current_ticks)); p_app->last_rating_block_status = 0; /* clear ratings string */ rating_timeout = true; } p_app->prog_rating_str[0] = 0; } /* send unblock message if both rating types have timed out */ if ((rating_timeout) && (p_app->last_rating_block_status != 1) && (p_app->last_psip_rating_block_status != 1)) { BDBG_WRN(("current rating timed out - unblocking!")); /* Unblock since a previous rating has timed out */ chm_evt.type = eCHM_EVT_BLOCK; chm_evt.id = 0; chm_evt.ticks = current_ticks; bos_post_event(s_p_app->msg_queue,(b_event_t*)&chm_evt); } #endif if (p_app->check_poweron) { if (p_app->poweron_ms < bos_getticks()) { p_app->check_poweron = false; } } if ((p_app->state == eAPP_STATE_NORMAL) && p_app->eas_timeout && (p_app->eas_timeout < end_tv.tv_sec) && p_app->eas_one_iteration) { p_app->eas_timeout = 0; p_app->eas_started = false; p_app->eas_one_iteration = false; if (p_app->eas_text || p_app->eas_activation_text) { p_app->eas_text = false; p_app->eas_activation_text = false; bapp_sync(p_app); screen_null_draw(p_app, NULL); bapp_flush_screen(p_app); } if (p_app->eas_ch_found) { bapp_tune_prev(p_app); p_app->eas_ch_found = false; } bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX); #ifdef CONFIG_EIA_708 bapp_enable_cc(p_app, true); #endif } #ifdef OLD_INFO_KEY_PROCESSING if (p_app->last_key_down == eIR_INFO) { BDBG_WRN(("%s: p_app->last_key_down == eIR_INFO \n",__FUNCTION__)); b_timeval cur_tv; GETTIMEOFDAY(&cur_tv); if ((p_app->last_key_tv.tv_sec + BAPP_DIAG_TIMEOUT) <= cur_tv.tv_sec) { BDBG_WRN(("%s: DIAG_TIMEOUT \n",__FUNCTION__)); bapp_set_current_screen(p_app, eSCREEN_DIAG_MENU, eSCREEN_MAX); bapp_new_screen(p_app); } } #endif if ((p_app->state == eAPP_STATE_NORMAL) && ((p_app->last_save_tv.tv_sec + BAPP_SAVE_TIMEOUT) < end_tv.tv_sec)) { p_app->last_save_tv = end_tv; if (p_app->settings_dirty) bapp_save_settings(p_app); } /* for audio only channel screen draw */ if ((p_app->state == eAPP_STATE_NORMAL) && (0 == p_app->eas_timeout) && (0 == p_app->cur_ch.video_pid && p_app->chm.decoding_audio)) { if ((eSCREEN_NULL == p_app->screen_id) || (eSCREEN_BANNER_SMALL == p_app->screen_id)) { if ((bos_getticks() - p_app->last_keypress_tick) > MS_TO_TICKS(BAPP_AUDIO_CHANNEL_KEYPRESS_CHECK_TIMEOUT * 1000)) { if ((p_app->audio_channel_tm.tv_sec + BAPP_AUDIO_CHANNEL_SWITCH_TIMEOUT) <= end_tv.tv_sec) { bapp_set_current_screen(p_app, eSCREEN_AUDIO_CHANNEL, p_app->screen_id); bapp_new_screen(p_app); } } else { GETTIMEOFDAY(&p_app->audio_channel_tm); } } } } /* Summary: Wait for vsync. Description: Block waiting for vsync so drawing can by syncronized with screen refresh. */ void bapp_sync(bapp_t *p_app) { /* do nothing */ } /* Summary: Enable closed captioning. Description: Enable closed captioning and send clear characters. */ void bapp_enable_cc(bapp_t *p_app, int enable) { #ifdef CONFIG_EIA_708 static bool first = true; bool changed = false; bdecode_config cfg; bool digital = bapp_eia708_enabled(p_app->eia708); bdecode_get_config(p_app->decode,&cfg); /* p_app->settings.dcc.captions_digital */ if (p_app->settings.dcc.captions_basic < 1) { if (cfg.cc_enabled || first) { cfg.cc_enabled = false; bapp_eia708_enable(p_app->eia708, false); changed = true; } } else { if (digital != enable || first) { cfg.cc_enabled = enable; bapp_eia708_enable(p_app->eia708, enable); changed = true; } } if (p_app->settings.dcc.captions_analog < 1) { if (!cfg.block_vbi || first) { cfg.block_vbi = true; changed = true; } } else { if (enable == cfg.block_vbi || first) { cfg.block_vbi = !enable; changed = true; } } if (changed) { bdecode_set_config(p_app->decode,&cfg); } p_app->cc_enabled = enable; first = false; #endif } /* Summary: Handle new screen. Description: Block waiting for vsync so drawing can by syncronized with screen refresh. */ static void bapp_screen_redraw(bapp_t *p_app) { bscreen_event_t screen_event; screen_event.type = eS_EVENT_REDRAW; screen_event.id = 0; BDBG_MSG(("%s:%d - sending setup event to %d.\n",__FUNCTION__,__LINE__,p_app->screen_id)); p_app->p_screens[p_app->screen_id].handle_event(p_app,(void*)&(p_app->p_screens[p_app->screen_id]),&screen_event); } /* Summary: Handle new screen. Description: Block waiting for vsync so drawing can by syncronized with screen refresh. */ static void bapp_new_screen(bapp_t *p_app) { bscreen_event_t screen_event; #ifdef TIME_APP_DRAWING b_timeval start_tv,end_tv,result_tv; unsigned int dt; #endif screen_event.type = 0; if (p_app->last_screen_id != (int)p_app->screen_id) { BDBG_MSG(("%s:%d - sending setup event to %d.\n",__FUNCTION__,__LINE__,p_app->screen_id)); screen_event.type = eS_EVENT_SETUP; screen_event.id = 0; p_app->p_screens[p_app->screen_id].handle_event(p_app,(void*)&(p_app->p_screens[p_app->screen_id]),&screen_event); } p_app->last_screen_id = p_app->screen_id; #ifdef TIME_APP_DRAWING GETTIMEOFDAY(&start_tv); #endif //bapp_sync(p_app); p_app->p_screens[p_app->screen_id].draw(p_app,(void*)&(p_app->p_screens[p_app->screen_id])); bapp_flush_screen(p_app); #ifdef TIME_APP_DRAWING GETTIMEOFDAY(&end_tv); timeval_subtract(&result_tv,&end_tv,&start_tv); dt = result_tv.tv_sec * 1000 + result_tv.tv_usec/1000; BDBG_WRN(("Drawing screen %d took %d ms",p_app->screen_id,dt)); #endif /* send a setup done event to start any post drawing setup */ if (screen_event.type == eS_EVENT_SETUP) { screen_event.type = eS_EVENT_SETUP_DONE; screen_event.id = 0; if (p_app->p_screens[p_app->screen_id].handle_event(p_app,(void*)&(p_app->p_screens[p_app->screen_id]),&screen_event)) { p_app->last_screen_id = p_app->screen_id; screen_event.type = eS_EVENT_SETUP; screen_event.id = 0; p_app->p_screens[p_app->screen_id].handle_event(p_app,(void*)&(p_app->p_screens[p_app->screen_id]),&screen_event); #ifdef TIME_APP_DRAWING GETTIMEOFDAY(&start_tv); #endif //bapp_sync(p_app); p_app->p_screens[p_app->screen_id].draw(p_app,(void*)&(p_app->p_screens[p_app->screen_id])); bapp_flush_screen(p_app); #ifdef TIME_APP_DRAWING GETTIMEOFDAY(&end_tv); timeval_subtract(&result_tv,&end_tv,&start_tv); dt = result_tv.tv_sec * 1000 + result_tv.tv_usec/1000; BDBG_WRN(("Drawing took %d milliseconds\n",dt)); #endif } } } /* * Summary: * Clear screen selection history * Description: * Clear screen selection history * */ void bapp_clear_screen_selection_history(bapp_t *p_app) { int i; for (i = 0; i < p_app->num_screens; i++) { p_app->p_screens[i].button_selection = 0; } } /* Summary: sets the current screen for display Description: sets the current screen for display. if id == eSCREEN_MAX then simply backup a screen if save_last == eSCREEN_MAX, also saves last screen id. */ void bapp_set_current_screen(bapp_t *p_app, bapp_screen_id_t id, bapp_screen_id_t save_last) { bscreen_t *p_screen = &(p_app->p_screens[p_app->screen_id]); bscreen_t *p_screen_new = &(p_app->p_screens[id]); #ifdef BCM_DEBUG unsigned int cur_screen = p_app->screen_id; #endif BDBG_WRN(("Attempt to change screen from %d to %d\n",cur_screen, id)); if (id == p_app->screen_id) return; if (id == eSCREEN_MAX) { bapp_goto_last_screen(p_app); } else { if (save_last == eSCREEN_MAX) p_screen_new->last_screen_id = p_app->screen_id; else { p_screen_new->last_screen_id = save_last; p_screen->button_selection = 0; /* if we do not save the last screen, clear out focus history */ } if (id < eSCREEN_MAX) p_app->screen_id = id; #ifdef CONFIG_EIA_708 if (id > eSCREEN_NULL) { if (p_app->cc_enabled) bapp_enable_cc(p_app, false); } #endif } if (p_app->screen_id == eSCREEN_MAX) { p_app->screen_id = eSCREEN_BANNER; /* Default to channel change screen */ } BDBG_WRN(("Changing screen from %d to %d\n",cur_screen, p_app->screen_id)); } /* Summary: sets the current screen for display to be the last screen Description: sets the current screen for display to be the last screen */ void bapp_goto_last_screen(bapp_t *p_app) { bscreen_t *p_screen = &(p_app->p_screens[p_app->screen_id]); p_app->screen_id = p_screen->last_screen_id; if (p_app->screen_id == eSCREEN_MAX) { p_app->screen_id = eSCREEN_BANNER; /* Default to channel change screen */ } } #ifndef NO_VCHIP /* * Summary: * Handle content advisory blocking/unblocking. * Returns 1 if blocking/unblocking results in a screen change, 0 otherwise * */ int bapp_handle_blocking(bapp_t *p_app) { int screen_changed = 0; if (p_app->ratings_override) return screen_changed; BDBG_MSG(("last_psip_rating_block_status:%d last_rating_block_status:%d\n", p_app->last_psip_rating_block_status ,p_app->last_rating_block_status)); /* check both types of ratings - if either one says "block", we block */ if ((p_app->last_psip_rating_block_status == 1) || (p_app->last_rating_block_status == 1)) { /* show pin verification screen if not in menus */ if ((p_app->screen_id == eSCREEN_BANNER_SMALL) || (p_app->screen_id == eSCREEN_NULL)) { bapp_set_current_screen(p_app, eSCREEN_PIN_VERIFY_LIVE, eSCREEN_NULL); screen_changed = 1; } } else { /* no blocking, need to re-enable decode and possibly hide pin verification screen */ if ((p_app->screen_id == eSCREEN_PIN_VERIFY_LIVE) || (p_app->screen_id == eSCREEN_WRONG_PIN_LIVE)) { bapp_set_current_screen(p_app, eSCREEN_NULL, eSCREEN_NULL); screen_changed = 1; } } return screen_changed; } #endif /* TODO: */ void bapp_power(bapp_t *p_app, bool power) { bapp_standby(p_app, power); } /* Summary: Enter/exit standby */ static void bapp_standby(bapp_t *p_app, bool power) { AC_standby(); if (!power && p_app->check_poweron) { return; } if (power) { /* turning power on */ BDBG_ERR(("######## Turn ON ########\n")); #ifdef CONFIG_STANDBY bpwr_control(p_app, false); bos_sleep(100); p_app->chm.force_tune = true; bapp_tune(p_app); #endif bapp_av_mute(p_app, 0); buser_AOV_input_LED(p_app->p_rfm,eLED_Status_G); } else { BDBG_ERR(("######## Turn OFF ########\n")); #ifdef CONFIG_NXP_TDA182I4 #ifdef MERGE_20121115 NXP_TDA182I4_SetLoopThrough(true);/*janzy@20121108,add NXP_TDA182I4_SetLoopThrough*/ #endif NXP_TDA182I4_SetStandby(); #endif bapp_av_mute(p_app,1); buser_AOV_input_LED(p_app->p_rfm,eLED_Status_R); if (p_app->settings_dirty) bapp_save_settings(p_app); /* turning power off */ #ifdef CONFIG_STANDBY if (p_app->active_standby) { bpwr_control(p_app, true); } else { b_s3_standby(USERIO_ID); /* don't switch task, experimental till figure out the issue */ while (1); } #endif } p_app->power = power; } #ifdef OLD_INFO_KEY_PROCESSING /* * Summary: * Handle diag events. * */ static bool bapp_enter_diag(bapp_t *p_app,bIR_codes_t code) { bool result = false; switch (code) { case eIR_INFO: bapp_set_current_screen(p_app, eSCREEN_DIAG_MENU, eSCREEN_MAX); bapp_new_screen(p_app); result = true; break; default: break; } return result; } #endif /* Summary: key sequence add. */ #define seq_len 4 typedef enum { NONE=0, RF3, RF4, }key_id; typedef struct { key_id id; int num_key; bIR_codes_t keys[seq_len]; }keyseqmem; keyseqmem s_keyseq[] = { {RF3,3,{eIR_DOT,eIR_3,eIR_MUTE}}, {RF4,3,{eIR_DOT,eIR_4,eIR_MUTE}}, {NONE,} }; key_id p_check_key_sequence(bapp_t *p_app,buser_input_event *p_event) { int i; static bIR_codes_t keyseq[seq_len]; // 4°¡Áö Á¶ÇÕ°¡Áö »ý¼º. bool key_up = (p_event->code & 0x40000000) ? true : false; #ifdef OLD_INFO_KEY_PROCESSING b_timeval cur_tv; #endif //////// key_up ¿¡¼­ ½ÇÇà if(key_up){ // printf("\n----- keyseq[3]:%x [2]:%x [1]:%x [0]:%x -------\n",keyseq[3],keyseq[2],keyseq[1],keyseq[0]); #ifdef OLD_INFO_KEY_PROCESSING if ((p_app->last_key_down == eIR_MUTE)) { GETTIMEOFDAY(&cur_tv); if ((p_app->last_key_tv.tv_sec + 3) <= cur_tv.tv_sec) { memcpy(&keyseq[0],&keyseq[1],sizeof(keyseq)-sizeof(keyseq[0])); //shift to front keyseq[seq_len-1] = p_app->last_key_down; } } #endif if ((p_app->last_key_down != eIR_MUTE)){ // add (append) key history queue memcpy(&keyseq[0],&keyseq[1],sizeof(keyseq)-sizeof(keyseq[0])); //shift to front keyseq[seq_len-1] = p_app->last_key_down; } } /////////// for (i=0; s_keyseq[i].id!=NONE; i++) { if (memcmp(&keyseq[seq_len-s_keyseq[i].num_key],s_keyseq[i].keys,s_keyseq[i].num_key*sizeof(bIR_codes_t))==0){ memset(keyseq,0,sizeof(keyseq)); return s_keyseq[i].id; } } return 0; } /* Summary: RF3 ->0 RF4 ->1 */ void RF_process(bapp_t *p_app,int val) { p_app->audio_mute = false; bapp_audio_mute(p_app, p_app->audio_mute); p_app->settings.rfm=val; brfm_set_ch3(p_app->p_rfm, p_app->settings.rfm); } /* Summary: Handle user events. */ static void bapp_handle_user_event(bapp_t *p_app, buser_input_event *p_event ) { bscreen_event_t screen_event; bool key_up = (p_event->code & 0x40000000) ? true : false; bIR_codes_t code = (bIR_codes_t)(p_event->code & ~0x40000000); static int rfm; static int RF_change=0; #ifdef OLD_INFO_KEY_PROCESSING b_timeval cur_tv; #endif BDBG_WRN(("%s 0x%02x(%s)",__FUNCTION__,code,(key_up) ? "up" : "down")); switch (code) { #ifdef CONFIG_STANDBY case eIR_POWER: if (key_up && !p_app->check_poweron) { if (p_app->settings.auto_power_off) { p_app->chm_cmd.cmd_id = eCHM_INFO; chm_cmd(&p_app->chm, &p_app->chm_cmd); } p_app->active_standby = 0; bapp_standby(p_app, !p_app->power); } break; #else case eIR_POWER: if (key_up && !p_app->check_poweron) { if (p_app->settings.auto_power_off) { p_app->chm_cmd.cmd_id = eCHM_INFO; chm_cmd(&p_app->chm, &p_app->chm_cmd); } bapp_standby(p_app, !p_app->power); } break; #endif default: #ifdef CONFIG_STANDBY if (!p_app->power) break; #endif /* Test to see if we should enter the diagnostic state */ #ifdef OLD_INFO_KEY_PROCESSING if (key_up && (p_app->last_key_down == code) && !p_app->settings.av_mute) { GETTIMEOFDAY(&cur_tv); if ((p_app->last_key_tv.tv_sec + BAPP_DIAG_TIMEOUT) <= cur_tv.tv_sec) { if (bapp_enter_diag(p_app,code)) break; } } #endif //RF 3/4 sequence add switch(p_check_key_sequence(p_app,p_event)) { case RF3: RF_process(p_app,0); break; case RF4: RF_process(p_app,1); break; default: break; } if(p_app->last_key_down== eIR_RF3) RF_process(p_app,0); if(p_app->last_key_down== eIR_RF4) RF_process(p_app,1); if ((p_app->state != eAPP_STATE_NORMAL) && (p_app->screen_id == eSCREEN_BANNER)) break; screen_event.type = eS_EVENT_IR; screen_event.id = p_event->code; if (p_app->p_screens[p_app->screen_id].handle_event(p_app, (void*)&(p_app->p_screens[p_app->screen_id]),&screen_event)) { BDBG_MSG(("%s screen_id=%d",__FUNCTION__,p_app->screen_id)); /* Wait for vsync then do screen drawing */ bapp_new_screen(p_app); } else { bapp_handle_event(p_app,&screen_event); } break; } if (p_app->state != eAPP_STATE_FACTORY) { } if (!key_up) { //BDBG_WRN(("%s: !key_up \n",__FUNCTION__)); p_app->last_key_down = code; GETTIMEOFDAY(&p_app->last_key_tv); } #ifdef OLD_INFO_KEY_PROCESSING else { BDBG_WRN(("%s: key_up \n",__FUNCTION__)); p_app->last_key_down = (bIR_codes_t)0xFFF; /* key up */ } #endif } /* Summary: Handle rrt events.Need requirements to implement correct handling. */ static bapp_state_t bapp_handle_set_screen_event(bapp_t *p_app, chm_event_t *p_event) { bapp_set_current_screen(p_app, p_event->id, eSCREEN_MAX); bapp_new_screen(p_app); return eAPP_STATE_NORMAL; } /* Summary: Handle channel manager events. */ static bapp_state_t bapp_handle_chm_event(bapp_t *p_app) { bscreen_event_t screen_event; chm_event_t *p_event; b_timeval start_tv; static int scan_ch_cnt = 0; bapp_state_t new_state = p_app->state; /* Check for notification events */ if ((p_event = (chm_event_t*)bos_pend_event(p_app->msg_queue,0)) != NULL) { screen_event.type = eS_EVENT_MAX; screen_event.id = p_event->id; switch (p_event->type) { case eCHM_EVT_SET_SCREEN: /* set current screen event */ new_state = bapp_handle_set_screen_event(p_app,p_event); break; case eCHM_EVT_CANCEL: screen_event.type = eS_EVENT_CANCEL; break; case eCHM_EVT_DONE: screen_event.type = eS_EVENT_DONE; break; case eCHM_EVT_REDRAW: screen_event.type = eS_EVENT_REDRAW; break; case eCHM_EVT_SIGNAL: { chm_signal_event_t *p_sig = (chm_signal_event_t*)p_event; p_app->lock = (p_sig->lock) ? true : false; p_app->power_level = p_sig->power; p_app->tuned_freq = p_sig->freq_hz; p_app->snr = p_sig->SNR; p_app->signal_quality = p_sig->signal_quality; if (p_app->screen_id == eSCREEN_ANTENNA) { screen_event.type = eS_EVENT_PROGRESS; screen_event.id = p_app->power_level; } } break; #ifndef NO_VCHIP case eCHM_EVT_CAD: { unsigned char blocked; unsigned char region,dim,val; b_timeval tv; uint32_t current_ticks = bos_getticks(); /* ignore rating if ratings was received while tuned to a different channel. */ if (current_ticks < (s_p_app->last_tune_tick + MS_TO_TICKS(BAPP_RATINGS_EVAL_DELAY))) break; GETTIMEOFDAY(&tv); //BDBG_WRN(("PSIP Ratings @ %d\n",tv.tv_sec)); s_p_app->last_cad = tv.tv_sec; blocked = (uint8_t)(screen_event.id >> 24) & 0xFF; region = (uint8_t)(screen_event.id >> 16) & 0xFF; dim = (uint8_t)(screen_event.id >> 8) & 0xFF; val = (uint8_t)(screen_event.id & 0xFF); if ((s_p_app->ratings_region != region) || (s_p_app->ratings_dim != dim) || (s_p_app->ratings_val != val)) { s_p_app->ratings_region = region; s_p_app->ratings_dim = dim; s_p_app->ratings_val = val; } p_app->last_psip_rating_block_status = blocked; if (bapp_handle_blocking(p_app)) screen_event.type = eS_EVENT_SETUP; else /* Update OSD */ screen_event.type = eS_EVENT_REDRAW; } break; case eCHM_EVT_BLOCK: /* ignore rating if ratings was received while tuned to a different channel. */ if (bos_getticks() < (s_p_app->last_tune_tick + MS_TO_TICKS(BAPP_RATINGS_EVAL_DELAY))) break; /* p_app->last_rating_block_status = screen_event.id; - not necessary because already updated by bapp_xds_callback() */ if (bapp_handle_blocking(p_app)) { screen_event.type = eS_EVENT_SETUP; } break; case eCHM_EVT_RRT: { unsigned char rating_region; unsigned char version_number; uint32_t current_ticks = bos_getticks(); if (p_app->settings.ratings.ratings_lock < 2) break; /* ignore rating if ratings was received while tuned to a different channel. */ if (current_ticks < (s_p_app->last_tune_tick + MS_TO_TICKS(BAPP_RATINGS_EVAL_DELAY))) break; rating_region = (uint8_t)(screen_event.id >> 8) & 0xFF; version_number = (uint8_t)(screen_event.id & 0x1F); if (rating_region == 1) break; /* this will be dealt with in the default screen idle loop since we only want to alter rrt settings when the user is not in the menu system. */ if (screen_event.id != p_app->settings.rrt_settings.last_rrt_id) { BDBG_WRN(("### NEW RRT(0x%02x,0x%02x) ###\n",rating_region,version_number)); p_app->settings.rrt_settings.last_rrt_id = screen_event.id; p_app->settings.rrt_settings.rrt_status = eRRT_AVAILABLE; switch (p_app->screen_id) { case eSCREEN_RATINGS: case eSCREEN_RATINGS_LOCK: case eSCREEN_RATINGS_LIMITS: case eSCREEN_RATINGS_TV: case eSCREEN_RATINGS_MOVIES: case eSCREEN_RATINGS_RRT_DIM: case eSCREEN_RATINGS_RRT_VAL: case eSCREEN_RATINGS_RRT_UPDATE: bapp_set_current_screen(p_app, eSCREEN_RATINGS_RRT_UPDATE, eSCREEN_NULL); bapp_new_screen(p_app); break; default: bapp_set_current_screen(p_app, eSCREEN_RATINGS_RRT_UPDATE, eSCREEN_MAX); bapp_new_screen(p_app); break; } } } break; #endif case eCHM_EVT_EAS: BDBG_MSG(("%s:%d EAS TIMER STARTED",__FUNCTION__,__LINE__)); if ((p_app->state == eAPP_STATE_NORMAL) && (p_app->screen_id == eSCREEN_BANNER || p_app->screen_id == eSCREEN_WIZ_CH_SCAN || p_app->screen_id == eSCREEN_BANNER_SMALL || p_app->screen_id == eSCREEN_GUIDE)) { GETTIMEOFDAY(&start_tv); p_app->eas_timeout = start_tv.tv_sec + p_event->ticks; /* for default: eas_one_iterlation completed as soon as eas display starts */ //p_app->eas_one_iteration = true; #ifdef CONFIG_EIA_708 bapp_enable_cc(p_app, false); #endif /* with this flag, we don't null eas sequence number */ if ((bscreen_eas_text_scrolling_info(p_app, p_app->eas_buf, p_app->eas_buf_size)==BERR_SUCCESS) && p_app->eas_text) { p_app->eas_started = true; if (p_event->data[0]) { /* channel found */ p_app->cur_ch_num = p_event->id && 0xFFFF; bapp_tune(p_app); } p_app->eas_ch_found = p_event->data[0]; } } break; case eCHM_EVT_STATUS: switch (p_event->id) { #if 0 case eCHM_STATUS_HUNT: /* HUNT MODE */ BDBG_WRN(("eCHM_STATUS_HUNT %d", p_app->scan_in_progress)); if (!p_app->scan_in_progress) { bapp_eval_state(p_app,eAPP_STATE_HUNT); scan_ch_cnt = 0; BDBG_WRN(("eCHM_STATUS_HUNT\n")); } break; #endif case eCHM_STATUS_CHMAP: BDBG_WRN(("eCHM_STATUS_CHMAP flags = 0x%08x\n",p_event->ticks)); if (p_app->settings.num_channels > 0 && (2 == p_event->ticks)) { /* channels have been added during channel scan, so no need to copy */ if (p_app->cur_ch_num > 0) { if (p_app->cur_ch_num >= p_app->settings.num_channels) { p_app->cur_ch_num = 0; p_app->prev_ch = p_app->cur_ch = p_app->settings.ch[p_app->cur_ch_num]; } } else { /* new channel scan, set to 0 first */ p_app->cur_ch_num = 0; p_app->prev_ch = p_app->cur_ch = p_app->settings.ch[p_app->cur_ch_num]; } p_app->settings_dirty |= DIRTY_CHANNEL_MAP; } else { BDBG_WRN(("Channel map NOT changed\n")); } if (p_app->settings.psi_scan && (2 == p_event->ticks)) { p_app->settings_dirty |= DIRTY_CHANNEL; bapp_save_settings(p_app); bapp_load_settings(p_app); } if ((p_app->state == eAPP_STATE_NORMAL) && p_event->ticks) { /* if just scanned and have channnels, force to tune first channel */ if (p_app->settings.num_channels && (eSCREEN_GUIDE != p_app->screen_id && (eSCREEN_CH_SCAN != p_app->screen_id) && (eSCREEN_DIAG_MENU != p_app->screen_id))) { p_app->chm.last_freq_hz = true; p_app->chm.force_tune = true; bapp_audio_do_mute(p_app, false); bapp_audio_mute(p_app, false); bapp_tune(p_app); new_state = eAPP_STATE_NORMAL; } } else { #ifdef ACB612 if(!p_app->factory_test) new_state = eAPP_STATE_NORMAL; #else new_state = eAPP_STATE_NORMAL; #endif } break; case eCHM_STATUS_PAT: p_app->has_PAT = true; if (p_app->screen_id == eSCREEN_CH_SCAN_PROGRESS) { if (p_event->ticks != 0) { screen_event.type = eS_EVENT_PROGRESS; screen_event.id = p_event->ticks; scan_ch_cnt = p_app->settings.num_channels; screen_event.data = &scan_ch_cnt; } } break; case eCHM_STATUS_NOPAT: p_app->has_PAT = false; if (p_app->screen_id == eSCREEN_CH_SCAN_PROGRESS) { if (p_event->ticks != 0) { screen_event.type = eS_EVENT_PROGRESS; screen_event.id = p_event->ticks; scan_ch_cnt = p_app->settings.num_channels; screen_event.data = &scan_ch_cnt; } } break; case eCHM_STATUS_TUNE_MS: p_app->tune_ms = p_event->ticks; break; case eCHM_STATUS_SI_MS: p_app->si_ms = p_event->ticks; break; } break; case eCHM_EVT_AV_MUTE: bapp_standby(p_app,!p_event->id); break; case eCHM_EVT_TIME: { chm_time_event_t *p_time_evt = (chm_time_event_t*)p_event; p_app->system_time = p_time_evt->system_time; p_app->system_offset = p_time_evt->system_offset; //p_app->settings.utc_offset = (int)p_time_evt->utc_offset; p_app->have_time = true; } break; case eCHM_EVT_RESET: switch (p_event->id) { default: case 0: /* nop */ break; case 1: /* reset */ bapp_do_poweroff(p_app); break; case 2: /* reset some */ bapp_reset_settings(p_app); /* save everything */ p_app->settings_dirty = DIRTY_ALL; bapp_save_settings(p_app); bapp_do_poweroff(p_app); break; case 3: /* reset full */ bapp_reset_settings(p_app); /* save everything */ p_app->settings_dirty = DIRTY_ALL; bapp_save_settings(p_app); /* Erase downloaded firmware here */ bapp_do_poweroff(p_app); break; } break; case eCHM_EVT_SAVE: /* Must be careful of when this is done if running from flash */ if ((p_app->settings.audio_vol != p_app->audio_vol) || p_app->settings_dirty) { p_app->settings.audio_vol = p_app->audio_vol; bapp_save_settings(p_app); } break; case eCHM_EVT_PROGRESS: if (p_app->screen_id == eSCREEN_CH_SCAN_PROGRESS) { scan_ch_cnt = p_app->settings.num_channels; screen_event.type = eS_EVENT_PROGRESS; screen_event.id = p_event->ticks; screen_event.data = &scan_ch_cnt; } else { screen_event.id = p_event->id; screen_event.type = eS_EVENT_PROGRESS; } break; default: BDBG_WRN(("%s:%d CHM EVENT = %d NOT HANDLED\n",__FUNCTION__,__LINE__,p_event->type)); break; } //BDBG_MSG(("%s %s, id=0x%04x\n",__FUNCTION__,s_chm_evt_str[p_event->type], p_event->id)); if (p_app->p_screens[p_app->screen_id].handle_event(p_app, (void*)&(p_app->p_screens[p_app->screen_id]),&screen_event)) { //BDBG_MSG(("%s:%d screen_id %d\n",__FUNCTION__,__LINE__,p_app->screen_id)); /* Wait for vsync then do screen drawing */ bapp_new_screen(p_app); } else { /* EIT update for Banner (SMALL or BIG) and GUIDE screen */ if ((eS_EVENT_REDRAW == screen_event.type) && (1 == p_event->ticks)) { bool redraw = false; if (eSCREEN_GUIDE == p_app->screen_id) redraw = true; else if (eSCREEN_BANNER == p_app->screen_id || eSCREEN_BANNER_SMALL == p_app->screen_id) { banner_state_t *p_bs = (banner_state_t*)p_app->p_screens[p_app->screen_id].local_state; redraw = (eLS_BANNER_SMALL == p_bs->mode || eLS_BANNER_BIG == p_bs->mode); } if (redraw) { p_app->p_screens[p_app->screen_id].draw(p_app,(void*)&(p_app->p_screens[p_app->screen_id])); bapp_flush_screen(p_app); } } bapp_handle_event(p_app,&screen_event); } } return new_state; } /* Summary: Main event loop when in normal operation mode. */ static bapp_state_t bapp_run_main(bapp_t *p_app) { buser_input_event event; unsigned event_cnt; static bscreen_event_t screen_event; /* Check for UI event */ if (buser_input_get_event(p_app->user_io,&event,1,&event_cnt) == b_ok) { if (event_cnt > 0) { p_app->last_keypress_tick = bos_getticks(); /* now use power_saver_tick for tracking power saver timer so that it wouldn't be reset if signal contion changes */ p_app->power_saver_tick = bos_getticks(); bapp_handle_user_event(p_app,&event); } } /* Yield control */ bos_sleep(p_app->yield_ms); if (!p_app->power) return p_app->state; screen_event.type = eS_EVENT_IDLE; screen_event.id = 0; /* Give screen idle time to handle menu timeouts, etc */ if (p_app->p_screens[p_app->screen_id].handle_event(p_app, (void*)&(p_app->p_screens[p_app->screen_id]),&screen_event)) { /* Wait for vsync then do screen drawing */ bapp_new_screen(p_app); } /* Do application idle time processing */ bapp_idle(p_app); return p_app->state; } void bapp_channel_scan(bapp_t *p_app) { p_app->chm.cmd = eCHM_CANCEL; p_app->chm_cmd.cmd_id = eCHM_CANCEL; chm_cmd(&p_app->chm,&p_app->chm_cmd); p_app->settings.num_channels = 0; p_app->cur_ch_num = 0; p_app->scan_in_progress = false; bapp_channel_hunt(p_app); //bos_sleep(50); bapp_eval_state(p_app,eAPP_STATE_HUNT); } /* Summary: Perform a channel hunt (for cable), channel scan for NTIA box */ static int bapp_channel_hunt(bapp_t *p_app) { p_app->hunt_cmd.cmd_id = eCHM_HUNT; chm_cmd(&p_app->chm,&p_app->hunt_cmd); return 0; } /* Summary: Main app loop. Description: Main application event loop. */ #ifdef BCM_DEBUG static const char *s_app_state_name[] = { "DEFAULT","HUNT","NORMAL","FACTORY","DONE"}; #endif static void bapp_eval_state(bapp_t *p_app,bapp_state_t new_state) { bapp_led_set_mode(p_app); led_update(APP_DEFAULT_YIELD); if (p_app->state == new_state) return; BDBG_WRN(("from %s to %s\n",s_app_state_name[p_app->state], s_app_state_name[new_state] )); /* Handle exiting current state */ switch (p_app->state) { case eAPP_STATE_NORMAL: p_app->last_screen_id = eSCREEN_MAX; break; case eAPP_STATE_HUNT: bapp_screen_redraw(p_app); bos_sleep(250); /* must display full progress bar for at least 250ms before proceding */ case eAPP_STATE_FACTORY: case eAPP_STATE_DEFAULT: case eAPP_STATE_DONE: break; } /* Handle entering new state */ switch (new_state) { case eAPP_STATE_HUNT: if ((p_app->screen_id != eSCREEN_CH_SCAN_PROGRESS) && (eSCREEN_FREQUENCY_CONFIGURE != p_app->screen_id)) { if (p_app->power) bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX); else bapp_set_current_screen(p_app, eSCREEN_POWER_OFF, eSCREEN_MAX); bapp_new_screen(p_app); } #if 0 if (!p_app->scan_in_progress) { bapp_channel_hunt(p_app); bos_sleep(250); /* must display full progress bar for at least 250ms before proceding */ } #endif break; case eAPP_STATE_NORMAL: if ((p_app->screen_id != eSCREEN_CH_SCAN_PROGRESS) && (p_app->screen_id != eSCREEN_GUIDE) && (p_app->settings.num_channels > 0)) { if (p_app->power) { /* in wizard mode, don't change the screen through eval_state*/ if (p_app->settings.wiz_completed) bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX); } else bapp_set_current_screen(p_app, eSCREEN_POWER_OFF, eSCREEN_MAX); } bapp_new_screen(p_app); if (p_app->settings.num_channels && ((eSCREEN_GUIDE != p_app->screen_id) && (eSCREEN_DIAG_MENU != p_app->screen_id))) { p_app->chm.last_freq_hz = true; p_app->chm.force_tune = true; bapp_audio_do_mute(p_app, false); bapp_audio_mute(p_app, false); bapp_tune(p_app); } break; case eAPP_STATE_FACTORY: bapp_set_current_screen(p_app, eSCREEN_STATUS, eSCREEN_MAX); bapp_new_screen(p_app); break; case eAPP_STATE_DEFAULT: case eAPP_STATE_DONE: break; } /* Make new state the current state */ p_app->state = new_state; } /* Summary: Main app loop. Description: Main application event loop. */ void bapp_run(bapp_t *p_app) { bapp_state_t new_state; BDBG_WRN(("%s:%d - Start running.\n",__FUNCTION__,__LINE__)); while (p_app->state != eAPP_STATE_DONE) { new_state = p_app->state; switch (p_app->state) { case eAPP_STATE_HUNT: case eAPP_STATE_NORMAL: case eAPP_STATE_FACTORY: new_state = bapp_run_main(p_app); break; case eAPP_STATE_DEFAULT: case eAPP_STATE_DONE: /* Yield control */ bos_sleep(p_app->yield_ms); break; default: break; } /* Check for chm event */ if (new_state == p_app->state) new_state = bapp_handle_chm_event(p_app); bapp_eval_state(p_app,new_state); } /* finish */ bsettop_uninit(); } #if 0 /* Summary: Return current application channel map. */ ch_map_t *bapp_cur_ch_map(bapp_t *p_app) { return &(p_app->settings.ch_map); } #endif /* Summary: Channel Up or Down for previous or next favorite channel if any Description: To go to previous/next faviorite channel if any. If no favorite channel set, then stay current channel */ int bapp_change_channel_fav(bapp_t *p_app, int ch_up, int tune) { int retval = -1, i, j, cur; BDBG_WRN(("%s (up=%d,tune=%d)\n",__func__,ch_up,tune)); if (p_app->settings.num_channels < 2) return retval; j = cur = p_app->cur_ch_num; NEXT_FAV_CHANNEL: if (ch_up) { i = (j + 1) % p_app->settings.num_channels; } else { i = (j - 1); if (i < 0) i = (p_app->settings.num_channels - 1); } if (p_app->settings.ch[i].skip) { if (i != cur) { if (ch_up) j = (j + 1) % p_app->settings.num_channels; else { j--; if (j < 0) j = (p_app->settings.num_channels - 1); } goto NEXT_FAV_CHANNEL; } else { /* what do we need to do */ } } if (!p_app->settings.ch[i].favorite) { if (i != cur) { if (ch_up) j = (j + 1) % p_app->settings.num_channels; else { j--; if (j < 0) j = (p_app->settings.num_channels - 1); } goto NEXT_FAV_CHANNEL; } } p_app->cur_ch_num = i; if (tune) { /* make sure current one is not skip */ if (!p_app->settings.ch[i].skip) { retval = bapp_tune(p_app); if (i != cur) { p_app->settings_dirty |= DIRTY_CHANNEL; } } } else { if (p_app->settings.ch[i].skip) BDBG_WRN(("Not tune: chm->state=%d, mgt_state=%d, SKIP", p_app->chm.state, p_app->chm.mgt_state)); else BDBG_WRN(("Not tune: chm->state=%d, mgt_state=%d", p_app->chm.state, p_app->chm.mgt_state)); retval = 0; } return retval; } /* Summary: Channel Up or Down Description: To go to next channel if any */ int bapp_change_channel(bapp_t *p_app, int ch_up, int tune) { int retval = -1, i, j, cur; BDBG_WRN(("%s (up=%d,tune=%d)\n",__func__,ch_up,tune)); if (p_app->settings.num_channels < 2) return retval; j = cur = p_app->cur_ch_num; NEXT_VALID_CHANNEL: if (ch_up) { i = (j + 1) % p_app->settings.num_channels; } else { i = (j - 1); if (i < 0) i = (p_app->settings.num_channels - 1); } if (p_app->settings.ch[i].skip) { if (i != cur) { if (ch_up) j = (j + 1) % p_app->settings.num_channels; else { j--; if (j < 0) j = (p_app->settings.num_channels - 1); } goto NEXT_VALID_CHANNEL; } else { /* what do we need to do */ } } p_app->cur_ch_num = i; if (tune) { /* make sure current one is not skip */ if (!p_app->settings.ch[i].skip) { retval = bapp_tune(p_app); if (i != cur) { p_app->settings_dirty |= DIRTY_CHANNEL; } } } else { if (p_app->settings.ch[i].skip) BDBG_WRN(("Not tune: chm->state=%d, mgt_state=%d, SKIP", p_app->chm.state, p_app->chm.mgt_state)); else BDBG_WRN(("Not tune: chm->state=%d, mgt_state=%d", p_app->chm.state, p_app->chm.mgt_state)); retval = 0; } return retval; } /* Summary: Tune to the specified channel given by major and minor Description: Tune to the specified channel or nearest to the channel. Returns non-zero on failure. */ int bapp_set_channel_by_major(bapp_t *p_app, int major, int minor) { int retval = -1; int i, first_minor = -1; bapp_ch_t *pch = NULL; BDBG_WRN(("%s %d%.%d\n",__func__, major, minor)); if (p_app->settings.num_channels < 1) return 0; for (i = 0; i < p_app->settings.num_channels; i++) { pch = &p_app->settings.ch[i]; if (pch->major == major) { /* find major, and now look for minor match, if not, take first one */ if (pch->minor == minor) { break; } if (-1 == first_minor) first_minor = i; } } if (i >= p_app->settings.num_channels) { /* no match found */ if (-1 == first_minor) return retval; i = first_minor; } if (pch->hidden) { BDBG_WRN(("%s Hidden channel %d.%d\n",__FUNCTION__,major, minor)); return 0; } p_app->cur_ch_num = i; p_app->settings_dirty |= DIRTY_CHANNEL; retval = bapp_tune(p_app); return retval; } /* Summary: Tune to the specified channel. Description: Tune to the specified channel or nearest to the channel. Returns non-zero on failure. */ int bapp_set_channel(bapp_t *p_app, bapp_ch_t *pch) { int retval = -1; int i; BDBG_MSG(("%s %d.%d\n",__func__, pch->major, pch->minor)); if (pch->hidden) { BDBG_WRN(("%s Hidden channel %d.%d\n",__FUNCTION__,pch->major, pch->minor)); return 0; } /* currently do nothing, will let user to define the behaviour, later */ if (pch->skip) { BDBG_WRN(("%s Skip channel %d.%d\n",__FUNCTION__,pch->major, pch->minor)); return 0; } /* don't check major/minor but just set whatever channel user selection, in case there are duplicate major/minor and the user select it from with EPG screen */ p_app->settings_dirty |= DIRTY_CHANNEL; retval = bapp_tune(p_app); return retval; } /* Summary: Tune to the current channel. */ int bapp_tune(bapp_t *p_app) { bapp_ch_t tmp_prev_ch; BDBG_MSG(("%s",__func__)); if (p_app->settings.av_mute) return 0; #ifndef NO_VCHIP if (p_app->ratings_override_set) { p_app->ratings_override_set = false; } p_app->ratings_override = false; /* reset so ratings will be re-evaluated when returned to full tv */ p_app->last_rating_block_status = -1; /* assume psip unblock */ p_app->last_psip_rating_block_status = 0; /* clear ratings string */ p_app->prog_rating_str[0] = 0; p_app->psip_rating_str[0] = 0; #endif /* remember previous channel so that we can go back, e.g. EAS turned */ tmp_prev_ch = p_app->prev_ch; p_app->prev_ch = p_app->cur_ch; /* set current channel */ p_app->cur_ch = p_app->settings.ch[p_app->cur_ch_num]; if (p_app->decoding) { /* TODO */ } /* if they are same, use previous saved one */ if ((p_app->prev_ch.major == p_app->cur_ch.major) && (p_app->prev_ch.minor == p_app->cur_ch.minor)) p_app->prev_ch = tmp_prev_ch; p_app->lock = false; /* need to update as it will be late in updating in the chm_tune time in Banner UI */ p_app->num_sap = p_app->cur_ch.num_audio; p_app->current_sap = p_app->cur_ch.cur_audio; /* don't reset power level as in general, there should be some power, so it is better than show 0 */ //p_app->power_level = 0; p_app->signal_quality = 0; p_app->tune_cmd.cmd_id = eCHM_TUNE; p_app->tune_cmd.type = eCHM_CURRENT; chm_cmd(&p_app->chm,(chm_cmd_event_t*)&p_app->tune_cmd); p_app->decoding = true; p_app->last_tune_tick = bos_getticks(); /* reset audio channel timeout in case it is audio only channel */ GETTIMEOFDAY(&p_app->audio_channel_tm); return 0; } /* Summary: Tune to the current channel. */ int bapp_tune_prev(bapp_t *p_app) { return bapp_set_channel(p_app, &p_app->prev_ch); } /* Summary: Restart audio decode (after SAP swap audio PID) */ int bapp_rotate_audio_sap(bapp_t *p_app) { bapp_ch_t *pch; int i; pch = &p_app->settings.ch[p_app->cur_ch_num]; for (i = 0; (i < MAX_AUDIO_PIDS - 1); i++) { pch->cur_audio++; pch->cur_audio %= MAX_AUDIO_PIDS; if (pch->audio_pid[pch->cur_audio]) break; } p_app->current_sap = pch->cur_audio; /* the SAP audio rotate function is moved to chan_mgr.c */ p_app->chm_cmd.cmd_id = eCHM_SAP; chm_cmd(&p_app->chm,&p_app->chm_cmd); return 0; } /* Summary: set CLUT */ void bapp_set_palette(bapp_t *p_app, bapp_palette_t palette) { #ifndef CONFIG_GFX_ARGB32 unsigned int *clut; /* [out] address of palette */ int width; /* [out] width of the OSD surface */ int height; /* [out] height of the OSD surface */ int pitch; /* [out] pitch of the OSD surface */ unsigned int *p_palette; unsigned int size; bgraphics_get_framebuffer(p_app->graphics,(void**)&p_app->osd_mem,(unsigned int **)&clut,&width,&height,&pitch); switch (palette) { case ePALETTE_SCREENSAVER: if (p_app->logo) { bcm_raw_8_t *p_header = (bcm_raw_8_t *)p_app->logo; uint8_t *p_clut = (uint8_t *)p_header; p_clut += sizeof(bcm_raw_8_t); memcpy(clut, p_clut, p_header->clut_size*sizeof(unsigned int)); } else if (bapp_palette_get(ePALETTE_LOGO, &p_palette, &size) == b_ok) { BKNI_Memcpy(clut, p_palette, size*sizeof(p_palette[0])); } bgraphics_load_palette(p_app->graphics); break; case ePALETTE_DEFAULT: default: if (bapp_palette_get(palette,&p_palette,&size) == b_ok) { BKNI_Memcpy(clut,p_palette,size*sizeof(p_palette[0])); bgraphics_load_palette(p_app->graphics); } break; } #endif } /* Summary: returns true is sufficient signal strength, false otherwise always returns true for TUNE_DURATION msecs after tuning begins. */ bool bapp_get_signal_status(bapp_t *p_app) { static bool first_call = true; static bool good_signal = true; static uint32_t last_video_pts = 0; static uint32_t last_video_pts_ticks = 0; static uint32_t last_audio_pts = 0; bdecode_config cfg; static bdecode_status status; static baudio_decode_status audio_status; uint32_t current_ticks = bos_getticks(); /* If the decode is stopped dont report bad signal */ if (p_app->decoding == false) return true; /* check for tune duration timeout - this is used to restrict display of the 'no signal' popup for a period of time (TUNE_DURATION) after tuning */ if (current_ticks < (p_app->last_tune_tick + MS_TO_TICKS(TUNE_DURATION))) return true; if (p_app->settings.num_channels < 1) return false; /* if first time calling function get baseline video pts * then wait 500msecs and continue. since we require 2 samples * of decoder status at least 500msecs apart to determine signal * status, we need to "prime the pump" on the very first call only */ if (first_call) { first_call = false; bdecode_get_status(p_app->decode,&status); baudio_decode_get_status(p_app->audio, &audio_status); last_video_pts = status.video_pts; last_video_pts_ticks = current_ticks; bos_sleep(500); current_ticks = bos_getticks(); last_audio_pts = audio_status.pts; } /* make sure video pts is changing - indicates successful decoding. * only check every 500msecs or so */ if ((current_ticks - last_video_pts_ticks) > MS_TO_TICKS(500)) { bdecode_get_status(p_app->decode,&status); baudio_decode_get_status(p_app->audio, &audio_status); /* if pts is changing, we are decoding properly */ good_signal = (last_video_pts != status.video_pts); if (good_signal == false) { good_signal = (last_audio_pts != audio_status.pts); } last_audio_pts = audio_status.pts; //BDBG_MSG(("good_signal:%d vpts:0x%08x last_vpts:0x%08x ticks:%d", good_signal, status.video_pts, last_video_pts, current_ticks)); last_video_pts = status.video_pts; last_video_pts_ticks = current_ticks; } bdecode_get_config(p_app->decode,&cfg); if (!good_signal) { //if (cfg.channel_change != 0 || !cfg.mute) if (!cfg.mute) { bapp_audio_mute(p_app, 1); cfg.mute = 1; cfg.channel_change = 0; bdecode_set_config(p_app->decode,&cfg); } } else { //if (cfg.channel_change != 2) if (cfg.mute) { bapp_audio_mute(p_app, 0); cfg.mute = 0; cfg.channel_change = 0; /* black instead of last video */ bdecode_set_config(p_app->decode,&cfg); } } return good_signal; } /* Summary: Return the current screen. */ bscreen_t * bapp_get_current_screen(bapp_t *p_app) { return &p_app->p_screens[p_app->screen_id]; } void ram_start() { static bapp_t app; AC_check(); bapp_init(&app); bapp_run(&app); } /* Summary: Mute audio Description: Mute audio when enable is non-zero. */ void bapp_audio_do_mute(bapp_t *p_app, int mute) { baudio_decode_config config; if(p_app->factory_test) return; BDBG_WRN(("%s mute = %d, audo_vol = %d, is_muted = %d...\n",__FUNCTION__,mute,p_app->audio_vol,p_app->is_muted)); if (p_app->is_muted && !mute) { p_app->system_mute = (mute == 0)?false:true; return; } baudio_decode_get_config(p_app->audio, &config); if (mute != config.mute) { config.mute = mute; baudio_decode_set_config(p_app->audio, &config); } p_app->system_mute = (mute== 0) ? false : true; } /* * Callback to process first pts timing profiling */ static void bapp_first_pts_callback(void) { BDBG_WRN(("##### timing profile ####")); timing_profile_stop(s_p_app->ptp_first_pts); } /* * Callback to process first pts timing profiling */ static void bapp_seq_hdr_callback(void) { BDBG_WRN(("##### timing profile ####")); timing_profile_stop(s_p_app->ptp_decode); } bool bapp_get_block_status(bapp_t *p_app) { return false; } /* select primary output path to enable deinterlacer * mode : 1 for HD path, 2 for SD path */ void bapp_select_primary_output(bapp_t *p_app, int mode) { if (!p_app) p_app = s_p_app; bdisplay_set_deinterlacer(p_app->display,(mode==2)?1:0, true); } /* select SCL's coefficient index * val : 1- 26 (1: soft -> 26: sharp */ void bapp_select_scaler_coefficient(bapp_t *p_app, bool horizontal, int output, int coeff_idx) { if (!p_app) p_app = s_p_app; if (coeff_idx < 1 || coeff_idx > 26) { BDBG_WRN(("Invalid SCL coefficient index : %d", coeff_idx)); return; } bdisplay_set_coefficient_index(p_app->display, horizontal, output, coeff_idx); } #ifdef OOB_TUNER_SUPPORT /* * Set OOB flag so that the message filter will get message from OOB input instead */ void bapp_set_oob_flag(int oob) { } #endif void bapp_get_avl_settings(int *target, int *low, int *boost) { baudio_decode_config aconfig; bapp_t *p_app = (bapp_t *)s_p_app; baudio_decode_get_config(p_app->audio, &aconfig); *target = aconfig.avl_target/100; *low = aconfig.avl_lowerbound/100; *boost = aconfig.avl_fixedboost/100; } void bapp_set_avl_settings(int target, int low, int boost) { baudio_decode_config aconfig; bapp_t *p_app = (bapp_t *)s_p_app; baudio_decode_get_config(p_app->audio, &aconfig); aconfig.avl_fixedboost = boost*100; aconfig.avl_target = target*100; aconfig.avl_lowerbound = low*100; baudio_decode_set_config(p_app->audio, &aconfig); } /* * validation of current channel * * Return: * pointer to a structure with channel information * NULL if invalid */ bapp_ch_t *bapp_is_channel_valid(bapp_t *p_app) { if (p_app->settings.num_channels < 1 || p_app->cur_ch_num >= p_app->settings.num_channels) return NULL; return &p_app->settings.ch[p_app->cur_ch_num]; } /* * Summary: * Set closed captions CS options * Description: * Set closed captions CS options */ void bapp_set_captions_options(bapp_t *p_app) { BDBG_MSG(("%s current %d, new %d", __FUNCTION__,p_app->settings.dcc.captions_basic,p_app->captions_basic)); if (p_app->captions_basic != p_app->settings.dcc.captions_basic) { p_app->settings.dcc.captions_basic = p_app->captions_basic; p_app->settings_dirty |= DIRTY_DCC; /* set it */ bapp_set_wide_aspect_ratio(p_app); #ifdef ACB612 #ifdef CONFIG_EIA_708 bapp_eia708_set_cc_service(p_app->eia708, 1 , p_app->settings.dcc.captions_basic); #endif #endif } } /* * Summary: * Set AspectRatio option selected from IR AR button * Description: * Set AspectRatio option selected from IR AR button */ void bapp_set_ar_options(bapp_t *p_app) { BDBG_WRN(("%s current %d, new %d", __FUNCTION__,p_app->settings.sd_options,p_app->sd_options)); if (p_app->sd_options != p_app->settings.sd_options) { bdisplay_settings display_settings; bdisplay_get(p_app->display,&display_settings); display_settings.sd_options = p_app->sd_options; bdisplay_set(p_app->display,&display_settings); p_app->settings.sd_options = display_settings.sd_options; p_app->settings_dirty |= DIRTY_MISC; } } /* * enable or disable AVL * * Return: * None. */ void bapp_P_enable_avl(bapp_t *p_app, bool enable) { baudio_decode_config aconfig; baudio_decode_get_config(p_app->audio, &aconfig); if (aconfig.avl != enable) { aconfig.avl = enable; baudio_decode_set_config(p_app->audio, &aconfig); } } /* * enable or disable AVL * * Return: * None. */ void bapp_enable_avl(bool enable) { if (s_p_app) { bapp_P_enable_avl(s_p_app, enable); } } /* * get application instance pointer * * Return: * application instance pointer */ bapp_t *bapp_get_app_instance(void) { BDBG_ASSERT(s_p_app); return s_p_app; } /* * return current wide_aspect_ratio on current service if defined */ int bapp_get_wide_aspect_ratio_cb(void) { bapp_t *p_app = s_p_app; if (p_app) { return p_app->wide_aspect_ratio; } /* default not wide_aspect_ratio */ return 0; } /* * set current wide_aspct_ratio based on currnet channel's service number */ void bapp_set_wide_aspect_ratio(bapp_t *p_app) { bool wide_aspect_ratio; if (chm_has_valid_cc_service(&p_app->chm, &wide_aspect_ratio)) { p_app->wide_aspect_ratio = wide_aspect_ratio; } else p_app->wide_aspect_ratio = 0; } void aov_scan_psi_a_freq(uint32_t freq_khz) { if (s_p_app) { #ifdef TUNER_DEBUG if (chm_scan_psi_a_freq(&s_p_app->chm, freq_khz) > 0) { s_p_app->chm.force_tune = true; bapp_tune(s_p_app); s_p_app->settings_dirty |= DIRTY_MISC; } #endif } } #ifdef TUNER_DEBUG void bapp_scan_psi_a_freq(uint32_t freq_khz) { if (s_p_app) { if (chm_scan_psi_a_freq(&s_p_app->chm, freq_khz) > 0) { s_p_app->chm.force_tune = true; bapp_tune(s_p_app); s_p_app->settings_dirty |= DIRTY_MISC; } } } void bapp_get_tuner_status(void) { if (s_p_app) { p_app->tuner_status.cancal_callback = NULL; btuner_get_status(s_p_app->chm.tuner,&s_p_app->tuner_status); BDBG_WRN(("lock=%d", s_p_app->tuner_status.lock)); BDBG_WRN(("fecLock=%d", s_p_app->tuner_status.fecLock)); BDBG_WRN(("snr=%d", s_p_app->tuner_status.snr)); BDBG_WRN(("goodRsBlockCount=%d", s_p_app->tuner_status.goodRsBlockCount)); BDBG_WRN(("berRawCount=%d", s_p_app->tuner_status.berRawCount)); BDBG_WRN(("agcIntLevel=%d", s_p_app->tuner_status.agcIntLevel)); BDBG_WRN(("postRsBER=%d", s_p_app->tuner_status.postRsBER)); BDBG_WRN(("correctedCount=%d", s_p_app->tuner_status.correctedCount)); BDBG_WRN(("uncorrectedCount=%d", s_p_app->tuner_status.uncorrectedCount)); BDBG_WRN(("resyncCount=%d", s_p_app->tuner_status.resyncCount)); BDBG_WRN(("mode=%d", s_p_app->tuner_status.mode)); } } #endif /*janzy@20121108,add bapp_brfm_set_ch3*/ void bapp_brfm_set_ch3(bool ch) { brfm_set_ch3(s_p_app->p_rfm, ch); return; } /*janzy@20121108,add set Rf Output*/ void bapp_bdisplay_setRfOutput(bool isOutput) { bdisplay_output_rf_enable(s_p_app->display,isOutput); return; } /*janzy@20121109,add bapp_audio_1k_TONE*/ void bapp_audio_1k_TONE(void) { #ifdef MERGE_20121115 bscreen_audio_1k_TONE(); #endif return; } /*janzy@20121113,audio,video start/stop ctrl begin*/ void bapp_audio_stop(void) { if (s_p_app->audio) baudio_decode_stop(s_p_app->audio); return; } void bapp_video_stop(void) { if (s_p_app->decode) bdecode_stop(s_p_app->decode); return; } void bapp_AV_start(unsigned int vid,unsigned int aud,unsigned int pcr) { /*RLQ*/ #if 0 aov_dbg_print1(); #endif if (s_p_app->settings.av_mute) return; /* remember previous channel so that we can go back, e.g. EAS turned */ s_p_app->prev_ch = s_p_app->cur_ch; s_p_app->settings.ch[s_p_app->cur_ch_num].video_pid = vid; s_p_app->settings.ch[s_p_app->cur_ch_num].pcr_pid = pcr; s_p_app->settings.ch[s_p_app->cur_ch_num].audio_pid[0] = aud; printf("cur_ch_num = %d\n",s_p_app->cur_ch_num); printf("voide PID = %d\n",s_p_app->settings.ch[s_p_app->cur_ch_num].video_pid); printf("audio PID = %d\n",s_p_app->settings.ch[s_p_app->cur_ch_num].audio_pid[0]); printf("pcr PID = %d\n",s_p_app->settings.ch[s_p_app->cur_ch_num].pcr_pid); if (bos_acquire_mutex(&(s_p_app->flash_mutex), 250) != b_ok) { printf("%s:%d mutex timeout\n", __FUNCTION__, __LINE__); return; } bast_channel_map_save(s_p_app); bos_release_mutex(&(s_p_app->flash_mutex)); /* set current channel */ s_p_app->cur_ch = s_p_app->settings.ch[s_p_app->cur_ch_num]; if (s_p_app->decoding) { /* TODO */ } s_p_app->lock = false; s_p_app->power_level = 0; s_p_app->tune_cmd.cmd_id = eCHM_TUNE; s_p_app->tune_cmd.type = eCHM_CURRENT; chm_cmd(&s_p_app->chm,(chm_cmd_event_t*)&s_p_app->tune_cmd); s_p_app->decoding = true; s_p_app->last_tune_tick = bos_getticks(); return; } /*janzy@20121113,add ColorBars*/ void bapp_Set_ColorBars(bool enable) { uint16_t temp_w,tmp_h,tmp_y,tmp_X; double numb1,numb2,numb3; bapp_sync(s_p_app); if (enable) { bgfx_fill_rect(&s_p_app->surf,0 ,0 ,eWIDTH ,eHEIGHT,0XFF131313); /* x, y,w,h*/ temp_w = (uint16_t)(eWIDTH/7)+1; numb1 = 325.0; numb2 = 480.0; numb3 = (numb1/numb2)*eHEIGHT; tmp_h = (uint16_t)numb3; bgfx_fill_rect(&s_p_app->surf,temp_w*0 ,0 ,temp_w ,tmp_h,0xFFCCCCCC); bgfx_fill_rect(&s_p_app->surf,temp_w*1 ,0 ,temp_w ,tmp_h,0XFFFFFF00); bgfx_fill_rect(&s_p_app->surf,temp_w*2 ,0 ,temp_w ,tmp_h,0XFF00FFFF); bgfx_fill_rect(&s_p_app->surf,temp_w*3 ,0 ,temp_w ,tmp_h,0XFF00FF00); bgfx_fill_rect(&s_p_app->surf,temp_w*4 ,0 ,temp_w ,tmp_h,0XFFFF00FF); bgfx_fill_rect(&s_p_app->surf,temp_w*5 ,0 ,temp_w ,tmp_h,0XFFFF0000); bgfx_fill_rect(&s_p_app->surf,temp_w*6 ,0 ,temp_w ,tmp_h,0XFF0000FF); tmp_y = tmp_h; numb1 = 40.0; numb2 = 480.0; numb3 = (numb1/numb2)*eHEIGHT; tmp_h = (uint16_t)numb3; bgfx_fill_rect(&s_p_app->surf,temp_w*0 ,tmp_y ,temp_w ,tmp_h,0xFF0000FF); bgfx_fill_rect(&s_p_app->surf,temp_w*1 ,tmp_y ,temp_w ,tmp_h,0XFF131313); bgfx_fill_rect(&s_p_app->surf,temp_w*2 ,tmp_y ,temp_w ,tmp_h,0XFFFF00FF); bgfx_fill_rect(&s_p_app->surf,temp_w*3 ,tmp_y ,temp_w ,tmp_h,0XFF131313); bgfx_fill_rect(&s_p_app->surf,temp_w*4 ,tmp_y ,temp_w ,tmp_h,0XFF00FFFF); bgfx_fill_rect(&s_p_app->surf,temp_w*5 ,tmp_y ,temp_w ,tmp_h,0XFF131313); bgfx_fill_rect(&s_p_app->surf,temp_w*6 ,tmp_y ,temp_w ,tmp_h,0XFFCCCCCC); tmp_y = tmp_y+tmp_h; temp_w = (uint16_t)(eWIDTH/7)+1; numb1 = (double)temp_w; numb1 = (numb1*5)/4; temp_w = (uint16_t)numb1+1; bgfx_fill_rect(&s_p_app->surf,temp_w*0 ,tmp_y ,temp_w ,eHEIGHT,0xFF083E59); bgfx_fill_rect(&s_p_app->surf,temp_w*1 ,tmp_y ,temp_w ,eHEIGHT,0XFFFFFFFF); bgfx_fill_rect(&s_p_app->surf,temp_w*2 ,tmp_y ,temp_w ,eHEIGHT,0XFF3A0078); bgfx_fill_rect(&s_p_app->surf,temp_w*3 ,tmp_y ,temp_w ,eHEIGHT,0XFF131313); tmp_X = temp_w*4; temp_w = (uint16_t)(((eWIDTH/7)+1)/3); bgfx_fill_rect(&s_p_app->surf,tmp_X+temp_w*0 ,tmp_y ,temp_w ,eHEIGHT,0xFF000000); bgfx_fill_rect(&s_p_app->surf,tmp_X+temp_w*1 ,tmp_y ,temp_w ,eHEIGHT,0XFF131313); bgfx_fill_rect(&s_p_app->surf,tmp_X+temp_w*2 ,tmp_y ,temp_w ,eHEIGHT,0XFF262626); } else { bgfx_fill_rect(&s_p_app->surf,0 ,0,eWIDTH,eHEIGHT,0); } bapp_flush_screen(s_p_app); return; } void bapp_do_exit()/*janzy@20121115,OSD TimeOut*/ { aov_Set_Button_CHUpDown(3); return; } bool bapp_is_dolby_type(bapp_t *p_app) { bapp_ch_t *pch; pch = &p_app->settings.ch[p_app->cur_ch_num]; if ((BAVC_AudioCompressionStd_eAc3 == pch->audio_type[pch->cur_audio]) || (BAVC_AudioCompressionStd_eAc3Plus == pch->audio_type[pch->cur_audio])) { return true; } return false; } /*end*/