/*************************************************************************** * 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 BDBG_MODULE(bapp); /* Register software module with debug interface */ #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_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_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[]; extern unsigned int g_FrancophilB_40_aa_size; extern const unsigned char g_FrancophilB_40_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); /* * 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 }; /* * 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_hd_output_options_config_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_hd_output_options_config, bscreen_default_draw, screen_hd_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_NULL, 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}, #if 0 { eTEXT_CAPTIONS_ON_OFF_MENU, eTEXT_CAPTIONS_ON_OFF_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_on_off_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_on_off, bscreen_default_draw, screen_captions_on_off_event, 0}, { eTEXT_CAPTIONS_BASIC_MENU, eTEXT_CAPTIONS_BASIC_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_captions_basic_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, g_buttons_captions_basic, bscreen_default_draw, screen_captions_basic_event, 0}, { eTEXT_CAPTIONS_ADVANCED_MENU, eTEXT_CAPTIONS_ADVANCED_MENU_DESC, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_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}, #endif { 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_HELP10,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_HELP11,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, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_NULL, 0, bscreen_status_draw, bscreen_status_event, 0}, { eTEXT_MAX, 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, 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, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_dta_status_draw, bscreen_dta_status_event, 0}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_mso_info_draw, bscreen_mso_info_event, 0}, { eTEXT_MAX, 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, 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, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_ch_map_status_draw, bscreen_ch_map_status_event, 0}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_msg_status_draw, bscreen_msg_status_event, 0}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_code_objects_draw, bscreen_code_objects_event, 0}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_code_download_draw, bscreen_code_download_event, 0}, { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_decoder_status_draw, bscreen_decoder_status_event, 0}, // { eTEXT_MAX, eTEXT_MAX, eTEXT_MAX, 0, 0, 0, 0, SCREEN_DEFAULT_TIMEOUT, eSCREEN_MAX, 0, bscreen_status_draw, bscreen_status_event, 0}, { eTEXT_VIDEO_OUTPUT_FORMAT_BUTTON, eTEXT_VIDEO_OUTPUT_FORMAT, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_video_output_format_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_BANNER, g_buttons_video_output_format, bscreen_default_draw, bscreen_video_format_event, 0}, { eTEXT_VIDEO_OUTPUT_FORMAT_CONFIRM_BUTTON, eTEXT_VIDEO_OUTPUT_FORMAT_CONFIRM, eTEXT_MENU_HELP2, eMENU_TITLE_AREA_HEIGHT_1_LINE, 0, 0, g_buttons_video_output_format_confirm_num, SCREEN_DEFAULT_TIMEOUT, eSCREEN_BANNER, g_buttons_video_output_format_confirm, bscreen_default_draw, bscreen_confirm_change_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_SD_CONFIG_OPTIONS_BUTTON, 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_BANNER, g_buttons_sd_output_options_config, bscreen_default_draw, screen_sd_output_options_config_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 static const char *s_chm_evt_str[] = { "CHM_EVT_CANCEL", "CHM_EVT_DONE", "CHM_EVT_REDRAW", "CHM_EVT_PROGRESS", "CHM_EVT_SIGNAL", "CHM_EVT_DOWNLOAD", "CHM_EVT_EAS", "CHM_EVT_CA", "CHM_EVT_NETWORK", "CHM_EVT_STATUS", "CHM_EVT_AV_MUTE", "CHM_EVT_ACTIVATION", "CHM_EVT_CONFIGURATION", "CHM_EVT_VCT_ID", "CHM_EVT_LOCATION", "CHM_EVT_TIMEZONE", "CHM_EVT_PHONENUMBER", "CHM_EVT_RESET", "CHM_EVT_SAVE", "CHM_EVT_TIME", "CHM_EVT_PAIRING", "eCHM_EVT_RRT", "eCHM_EVT_CAD", "eCHM_EVT_BLOCK", "eCHM_EVT_AMM", "eCHM_EVT_SCC_AMM", "eCHM_EVT_CAP_SERVICE", "eCHM_EVT_SET_SCREEN", }; #endif /* Summary: Reset Site Error Count. This function will be used by other DIG section as well. */ void bapp_set_hd_configuration(bapp_t *p_app) { bdisplay_settings s; bdisplay_get(p_app->display,&s); if ((s.hd_options != p_app->settings.hd_config.hd_options) || (s.format != p_app->settings.hd_config.output_format)) { s.format = p_app->settings.hd_config.output_format; s.hd_options = p_app->settings.hd_config.hd_options; // note that we also set 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_PENDING: mode = led_pending_init_mode; break; case eAPP_STATE_NORMAL: mode = led_on_mode; break; case eAPP_STATE_DOWNLOAD: mode = led_download_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 } /* 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; } /* 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; } /* 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); } /* Summary: Reset the closed captioning settings 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 */ } /* 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)); ch_map_init(&(p_app->settings.ch_map),&(p_app->ch_map_mutex)); p_app->settings.network_PID = CONFIG_NETWORK_PID; p_app->settings.VCT_ID = CONFIG_DEF_VCT_ID; p_app->settings.EMM_PID = CONFIG_DEF_EMM_PID; /* this will make sure volume is reset to default from UI */ p_app->settings.audio_vol = BAPP_MAX_VOLUME; p_app->audio_vol = BAPP_MAX_VOLUME; p_app->settings.pin = DEFAULT_PIN; p_app->settings.activated = 1; p_app->settings.psi_scan = 1; p_app->settings.wiz_completed = 1; bapp_reset_hd_config_settings(p_app); p_app->settings.sd_options = bdisplay_sd_output_options_full; } /* Summary: Load current settings from NVM */ static void bapp_load_settings(bapp_t *p_app) { int result = 0; ch_map_init(&(p_app->settings.ch_map), &(p_app->ch_map_mutex)); ch_map_reset(&(p_app->settings.ch_map)); p_app->settings_dirty = 0; if (bos_acquire_mutex(p_app->settings.ch_map.p_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) { result = bast_misc_read(p_app); if (0 == result) { result = bast_channel_map_read(p_app); if (0 == result) { result = bast_phone_number_read(p_app); if (0 == result) { result = bast_screen_read(p_app); if (0 == result) { result = bast_eas_read(p_app); } } } } } bos_release_mutex(&(s_p_app->flash_mutex)); } else { BDBG_WRN(("%s:%d mutex timeout", __FUNCTION__, __LINE__)); } bos_release_mutex(p_app->settings.ch_map.p_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_PHONE | 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); 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.sd_options = s.sd_options; p_app->settings_dirty &= ~DIRTY_HD_CONFIG; 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_PHONE)) { bast_phone_number_save(p_app); p_app->settings_dirty &= ~DIRTY_PHONE; } 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->settings.ch_map.p_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->settings.ch_map.p_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) { /* JPF TODO Power OFF */ } /* 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; BDBG_MSG(("%s:%d\n",__FUNCTION__,__LINE__)); 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); GETTIMEOFDAY(&p_app->timeout_tv); p_app->user_io = buser_input_open(B_ID(USERIO_ID)); bast_init(p_app); bgraphics_get(&graphics_settings); graphics_settings.format = bgraphics_pixel_format_palette4; bgraphics_set(&graphics_settings); 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); 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; rc = bsettop_hdmi_open(&(p_app->hdmi),p_app->display,p_app->audio, NULL /* no hdcp authentication callback needed*/); BDBG_ASSERT(rc == b_ok); #if (BCHP_VER>=BCHP_VER_B0) p_app->p_rfm = brfm_open(0); #endif 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)); p_app->logo = (unsigned char *)s_logo; p_app->logo_size = s_logo_size; 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); 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); 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_22_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_28_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_40_aa; p_app->br.size = g_FrancophilB_40_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 HD configuration if not match default */ bapp_set_hd_configuration(p_app); if (p_app->settings.activated) { if (((int)p_app->settings.timeout_cnt) >= 2) { p_app->settings.timeout_cnt -= 2; } else { p_app->settings.activated = false; p_app->settings_dirty |= DIRTY_MISC; } } #ifdef CONFIG_DTA_CABLE_TESTING { b_mutex_t *p_mutex = p_app->settings.ch_map.p_mutex; extern const ch_map_t s_ch_map; memcpy(&p_app->settings.ch_map,&s_ch_map, sizeof(s_ch_map)); p_app->settings.ch_map.p_mutex = p_mutex; p_app->settings.activated = true; } #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; bdecode_set_config(p_app->decode, &cfg); #endif #ifdef CONFIG_DVB_SUBTITLE p_app->dsub = bapp_dsub_open(p_app); BAPP_ASSERT(p_app->dsub); #endif bapp_av_mute(p_app,0); bapp_flush_screen(p_app); if (p_app->settings.ch_map.vch_map.num_vch > 0) bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX); else { if (p_app->settings.activated == false) { /* system is not activated yet. launch welcom screen */ if (0 == p_app->settings.audio_vol) { p_app->settings.audio_vol = BAPP_MAX_VOLUME; bapp_apply_settings(p_app); } bapp_set_current_screen(p_app, eSCREEN_WIZ_WELCOME, eSCREEN_MAX); } else { bapp_set_current_screen(p_app, eSCREEN_MAIN, eSCREEN_MAX); } } 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.activated = 1; 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 BCM_DEBUG BDBG_SetModuleLevel("bscreen",BDBG_eMsg); 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; // AFD support #if 0 cfg.afd_reset_callback = bdisplay_afd_reset; cfg.afd_set_format_callback = bdisplay_afd_set_format; #endif 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\n",__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) { p_app->settings.activated = 1; p_app->settings_dirty |= DIRTY_MISC; } else { chm_get_hunt_progress(&p_app->chm); } 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); 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 chm_event_t evt; static b_timeval last_tv = { 0, 0}; 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; } if ((p_app->state == eAPP_STATE_NORMAL) && p_app->settings.activated && !p_app->settings.psi_scan) { if (((int)p_app->settings.timeout_cnt) <= 0) { evt.id = 0; evt.type = eCHM_EVT_ACTIVATION; bos_post_event(p_app->msg_queue,(b_event_t*)&evt); } } 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_timeout = 0; if (p_app->eas_text) { p_app->eas_text = false; /* clear eas text scrolling screen */ bapp_sync(p_app); screen_null_draw(p_app, NULL); bapp_flush_screen(p_app); } bapp_tune_prev(p_app); bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX); } #ifndef 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 } /* 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) { bdecode_config cfg; bdecode_get_config(p_app->decode,&cfg); if (cfg.cc_enabled != enable) { cfg.cc_enabled = (enable == 0) ? 0 : 1; bdecode_set_config(p_app->decode,&cfg); } } /* 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 //BDBG_MSG(("%s:%d - drawing screen:%d.\n",__FUNCTION__,__LINE__,p_app->screen_id)); 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\n",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: 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; } 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 */ } } /* 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) { if (!power && p_app->check_poweron) { return; } if (power) { /* turning power on */ BDBG_ERR(("######## Turn ON ########\n")); bapp_av_mute(p_app, 0); } else { bapp_av_mute(p_app,1); /* turning power off */ } p_app->power = power; } /* Summary: Handle diag events. */ #ifdef OLD_INFO_KEY_PROCESSING 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: 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); #ifdef OLD_INFO_KEY_PROCESSING b_timeval cur_tv; #endif BDBG_WRN(("%s:%d 0x%02x(%s)\n",__FUNCTION__,__LINE__,code,(key_up) ? "up" : "down")); switch (code) { 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; case 0x71: case 0x72: case eIR_RFM: if (key_up) { } break; default: if (!p_app->power) break; /* 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 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:%d screen_id %d\n",__FUNCTION__,__LINE__,p_app->screen_id)); /* Wait for vsync then do screen drawing */ bapp_new_screen(p_app); } else { bapp_handle_event(p_app,&screen_event); } } 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); } #ifndef 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; unsigned short cur_ch; 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; if (p_event->type != eCHM_EVT_SIGNAL) { BDBG_MSG(("%s (%s)\n",__FUNCTION__,s_chm_evt_str[p_event->type])); } 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_PROGRESS: screen_event.type = eS_EVENT_PROGRESS; 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; if (p_app->screen_id == eSCREEN_ANTENNA) { screen_event.type = eS_EVENT_PROGRESS; screen_event.id = p_app->power_level; } //p_app->qam_b_mode = p_sig->qam_b_mode; } break; case eCHM_EVT_DOWNLOAD: new_state = eAPP_STATE_DOWNLOAD; break; case eCHM_EVT_EAS: BDBG_MSG(("%s:%d EAS TIMER STARTED)\n",__FUNCTION__,__LINE__)); if (p_app->state == eAPP_STATE_NORMAL) { GETTIMEOFDAY(&start_tv); if (ch_map_set(bapp_cur_ch_map(p_app),p_event->id && 0xFFFF)) { /* if 0, don't timeout */ if (p_event->id >> 16) p_app->eas_timeout = start_tv.tv_sec + (p_event->id >> 16); else p_app->eas_timeout = 0; bapp_set_current_screen(p_app, eSCREEN_BANNER, eSCREEN_MAX); bapp_tune(p_app); /* use a local buffer to avoid conflict when eas getting other data and while text scrolling in progress*/ if (BERR_SUCCESS == bscreen_eas_text_scrolling_info(p_app, p_app->eas_buf, p_app->eas_buf_size)) { p_app->eas_text = true; } } } break; case eCHM_EVT_CA: { chm_ca_event_t *p_ca_evt = (chm_ca_event_t*)p_event; if ((p_app->settings.CA_System_ID != p_ca_evt->CA_System_ID) || (p_app->settings.EMM_PID != p_ca_evt->EMM_PID)) { p_app->settings.CA_System_ID = p_ca_evt->CA_System_ID; p_app->settings.EMM_Provider_ID = p_ca_evt->EMM_Provider_ID; p_app->settings.SCP_operating_mode = p_ca_evt->SCP_operating_mode; p_app->settings.EMM_PID = p_ca_evt->EMM_PID; p_app->settings.has_CAT = true; // p_app->settings.turn_on_freq_khz = p_ca_evt->freq_khz; p_app->settings_dirty |= DIRTY_MISC; } } break; case eCHM_EVT_NETWORK: p_app->settings.network_PID = p_event->id; p_app->settings_dirty |= DIRTY_MISC; break; case eCHM_EVT_STATUS: switch (p_event->id) { case eCHM_STATUS_HUNT: /* HUNT MODE */ if (p_app->screen_id == eSCREEN_CH_SCAN_PROGRESS) { scan_ch_cnt = 0; } BDBG_WRN(("eCHM_STATUS_HUNT\n")); break; case eCHM_STATUS_PENDING_INIT: /* Pending Init MODE */ BDBG_WRN(("eCHM_STATUS_PENDING_INIT\n")); new_state = eAPP_STATE_PENDING; break; case eCHM_STATUS_CHMAP: BDBG_WRN(("eCHM_STATUS_CHMAP flags = 0x%08x\n",p_event->ticks)); if ( ((ch_map_cmp(&(p_app->settings.ch_map),&(p_app->chm.ch_map)) & p_event->ticks)) || ((p_event->ticks == 0x82) && ch_map_cmp_vch_with_pid(&(p_app->settings.ch_map.vch_map),&(p_app->chm.ch_map.vch_map))!=0)) { BDBG_WRN(("Channel map changed 0x%08x\n",p_event->ticks)); cur_ch = p_app->settings.ch_map.cur_ch; ch_map_copy(&(p_app->settings.ch_map),&(p_app->chm.ch_map),p_event->ticks); p_app->settings.ch_map.cur_ch = cur_ch; #ifdef BCM_DEBUG ch_output(bapp_cur_ch_map(p_app)); #endif p_app->settings_dirty |= DIRTY_CHANNEL_MAP; } else { BDBG_WRN(("Channel map NOT changed\n")); } if (p_app->settings.psi_scan) { p_app->settings.activated = 1; p_app->settings.timeout_cnt = 8; p_app->settings_dirty |= DIRTY_MISC; memset(&p_app->cur_vch,0,sizeof(p_app->cur_vch)); bapp_save_settings(p_app); bapp_load_settings(p_app); } if (p_app->settings.activated) { if ((p_app->state == eAPP_STATE_NORMAL) && p_app->settings_dirty) { bapp_save_settings(p_app); /* if just scanned and have channnels, force to tune first channel */ if (p_app->settings.ch_map.vch_map.num_vch) { p_app->chm.force_tune = true; bapp_tune(p_app); } } else { new_state = eAPP_STATE_NORMAL; } } else { BDBG_WRN(("### ERROR recieve new channel map while still not activated - return to Hunt Mode\n")); new_state = eAPP_STATE_HUNT; } break; case eCHM_STATUS_PAT: p_app->has_PAT = true; if (p_app->screen_id == eSCREEN_CH_SCAN_PROGRESS) { scan_ch_cnt++; } #if 0 if (ch_map_cmp(&(p_app->settings.ch_map),&(p_app->chm.ch_map)) & p_event->ticks) { BDBG_WRN(("Channel map changed 0x%08x\n",p_event->ticks)); cur_ch = p_app->settings.ch_map.cur_ch; ch_map_copy(&(p_app->settings.ch_map),&(p_app->chm.ch_map),p_event->ticks); p_app->settings.ch_map.cur_ch = cur_ch; #ifdef BCM_DEBUG ch_output(bapp_cur_ch_map(p_app)); #endif p_app->settings_dirty |= DIRTY_CHANNEL_MAP; } else { BDBG_WRN(("Channel map NOT changed\n")); } #endif break; case eCHM_STATUS_NOPAT: 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; screen_event.data = &scan_ch_cnt; } } p_app->has_PAT = false; 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_ACTIVATION: { bool current_activation = p_app->settings.activated; p_app->settings.activated = p_event->id; if (p_app->settings.activated != current_activation) { p_app->settings_dirty |= DIRTY_MISC; if (!p_app->settings.activated) { p_app->settings.deactivated = 1; new_state = eAPP_STATE_HUNT; } else { p_app->settings.deactivated = 0; if (p_app->settings.timeout_policy == 1) { p_app->settings.timeout_cnt = p_app->settings.timeout; } #ifdef BCM_DEBUG /* Some default value to prevent immediate de-activation in lab environments */ else if (p_app->settings.timeout == 0) { p_app->settings.timeout_cnt += 4; } #endif } } } break; case eCHM_EVT_VCT_ID: { unsigned short current_vct_id = p_app->settings.VCT_ID; p_app->settings.VCT_ID = p_event->id; if ((p_app->settings.VCT_ID != current_vct_id) && (CONFIG_DEF_VCT_ID != 0xFFFF)) { BDBG_WRN(("%s:%d Configuration VCT_ID %d does not match current value %d\n", __FUNCTION__,__LINE__,p_app->settings.VCT_ID,current_vct_id)); p_app->settings.activated = false; new_state = eAPP_STATE_PENDING; } p_app->settings_dirty |= DIRTY_MISC; } break; case eCHM_EVT_CONFIGURATION: { chm_config_event_t *p_cfg_evt = (chm_config_event_t*)p_event; unsigned short current_vct_id = p_app->settings.VCT_ID; p_app->settings.VCT_ID = p_cfg_evt->VCT_ID; p_app->settings.timeout = p_cfg_evt->timeout; p_app->settings.timeout_policy = p_cfg_evt->timeout_policy; p_app->settings.max_location_errors = p_cfg_evt->max_location_errors; if (p_app->settings.timeout_policy == 0) { p_app->settings.timeout_cnt = p_cfg_evt->timeout; } p_app->settings.location = p_cfg_evt->location; if (p_app->have_time) { p_app->settings.message_time = p_app->system_time; } else { BDBG_WRN(("%s:%d Need system time before configuration can be processed\n",__FUNCTION__,__LINE__)); break; } if ((p_app->settings.VCT_ID != current_vct_id) && (CONFIG_DEF_VCT_ID != 0xFFFF)) { BDBG_WRN(("%s:%d Configuration VCT_ID %d does not match current value %d\n", __FUNCTION__,__LINE__,p_app->settings.VCT_ID,current_vct_id)); p_app->settings.activated = false; new_state = eAPP_STATE_PENDING; } p_app->settings_dirty |= DIRTY_MISC; } break; case eCHM_EVT_LOCATION: if(p_app->settings.psi_scan) break; p_app->location = p_event->id; if (p_app->settings.location != p_event->id) { if (p_app->settings.location_errors > p_app->settings.max_location_errors) { p_app->settings.activated = false; new_state = eAPP_STATE_HUNT; } else { p_app->settings.location_errors++; p_app->settings_dirty |= DIRTY_MISC; } } else { if (p_app->settings.timeout_policy == 0) { p_app->settings.timeout_cnt = p_app->settings.timeout; } } 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_TIMEZONE: { chm_tz_event_t *p_tz_evt = (chm_tz_event_t*)p_event; if (p_tz_evt->utc_offset & 0x10000) p_app->settings.utc_offset = (int)((0xFFFF & p_tz_evt->utc_offset) | 0xFFFF0000); else p_app->settings.utc_offset = (int)(0xFFFF & p_tz_evt->utc_offset); p_app->settings.dst_delta = p_tz_evt->dst_delta; p_app->settings.dst_entry = p_tz_evt->dst_entry; p_app->settings.dst_exit = p_tz_evt->dst_exit; p_app->settings_dirty |= DIRTY_MISC; } break; case eCHM_EVT_PHONENUMBER: if (strcmp((char*)&(p_app->settings.phonenumber),p_event->data) != 0) { if (strlen(p_event->data) > MAX_PHONE_LEN) p_event->data[MAX_PHONE_LEN-1] = 0; strcpy((char*)&(p_app->settings.phonenumber),p_event->data); p_app->settings_dirty |= DIRTY_PHONE; } 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; default: BDBG_WRN(("%s:%d CHM EVENT = %d NOT HANDLED\n",__FUNCTION__,__LINE__,p_event->type)); break; } BDBG_MSG(("%s:%d CHM EVENT = %d)\n",__FUNCTION__,__LINE__,p_event->type)); 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_WRN(("%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 { 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; 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(); 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; } #if 0 /* Summary: Main event loop when in normal operation mode. */ static bapp_state_t bapp_pending(bapp_t *p_app) { bscreen_event_t screen_event; unsigned short num_vch, num_st; unsigned char num_freq ; buser_input_event event; unsigned event_cnt; /* 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(); bapp_handle_user_event(p_app,&event); } } 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); } /* Yield control */ bos_sleep(p_app->yield_ms); /* Check to see if there is a channel map */ ch_map_get_counts(bapp_cur_ch_map(p_app),&num_vch,&num_st,&num_freq); #if 0 if ((num_vch > 0) && (p_app->settings.activated || (p_app->settings.VCT_ID == 0))) { BDBG_WRN(("%s:%d Switch to NORMAL State(%d,%d,%d)\n",__FUNCTION__,__LINE__, num_vch,p_app->settings.activated,p_app->settings.VCT_ID)); return eAPP_STATE_NORMAL; } #endif return p_app->state; } #endif /* Summary: Main event loop when in normal operation mode. */ static bapp_state_t bapp_downloading(bapp_t *p_app) { /* Yield control */ bos_sleep(p_app->yield_ms); return(p_app->chm.cmd == eCHM_DOWNLOAD) ? eAPP_STATE_DOWNLOAD : eAPP_STATE_NORMAL; } /* Summary: Perform a channel hunt (for cable ). */ static int bapp_channel_hunt(bapp_t *p_app) { p_app->chm_cmd.cmd_id = eCHM_HUNT; chm_cmd(&p_app->chm,&p_app->chm_cmd); return 0; } /* Summary: Main app loop. Description: Main application event loop. */ #ifdef BCM_DEBUG static const char *s_app_state_name[] = { "DEFAULT","HUNTING","PENDING","NORMAL","DOWNLOAD","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_PENDING: if ((new_state == eAPP_STATE_NORMAL) && p_app->settings_dirty) { bapp_save_settings(p_app); } p_app->last_screen_id = eSCREEN_MAX; memset(&p_app->cur_vch,0,sizeof(p_app->cur_vch)); 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_DOWNLOAD: case eAPP_STATE_NORMAL: 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) // if (p_app->screen_id < eSCREEN_DIAG_MENU) { 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); } bapp_channel_hunt(p_app); break; case eAPP_STATE_NORMAL: if ((p_app->screen_id != eSCREEN_CH_SCAN_PROGRESS) && (p_app->screen_id != eSCREEN_GUIDE) && (p_app->settings.ch_map.vch_map.num_vch > 0)) // if (p_app->screen_id < eSCREEN_DIAG_MENU) { 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); bapp_tune(p_app); break; case eAPP_STATE_DOWNLOAD: if (p_app->screen_id < eSCREEN_DIAG_MENU) { 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); } p_app->chm_cmd.cmd_id = eCHM_DOWNLOAD; chm_cmd(&p_app->chm,&p_app->chm_cmd); break; case eAPP_STATE_FACTORY: bapp_set_current_screen(p_app, eSCREEN_STATUS, eSCREEN_MAX); bapp_new_screen(p_app); break; case eAPP_STATE_PENDING: case eAPP_STATE_DEFAULT: case eAPP_STATE_DONE: break; } /* Make new state the current state */ p_app->state = new_state; switch (new_state) { case eAPP_STATE_PENDING: bapp_screen_redraw(p_app); break; default: break; } } /* 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_PENDING: // new_state = bapp_pending(p_app); // break; case eAPP_STATE_NORMAL: case eAPP_STATE_FACTORY: new_state = bapp_run_main(p_app); break; case eAPP_STATE_DOWNLOAD: new_state = bapp_downloading(p_app); break; case eAPP_STATE_DEFAULT: case eAPP_STATE_DONE: /* Yield control */ bos_sleep(p_app->yield_ms); 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(); } /* Summary: Return current application channel map. */ ch_map_t *bapp_cur_ch_map(bapp_t *p_app) { return &(p_app->settings.ch_map); } /* Summary: Tune to the current frequency and get the VCT. Description: Tune to the current frequency and get the VCT. Returns non-zero on failure. */ int bapp_change_channel(bapp_t *p_app, int ch_up, int tune) { int retval = -1; bool result; BDBG_MSG(("%s (%d,%d)\n",__FUNCTION__,ch_up,tune)); if (ch_up) { result = ch_map_set_next(bapp_cur_ch_map(p_app)); } else { result = ch_map_set_prev(bapp_cur_ch_map(p_app)); } if (!result) { BDBG_ERR(("%s (%d,%d) failed \n",__FUNCTION__,ch_up,tune)); return retval; } if (tune) { retval = bapp_tune(p_app); p_app->settings_dirty |= DIRTY_CHANNEL; } else { retval = 0; } 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, int channel) { int retval = -1; vch_t cur_vch; st_t cur_st; freq_t cur_freq; BDBG_WRN(("%s (%d)\n",__FUNCTION__,channel)); if (!ch_map_get_current(bapp_cur_ch_map(p_app),&cur_vch,&cur_st,&cur_freq)) { BDBG_WRN(("%s Invalid current channel or map.\n",__FUNCTION__)); return 0; } #if 1 if (!ch_map_is_channel_visible(bapp_cur_ch_map(p_app),(unsigned short)channel)) { BDBG_WRN(("%s Hidden channel %d\n",__FUNCTION__,channel)); return 0; } #endif if (ch_map_set_ch(bapp_cur_ch_map(p_app),(unsigned short)channel)) { 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) { vch_t new_vch; st_t new_st; freq_t new_freq; if (p_app->settings.av_mute) return 0; p_app->prev_vch = p_app->cur_vch; /* check to see if the current channel info has changed */ if (p_app->decoding) { if (!ch_map_get_current(bapp_cur_ch_map(p_app),&new_vch,&new_st,&new_freq)) { BDBG_WRN(("%s Invalid current channel or map.\n",__FUNCTION__)); return 0; } if ((new_freq.freq_khz == p_app->cur_freq.freq_khz) && (new_vch.program_num == p_app->cur_vch.program_num)) { BDBG_WRN(("%s Channel info did not change skip re tune.\n",__FUNCTION__)); return 0; } BDBG_WRN(("%s Channel Navigation Changed - Retune\n",__FUNCTION__)); } p_app->lock = false; p_app->power_level = 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(); if (!ch_map_get_current(bapp_cur_ch_map(p_app),&p_app->cur_vch,&p_app->cur_st,&p_app->cur_freq)) { BDBG_WRN(("%s Invalid current channel or map.\n",__FUNCTION__)); return 0; } 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_vch.ch_num); } /* Summary: Restart audio decode (after SAP swap audio PID) */ int bapp_rotate_audio_sap(bapp_t *p_app) { // unsigned int flags; vch_t vch; st_t st; freq_t freq; if (p_app->settings.av_mute || !p_app->decoding) return 0; if (!ch_map_get_current(bapp_cur_ch_map(p_app),&vch,&st,&freq)) { BDBG_WRN(("%s Invalid current channel or map.\n",__FUNCTION__)); return 0; } if (vch.num_audio <= 1) return 0; vch.cur_audio++; if ( vch.cur_audio >= vch.num_audio) { vch.cur_audio = 0; } if (!ch_map_vch_update(bapp_cur_ch_map(p_app),&vch)) { BDBG_WRN(("%s Error updating channel map.\n",__FUNCTION__)); return 0; } p_app->chm_cmd.cmd_id = eCHM_SAP; chm_cmd(&p_app->chm,&p_app->chm_cmd); return 0; } int bapp_rotate_dsub(bapp_t *p_app) { #ifdef CONFIG_DVB_SUBTITLE vch_t vch; st_t st; freq_t freq; uint16_t cur_pid; if (!ch_map_get_current(bapp_cur_ch_map(p_app), &vch, &st, &freq)) { BDBG_WRN(("%s Invalid current channel or map.", __FUNCTION__)); return 0; } if (vch.num_dsub <= 1) return 0; cur_pid = vch.dsub_pid[vch.cur_dsub]; vch.cur_dsub++; if (vch.cur_dsub >= vch.num_dsub) vch.cur_dsub = 0; if (!ch_map_vch_update(bapp_cur_ch_map(p_app), &vch)) { BDBG_WRN(("%s Error updating channel map", __FUNCTION__)); return 0; } if (cur_pid != vch.dsub_pid[vch.cur_dsub]) { p_app->chm_cmd.cmd_id = eCHM_DSUB; chm_cmd(&p_app->chm, &p_app->chm_cmd); } #endif 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; vch_t vch; st_t st; freq_t freq; 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 (!ch_map_get_current(bapp_cur_ch_map(p_app),&vch,&st,&freq)) 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) { 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) { bapp_audio_mute(p_app, 0); cfg.mute = 0; cfg.channel_change = 2; 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; 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; 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); }