====================================================================== DUNE HD STB -- PLUGINS MECHANISM AND PHP API ====================================================================== Overview -------- The mechanism of plugins provides a possibility to integrate applications into the native Dune GUI. When an application is packaged as a plugin, it can appear in the native Dune GUI just an an icon in Dune menu. Such applications can be implemented using a variety of technologies supported by Dune HD STB: - It can be an application based on the native Dune HD GUI framework and implemented using PHP language and PHP API provided by Dune HD STB. - It can include some web server functionality (e.g. CGI scripts running on the STB) providing HTTP API for external systems or providing a way for HTML or FlashLite application to execute native code on the STB. - It can include any Linux software executed on demand or running in the background, and it can even include custom Linux kernel modules (e.g. drivers for certain USB hardware or kernel modules implementing certain DRM systems). - The application can also use a mix of different technologies. - There is also a possibility to use DirectFB/Qt-based custom GUI implementation, but this requires to use special firmware versions ("Native GUI SDK" firmware versions) and is not supported by standard firmware versions. - It can be a full-screen HTML application (on models which support HTML applications). - It can be a full-screen FlashLite application (on models which support FlashLite applications). A big part of the plugins mechanism is the PHP API for implementation of GUI functionality based on the native Dune HD GUI framework. This approach allows quick implementation of GUI functionality tightly integrated into the native Dune GUI. It is especially suitable for quick creation of simple IPTV/VOD applications. The following possibilities are provided: - HTML coding is NOT involved; the standard GUI (native Dune HD media player GUI) is used automatically. The PHP code is only responsible for the interaction with the server part of the service (typically via HTTP requests), and customizing the GUI look/behavior in some ways. - OSD GUI for IPTV and VOD playback is provided automatically (including TV channels navigation, TV channel categories, favorite channels management, EPG, series navigation, etc). - Plugin can easily visualize hierarchical catalogs of content (TV channel categories, VOD categories, etc). - Plugin can show various user interaction dialogs (login, movie purchase confirmation, settings, etc). Plugin examples --------------- IPTV/VOD applications implemented using PHP: - http://files.dune-hd.com/partners/sdk/plugins/dune_plugin_demo2.2011_12_22.zip - http://files.dune-hd.com/partners/sdk/plugins/dune_plugin_demo2_with_ad.zip Simple digital signage application (endless playback of a media_url) implemented using PHP: - http://files.dune-hd.com/partners/sdk/plugins/dune_plugin_simple_presenter.2013_07_19.zip HTML applications packaged as plugins: - See "HTML plugin examples" section here: - http://files.dune-hd.com/partners/sdk/html_apps.txt An application demonstrating deep Linux integration (daemon automatically started on STB boot, HTTP API allowing to control the daemon and access the data in Linux filesystem, simple HTML application interacting with this HTTP API via AJAX): - http://files.dune-hd.com/partners/sdk/plugins/dune_plugin_linux_code_demo.2014_03_20.zip Historical note --------------- When the mechanism of plugins was first introduced in Dune HD STB, it was originally intended for the implementation of custom GUI applications using the provided PHP API, and it was required that each plugin included at least some PHP code. This was the reason why plugins were originally called "PHP plugins". Later, various features allowing to use the mechanism of plugins w/o the need to use PHP code were added, but the term "PHP plugin" was still used. The documentation below refers to the term "PHP plugin", but all the features which are not directly related to the use of PHP language are also applicable to plugins which do not actually use any PHP code. Implementing GUI functionality using PHP API -------------------------------------------- The mechanism of PHP plugins allows to extend Dune GUI with custom applications implemented using PHP programming language and PHP API provided by Dune HD STB. PHP plugins created using this mechanism are stored in the STB flash memory and are running on the STB. This PHP API does not allow PHP plugins to directly render an arbitrary TV GUI and directly handle events from the remote control in arbitrary ways. Instead, there is a high-level GUI framework with a fixed set of possibilities, and PHP plugins may use these possibilities for custom GUI creation. The main goal of the PHP plugins mechanism is to allow to implement custom IPTV/VOD applications, but it also could be used for other similar purposes. The possibilities provided by the PHP plugins mechanism include: - Showing custom screens listing various objecs (e.g. TV channels, movies, categories, etc). The possibilities for the customizing the GUI of these screens are similar to those provided by the "dune_folder.txt" mechanism (see http://dune-hd.com/support/misc/dune_folder_howto.txt). - Showing "movie information" screens. - Showing custom screens and dialogs with some GUI controls for user input (e.g. text fields, buttons, etc). - Launching playback of TV and VOD content in a special mode (with special TV and VOD OSD GUI). The advantages for implementing custom applications (e.g. custom IPTV/VOD applications) using PHP plugins mechanism are the following: - Reduced implementation effort. - No need to implement the GUI from the scratch, a high-level GUI framework allows to very quickly and easily implement standard IPTV and VOD functionality. - Just feed the proper data into the GUI and everything is working automatically. - Smooth integration into Dune GUI. - The look and feel of the custom application is the same as the look and feel of other STB functions. - Choosing a different GUI skin automatically affects the custom application as well. - All features of Dune GUI are automatically provided for the custom application. - High-quality graphics with FullHD (1920x1080) resolution. - Fast GUI. - Animation effects. - GUI structure with 4 screen areas (path bar, widget zone with date/time and weather information, main content box, optional details panel at the right). - Ability to integrate custom screens into STB Setup menu. - PHP plugin is stored in the STB flash memory and runs on the STB. - This allows to integrate with the existing server-side IPTV middleware APIs, w/o the need to host anything on the web server. - This allows to reduce the amount of the functionality that should be hosted/executed on the web server. - This allows to implement client-side caching and improve the performance in other ways. Installing plugins ------------------ One STB may have one or several plugins installed. plugins may be preinstalled (included into STB firmware), or installed by the user (using plugin installer). For manual installation of a plugin, a special "plugin installer" file is needed. The plugin installer file is just a ZIP archive containing "dune_plugin.xml" file at the top level and other files (according to plugins needs). To install a plugin, just launch the plugin installer file (dune_plugin*.zip) from any media (e.g. from USB flash drive). The plugin will be installed into the flash memory of the STB. If plugin with the same name was already installed manually, then an option will appear allowing to overwrite plugin or cancel installation. Note, that the preinstalled (included into STB firmware) plugins cannot be overwritten. Note, the STB typically requires "Flash memory storage" (a special partition in the flash memory of the STB) or "System storage" (an external storage device used for system needs) to be activated in order to manually install plugins. If neither is activated yet, the STB will propose to activate "Flash memory storage" during plugin installation. For more information about "Flash memory storage" and "System storage", please see http://dune-hd.com/support/usb_flash_drive . All installed plugins are listed in "Setup / Misc / Plugins" menu. This menu allows to delete the previously manually installed plugins (select the plugin, press ENTER, choose "Delete"). Providing additional plugins via "dune_plugins" folder ------------------------------------------------------ There is a special possibility which allows to add plugins to the list of registered plugins, using a special "dune_plugins" folder. This folder should be located at the top-level of the "main" storage device. This folder should contain one or several subfolders, where each subfolder should contain the data of one plugin (i.e. the dune_plugin.xml and other plugin data). NOTE: In order to ensure that the storage device is recognized as the "main" one, it should be either the only storage device connected to the player at the moment, or the only storage device connected to the player at the moment when the player is switched on. NOTE: This possibility is not recommended for normal users; it is mostly intended for the development needs (e.g. when it is needed to edit the plugin PHP code and look at the result). NOTE: to apply changes made in "dune_plugins" folder one should press POWER remote button twice: first to turn STB into standby mode and second to turn it on again. Redirecting plugin logs to "dune_plugin_logs" folder ---------------------------------------------------- There is a special possibility which allows to redirect logs produced by all plugins which were installed manually to the special "dune_plugin_logs" folder. This folder should be located at the top-level of the "main" storage device. Normally, all logs are written to some temporary folder not accessible from the outside. If "dune_plugin_logs" exists all logs from the non-built-in plugins will be written to this folder. NOTE: In order to ensure that the storage device is recognized as the "main" one, it should be either the only storage device connected to the player at the moment, or the only storage device connected to the player at the moment when the player is switched on. NOTE: This possibility is not recommended for normal users; it is mostly intended for the development needs. It is recommended to use HDD instead of Flash drive as "main" storage device for writing logs to. Plugin files structure ---------------------- The plugin contains the following files: 1. dune_plugin.xml (required) - This is plugin manifest in XML format. This is the only file required by the STB in order to load the plugin. All other plugin files (if any) are specified in the plugin manifest, and can have any names. 2. For PHP plugins: the PHP program containing hd_create_plugin() function. (required) - The path to the file with this PHP program is specified in "dune_plugin.xml". 3. Translation tables - The files translations/dune_language_.txt will be automatically loaded to the global STB translation table on STB start or when interface language is changed by user. The keys provided in translation files can be accessed using special syntax in public string of PHP API. See the "Interface language translations" section for more details. 4. Some resources accessible by HTTP in web and web/cgi-bin directories. - These resources will be accessible using the following url schema: http:///plugins// http:///cgi-bin/plugins// See "HTTP server extension" section for more details. 5. Any other files, e.g. some resources (e.g. images/icons) (optional) - These files may be referenced by "dune_plugin.xml" or other files, or used in other ways by the PHP program. Plugin manifest --------------- The sample manifest of plugin called 'sample' may look as following: sample Sample php sample.php root://applications 0 yes plugin_file://icons/logo_big.png plugin_file://icons/logo_small.png Sample Section plugin_handle_user_input root enter_from_section_screen root://tv main_tv Sample.TV plugin_file://icons/sample_tv.png 030020 1.0 gui_skin://large_icons/4.png plugin_file://icons/logo_small.png no plugin_open_folder plugin_tv_play Clear TV Cache plugin_handle_user_input clear_cache yes show_tv_entry_point yes yes root://applications main_vod Sample.VOD plugin_file://icons/sample_vod.png plugin_file://icons/logo_small.png plugin_open_folder yes show_vod_entry_point yes yes yes yes yes 20 30 Details: - dune_plugin->name: plugin identifier. It should be nonempty and may contain only alphanumeric and ('-', '.', '_') characters. Length is limited by 64. - dune_plugin->caption: caption used in Setup / Misc / Plugins - dune_plugin->type and dune_plugin->params: the type of engine used to execute plugin and it's parameters. Currently only the 'php' type is supported having single mandatory 'program' parameter pointing to the main php file of plugin. - dune_plugin->entry_points: list of the plugin entry points in the Dune menu. Each dune_plugin->entry_points->entry_point may contain the following fields: - 'parent_media_url': the URL of folder containing this entry point. Now the following folders are allowed to contain plugin items: root://tv root://applications setup://applications root://video (*) available in firmware 130424_b6+ root://music_and_radio (*) available in firmware 130424_b6+ root://news_and_weather (*) available in firmware 130424_b6+ root://social_networks (*) available in firmware 130424_b6+ root://games (*) available in firmware 130424_b6+ root://setup (*) available in firmware 130424_b6+ - 'section_index' (*) available in firmware 120901+ 'is_default_section' (*) available in firmware 120901+ Specify the visualization of entry point in cas main screen style is "Folders". Other main screen styles are not affected. If 'section_index' is specified, then entry point is shown on the main screen (together with sections 'TV', 'Applications', 'Sources', 'Setup' etc...). The value of 'section_index' specifies the index number. The 'is_default_section' allows to force the entry point to be focused when main screen is entered first time. NOTE: in firmware versions other than 130906_b8+ the options 'section_index' and 'is_default_section' take effect only if 'parent_media_url' is root://applications. - 'caption': entry point caption. - 'icon_url' 'icon_margins' (*) available in firmware 120606+ 'icon_fit_scale_factor' (*) available in firmware 120606+ 'badge_icon_url' (*) available in firmware 120901+ 'override_default_badge' (*) available in firmware 141005_b9+ visualization parameters of entry point in parent folder. For more details see the description of similar ViewItemParams properties in "Regular folder GUI customization" section. - 'small_icon_url' Specifies URL to small icon of plugin. Depending on appearance settings, the plugin small icon can be shown in path box and, more rarely, in content box of type 'List'. The URLs of type plugin_file:// and gui_skin:// are supported. NOTE: Available in firmware 131106_b6+ - 'media_url': identifier of menu node of the plugin menu hierarchy Identifier should be unique in scope of plugin. The 'media_url' will be used in some plugin operations. - 'actions': the event->action mapping. The list of pairs: event_id => action specification. If entry point is focused and the specified key is pressed then the corresponding action will be executed by Dune GUI. See the "Plugin PHP program main features overview" section for more details about how the Dune GUI works with the entry points. See the "GUI Actions" section for more details about the concept of GUI action and for the list of available GUI actions. - 'popup_menu': the list of additional popup menu items to be addded to the context menu of entry point. - 'show_by_default' and 'show_cookie_name': this is a way for plugin to show/hide entry points. The 'show_cookie_name' is a name of plugin cookie (e.g. the persistent property name) whose value is used as boolean expression. The expression is evaluated to decide whether to show entry point in Dune menu. The expression syntax is the following: yes no lang(,...,). The 'show_by_default' is used if 'show_cookie_name' is not set. - 'show_action' Allows to specify GUI action to be executed each time GUI framework determines whether entry point is shown or not. The exit status of action is used to decide whether to show entry point: zero status is "yes", other status is "no". It is not recommended to use this way of hiding entry points, use 'show_cookie_name' instead when possible. NOTE: Available in firmware 130315_b6+ - 'ip_address_required': yes | no. If 'yes' is specified and the IP address is not available yet then opening of this entry point will cause the WaitIpAddress dialog to appear until the IP address is got or user presses Cancel button or dialog is cancelled by timeout. - 'valid_time_required': yes | no. If 'yes' is specified and the valid time is not synchronized from internet yet then opening of this entry point will cause the WaitValidTime dialog to appear until the valid time is got or user presses Cancel button or dialog is cancelled by timeout. - auto_resume: the specification of auto-resume feature which is disabled by default. The following fields supported: - enable: yes/no. This enables auto-resume feature. The default implementations supporting all use-cases (live TV playback, archive TV playback, VOD playback) will be used. - action: GUI action. This GUI action will be executed in case of auto-resume instead of the default algorithm. - ip_address_required: yes/no. If yes => the wait_ip_address dialog is shown if needed in auto-resume use-case. - valid_time_required: yes/no. If yes => the wait_valid_time dialog is shown if needed in auto-resume use-case. - operation_timeout: allows to change the default timeout for plugin operations. The operation timeout is 10 seconds by default. The default operation timeout can be changed to N using N. Also the operation timeout can be specified for each operation type. To change the timeout for operation 'op' to N use construction: N. Exapmle: 20 30 40 As a result, all operations has timeout 20 seconds, except the get_epg_day() (30 seconds) and handle_user_input() (40 seconds). High-level design overview for PHP plugins ------------------------------------------ There is central Dune GUI component, that does all the job to handle remote control, draw graphics, show video streams and so on. The Dune GUI can also manage multiple PHP plugins. Every PHP plugin runs in a separate process, where PHP engine is initialized. The Dune GUI communicates to PHP plugins using IPC (inter-process communication), in particular: UNIX pipes. The protocol is in plain text and uses JSON to represent structured data. The communication is actually one-way: Dune GUI makes a request (or a call) and asynchronously waits for a PHP plugin to reply. If the PHP plugin failed to reply within pre-defined timeout, an error is reported. PHP plugins are not able to initiate a call to Dune GUI. Basically, a call from the Dune GUI to a PHP plugin can be formulated by the following meta-declaration: string call_plugin(in string call_ctx_json); - The Dune GUI prepares a structure of some sort, where it specifies operation code and operation parameters (so called "input-data"); - This structure is then encoded (serialized) to a string using JSON; - The string is passed to the PHP plugin using IPC; - PHP plugin deserializes the string to a structure, retrieves operation code and operations parameters, executes the operation to get another structure (so called "output-data") to be passed back to the Dune GUI; - The output structure is again serialized to a string using JSON, and is passed back to the Dune GUI; - The Dune GUI deserializes the string into a structure and uses the data to do needed actions. Thus, ultimately, the PHP plugin need to implement the only one function: string call_plugin(in string call_ctx_json); (actual name see below in the "System PHP files" section) However, it's too cumbersome and error-prone to implement the same logic for every plugin over and over again, so SDK provides a framework, which does all the job of marshalling data and invoking the right operation. System PHP files ---------------- STB includes several system PHP files which are automatically sourced by the PHP engine instance before plugin PHP program loading. PHP definitions and symbols provided by these system PHP files are automatically available to plugin PHP program. In the STB firmware, these PHP files are located in "/firmware_ext/php" directory. These files basically defines an interface between Dune GUI and plugin PHP programs. The files are: - bootstrap.php - Setups error reporting within PHP engine so that all errors are logged to the internal log file. - Setups correct (current) timezone. - Provides the following global functions: - hd_print($text_message) This function should be used instead of PHP functions 'echo', 'print', 'printf' etc. By using this function developer makes sure the text gets to the log file in the proper format. This function uses global $HD_NEW_LINE contant, which is an empty string ('') by default. - hd_silence_warnings() This function should be used to temporarily disable warning from system PHP functions. - hd_restore_warnings() This function restores warning logging after hd_silence_warnings(). - The following global functions are also defined in bootstrap.php, but usually should not be used explicitly in PHP plugins: - hd_error_handler() - hd_shutdown_handler() - hd_error_silencer() - dune_plugin.php - Defines high-level interface between the Dune GUI and plugin PHP programs -- DunePlugin interface -- a set of operations, which the Dune GUI can call against the PHP program. If default framework (see below) is in use, all calls from the Dune GUI to a plugin PHP program are dispatched to an instance of DunePlugin interface. - dune_plugin_fw.php - Provides low-level interface (in terms of strings) between the Dune GUI and plugin PHP programs. - Provides utility functions. - dune_api.php - Contains definitions of various string constants which are helpful for passing the data between the plugin PHP program and Dune GUI. Plugin PHP program basics ------------------------- Every plugin PHP program eventually must do the following steps: - Provide a class derived from DunePluginFw; - Implement DunePluginFw::call_plugin() in the derived class; - Assign an instance of the new class to DunePluginFw::$instance; DunePlugin interface -------------------- On the high-level, the interface between the Dune GUI and a plugin PHP program is specified by the DunePlugin interface, declared in dune_plugin.php file. Currently the DunePlugin interface looks as follows: interface DunePlugin { // PluginFolderView public function get_folder_view( /* [in] String */ $media_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); // PluginFolderView public function get_next_folder_view( /* [in] String */ $media_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); // PluginTvInfo public function get_tv_info( /* [in] String */ $media_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); // String public function get_tv_stream_url( /* [in] String */ $playback_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); // PluginVodInfo public function get_vod_info( /* [in] String */ $media_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); // String public function get_vod_stream_url( /* [in] String */ $media_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); // PluginRegularFolderRange public function get_regular_folder_items( /* [in] String */ $media_url, /* [in] int */ $from_ndx, /* [inout] Map: Key -> Value */ &$plugin_cookies); // List public function get_day_epg( /* [in] String */ $channel_id, /* [in] int */ $day_start_tm_sec, /* [inout] Map: Key -> Value */ &$plugin_cookies); // String public function get_tv_playback_url( /* [in] String */ $channel_id, /* [in] int */ $archive_tm_sec, /* [in] String */ $protect_code, /* [inout] Map: Key -> Value */ &$plugin_cookies); // void public function change_tv_favorites( /* [in] String */ $op_type, /* [in] String */ $channel_id, /* [inout] Map: Key -> Value */ &$plugin_cookies); // GuiAction public function handle_user_input( /* [in] Map: Key -> Value */ &$user_input, /* [inout] Map: Key -> Value */ &$plugin_cookies); } The output type of plugin operation: class PluginOutputData { Boolean has_data; PluginOutputDataType data_type; Object data; Map plugin_cookies; Boolean is_error; GuiAction error_action; } Each plugin operation should return one of the following: - normal output: 'is_error' is false, 'error_action is null, 'has_data' is true, 'data' contains the normal output data of type specified in 'data_type'; - error output: 'is_error' is true, error_action may be set to some GUI action to be executed. Plugin PHP program lifecycle ---------------------------- Each PHP plugin is executed in its own instance of PHP engine (running in a its own separate process). The PHP engine instance for each PHP plugin is created when the PHP plugin is used for the first time. PHP plugin always handles just one call from Dune GUI at a time. Multiple calls from Dune GUI to PHP plugin are always serialized. Typically, subsequent calls from Dune GUI to PHP plugin are delivered to the same PHP engine instance. Thus, global PHP variables are preserved between subsequent calls. However, each PHP engine instance may be destroyed/recreated at any moment (between calls from Dune GUI to PHP plugin) when this is needed by Dune GUI. When this happens, global PHP variables are not preserved. So, PHP plugin must not assume that global PHP variables are preserved between subsequent calls from Dune GUI to PHP plugin. PHP plugin is allowed to use global PHP variables e.g. for the implementation of some caches (may be helpful for performance reasons), but it must be prepared that these global variables disappear between subsequent calls and implement a proper strategy for repopulating the caches when needed. When possible, PHP plugin should be designed as a stateless program. When some transient global state is needed and it is critical to preserve this state between subsequent calls to PHP plugin, this should be implemented in a special way, e.g.: - The state should be encoded in parameters which are passed between PHP plugin and Dune GUI, so Dune GUI keeps the state. - The state should be stored in the directory for temporary transient data (RAM disk in the STB). - The state should be stored on the Internet server (if PHP plugin interacts with some Internet server). Plugin PHP program environment ------------------------------ 1. Cookies. - each plugin has a list of persistent string settings known as plugin cookies. This map(string => string) is passed by reference to each plugin operation. So, operations may use cookie values and can modify them. The cookies keep their values between operations and even survive the STB restart. NOTE: plugin cookies are not supposed to keep large amount of data 2. System properties. - the PHP plugin code has access to the DuneSystem::$properties array. Currently the following properties are provided: 'plugin_name' - current plugin name; 'install_dir_path' - path to directory where plugin is installed to; 'tmp_dir_path' - path to directory under /tmp which is designed for storing plugin's temporary data. Dune GUI ensures that directory exists. 'data_dir_path' - path to directory for storing persistent data. NOTE: this directory is not available on STBs without System Storage and Flash Memory Storage. In the latter case 'data_dir_path' is unset. 'plugin_www_url' - the common HTTP prefix for WWW-files included into plugin (for local access); 'plugin_cgi_url' - the common HTTP prefix for CGI scripts included into plugin (for local access). In particular, the 'plugin_www_url' and 'plugin_cgi_url' contains strings: http://127.0.0.1/plugins// http://127.0.0.1/cgi-bin/plugins// NOTE: After each write into persistent location, "sync" UNIX command or system call should be performed immediately. Plugin PHP program main features overview ----------------------------------------- Each method in DunePlugin interface corresponds to the so-called plugin operation. Each operation has input type (simple) and output type (sometimes considerably complex). The output data should be returned from DunePlugin method as PHP array. The keys for output PHP arrays are defined in the dune_api.php. The PHP plugin may extend the base Dune functionality in the following ways: - extend Dune menu hierarchy (the Dune menus also known as 'folders'). Some of general Dune folders (in particular, the 'TV', 'Applications' and 'Setup->Applications') may be extended by adding new elements which are called 'plugin entry points'. Each entry point is owned by one plugin. Typically entry points contain folder hierarchy managed by plugin. - launch plugin-TV playback. Plugin-TV playback is the special playback mode allowing to play TV channels, browse list of channels united into categories (also known as groups), browse channel EPG etc. - launch plugin-VOD playback. Plugin-VOD playback is the special playback mode allowing to play movie or a series (list of episodes united by single title). The default look and behaviour of general Dune folders is extended by plugins in the following way: - new folder element is added for each registered plugin and each entry point in plugin manifest. The icon URL and caption for each entry point are taken from manifest; - the owner plugin takes control over user input when entry point is focused. Currently plugin may override the standard behaviour of the following remote keys in general folders: ENTER, PLAY. The technique used by plugins to affect the behaviour of Dune GUI is base on the concept of GUI actions. For more details about GUI actions see the "GUI actions" section. Briefly the GUI action is the instruction for Dune GUI what to do when user presses remote button in particular state of GUI. GUI action is typically created in PHP code as array with the following fields: - handler_string_id : [string] type of action - data: [array] PHP array of type-specific action parameters. There is a number of GUI action types including: - PLUGIN_OPEN_FOLDER. Browses into some GUI element. Opens a new folder (submenu) fully managed by plugin. Such folders are called 'plugin folders'. - PLUGIN_TV_PLAY. Launches the plugin-TV playback. - PLUGIN_VOD_PLAY. Launches the plugin-VOD playback. Also there is one special action type called HANDLE_USER_INPUT. Execution of HANDLE_USER_INPUT involves: - running some arbitrary plugin code. Specifically, the handle_user_input() plugin operation is executed having current Dune GUI state as a parameter; - immediate execution of another GUI action specified by plugin. Actually, the return value of handle_user_input() operation is executed as GUI action. The plugin folder has string identifier which is non-obviously called 'media_url'. So let's assume that every plugin folder (including entry point) has 'media_url' value unique in scope of plugin. The plugin folders are divided into 3 general types: 1. Regular folder. The most common type of folder used to show the list of objects of any kind as table with fixed number of rows and columns. Each table cell may contain image and text. The visualization of regular folder can be adjusted using large number of settings. Also plugin may specify several variants of folder representation; these variants can be switched by pressing A_RED remote button. Let's call variant of regular folder representation 'folder view'. The regular plugin folder behaves similar to general Dune folders but the effect of pressing several remote keys should be explicitly specified by plugin; otherwise they will be ignored. These remote keys are: ENTER, PLAY, INFO, POPUP_MENU, B_GREEN, C_YELLOW, D_BLUE. In other words plugin may assign GUI actions to the listed keys. The regular folders can be divided into: - simple (preloaded): the whole content of folder is returned at once; - lazy loaded with known size: the number of folder elements is known but it is considerably big and folder content is loaded by chunks when user scrolls; - lazy loaded with unknown size: the same as before but the number of total elements is unknown until end is reached. The most regular folders are simple; however Dune plugin framework have support for lazy-loading of regular folders. 2. Control folder. The folder type designed to be used in setup. The control folder looks as vertical list of GUI controls and constant text strings. The following controls are supported: - button. - combobox - text field Plugin may assign specific GUI actions to the following events: - button pressed; - combobox value changed; - text field value changed. The HANDLE_USER_INPUT GUI action should be used to apply/save changes. 3. Movie folder. The special layout for representing the detailed information about movie. The following movie properties can be shown in such folder: - movie name - movie name in the original language - poster image - list of genres - country - year - director(s) - actors etc.. The layout also includes one or two buttons: - mandatory button 'PLAY' in the left-bottom corner with the following predefined handling. When pressed the number of movie series is cheched:' - (number_of_series > 1) => folder with list of series is opened; - (number_of_series = 1) => VOD-playback is launched for movie. - optional button with custom caption and GUI action in the right-bottom corner. This button may be used to implement 'Add to favorites' and 'Remove from favorites' use-cases. To support the folder hierarchy the plugin PHP program should implement at least the DunePlugin::get_folder_view($media_url). To support the multiple folder views the plugin PHP program should implement DunePlugin::get_next_folder_view($media_url). To support lazy-loading of regular folders the plugin PHP program should implement DunePlugin::get_regular_folder_items($media_url) consistently with the DunePlugin::get_folder_view($media_url). To apply/save changes in setup settings the plugin PHP program should implement DunePlugin::handle_user_input($params). The TV playback has optional features: - EPG browsing; - archive playback; - protected channels; etc. Both TV and VOD playback modes have optional feature: - variable stream URLs. To support minimal TV playback the plugin PHP program should implement DunePlugin::get_tv_info($media_url) and DunePlugin::get_tv_playback_url($media_url, $archive_tm_sec, $protect_code). To support EPG browsing the plugin PHP program should implement DunePlugin::get_day_epg($channel_id, $day_start_tm_sec); To support archive playback the DunePlugin::get_tv_playback_url(...) should accept non-zero $archive_tm_sec argument (consistently with the returned data from get_tv_info()); To support protected channels feature the DunePlugin::get_tv_playback_url(...) should accept non-empty $protect_code. To support variable TV stream URLs the plugin PHP progam should implement DunePlugin::get_tv_stream_url($playback_url). To support VOD playback the plugin PHP program should implement DunePlugin::get_vod_info($media_url). To support variable VOD stream URLs the plugin PHP progam should implement DunePlugin::get_vod_stream_url($playback_url). Typical PHP program notes ------------------------- The typical plugin PHP consists of the following. 1. The manifest file dune_plugin.xml containing: - plugin name - plugin caption - plugin type (php) and the main PHP program file (.php) - the list of entry points - the auto_resume specification If plugin provides IPTV service then it adds entry point to the TV menu. This entry point reacts as PLUGIN_OPEN_FOLDER to the ENTER remote key and PLUGIN_TV_PLAY to the PLAY remote key. If plugin provides some non-IPTV services then it adds one or more entry points to the Applications menu. Also typical plugin adds one entry point to the Setup->Applications menu. The plugins providing playback of video/audio streams should usually turn on the 'auto_resume' feature to allow the automatic resume of playback state after STB restart. 2. Folder hierarchy. Usually the TV entry point contains 2-level regular folder hierarchy: - 1st level contains list of TV channel categories. Each category item acts as folder when ENTER pressed. The TV playback is launched when PLAY is pressed; - 2ns level contains channels. Each channel item react as TV_PLAY to the both ENTER and PLAY remote keys. The entry points providing access to VOD services may have folder hierarchy of arbitrary depth splitting the movie database into categories. Each category is represented as regular folder having subcategories and movies as elements. The movie element opens the folder or Movie type. Movie playback can be launched from inside the movie folder. 3. Playback. Typically the TV playback is launched: - by pressing ENTER/PLAY remote button on the regular folder element representing channel; - by pressing PLAY on the regular folder element representing channel category; - by pressing PLAY on the TV entry point. Typically the VOD playback is launched: - by pressing ENTER/PLAY remote button on the regular folder element representing movie or movie series; - by pressing ENTER/PLAY on the PLAY button in the movie folder. Also the TV/VOD playback can be launched automatically on STB power-on in the autoresume use-case. 4. Setup screen. The entry point to the setup screen is located in Setup->Applications menu. Setup screen is implemented as plugin folder of 'Control folder' type. Typically setup screen contains 'Show in main screen' combobox with Yes/No values. The HANDLE_USER_INPUT GUI action and the corresponding handle_user_input() plugin operation should be used to apply changes and save settings in the persistent location. Typically the plugin cookies are used to keep setup settings locally. Plugin operations ----------------- The short description of the plugin operations. NOTE: see the dune_api.php for the complete list of fields for each output data type. 1. Get_folder_view() ~~~~~~~~~~~~~~~~~~~~ // PluginFolderView public function get_folder_view( /* [in] String */ $media_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); Returns current folder content representation data for the plugin menu folder identified by $media_url. This operation is called when Dune GUI executes PLUGIN_OPEN_FOLDER GUI action. Output data: class PluginFolderView { PluginFolderViewKind view_kind; union (PluginFolderViewKind) data; Boolean multiple_views_supported; PluginArchiveDef archive; } The 'archive' is the optional specification of the plugin archive used with this folder. See "Plugin archives" section for more details about plugin archives. The 'multiple_views_supported' specifies whether the multiple views are are available for this folder. See description of GET_NEXT_FOLDER_VIEW plugin operation for more details. The 'view_kind' can be one of the following: - PLUGIN_FOLDER_VIEW_REGULAR - PLUGIN_FOLDER_VIEW_CONTROLS - PLUGIN_FOLDER_VIEW_MOVIE The 'data' is specific for view_kind: - regular folders: PluginRegularFolderView - control folders: PluginControlsFolderView - movie folders: PluginMovieFolderView Regular folder data ~~~~~~~~~~~~~~~~~~~ class PluginRegularFolderView { ViewParams view_params; ViewItemParams base_view_item_params; ViewItemParams not_loaded_view_item_params; GuiActionMap actions; GuiTimerDef timer; Boolean async_icon_loading; Boolean async_icon_loading_pipelining; int async_icon_loading_max_connects; PluginRegularFolderRange initial_range; } The 'initial_range' specifies the initial range of folder elements. The initial range for simple (preloaded) folders should contain all folder elements. The initial range for lazy-loaded folders should contain the first chunk of data or even the empty list. See the description of Get_regular_folder_items() plugin operation. The 'view_params' specifies the whole folder representation paramsters such as num_cols, num_rows, async_icon_loading etc.. The 'async_icon_loading' specifies whether to use asynchronous icon loading by default. See "Asynchronous image loading" section for more details. The 'async_icon_loading_pipelining' specifies value used as CURLMOPT_PIPELINING for asynchronous image loading (see libcurl documentation for more details). The default value is true. NOTE: Available in firmware 120616+. The 'async_icon_loading_max_connects' specifies value used as CURLMOPT_MAXCONNECTS for asynchronous image loading (see libcurl documentation for more details). The default value is 8. NOTE: Available in firmware 120616+. The 'base_view_item_params' specifies the default values for representation parameters of each folder element. The 'not_loaded_view_item_params' specifies the representation of the special state of each folder element. It is used when element's image is (1) not yet loaded or (2) loaded with error (loading failed). NOTE: currently this value is ignored if ViewParams::async_icon_loading == false. The 'actions' specifies the {event -> GUI action} mapping for interaction with user. The 'timer' allows to specify timer event delay. The timer event will be generated only once, but timer can be reset using ChangeBehaviour GUI action. Control folder data ~~~~~~~~~~~~~~~~~~~ class PluginControlsFolderView { Array defs; int initial_sel_ndx; PluginFolderViewParams params; } class PluginFolderViewParams { Boolean paint_path_box; Boolean paint_content_box_background; String background_url; } The 'defs' specifies list of GUI control definitions. See the "GUI controls" section for more details. The 'initial_sel_ndx' specifies the 0-based index of GUI control to gain focus first. The special value of -1 value indicates that default (first) GUI control should be focused first. Movie folder data ~~~~~~~~~~~~~~~~~ class PluginMovieFolderView { PluginMovie movie; String left_button_caption; GuiAction left_button_action; Boolean has_right_button; String String right_button_caption; GuiAction right_button_action; Boolean has_multiple_series; Boolean series_media_url; VAlign poster_valign; PluginFolderViewParams params; } class PluginFolderViewParams { Boolean paint_path_box; Boolean paint_content_box_background; String background_url; } The 'movie' specifies a number of movie properties. See the list of movie properties below. The 'left_button_caption' specifies caption of the left button. This property is optional, the 'Play' is used by default. The 'left_button_action' specifies GUI action assigned with left button. This value is optional, the VOD_PLAY gui action is used by default. The 'has_right_button' specifies whether button in the right-bottom corner of movie folder page should be painted. The 'right_button_caption' specifies caption of the right button. The 'right_button_action' specifies GUI action assigned with right button. The 'has_multiple_series' specifies the effect of pressing ENTER remote key on the PLAY GUI button located in the left-bottom corner of movie folder page: - when FALSE => PLUGIN_VOD_PLAY GUI action is executed - when TRUE => PLUGIN_OPEN_FOLDER GUI action is executed with explicit media_url taken from 'series_media_url' parameter. This scheme is designed to implement use-case of series, i.e. movie divided into series. In this case pressing ENTER remote key should have effect of opening the list of series. The 'series_media_url' is used with 'has_multiple_series' = true. It identifies the folder which should be opened when user press ENTER remote button having PLAY button focused. The 'poster_valign' specifies vertical alignment of poster. It is used when poster aspect ratio does not respect the default poster placeholder. NOTE: Available in firmware 120610+. class PluginMovie { String name; String name_original; String description; String poster_url; int length_min; int year; String directors_str; String scenarios_str; String actors_str; String genres_str; String rate_imdb; String rate_kinopoisk; String rate_mpaa; String country; String budget; Map details; Map rate_details; } - The 'details': additional pars in the main (scrollable) area. - The 'rate_details': additional lines in the ratings area (under poster). 2. Get_next_folder_view() ~~~~~~~~~~~~~~~~~~~~~~~~~ // PluginFolderView public function get_next_folder_view( /* [in] String */ $media_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); Returns next folder view for the plugin menu folder identified by $media_url. Some regular folders may have several views (e.g. with different num_rows, num_cols, different size of icons etc..). Such views can be switched by pressing A_RED remote button. To enable this feature for particular folder, plugin should specify PluginFolderView::multiple_views_supported == true. In this case pressing A_RED will cause Get_next_folder_view() to be called. See Get_folder_view() plugin operation description for more details. 3. Get_regular_folder_items() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // PluginRegularFolderRange public function get_regular_folder_items( /* [in] String */ $media_url, /* [in] int */ $from_ndx, /* [inout] Map: Key -> Value */ &$plugin_cookies); Returns the specified chunk of folder element for the folder identified by $media_url. This is part of lazy-loading feature of regular folders. Dune GUI never calls this operation for simple (preloaded) folder. The Get_regular_folder_items() operation is called for lazy-loaded folder each time some not yet loaded elements should be visualized (typically when user scrolls though the folder elements). The folders element are cached in memory until folder is exitted. See Get_folder_view() operation description for more details. 4. Get_tv_info() ~~~~~~~~~~~~~~~~ // PluginTvInfo public function get_tv_info( /* [in] String */ $media_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); Returns data needed to launch plugin TV playback. The $media_url argument is used as hint about what channel should be played first. This operation is called when Dune GUI executes PLUGIN_TV_PLAY GUI action. The output data of get_tv_info: class PluginTvInfo { unixtime_t server_time; List groups; List channels; Boolean show_group_channels_only; Boolean favorites_supported; List favorite_channel_ids; String favorites_icon_url; String initial_group_id; String initial_channel_id; Boolean initial_favorites; unixtime_t initial_archive_tm; GuiActionMap actions; GuiTimerDef timer; Boolean ip_address_required; Boolean valid_time_required; EpgMode epg_mode; PluginFontSize epg_font_size; Boolean epg_day_use_local_tz; int epg_day_shift_sec; Boolean custom_protect_code_handling; Boolean subtitles_osd_enabled; PluginArchiveDef archive; } The 'server_time' specify the current time to be used during TV playback. The local time is used if server time is non-positive. The 'groups' and 'channels' specify the list of channels and the list of channel groups. See the description of group and channel properties below. The 'show_group_channels_only' specifies the way channels are grouped. The plugin TV browser OSD consists of 3 columns: - 1st column contains list of groups; - 2nd column contains list of channels for the selected group; - 3rd column contains list of EPG programs for the selected channel and the choosen day. - if ['show_group_channels_only' == false] the 2nd column contains all channels sorted by groups not depending on what group is selected. This mode requires the 1-to-N relationship between groups and channels, i.e. each channel should belong to exactly one group. The group selection in 1st column is adjusted automatically when user scrolls channel list in 2nd column. - if ['show_group_channels_only' == true] the 2nd column contains channels of the selected group only. This mode suports N-to-N relationship between groups and channals: channal can be included into multiple groups. As a consequence user has to move focus between 2nd and 1st columns by pressing LEFT/RIGHT to select channel from another group. When 'favorites_supported' enables *favorites* feature including: - special "favorites" group added to the list of groups; - special key handling for modification of the list of favorite channels. In particular Dune GUI calls Change_tv_favorites() operation when user press D_BLUE, B_GREEN, C_YELLOW remote keys. The implementation of Change_tv_favorites() should write the list of favorite channels to the persistent storage (e.g. by means of cookies). The 'favorite_channel_ids' specify the list of favorite channels. The 'favorites_icon_url' specify the icon for "favorites" group. The 'initial_group_id', 'initial_channel_id', 'initial_favorites' and 'initial_archive_tm' specify the initial state of playback and selection. All these properties are optional; if property is unset then it is automatically set to the appropriate value. If positive value given, the 'initial_archive_tm' specify that archive playback should be started from the given timestamp (GMT unixtime). The 'actions' specifies the {event -> GUI action} mapping for interaction with user. NOTE: Available in firmware 131029_b9+. The 'timer' allows to specify timer event delay. The timer event will be generated only once, but timer can be reset using ChangeBehaviour GUI action. NOTE: Available in firmware 131029_b9+. The 'ip_address_required' and 'valid_time_required' specify the additional requirements for the TV playback. See the desciption of the similar fields in plugin manifest for more details. In particular, it is common that some plugins do not require valid current time for browsing groups/channels in Dune menu but they do requre valid time for TV playback. The 'epg_mode' it can take 3 values: - "disabled": the get_day_epg() calls are avoided, but EPG-column is still shown with "No program available." text. This mode should be used if no EPG is available at all. The concrete behaviour may be changed in future. (*) update in firmware 130726_b6+: EPG column not shown at all - "use_day_request": the default mode. - "get_from_stream": not implemented yet. The 'epg_font_size' specify EPG font size. PHP constants available: FONT_SIZE_NORMAL, FONT_SIZE_SMALL The 'epg_day_use_local_tz', 'epg_day_shift_sec' specify a start of EPG day. If epg_day_use_local_tz is false, EPG day is started from 00:00 (GMT) + epg_day_shift_sec, otherwise it is started from 00:00 (current time zone) + epg_day_shift_sec. NOTE: Available in firmware 121114+. The 'custom_protect_code_handling' enables the more flexible protect code handling for channels with 'is_protected'=true: if get_tv_playback_url() return string 'protected' then protect-code dialog is shown, if return other string => stream is considered non-protected. NOTE: Available in firmware 121116+. The 'subtitles_osd_enabled' enables/disables the subtitles OSD feature: OSD control which shows the list of available subtitles and allows to switch between them. Enabled by default. NOTE: Available in firmware 140521_b9+. NOTE: The subtitles OSD was not available for plugins in earlier firmware versions. Each group has the following properties: class PluginTvGroup { String id; String caption; String icon_url; } The 'id' specifies group identifier. The 'caption' and 'icon_url' specify group representation. Each channel has the following properties: class PluginTvChannel { String id; String caption; List group_ids; String icon_url; int number; Boolean have_archive; Boolean is_protected; Boolean recording_enabled; int buffering_ms; int timeshift_hours; int past_epg_days; int future_epg_days; int epg_icon_width; int epg_icon_height; int epg_icon_x_offset; int epg_icon_y_offset; int archive_past_sec; int archive_delay_sec; Boolean playback_url_is_stream_url; } The 'id' specifies channel identifier. The 'caption' and 'icon_url' specify channel representation. The 'group_ids' specifies groups this channel belongs to. There should be at least one group specified. Some plugins allow channel to belong to multiple groups, the others are not. See the description of PluginTvInfo::show_group_channels_only for more details. The 'number' allows to assign the concrete number to TV channel. If number <= 0 => the number will be assigned automaticaly to the first unused positive integer. The 'have_archive' enables archive feature for this channel. If enabled, the corresponding support in the implementation of Get_tv_playback_url() operation whould be provided. See "Plugin TV archive playback" section for more details about TV archive playback. The 'is_protected' marks this channel as protected, i.e. restricted for users who do not know the key. If plugin have some protected channels, the corresponding support in the Get_tv_playback_url() should be provided. The 'recording_enabled' specifies whether recording is enabled for this channel. The 'buffering_ms' specify the prebuffering time for channel playback. The 'timeshift_hours' specify the timeshift in hours. NOTE: not implemented yet. The 'past_epg_days', 'future_epg_days' specify the limits of scrolling the EPG. The default values are 14. The 'epg_icon_width', 'epg_icon_height': positive integers, dimensions for the EPG program icons. The 'epg_icon_x_offset', 'epg_icon_y_offset': signed integers allowing to adjust position of EPG program icons. See description of PluginTvEpgProgram::icon_url for more details. NOTE: the 'epg_icon_*' properties available in firmware 150527_r10+. The 'archive_past_sec' specifies the maximum time interval from current moment and the last moment in the past the archive is available for. See "Plugin TV archive playback" section feature for more details about TV archive playback. The 'archive_delay_sec' specifies the time interval in seconds between the current moment and the nearest moment in past the archive is available for. See "Plugin TV archive playback" section feature for more details about TV archive playback. So EPG program is considered to have archive if it has EpgProgram::have_archive flag set or if EpgProgram::start_tm_sec belongs to range [ current_time - PluginTvChannel::archive_past_sec, current_time - PluginTvChannel::archive_delay_sec ] The 'playback_url_is_stream_url' specifies whether the playback URL is stream URL for this channel. 5. Get_day_epg() ~~~~~~~~~~~~~~~~ // List public function get_day_epg( /* [in] String */ $channel_id, /* [in] int */ $day_start_tm_sec, /* [inout] Map: Key -> Value */ &$plugin_cookies); Returns list of EPG program structures for the given channel and given day. The day is specified by the unixtime of it's beginning (0:00). I.e. the $day_start_tm_sec is always divisible by 86400. The output should be a (possibly empty) list of structures sorted by time in ascending order: class PluginTvEpgProgram { unixtime_t start_tm_sec; unixtime_t end_tm_sec; String name; String description; Boolean have_archive; // Optional, default: false. String icon_url; // Optional. } The 'start_tm_sec' and 'end_tm_sec' are the program start/end time in unixtime format. The 'end_tm_sec' is optional (the -1 value means unset). The 'name' is required non-empty program name. The 'description' is optional program description. The 'have_archive' whether archive is available for program. This flag is used together with pair of properties 'archive_past_sec' and 'archive_delay_sec' of PluginTvChannel: the program is considered to have archive if it has 'have_archive' flag or it's 'start_tm_sec' belongs to range [ current_time - archive_past_sec, current_time - archive_delay_sec ] NOTE: 'have_archive' property is available in firmware 150526_r10+. The 'icon_url': URL of the small image to be painted in the EPG program block. This icon replaces the standard 'R' sign of the archived program, but can be used for non-archived programs too. This property is used together with 'epg_icon_width', 'epg_icon_height', 'epg_icon_x_offset', 'epg_icon_y_offset' of PluginTvChannel. The icon_url is ignored until epg_icon_width and epg_icon_height are specified. NOTE: 'icon_url' property is available in firmware 150527_r10+. 6. Change_tv_favorites() ~~~~~~~~~~~~~~~~~~~~~~~~ // GuiAction public function change_tv_favorites( /* [in] String */ $op_type, /* [in] String */ $channel_id, /* [inout] Map: Key -> Value */ &$plugin_cookies); Updates the list of favorite TV channels. Is called from TV playback mode when user press B_GREEN, C_YELLOW, D_BLUE remote buttons. The return value is the optional GUI action to be executed immediately. The following update operations supported: - PLUGIN_FAVORITES_OP_ADD - PLUGIN_FAVORITES_OP_REMOVE - PLUGIN_FAVORITES_OP_MOVE_UP - PLUGIN_FAVORITES_OP_MOVE_DOWN The implementation of change_tv_favorites() should update it's own persistent copy of favorites. There list of favorites inside Dune GUI will be updated automatically. 7. Get_tv_playback_url() ~~~~~~~~~~~~~~~~~~~~~~~~ // String public function get_tv_playback_url( /* [in] String */ $channel_id, /* [in] int */ $archive_tm_sec, /* [in] String */ $protect_code, /* [inout] Map: Key -> Value */ &$plugin_cookies); Returns the playback URL for the given channel as string. This operation is called for getting playback URL of: - live playback if $archive_tm_sec <= 0; - archive playback if $archive_tm_sec > 0. See "Plugin TV archive playback" section for more details about TV archive playback. The nonempty protect_code can be specified for protected channels. See "Protected TV channels" section for more details about protected TV channels. This operation is called each time the playback of particular channel is started or resumed. NOTE: some channels require to perform additional call to Get_tv_stream_url() for getting the actual stream URL having playback URL as the parameter. This use-case is indicated by PluginTvChannel::playback_url_is_stream_url == false. 8. Get_tv_stream_url() ~~~~~~~~~~~~~~~~~~~~~~ // String public function get_tv_stream_url( /* [in] String */ $playback_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); Returns the TV stream url having the TV playback url as input. Examples of possible TV stream urls: - Multicast TS-over-UDP stream (raw-UDP or RTP-over-UDP): - udp:/@ip-address:port - Unicast TS-over-HTTP stream: - http://ts://host[:port][/path] The reason for separation of terms 'playback URL' and 'stream URL' is the following. Sometimes plugin is unable to provide fixed URL for IPTV stream playback and can only provide a way of receiving this URL by means of remote call. And each call will return different result. To implement such plugins one should do the followig: - for each such channel the PluginTvChannel::playback_url_is_stream_url should be set to false - the Get_tv_playback_url() should return string which: 1. will be used for default playback engine initialization. So it must have correct prefix (e.g. http://ts://); 2. will be passed to the Get_tv_stream_url() operation as parameter. - the Get_tv_stream_url() should be implemented to decode the playback URL, perform the remote call, parse the results and return the actual IPTV stream URL. So lets call 'playback URL' such intermediate URL which is used for playback engine pre-initiallization and for being passed to Get_tv_stream_url() operation. Lets call 'stream URL' the result of Get_tv_stream_url() operation which is used for actual playback. NOTE: if PluginTvChannel::playback_url_is_stream_url is set to TRUE then playback URL is interpreted as stream URL and Get_tv_stream_url() is never called. 9. Get_vod_info() ~~~~~~~~~~~~~~~~~ // PluginVodInfo public function get_vod_info( /* [in] String */ $media_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); Returns data for launching plugin VOD playback using the given optional $media_url as the hint about what series to start from. This operation is typically called when user presses PLAY or ENTER remote button on some plugin folder item having the 'plugin_vod_play' action registered for the corresponding key event. This operation launches the playback of the list of movie series. Number of series >= 1. The output data of get_vod_info: class PluginVodInfo { String name; String description; String poster_url; List series; int initial_series_ndx; int initial_position_ms; int buffering_ms; Boolean advert_mode; GuiActionMap actions; GuiTimerDef timer; Boolean ip_address_required; Boolean valid_time_required; Boolean subtitles_osd_enabled; } class PluginVodSeriesInfo { String name; String playback_url; Boolean playback_url_is_stream_url; } The 'name', 'description', 'poster_url' and 'series[i]->name' are used for OSD representation. The 'series' specifies the list of series to play. They form a some sort of playlist. The 'initial_series_ndx' specifies the index of series to start playback from. The 'initial_position_ms' specifies the initial playback position in milliseconds. If negative value specified then the default initial position will be chosen (resume is possible). The 'advert_mode': if TRUE, the VOD playback will be started with the following limitations: - some features disabled: seek, jump, change playback speed and similar; - very limited OSD is shown (e.g. the info block and status never shown). However, some features are enabled: image setup, zoom, audio/subtitles setup etc. The 'ip_address_required' and 'valid_time_required' specify correct behaviour in the case of unavailable IP address and/or valid time. See the description of GET_TV_INFO operation output data for more details. The 'buffering_ms' specify the prebuffering time in milliseconds. NOTE: not implemented now. The 'actions' allows to specify actions to be executed in the following use-cases during VOD playback: - particular key is pressed. Currently only color-keys are supported (A_RED, B_GREEN, C_YELLOW and D_BLUE); The events of the following kinds can be used: GUI_EVENT_KEY_A_RED, GUI_EVENT_KEY_B_GREEN, GUI_EVENT_KEY_C_YELLOW, GUI_EVENT_KEY_D_BLUE. - timer event occured. The event of kind GUI_EVENT_TIMER should be used for the case. - playback stopped, or playback of another media_url started, or power off requested. The event of kind GUI_EVENT_PLAYBACK_STOP should be used for the case. If action is specified for playback stop, the actual playback stop/switch/shutdown will be delayed until action execution is finished. However, the additional STOP/POWER-OFF key press will cancel the action execution. - playback The 'timer' allows to specify timer event delay. The timer event will be generated only once, but timer can be reset using ChangeBehaviour GUI action. The 'series->playback_url' specify the playback URL for specific series. The 'series->playback_url_is_stream_url': - true => playback URL should be used as stream URL; - false => Get_vod_stream_url() operation should be called to get stream URL each time it is needed. See the descripton of GET_TV_STREAM_URL and GET_VOD_STREAM_URL for more details. The 'subtitles_osd_enabled' enables/disables the subtitles OSD feature: OSD control which shows the list of available subtitles and allows to switch between them. Enabled by default. NOTE: Available in firmware 140521_b9+. NOTE: The subtitles OSD was not available for plugins in earlier firmware versions. 10. Get_vod_stream_url() ~~~~~~~~~~~~~~~~~~~~~~~~ // String public function get_vod_stream_url( /* [in] String */ $playback_url, /* [inout] Map: Key -> Value */ &$plugin_cookies); Returns the VOD stream url having the VOD playback url as input. Examples of possible VOD stream urls: - MP4 container over HTTP (the most recommended one): - http://mp4://host[:port][/path] - TS container over HTTP: - http://ts://host[:port][/path] - Other container over HTTP (support/performance is limited): - http://host[:port][/path] - MMS (support is limited) - mms://host[/path] This operation is called each time the playback should be stared or resumed and the PluginVodInfo::series[ndx]->playback_url_is_stream_url is false. The PluginVodInfo::series[ndx]->playback_url is passed as a parameter. See description of Get_tv_stream_url() operation for more details. 11. Handle_user_input() ~~~~~~~~~~~~~~~~~~~~~~~ // GuiAction public function handle_user_input( /* [in] Map: Key -> Value */ &$user_input, /* [inout] Map: Key -> Value */ &$plugin_cookies); This operation is called during execution of HANDLE_USER_INPUT GUI action. Handle_user_input() operation may return another GuiAction object which will be executed immediately. This operation allows to implement many complex use-cases. Here are some of them: - regular folders with elements of different types: the HANDLE_USER_INPUT GUI action is mapped to some keys in definition of such folders. - setup screens with possibility to edit list of settings; the HANDLE_USER_INPUT is specified as confirm/apply action to text_fields/comboboxes or assigned to some "Apply" button. - implementing 'Control dialogs': flexible dialogs with custom list of controls. The behaviour of control dialogs is very close to the behaviour of control folders. GUI actions ----------- GUI action concept is an important part of plugin PHP API. It is used by plugins to specify the behaviour of Dune GUI in many use-cases. In particular, GUI action is often assigned to the event of pressing remote key by user. Also GUI action can be produced as a result of execution of another GUI action. Also GUI action can be returned by every operation instead of normal output in case of error. Each GUI action implies some algorithm to be performed by Dune GUI. The GUI action is received from plugin in form of GuiAction: class GuiAction { String handler_string_id; Any data; Map params; } The 'handler_string_id' specifies string identifier of the action type. Each action type will be described below. The 'data' specifies parameters of action. The 'data' is object of class, specific for the action type. The data classes for all supported action types will be described below. The 'params' specify additional action parameters of String type. These parameters are automatically filled with some kind of 'execution context' in particular use-cases desribed below. The GUI action is created to be executed by Dune GUI when some event occur. Here is the details of action execution: 1. First the Dune GUI chooses the executor according to the current GUI state. Now there are 3 types of executors: - Main executor. It is used during browsing of the Dune menu (browsing of the folder hierarchy), including the popup menus and dialogs. This executor can handle all types of actions. - Playback executor. This executor is used during plugin TV/VOD playback. Currently it may perform only the following action types: - PluginHandleUserInput - PluginShowError - ChangeBehaviour - PluginInvalidateFolders - PluginVodPlay (currently with some limitations: vod_info parameter is mandatory). - Light executor. It is used when handling the error-actions produced by plugin operations during plugin TV/VOD playback. Currently this executor may perform only PluginShowError action. 2. Executor analyzes type of the action. If type is not known for executor then execution is finished with status 'Action not recognized'. The actual not recognized action is also provided. 3. Executor performs actual execution of the given action. As a result of this step the following data is produced: - [int] execution status (Ok = 0, Error = -1, etc..) - [GuiAction] post action. Optional. If post action is not null then it should be executed immediately; so we replace the old action with new one and go to the step (2). Otherwise execution is finished with execution status returned from the last executed action. GUI event kinds --------------- There is a number of GuiEventKind constants, allowing to assign GuiAction to some GUI event. The most of them represent some remote buttons. Here is the list: - GUI_EVENT_KEY_ENTER - GUI_EVENT_KEY_PLAY - GUI_EVENT_KEY_A_RED - GUI_EVENT_KEY_B_GREEN - GUI_EVENT_KEY_C_YELLOW - GUI_EVENT_KEY_D_BLUE - GUI_EVENT_KEY_POPUP_MENU - GUI_EVENT_KEY_INFO - GUI_EVENT_TIMER - special event kind, representing a periodic activity. This event is generated once after a time-out specified in GuiTimerDef::delay_ms. Typically, new timer is specified by means of ChangeBehaviour GUI action. - GUI_EVENT_PLAYBACK_STOP - special event kind, representin playback stop. This event is generated on playback stop or power-off or before playback switch. In case some action is registered for event, the player first suspends playback, executes the action, waits for completion of the action chain, and then proceeds with actual stop, power-off or switch. (*) update in firmware 120902+ The following key events added available only in control dialogs: - GUI_EVENT_KEY_LEFT - GUI_EVENT_KEY_RIGHT - GUI_EVENT_KEY_UP - GUI_EVENT_KEY_DOWN - GUI_EVENT_KEY_P_PLUS - GUI_EVENT_KEY_P_MINUS - GUI_EVENT_KEY_NEXT - GUI_EVENT_KEY_PREV - GUI_EVENT_KEY_0 - GUI_EVENT_KEY_1 - GUI_EVENT_KEY_2 - GUI_EVENT_KEY_3 - GUI_EVENT_KEY_4 - GUI_EVENT_KEY_5 - GUI_EVENT_KEY_6 - GUI_EVENT_KEY_7 - GUI_EVENT_KEY_8 - GUI_EVENT_KEY_9 (*) update in firmware 130315_b6+ The following special event kinds added for "Global plugin actions": - GUI_EVENT_BOOT - GUI_EVENT_INSTALL - GUI_EVENT_UPDATE - GUI_EVENT_UNINSTALL (*) update in firmware 130819_b8+ All previously specified key events now can be used in plugin regular folders. NOTE: GUI_EVENT_KEY_ENTER cannot be overridden for empty plugin regular folders. The following event kinds added to be used in control dialogs and plugin regular folders: - GUI_EVENT_KEY_SETUP - GUI_EVENT_KEY_RETURN - GUI_EVENT_KEY_SELECT - GUI_EVENT_KEY_CLEAR (*) update in firmware 130904_b8+ The following event kinds added to be used in control dialogs and plugin regular folders: - GUI_EVENT_KEY_PAUSE (*) update in firmware 131029_b9+ All previously specified key events now can be used in plugin TV playback and plugin VOD playback. Also, the timer event can be in plugin TV playback (in the same way as in plugin VOD playback). The following event kinds added to be used in control dialogs, plugin regular folders, plugin TV playback, plugin VOD playback (with some restrictions described below): - GUI_EVENT_KEY_FWD - GUI_EVENT_KEY_REW - GUI_EVENT_KEY_SLOW - GUI_EVENT_KEY_STOP - GUI_EVENT_KEY_TOP_MENU - GUI_EVENT_KEY_POWER - GUI_EVENT_KEY_EJECT - GUI_EVENT_KEY_MODE - GUI_EVENT_KEY_VENDOR - GUI_EVENT_KEY_MUTE - GUI_EVENT_KEY_V_PLUS - GUI_EVENT_KEY_V_MINUS - GUI_EVENT_KEY_SEARCH - GUI_EVENT_KEY_ZOOM - GUI_EVENT_KEY_SUBTITLE - GUI_EVENT_KEY_REPEAT - GUI_EVENT_KEY_AUDIO - GUI_EVENT_KEY_REC - GUI_EVENT_KEY_DUNE - GUI_EVENT_KEY_URL (*) update in firmware 150529+ - GUI_EVENT_PLAYBACK_SWITCHED - this event is generated after switching playback to new media URL (including the very first one). - GUI_EVENT_PLAYBACK_GOING_TO_SWITCH - this event is generated before switching playback to new media URL playback. Unlike GUI_EVENT_PLAYBACK_STOP, this event is not generated in case of stop/power-off. Another difference from GUI_EVENT_PLAYBACK_STOP is that player does not wait for completion of action, registered for GUI_EVENT_PLAYBACK_GOING_TO_SWITCH event. NOTE: the following events cannot be overridden in plugin regular folders: - ZOOM, POWER, EJECT NOTE about control dialogs: some RC buttons have special meaning when text editor is active or combobox drop-down is shown and cannot be overridden by control dialog 'actions' map. List of GUI action types ------------------------ The full list of GUI action types and their explicit properties is provided below: 1. PluginOpenFolderAction Data: class PluginOpenFolderActionData { String caption; // optional; default = null (auto) String media_url; // optional; default = null (auto) } Action: browses into plugin folder. In more details: - folder caption is added to path block; - the Get_folder_view($media_url) plugin operation executed; - the output data is used to show contents of folder. Params: 'media_url': - if not null it is used as identifier of folder to be opened; otherwise media_url of the currently selected folder element is used. If no element is selected => action is ignored. 'caption': - is used as path element if not null; otherwise caption of currently selected folder element is used. Returns: post action: never status: ok/failed 2. PluginTvPlayAction Data: class PluginTvPlayActionData { String initial_group_id; // optional, default = null (auto) String initial_channel_id; // optional, default = null (auto) Boolean initial_is_favorite; // optional, default = false; unixtime_t initial_archive_tm; // optional, default = -1 (unset) } Action: launches TV playback. The selection and playback state is initialized using the given parameters. In more details: - media_url of currently selected folder element is taken; if none is selected then $media_url is null; - Get_tv_info($media_url) plugin operation is executed; - if output is invalid => action is failed; - TV playback state is initialized using received PluginTvInfo; - if some of initial_XXX parameters are set => they override the default selection and playback state. Returns: post action: never status: ok/failed 3. PluginVodPlayAction Data: class PluginVodPlayActionData { PluginVodInfo vod_info; // optional, default = null. } Action: launches VOD playback. If 'vod_info' is specified, it is used to initialize VOD playback. Otherwise, the get_vod_info($current_media_url) will be called and the result vod info will be used. The $current_media_url is the media_url of currently selected folder element; if none is selected then $media_url is null. Returns: post action: never status: ok/failed 4. PluginHandleUserInputAction Data: [none] Action: runs Handle_user_input(GuiAction::$params) plugin operation. The output data from Handle_user_input() is returned as post action. Returns: post action: the action returned from Handle_user_input() operation status: ok/failed 5. PluginShowErrorAction Data: class PluginShowErrorActionData { Boolean fatal; String title; List msg_lines; [optional] } Action: - shows error to the user. In playback state the single text line is shown in the center of the screen; in Dune menu state the dialog is shown with given title and message lines; - if (fatal == true) => the exit from plugin by fatal error is scheduled. In this case playback is stopped and Dune browser is moved to the top menu; - returns error status. Returns: post action: never status: failed 6. ShowDialogAction Data: class ShowDialogActionData { String title; List defs; GuiActionMap actions; // optional GuiTimerDef timer; // optional Boolean close_by_return; // optional, default = false int preferred_width; // optional, default = 0 (auto) int max_height; // optional, default = 0 (auto) int min_item_title_width; // optional, default = 0 (auto) int initial_sel_ndx; // optional, default = -1 (auto) Map params; // optional params } class GuiTimerDef { // Timer delay in milliseconds. Zero value is allowed here. int delay_ms; } Action: shows the specified control dialog and interacts with user until dialog is closed. The dialog shows the vertical list of controls, each control may be preceeded with optional title text. So dialog may consist of 1 or 2 columns. The special "vgap" control can be used to increase or decrease vertical gaps between controls. The vertical scrollbar appears when needed. - actions: allows to specify actions to be executed when particular key is pressed or timer event occured. The GUI_EVENT_KEY_ENTER behaviour cannot be changed. - timer: allows to specify the timer event. The timer event will be generated only once, but the timer can be reset using ChangeBehaviour GUI action. - close_by_return: whether to close dialog by pressing RETURN. - preferred_width: preferred dialog content width, including titles. When set to 0 (default), the dialog preferred width is automatically calculated using the preferred width of listed controls. - max_height: maximum dialog height. - min_item_title_width: minimum width resered for control titles. NOTE: Available in firmware 121201+. - initial_sel_ndx: index of focusable control to select first (index in list of all focusable controls: comboboxes, buttons and text fields). - params: additional customization parameters in form of key/value map. Supported keys: - frame_style=default|glass (PHP constants available: DIALOG_FRAME_STYLE_DEFAULT, DIALOG_FRAME_STYLE_GLASS). NOTE: Available in firmware 130824_b8+. - exit_seq= Sequence allowing to close dialog. Syntax of 'exit_seq' string: comma-separated list of GUI event kinds. Example: "key_1,key2,key3,key9,key_c_yellow". NOTE: Available in firmware 130904_b8+. Returns: post action: if dialog is closed by means of CloseDialogAndRun GUI action => the CloseDialogAndRunActionData::post_action is returned as post action status: ok 7. CloseDialogAndRunAction Data: class CloseDialogAndRunActionData { GuiAction post_action; // optional, default = null (none) } Action: Closes current control dialog and returns 'post_action' as a result of caller SHOW_DIALOG GUI action. This action is ignored when executed outside of control dialog. Returns: post action: none status: ok 8. ResetControlsAction Data: class ResetControlsActionData { List defs; int initial_sel_ndx; // optional, default = -1 (do not change selection) GuiAction post_action; // optional, default = null (none) } Action: replaces state of current control dialog or control folder. This action is ignored when executed outside of control dialog or folder. Returns: post action: from action data status: ok 9. ShowPopupMenuAction Data: class ShowPopupMenuActionData { List menu_items; int selected_menu_item_index; // optional, default = 0 } Action: shows the specified popup menu and interacts with user until popup menu is closed. If user chooses popup menu item then the corresponding action is returned as post action. Returns: post action: the action assigned to menu item chosen by user status: ok 10. StatusAction Data: class StatusActionData { int status; } Action: just returns the given status. Returns: post action: none status: ok 11. PluginUpdateFolderAction Data: class PluginUpdateFolderAction { PluginRegularFolderRange range; Boolean need_refresh; int sel_ndx; // optional, default = -1 (do not change current) } Action: Partially replaces state of current plugin regular folder: - if need_refresh is TRUE => cached folder state is cleared; - the given range is applied/replaced; - if sel_ndx >= 0 then focus is moved to element with given index. This action is ignored when executed outside of regular folder. Returns: post action: none status: ok 12. PluginInvalidateFolders Data: class PluginInvalidateFoldersActionData { List media_urls; GuiAction post_action; // optional, default = null (none) } Action: clears the cached data about plugin folders identified by given media_urls forcing them to be fully reloaded. This action is needed for the case when some actions inside child folder changed state of parent folder. Using this action one is able to force parent folder to reload it's state. If mentioned media_url is not cached => it is ignored. Returns: post action: from action data status: ok 13. PluginRunNativeCode GUI action. Data: [none] Action: loads native library 'native_code.so' from plugin installation directory and tries to invoke some function from this library. Returns: post action: none status: ok/failed 14. PluginClearArchiveCache GUI action. Data: class PluginClearArchiveCacheActionData { String archive_id; // optional, default = null (all) GuiAction post_action; // optional, default = null (none) } Action: deletes the cached data of the plugin archives from file system (if exist). If 'archive_id' is set => only the specified archive is cleared; otherwise all archives of the current plugin are cleared. Returns: post action: from action data status: ok 15. DvdPlay Data: class DvdPlayActionData { String url; } Action: launches DVD playback of the given url. Returns: post action: never status: ok/failed 16. BlurayPlay Data: class BlurayPlayActionData { String url; } Action: launches Blu-Ray playback of the given url. This action is available in firmware supports blu-ray playback. Returns: post action: never status: ok/failed 17. FilePlay Data: class FilePlayActionData { String url; } Action: launches normal playback on the single file pointed by given URL. URL should point to audio or video file or stream of supported format. Returns: post action: never status: ok/failed 18. PlaylistPlay Data: class PlaylistPlayActionData { String url; int start_index; } Action: launches normal file playback on the playlist built from the file or folder pointed by the given URL. URL may point to: - single local/network/http audio/video file or other supported network resource; - local/network/http playlist file (m3u, pls); - local/network folder containing audio/video/playlist files. The first played playlist item will be selected using the given "start_index", if valid. Returns: post action: never status: ok/failed 19. LaunchMediaUrl Data: class LaunchMediaUrlActionData { String url; GuiAction post_action; } Action: 1. build playlist recursively using the given URL as root element of hierarchy; 2. analyze the content of playlist and choose the actual executor; 3. run the chosen executor against the playlist. The recursive algorithm does the following: - enters recursively into local/network folders, local/network/http playlists (m3u, pls); - adds to the playlist audio/video/image files and streams, DVD/Bluray files and folders, Flash-applications (swf://* and local *.swf), WWW-urls (www://*, *.url, *.URL) Possible playlist executors are: - DVD player; it is chosen if playlist contains only one element which is either DVD folder or DVD disk image file; - Blu-ray player; it is chosen if playlist contains only one element which is either Blu-ray folder or Blu-ray disk image file; - Flash player; it is chosen if playlist contains only one element: either *.swf file or swf://* url; - Web browser; it is chosen if playlist contains only one element: either *.url/*.URL file or www://* URL; - Photo viewer: it is chosen if playlist contains only image files of known types (jpg, png, bmp, gif); - Plugin installer: it is chosen if playlist contains only one element: plugin_installer://* URL. - Plugin uninstaller: it is chosen if playlist contains only one element: plugin_uninstaller://* URL. - Plugin launcher: it is chosen if playlist contains only one element: plugin_launcher://* URL. - general file playback: otherwise. Returns: post action: from action data. NOTE: post-playback action execution now is not fully implemented; currently post action will be taken into account only if actual playlist executor is one of the following: - plugin installer; - plugin uninstaller; - plugin launcher; - general file playback (some restrictions are possible). In future, support for action post-execution will be added for more playlist executors. status: ok/failed 20. ShowMainScreen Data: class ShowMainScreenActionData { GuiAction post_action; } Action: switches to the main screen. This action is added to improve some auto_start use-cases. NOTE: current implementation has limitations. Returns: post action: from action data status: ok/failed 21. ShowBlackScreen Data: class ShowBlackScreenActionData { String bg_url; GuiAction post_action; } Action: Switches to the black screen with optional background picture. If 'bg_url' if specified, it is used as background picture instead of solid black background. NOTE: 'bg_url' available in firmware 130914_b8+. Returns: post action: from action data status: ok/failed 22. ChangeBehaviour Data: class ChangeBehaviourActionData { GuiActionMap actions; // Optional. GuiTimerDef timer; // Optional. GuiAction post_action; // Optional. } class GuiTimerDef { // Timer delay in milliseconds. int delay_ms; } Action: changes the behaviour in the current GUI container. Currently the following GUI containers supported: - regular folder; - control dialog; - VOD playback. In future, other containers will be supported too (control/movie folder, TV playback, general playback). If 'actions' is set, it replaces the existing one. If 'timer_ms' is set, the timer is restarted from the current time moment. Returns: post action: from action data status: ok/failed 23. OpenFolder Data: class OpenFolderActionData { String media_url; // optional; default = null (auto) } Action: browses into general folder. If media_url is not specified, the currently selected folder item will be opened in general way. Params: 'media_url': - if not null it is used as URL of folder to be opened. The URL can point local folders using smb://, nfs://, storage_name://, main_storage:// -- see http://dune-hd.com/firmware/misc/media_url.txt for more details. Also there can be dune_http:// URl (see http://dune-hd.com/firmware/misc/dune_folder_howto.txt for more details). Also there can be dune_setup:// URLs. For example, setup://applications, setup://video. Returns: post action: never status: ok/failed Note: Available in firmware 130315_b6+. 24. CloseAndRunAction Data: class CloseAndRunActionData { GuiAction post_action; // optional, default = null (none) } Action: If control dialog is active, then it works in the same way as CloseDialogAndRunAction. Does nothing, if some other kind of dialog is opened. If no dialogs is currently opened and some folder is active, then it closes folder (goes to the upper folder) and returns 'post_action'. Returns: post action: from action data when folder is acti status: ok Note: Available in firmware 121114+. Update in firmware 131029_b9+: Now this action works as 'stop playback' when called from TV playback / plugin VOD playback when no dialog is active. 24. PluginSystemAction Data: class PluginSystemActionData { String run_string; GuiAction post_action; // optional, default = null (none) } Action: Prepares a command for unix shell interpreter by prepending the plugin installation path to the 'run_string'. Then command is executed by running system(). Command can be run in background if 'run_string' ends with '&' character. For example, if plugin installation directory contains the bin/prepare.sh script, then it can be called by specifying it as global action 'boot' in plugin manifest and setting the 'run_string' to "bin/script.sh param1 param2" or "bin/script.sh param1 param2 &". Returns: post action: from action data status: ok Note: Available in firmware 130315_b6+. 25. RunBuiltinAction Data: class RunBuiltinActionData { String builtin_action_id; Map params; GuiAction post_action; // optional, default = null (none) } Action: This action is introduced for internal purposes. It runs some built-in functionality, identified by 'builtin_action_id' with parameters 'params'. The list of available public "built-in actions" depends on firmware and currently is empty. Returns: post action: from action data status: ok Note: Available in firmware 130315_b6+. 26. WaitForIpAddressAction Data: class WaitForIpAddressActionData { int timeout_sec; GuiAction post_action; // optional, default = null (none) } Action: If IP-address is not yet received by DHCP (in case of DHCP network configuration), then standard "Wait For IP Address" dialog is shown until IP address is received or 'timeout_sec' seconds passed. Returns: post action: from action data status: ok Note: Available in firmware 130914_b8+. 27. WgetAction Data: class WgetActionData { String url; String post_data; String result_key_prefix; GuiAction post_action; // optional, default = null (none) } Action: Performs HTTP request to 'url' with 'post_data', passing result status and data to the 'post_action'. This action is strongly not recommended to be used from PHP plugins; it was introduced for internal reasons. PHP plugins should use native 'curl' methods for performing HTTP requests. Returns: post action: from action data status: ok Note: Available in firmware 130924_b9+. 28. ChangeSettingsAction Data: class ChangeSettingsActionData { Map settings; Boolean reboot; Boolean restart_gui; GuiAction post_action; // optional, default = null (none) } Action: Changes internal Dune settings. The 'settings' specifies the setting_name -> setting_value key/value pairs to be changed. The list of available setting names and possible setting values is out of the current document's scope. The current settings are always stored in /config/settings.properties. The 'reboot' specifies whether to reboot STB immediately. The 'restart_gui' specifies whether to reboot STB immediately. NOTE: currently the 'reboot' is the only reliable way to apply setting from PHP plugin. This may change in future firmware versions. This action has no effect in plugin TV/VOD playback mode. Returns: post action: from action data status: ok Note: Available in firmware 140905_r10+. 29. PluginUpdateInfoBlockAction Data: class PluginUpdateInfoBlockActionData { String text_above; String text_color; // optional, default is 15 Boolean text_halo; // optional, default is false int text_y_offset; // optional, default is 0 GuiAction post_action; // optional, default = null (none) } Action: Updates current state of the information block. The information is shown sometimes in the lower part of screen, typically it is toggled by pressing INFO button. The changes are only visible when information block itself is visible. The following properties specifies the multi-line text message shown just above the upper bound of the information block. Once specified using PluginUpdateInfoBlock action, this message will always adjoin the information block until playback stops or another PluginUpdateInfoBlock adjusts or hides message. Action has no effect unless called in plugin TV or VOD playback mode. The 'text_above': multi-line message text. The text string is split automatically to fit the information block width. Special LF character ('\n') can be used to force line break. The empty or missing value can be used to hide message. The 'text_color': color index (integer 0..23, default=15) The 'text_halo': whether to draw black shade ('halo') around text to make it visible on the bright background. The 'text_y_offset': signed integer, allows to adjust vertical position of message. Returns: post action: from action data status: ok Note: Available in firmware 150526_r10+. 30. PluginUpdateEpgAction Data: class PluginUpdateEpgActionData { String channel_id; Boolean clear; int day_start_tm_sec; PluginTvEpgProgramList programs; GuiAction post_action; // optional, default = null (none) } Action: Updates the EPG information cached in player memory. There are 3 useful cases covered by this action: 1. Clear all cached EPG information: 'clear' is TRUE; 'channel_id', 'day_start_tm_sec', 'programs' not specified. 2. Clear cached EPG information for a particular channel and (optionally) put a specified program list for a specified day into cache instead: 'clear' is TRUE, 'channel_id', 'day_start_tm_sec', 'programs' are set correspondingly. 3. Just update EPG program list for the specified channel and day: 'clear' is FALSE, 'channel_id', 'day_start_tm_sec', 'programs' are set correspondingly. Action has no effect unless called in plugin TV playback mode. The 'channel_id': identifier of channel to be cleared/updated. Can be avoided allowing to clear EPG data for all channels. The 'clear': whether to clear EPG data. The 'day_start_tm_sec': day specification, the unix timestamp of day's beginning. Used together with 'channel_id' and 'programs'. Optional. The 'programs': list of EPG program data to be cached and used in GUI for given channel and day. Used together with 'channel_id' and 'day_start_tm_sec'. Optional. Returns: post action: from action data status: ok Note: Available in firmware 150528_r10+. 30. PluginUpdateOsdAction Data: class PluginUpdateOsdActionData { PluginOsdComponenetList components; GuiAction post_action; // optional, default = null (none) } class PluginOsdComponent { int x; int y; String image_url; int image_width; // optional, default is actual image size int image_height; // optional, default is actual image size String text; PluginFontSize text_font_size; // optional, default = FONT_SIZE_NORMAL String text_color; // optional, default = 15 Boolean text_halo; // optional, default = false } Action: Updates the state related with the new feature: possibility to paint the arbitrary number of custom images and text messages in plugin TV/VOD playback mode. These images/messages are painted under (before) the standard native OSD GUI components/controls: playlist browser, information block, etc.. The PluginUpdateOsdAction acts by replacing old sequence of OSD compenents with the new sequence. Once set by PluginUpdateOsdAction action execution, these components remain onscreen until removed/replaced by means of another PluginUpdateOsdAction execution or when playback stops. The PluginOsdComponent specifies either image or single-line text message, depending on whether 'image_url' or 'text' is set. The order of components specifies the actual order of their painting. Action has no effect unless called in plugin TV or VOD playback mode. The 'components': list of plugin OSD components. Empty list or null value specifies empty list of components (nothing to paint). PluginOsdComponent properties: The 'x', 'y': top left corner of image or text. The 'image_url', 'image_width', 'image_height': specify image to be shown. The actual image dimension are used in case of zero values of image_width/heigh, which is the default. The image loading is performed asynchronously. The 'text': single-line text message. It is not clipped except for screen bounds. The 'text_font_size': PLUGIN_FONT_NORMAL or PLUGIN_FONT_SMALL. Optional, default is PLUGIN_FONT_NORMAL. The 'text_color': color index (integer 0..23, default=15) The 'text_halo': whether to draw black shade ('halo') around text to make it visible on the bright background. Returns: post action: from action data status: ok Note: Available in firmware 150528_r10+. GUI controls ------------ GUI controls may appear in the following GUI control containers: - plugin control folders; - control dialogs. The look and behaviuor of control folders and control dialogs is very similar. GUI controls are positioned from top to the bottom, have 1 or 2 columns and each column is left-aligned. Each control may have optional 'title' text string. When title is specified, it is located in 1st column and control itself is located in 2nd column. When title is not specified, GUI control is located in 1st column and nothing is placed into 2nd column. The width of GUI controls in 2nd column can be automatically arranged (if GUI control does not specify width explicitly). Control folder is opened by means of PLUGIN_OPEN_FOLDER GUI action. The subsequent call to Get_folder_view() operation returns, among the other data, the control folder specification: class PluginControlsFolderView { Array defs; int initial_sel_ndx; } The plugin control folders can be closed in the same way as other Dune folders: by means of RETURN, TOP_MENU. Control dialog is opened by means of SHOW_DIALOG GUI action: class ShowDialogActionData { String title; List defs; Boolean close_by_return; // optional, default = false int preferred_width; // optional, default = 0 (auto) } If 'close_by_return' is true => dialog can be closed by RETURN; otherwise it cannot. The only other way to close dialog is to provoke execution of CLOSE_DIALOG_AND_RUN GUI action. Normally actions of this type are assigned to at least one button in control dialog. The core of control folder and dialog's specification is the list of GUI control definitions of type: class GuiControlDef { String name; String title; GuiControlKind kind; Object specific_def; Map params; } The 'name' specify identifier of GUI control. It is used for passing the current value of GUI control to the GUI actions invoked inside the container. The 'title' specify optional string title. The 'kind' specify kind of GUI action: enum GuiControlKind { GUI_CONTROL_LABEL, GUI_CONTROL_COMBOBOX, GUI_CONTROL_TEXT_FIELD, GUI_CONTROL_BUTTON, GUI_CONTROL_VGAP } The 'specific_def' contains GUI control parameters specific for the particular GUI control kind. The 'params' contains additional parameters in form of key/value string map. Label ~~~~~ Data: class GuiLabelDef { String caption; } Supported GuiControlDef::params keys: 'smart', 'max_lines', 'lines_vgap', 'pars_vgap'. NOTE: Available in firmware 130820_b8+. Details: GUI label is painted as fixed single-line text string. If string is too long, it is truncated in center. Parameters: 'caption' - the text string. Additional parameters: NOTE: Available in firmware 130820_b8+. 'max_lines' - if > 1 then label is auto-split into paragraphs by ASCII character 0xA (LF) and auto-split into lines by spaces. 'lines_vgap' - vertical gap between lines, in pixels. Default is 0. 'pars_vgap' - vertical gap between paragraphs, in pixels. Default is 'lines_vgap'. 'smart' - if '1' => the smart mode is turned on. In smart mode label is assumed to be a single line containing small icons and text strings. The 'caption' is assumed to be specific XML; see below the example. Smart label example: gui_skin://special_icons/controls_button_green.aai Next gui_skin://special_icons/controls_button_yellow.aai Cancel gui_skin://special_icons/controls_button_blue.aai Keyboard Smart label syntax: The takes url from element body, and 'width', 'height', 'dy' from attributes. The takes text from element body, and 'color', 'size', 'dy' from attributes. The 'color' shall be integer from '0' to '23', the 'size' shall be one of the 'normal', 'small', 'tiny'. The has only 'width' attribute. Combobox ~~~~~~~~ Data: class GuiComboboxDef { String initial_value; // Optional, default = null (first) List> value_caption_pairs; int width; // optional; default = -1 (auto) GuiAction confirm_action; // optional; default = null (none) GuiAction apply_action; // optional; default = null (none) } Details: GUI combobox is painted as standard Dune combobox. It can reside in 3 states: - unfocused: main component painted without focus; - focused: main component painted with focus; ENTER key is intercepted to swith to active state; - active; main component painted with focus and the drop-down menu component is painted; the arrow keys, ENTER and RETURN are intercepted. Parameters: 'value_caption_pairs' - the combobox model: the list of pairs {choice_value, choice_caption}. The choice_caption is painted on screen and the choice_value is used as choice identifier. 'initial_value' - the choice_value to be selected first. 'width' - the width of combobox; if not specified => the default width is used; actually combobox width cannot be less than the default value. 'confirm_action' - if specified, it is executed when user press ENTER in the drop-down menu. During confirm_action's execution the choice is not applied and combobox remains in 'active' state. If execution status is OK => choice is applied (combobox is switched into 'focused' state, main component is updated); othewise the choice is not applied and combobox remains in 'active' state. 'apply_action' - if specified, it is executed after changes are applied. The action execution status is ignored. Text field ~~~~~~~~~~ Data: class GuiTextFieldDef { String initial_value; // Optional, default = null (first) Boolean numeric; // Optional, default = false Boolean password; // Optional, default = false Boolean has_osk; // Optional, default = false Boolean always_active; // Optional, default = false int width; // optional; default = -1 (auto) GuiAction confirm_action; // optional; default = null (none) GuiAction apply_action; // optional; default = null (none) } Details: GUI text field is painted as standard Dune text field. It can reside in states: - unfocused: text field painted without focus; - focused: text field painted with focus; ENTER key is intercepted to switch to the active state; - active; text field painted with focus and some additional graphics; the arrow keys, ENTER, RETURN and some other keys are intercepted. Parameters: 'initial_value' - the initial string. 'numeric' - if true => only number characters can be added; 'pasword' - if true => all characters are visualized as '*'; 'has_osk' - if true => the on-screen keyboard is painted under the text field; NOTE: currenly the OSK height is not taken into account when components are layouted; so one should add VGapis to achieve nice looking of container. 'always_active' - if true => the 'focused' state of text field is avoided, i.e. text field is automatically switched to 'active' state when it gains focus. 'width' - the width of text field; if not specified => some predefined width is used. 'confirm_action' - if specified, it is executed when user press ENTER in the active state of control. During confirm_action's execution the changes in text string are not applied and text field remains in 'active' state. If execution status is OK => changes are applied and text field is switched to 'focused' state; othewise the changes are reverted and text field remains in 'active' state. 'apply_action' - if specified, it is executed after changes are applied. The action execution status is ignored. Button ~~~~~~ Data: class GuiButtonDef { String caption; int width; // optional; default = -1 (auto) GuiAction push_action; // optional; default = null (none) } Map params; Supported GuiControlDef::params keys: 'button_caption_centered' Details: GUI button is painted as standard Dune button. It can reside in states: - unfocused: button painted without focus; - focused: button painted with focus; ENTER key is intercepted to execute the push_action; Parameters: 'capiton' - the text over the button; 'width' - the width of button; if not specified => the default width is used; 'push_action' - if specified, it is executed when user press ENTER on focused button. Additional parameters: 'button_caption_centered' - boolean specifies whether button caption should be centered instead of being left-aligned. VGap ~~~~ Data: class GuiVGapDef { int vgap; } Details: This pseudo-control is used to change the default distances between GUI controls. It is not painted at all. Parameters: 'vgap' - the integer value to be added to the default distance between neighbour controls. If positive => distance increased, if negative => distance reduced. Gui action execution in GUI control containers ---------------------------------------------- Every action executed from GUI control takes additional parameters in the 'params' key-value maps The value of 'selected_control_id' is set to GuiControlDef::name of the currently selected control. This control is always the action producer. For each GUI control of type (combobox | text_field) the value of 'GuiControlDef::name' is set to the current state-value of this control. The state-value of text field is the current state of edited text; the state-value of comobox is the currently selected choice_value. Actually, the only GUI action which is used in GUI control containers is HANDLE_USER_INPUT. When plugin creates HANDLE_USER_INPUT action to be assigned to some GUI control, it should preliminary add some additional marks to 'params' map in order to be able to further recognize the context of action invocation from the implementation of Handle_user_input() operation. So, the implementation of Handle_user_input() can distinguish the different GUI control containers and have all information about the current state of all GUI controls in the current container. Preinstalled plugin resources ----------------------------- - Each plugin's installation may contain some resources (images). These images may be accessed using special url syntax: plugin_file://path/to/resource or plugin_file://%plugin_name%/path/to/resource The 1st syntax accesses the resources of the 'current' plugin (context-dependent). The 2nd syntax allows to use preinstalled resources of plugin with specified name. Plugin archives --------------- - Currently there is a way of caching the images used for representation of plugin menu folders in the system storage or flash memory storage (if supported). The PluginFolderView and PluginTvInfo may have the 'archive' field of type PluginArchiveDef: { string $id; map(string,string) $urls_with_keys; string $all_tgz_url; // optional long long total_size; # etc.. } So if one does NOT use plugin archive for folder, it leaves the PluginFolderView::archive as null, and writes the http://xxx/yyy.png image url to the corresponding ViewItemParams::icon_path. In this case, image will be http-downloaded many times. To use plugin archive, one should specify as PluginFolderView::archive: array( 'id' => 'myarchive', 'urls_with_keys' => array( 'xxx_key.png' => 'http://xxx/yyy.png', # etc ), 'all_tgz_url' => 'http://xxx/all.tgz', // optional 'total_size' => '1234567', ) and use special syntax for ViewItemParams::icon_path: plugin_archive://myarchive/xxx_key.png The execution of the PLUGIN_OPEN_FOLDER/PLUGIN_TV_PLAY operation first checks whether archive is specified and launches the 'Update Archive' dialog if needed. The Update Archive dialog checks whether archive is changed. Then it checks whether suitable storage exists and has enough free space. Then it and performes synchronization of the remote archive state with local cache (the extra files are deleted, missing files are downloaded). The keys are used as file names in the local cache. The 'total_size' value is trusted to be the cumulated size of all files in archive. The files can be downloaded by 2 different methods: - first, if number of images to download is more than some limit (now 50) => then gzipped tarball is downloaded from 'all_tgz_url' URL, unpacked and used as new local cache. The tarball's content should be consistent with keys of the 'urls_with_keys' map: it should contain the same set of files. - Otherwise (if < 50 files have to be downloaded or 'all_tgz_url' is unset) => the needed files are downloaded from their remote locations specified in 'urls_with_keys'. The handling of the icon URLs of type 'plugin_archive:///' work correctly even when Dune GUI was unable to keep local copy of archive. In this case plugin_archive:// URLs work as http:// URLs. Asynchronous image loading -------------------------- The asynchronous image loading is used in regular folders with FolderViewParams::async_icon_loading == true. If async_icon_loading == false then GUI is blocked until all visible icons are loaded. If async_icon_loading == true then icon files are downloaded in separate thread. During the download process the PluginRegularFolderView::not_loaded_view_item_params is used for representing the element and therefore another image may be used instead. NOTE: some image resources are never loaded asynchronously: 1. standard Dune skin resources, e.g. urls gui_skin://xxx 2. preinstalled plugin resources, e.g. urls plugin_file://xxx 3. resources from the already cached plugin archive, e.g. urls plugin_archive:///path Plugin TV archive playback -------------------------- Each plugin TV channel may have support for archive playback. To enable archive playback: - PluginTvChannel::have_archive should be set to true; - Get_tv_playback_url() + Get_tv_stream_url() should accept real unixtime values of 'archive_tm_sec' parameter and return the correct archive stream URL; - archive_past_days and archive_delay_sec of PluginTvChannel should be set appropriately. The default is 14 days and 31 minutes correspondingly. Protected TV channels --------------------- Currently the only way to enable the protect code checking for some channels one should do the following: - set PluginTvChannel::is_protected to true; - set PluginTvChannel::playback_url_is_stream_url to false if not done yet; - encode given protect_code into the result playback_url in the implementation of Get_tv_playback_url(); - ensure that Get_tv_stream_url() returns string 'protected' each time the protect code is incorrect and the actual stream url otherwise. Auto-resume ----------- The auto-resume feature is enabled by setting yes ... in the plugin manifest. The auto-resume procedure is triggered when STB is turned on or resumed from standby mode. This procedure tries to restore the last state of Dune GUI before STB was turned off or sent to standby. Currently only the following GUI states can be auto-resumed: - Live TV playback of the particular channel; - Archive TV playback of the particular channel and timestamp. - VOD playback of the particular movie. NOTE: the position of Dune GUI in folder hierarchy is not remembered now and therefore cannot be restored. It is possible to add the standard IP address and valid time requirements for the auto-resume: ... yes yes Also there is a way to specify custom GUI action to be executed instead of the default auto-resume procedure. Example: yes plugin_handle_user_input The all values of the resume_state.properties will be passed to the auto-resume actions as parameters. Including executable Linux programs into plugin ----------------------------------------------- If plugin archive contains 'bin' directory (at the same level as the plugin manifest), all files and subdirectories in the 'bin' directory will be made executable during installation. In other words, if the plugin needs executable files, they should be put under the 'bin' directory. Note, that ZIP-archives don't support UNIX file attributes, thus, even if an archive has been created from the executable files, those files will not have executable attribute after extracting from the archive. Files in 'www/cgi-bin' directory are processed the same way. Executables for SMP87xx ARM platforms should be put into the following directories, files in these directories are processed the same way: .platform.87xx/bin/ .platform.87xx/www/cgi-bin/ Interface language translations ------------------------------- Each plugin may provide additional local translation tables located in $install_dir_path/translations directory and having names dune_language_.txt. These files will be loaded to the global STB translation table on STB start or when interface language is changed by user. The local plugin translation files have the same format as global Dune translation files. They define additional keys to be added to the global table. The local translation keys are added to the plugin's own namescope and cannot conflict with the global keys. Only the owner plugin can access translation keys provided by itself. The translation keys can be used in so-called public strings. Such strings can be: 1. returned from DunePlugin interface calls; 2. declared in dune_plugin.xml. Public strings are easily recognized: they are intended to be painted on screen in some use-cases. For example, the plugin caption, entry point caption, and all other "captions" are the public strings. Each public string may be: 1. Just fixed string (not translated) "Movie" 2. Simple reference: "%tr%movie_caption" For example, if current interface language is "english" and plugin has the following record in it's translations/dune_language_english.txt: movie_caption = Movie and another on in translations/dune_language_french.txt: movie_caption = Film then this string will be dereferenced to "Movie" or "Film" depending on current interface language setting. 3. Extended public string syntax: extended_public_string ::= "%ext%" string_with_refs string_with_refs ::= string {ref string} ref ::= "" key_name {param} "" param ::= "<" param_name ">" string_with_refs ""; key_name ::= string param_name ::= string Examples: 1) Using of positional parameters: String: "%ext%movie_folder_contains__1

20

" Translation record: movie_folder_contains__1 = Folder contains %s movies. Result string: "Folder contains 20 movies." 2) Using of named parameters: String: "%ext%cur_time3213800" Translation record: cur_time3 = Current time is %{h}:%{m}:%{s}. Result string: "Current time is 21:38:00." HTTP server extension --------------------- The local STB HTTP server is configured to provide access to files in the following directories in plugin file structure: $install_dir_path/www/* - normal access; $install_dir_path/www/cgi-bin/* - access with CGI execution enabled. The following HTTP urls are mapped to these directories: http:///plugins//* http:///cgi-bin/plugins//* The following language constructions are provided for convenience in PHP code: DuneSystem::$properties['plugin_www_url'] = http://127.0.0.1/plugins// DuneSystem::$properties['plugin_cgi_url'] = http://127.0.0.1/cgi-bin/plugins// Auto-start specification in plugin manifest ------------------------------------------- The auto start specification in the plugin manifest dune_plugin.xml allows to enable automatic startup of the plugin when the plugin is declared as "main" plugin (there may be at most one plugin declared as "main" plugin). For more information about "main plugin", see the description of "/firmware/config/main_plugin_name.txt" here: http://files.dune-hd.com/partners/sdk/dune_custom_firmware.txt The auto_start section in plugin manifest affects the following use-cases: - STB power-on; - resume from the stand-by mode. For "main" plugin the section in dune_plugin.xml is taken into account; the section of other plugins is just ignored. The example of the auto_start section: ... main_tv plugin_open_folder ... NOTE: the 'plugin_open_folder' is just an example. Typically, the auto_start action should be the same as 'key_enter' action in the corresponding entry point. This specification will cause STB to enter the "main_tv" plugin folder on each startup (of course, if the described plugin is "main" plugin). Details: - entry_point_media_url (optional, default = unset) the media_url of the plugin entry point. On STB startup the folder containing the specified entry point will be entered and the entry point itself will be focused. If not set, the default folder will be opened on startup. - action (optional, default = unset) the action to be executed on startup (just after entry point is selected, if specified). - ip_address_required = yes|no (optional, default = no) - valid_time_required = yes|no (optional, default = no) if yes, the standard dialog will appear waiting for IP address or valid time. - run_action_before_auto_resume = yes|no (optional, default = no) By default, the auto-start action will not be executed when STB tries to auto-resume playback. Setting the 'run_action_before_auto_resume' to 'yes' will force STB to execute auto-start action even in the auto-resume use-case. See the details about the auto-resume feature in the corresponding section ('Auto-resume'). - skip_initial_dialogs = yes|no (optional, default = no) if yes, the action will be executed before the initial STB setup wizard; otherwise action will be executed after setup wizard. This only affects the use-case of first STB power-on after the Reset Settings procedure. - force_on_start = none|main_screen|black_screen - force_on_finish = none|main_screen|black_screen allows to specify the background for auto_start action execution. Configuring plugin auto-start via menu -------------------------------------- The user can manually configure the STB to automatically launch a certain plugin on STB boot. To do it: - First, add the plugin into the favorites menu (choose the plugin, press "POP UP MENU" RC button, choose "Add to favorites"). - Then, go into the favorites menu and enable autostart for the plugin (choose the plugin, press "POP UP MENU" RC button, choose "Enable autostart"). Image file formats (for icons etc) ---------------------------------- - JPEG - PNG with alphachannel - BMP with alphachannel - AAI with alphachannel - This is Dune HD proprietary format. - See: - http://dune-hd.com/firmware/misc/ - http://dune-hd.com/firmware/misc/AAImageGen-README.txt Ways to reference image files from plugins ------------------------------------------ - Image file from web server: - Icon path/URL: http://host[:port][path] - Image file from web server, preloaded/cached via plugin archive: - Icon path/URL: plugin_archive://archive-name/path - Image file built-in into plugin (part of plugin): - Icon path/URL: plugin_file://path-to-file - Example: plugin_file://plugin_icon.png - Image file built-in into firmware (part of standard GUI skin): - Icon path/URL: gui_skin://path-to-file - Example: gui_skin://large_icons/tv.aai - More information about GUI skins: - http://dune-hd.com/support/skins Features added in firmware version 120531_2200_beta --------------------------------------------------- Starting with the firmware version 120531_2200_beta, the following Dune PHP Plugins API extensions and improvements were added: - New GUI actions: - file_play - dvd_play - bluray_play - playlist_play - launch_media_url - change_behavior - show_black_screen - show_main_screen - New GUI events: - timer - playback_stop - New properties in existing data structures: - GuiAction::params - PluginInvalidateFoldersActionData::details - PluginInvalidateFoldersActionData::rate_details - PluginMovieFolderView::left_button_caption - PluginMovieFolderView::left_button_action - PluginMovieFolderView::params - PluginRegularFolderView::timer - PluginTvInfo::epg_mode - PluginVodInfo::initial_position_ms - PluginVodInfo::advert_mode - PluginVodInfo::actions - PluginVodInfo::timer - ShowDialogActionData::actions - ShowDialogActionData::timer - ShowDialogActionData::max_height - ShowDialogActionData::initial_sel_ndx - ViewItemParams::item_caption_color - ViewItemParams::item_sandwich_icon_scale_factor - ViewParams::paint_details_box_background - ViewParams::help_line_text_color - ViewParams::item_detailed_info_title_color - ViewParams::item_detailed_info_text_color - New data structures and their properties: - BlurayPlayActionData::url - ChangeBehaviourActionData::actions - ChangeBehaviourActionData::timer - ChangeBehaviourActionData::post_action - DvdPlayActionData::url - FilePlayActionData::url - GuiTimerDef::delay_ms - LaunchMediaUrlActionData::url - LaunchMediaUrlActionData::post_action - PlaylistPlayActionData::url - PlaylistPlayActionData::start_index - PluginFolderViewParams::paint_path_box - PluginFolderViewParams::paint_content_box_background - PluginFolderViewParams::background_url - PluginVodPlayActionData::vod_info - ShowBlackScreenActionData::post_action - ShowMainScreenActionData::post_action - New features related to plugin file structure: - {plugin_install_dir}/bin/ - The player automatically sets executable permissions on all files in this directory during plugin installation. - {plugin_install_dir}/www/{path} - The player automatically makes these files accessible via HTTP (locally inside the player, and from the local network): - http://localhost-or-dune-ip-address/plugins/{plugin_name}/{path} - {plugin_install_dir}/www/cgi-bin/{path} - The player automatically makes these CGI applications accessible via HTTP (locally inside the player, and from the local network): - http://localhost-or-dune-ip-address/cgi-bin/plugins/{plugin_name}/{path} - Other new features: - Ability to package FlashLite application into plugin and launch it when the user enters plugin entry point, or when PHP plugin code decides to call it. Supported via the new "launch_media_url" action. - Ability to package HTML page/application into plugin and launch it in web browser when the user enters plugin entry point, or when PHP plugin decides to call it. Supported via the new "launch_media_url" action. - If the plugin is pure FlashLite or HTML application and does not need to execute any PHP code, "plain" plugin type can be specified in plugin manifest instead of "php"; in this case, there is no need to include PHP program into the plugin and specify "program" parameter in plugin manifest. Implementing advanced playback control in PHP plugins ----------------------------------------------------- The following features of PHP API (introduced in firmware version 120531_2200_beta) can be used to implement advanced playback control use cases in PHP plugins. PluginVodInfo::timer PluginVodInfo::initial_position_ms PluginVodInfo::advert_mode GUI_EVENT_TIMER GUI_EVENT_PLAYBACK_STOP Examples: 1) Playback AD video before and after main video. First perform PluginVodPlay action with media_url pointing to AD pre-roll video, PluginVodInfo::advert_mode == TRUE, and GUI_EVENT_PLAYBACK_STOP event registered in PluginVodInfo::actions. When GUI_EVENT_PLAYBACK_STOP event occurs, another PluginVodPlay action should be performed: media_url pointing to main video, PluginVodInfo::advert_mode == FALSE, and GUI_EVENT_PLAYBACK_STOP event registered in PluginVodInfo::actions. When GUI_EVENT_PLAYBACK_STOP event occurs, another PluginVodPlay action should be performed: media_url pointing to AD post-roll video, PluginVodInfo::advert_mode == TRUE. The following plugin demonstrates this approach: dune_plugin_demo2_with_ad.zip 2) Playback AD video in the middle of main video. There is no direct support for this, but the following approach can be potentially used (not really tested, but should work if there are no bugs). Start main video playback with PluginVodInfo::timer specified with appropriate timer delay (one second or a few seconds), and GUI_EVENT_TIMER registered in PluginVodInfo::actions. When GUI_EVENT_TIMER event occurs, the plugin code should check the current playback position, and, if needed (it is time to show ad), request playback of AD media url: perform PluginVodPlay action with PluginVodInfo::advert_mode == TRUE and GUI_EVENT_PLAYBACK_STOP event registered in PluginVodInfo::actions. When GUI_EVENT_PLAYBACK_STOP event occurs, another PluginVodPlay action should be performed: media_url pointing to main video, PluginVodInfo::advert_mode == FALSE, and PluginVodInfo::initial_position_ms pointing to the position where the main video was interrupted by the ad. Checking the current playback position can be performed in the following way: Read "playback_position" field in the file "/tmp/run/ext_command.state". NOTE: this is not part of official PHP API, but can be used as a temporary solution. 3) Rememebering and resuming VOD playback position. Approach A: ~~~~~~~~~~~ Specify "auto_resume" feature in plugin manifest. If "action" is not specified, PHP engine will automatically resume VOD playback. If "action" is specified (required if PHP plugin needs to do some checking/processing before resuming VOD playback), see Approach B. Approach B: ~~~~~~~~~~~ Specify "auto_resume" feature in plugin manifest, and specify PluginHandleUserInputAction "action". Instead of standard auto resume processing, the specified action will be executed. Then, in PHP code, read the information required for auto-resume from the following file: /config/resume_state.properties NOTE: this is not part of official PHP API, but can be used as a temporary solution. Sample content of this file: mode = PLUGIN_VOD_PLAYBACK plugin_name = some_plugin plugin_entry_media_url = vod_category_list plugin_media_url = {"screen_id":"vod_scene_info","scene_id":"193115"} plugin_vod_id = 193115 plugin_vod_series_ndx = 0 plugin_vod_position_seconds = 37 plugin_tv_group = 1 plugin_tv_channel = 5 plugin_tv_is_favorite = 0 plugin_tv_archive_tm = 1343834591 Then, perform VOD playback with PluginVodInfo::initial_position_ms specified. Approach C: ~~~~~~~~~~~ The same as Approach B, but w/o using "auto_resume" feature in plugin manifest. The file "/config/resume_state.properties" is created by the system even if "auto_resume" feature is not used, and this file can be read and handled by PHP plugin code. Approach D: ~~~~~~~~~~~ Start main video playback with PluginVodInfo::timer specified with appropriate timer delay (one second or a few seconds), and GUI_EVENT_TIMER registered in PluginVodInfo::actions, and GUI_EVENT_PLAYBACK_STOP registered in PluginVodInfo::actions. When GUI_EVENT_TIMER event occurs, the plugin code should check the current playback position and remember it. (See above for the info how to do it.) When GUI_EVENT_PLAYBACK_STOP event occurs, the plugin code should persistently remember the latest playback position remembered when handling GUI_EVENT_TIMER events. Then, use the persistently remembered position when starting playback next time, by specifying PluginVodInfo::initial_position_ms. Plugin online update mechanism ------------------------------ Dune STB firmware includes support for online update of plugins. Each plugin may specify that it should be updated from from the given HTTP URL. When the user launches any entry point of the plugin, the system checks for available updates using this URL. If an update is available, it is automatically proposed for installation to the user. After the update is installed, the originally requested plugin entry point is launched. To enable online update for a plugin, the plugin manifest file ("dune_plugin.xml") should include the following XML specification inside the root ("dune_plugin") XML-element: 5 130528_1700 2 http://some-server/some-path/update_info.xml 0 no no Here, the semantics of XML-elements is the following: version_index The numeric version index, which should increase each time a new plugin version is published on the server. Is not shown in the UI. version The version caption, which is shown in the UI when the system proposes/performs update to this version. check_update / schema Update schema version. The version 1 is legacy and must not be used. The version 2 must be used. url The HTTP URL pointing to "update_info" XML document. timeout The timeout (in seconds). It specifies minimum timeout between attempts to check available updates performed. If the value is 0, the system checks for available updates everytime when the user launches any entry point of the plugin. required The flag indicating if the update is required or not. Possible values are "yes" and "no". auto The flag indicating whether background autocheck for updates is enabled for plugin. It is disabled by default. NOTE: 'auto' feature is available in firmwares 150430_r10+. The "update_info" XML document has the following structure: 2 plugin_name 5 130528_1700 no no http://some-server/some-path/5.tgz a209a234fc9c518d3a165750a1f0dde4 2244608 plugin_caption Here, the semantics of XML-elements is the following: schema The value must be 2. name Plugin name. caption Plugin caption. plugin_version_descriptor / version_index Plugin version index corresponding to the plugin available on the server. Must be the same as the plugin version index specified in the plugin archive available on the server. plugin_version_descriptor / version Plugin version caption corresponding to the plugin available on the server. Must be the same as the plugin version caption specified in the plugin archive available on the server. plugin_version_descriptor / beta The flag indicating if this plugin update is beta or non-beta (stable). Possible values: "yes" (beta), "no" (non-beta). Reserved for future use, currently the value is ignored; it is recommended to use "no" value. plugin_version_descriptor / critical The flag indicating if this plugin update is critical. Possible values: "yes" (critical), "no" (non-critical). The value "yes" can be used for plugins which specify "check_update / timeout" = 0 and "required" = "yes" in their manifest file; in this case, the system does not allow to launch the old version of the plugin if plugin update is available on the server and this plugin update is critical. plugin_version_descriptor / url HTTP URL pointing to the plugin archive in the .tar.gz format. The content of the .tar.gz archive must be exactly the same as the content of the regular plugin installed archive (dune_plugin*.zip file). plugin_version_descriptor / md5 MD5 checksum of the .tar.gz file specified in "plugin_version_descriptor / url" element. plugin_version_descriptor / size Specifies the storage space (in bytes) occupied by the plugin after it is installed into the flash memory of the STB. Can be computed using the following algorithm: "du -sk /path/to/folder" * 1024. plugin_version_descriptor / caption Plugin caption. This caption will be used in the UI dialogs shown during plugin update. If plugin caption does not change between plugin versions, it should be the same as plugin caption specified in the plugin manifest file. NOTE: The "update-info" XML document may contain multiple "plugin_version_descriptor" elements. Only the one with the biggest value of version_index is actually used; the rest are ignored. Signed plugins -------------- Plugins preinstalled in the standard retail Dune firmware or available in the standard retail Dune firmware via Dune Store are specially signed by Dune HD. Signed plugins include the following additional files: dune_plugin.sign This file contains the plugin signature. dune_plugin_signer_id.txt This file contains "signer ID" -- an identifier of the key used for plugin signing. Allowed values are: - The string "com.dune-hd" -- reserved for the use by Dune HD only. - Customer ID of the custom firmware build. (*) Available in firmware 150326_r10+. When a plugin is signed, the system verifies the signature of the plugin and refuses to use it if the signature does not match the plugin or if the specified signer ID is not allowed. Custom firmware versions (e.g. used by operators) may be configured to allow only signed plugins (provided/approved by Dune HD and/or the customer) and disallow unsigned plugins (provided by 3-parties and not approved by the customer). Using custom signing keys ------------------------- NOTE: This functionality is available in firmware 150326_r10+. To sign plugins using a custom signing key, perform the following steps: 1. Generate a pair of private and public DSA keys for plugin signing and vertification. Perform the following commands on a Linux PC: openssl dsaparam -out dsaparam.pem 2048 openssl gendsa dsaparam.pem -out plugin_private_key.pem openssl dsa -in plugin_private_key.pem -pubout -out plugin_public_key.pem 2. Sign plugins using private plugin key. Download "plugin_sign" utility, using one of the following options: http://files.dune-hd.com/partners/sdk/misc/plugin_sign.x86 A precompiled executable for Linux PC (x86), dynamically linked. Requires libcrypto 0.9.8 to be installed in the system. http://files.dune-hd.com/partners/sdk/misc/plugin_sign_static.x86 A precompiled executable for Linux PC (x86), statically linked. Use the utility in the following way (on a Linux PC): /path/to/plugin_sign.x86 /path/to/plugin/dir {signer_id} plugin_private_key.pem Here, {signer_id} should be the customer ID of the custom firmware. The utility will generate "dune_plugin.sign" and "dune_plugin_signer_id.txt" files in the plugin directory. 3. Include the public plugin key into the custom firmware. Put the file "pluging_public_key.pem" into the following location: /firmware/config/plugin_key.pem Plugins signed by the corresponding private key and using the value of "signer ID" equal to the value of "customer ID" of the custom firmware will be allowed by this custom firmware. Global plugin actions --------------------- NOTE: Available in firmware 130315_b6+. The mechanism of "global plugin actions" allows a plugin to force the STB to perform certain actions (e.g. launch a shell script shipped within a plugin) on certain system events (e.g. on STB boot or plugin install/uninstall). This mechanism is available in firmware versions 130515_2104_b6+. Supported system events: boot Is launched on cold STB boot immediately after the STB engine initializes plugins. Is launched in all cases, even if custom stb_home application is started instead of the native Dune GUI. At this moment, /tmp/sysinfo.txt is not available yet and other parts of the STB engine may not be initialized yet. Can modify visibility of plugin entry points. Cannot launch dialogs, playback and other GUI-related actions. boot_end Is launched on cold STB boot at the very end of the STB boot process. Is launched in all cases, even if custom stb_home application is started instead of the native Dune GUI. At this moment, it is guaranteed that /tmp/sysinfo.txt file is already available. Cannot launch dialogs, playback and other GUI-related actions. NOTE: Available in firmware 130917_b9+. gui_start Is launched during startup of the native Dune GUI -- on STB boot or when the STB exists software standby mode. Is not launched if custom stb-home application is started instead of native Dune GUI. Is launched after the initial setup wizard of the native Dune GUI. NOTE: Available in the firmware 130914_b8+. install: Is launched immediately after plugin has been installed. update: Is launched immediately after plugin has been updated. uninstall: Is launched before plugin is deleted. To perform an action on a system event, the plugin should declare corresponding global action in the plugin manifest file. The action can be any standard plugin GUI action, or "plugin_system" action which allows to launch an executable file shipped within the plugin. For "boot" system event, only "plugin_system" action is supported. Example of defining global actions in the plugin manifest file: ... plugin_system bin/smbserver_ctl.sh start & plugin_system bin/smbserver_ctl.sh start & plugin_system bin/smbserver_ctl.sh start & plugin_system bin/smbserver_ctl.sh stop & ... Regular folder GUI customization -------------------------------- Here are some specific notes about ViewParams and ViewItemParams used for regular folder GUI customizataion. Additional information can be found here: http://dune-hd.com/support/misc/dune_folder_howto.txt The ViewParams are assigned with some regular folder and specify different aspects of folder content visualisation. The ViewItemParams are assigned with each folder element and (together with folder's ViewParams) affect it's visualication inside parent folder. Normally regular folder screen is divided into 3 areas: - "path block" in the top (optional) - "content block" in the bottom-left - "details block" in the bottom-right The rectangular content block of regular folder is divided into small 'item' rectangles of equal dimentions, using number of rows/columns as parameter. Each non-empty item rect normally contains and icon and a caption text. The details block normally contains additional information about currently selected content item: some icon in the top and a structured text below. List of ViewParams properties ----------------------------- - num_cols (positive integer, mandatory) - num_rows (positive integer, mandatory) Content area grid parameters. - animation_enabled (boolean, default=yes) Whether to enable cursor animation. - scroll_animation_enabled (boolean, default=yes) Whether to enable content scrolling animation. Currently has effect only on horizontal orientation. NOTE: Available in firmware 131203_b9+. - orientation (vertical|horizontal, default=vertical) NOTE: Available in firmware 131203_b9+ - cycle_mode_enabled (boolean, default=no) When enabled, selection rectangle is always in center while folder elements are scrolled left/right. Has effect only on horizontal orientation with single row and odd number of columns >= 5. NOTE: Available in firmware 131203_b9+ - cycle_mode_gap (yes|no|auto, default=no) Specifies whether to paint additional horizontal gap between last and first folder elements. "Auto" means to paint gap when number of element greater then number of columns. Has effect only when cycle_mode is effectively enabled. NOTE: Available in firmware 131203_b9+ - cycle_mode_gap_width (integer, default=auto=half item width) Specifies horizontal gap width. Has effect only when cycle_mode is effectively enabled. NOTE: Available in firmware 131203_b9+ - cycle_mode_gap_icon_path (image URL string, default=unset) Specifies icon to be painted in the middle of horizontal gap. Has effect only when cycle_mode is effectively enabled. NOTE: Available in firmware 131203_b9+ - background_path (image URL string, default=unset) - background_x (non-negative integer, default=0) - background_y (non-negative integer, default=0) - background_width (positive integer, default=real image width) - background_height (positive integer, default=real image height) - optimize_full_screen_background (boolean, default=false) - background_order (before_all|before_icons|after_all, default=before_icons) If background_path is set, then specifies custom background which is painted after the default full-screen background. The background properties have effect only when backgroun_path is set. The 'optimize_full_screen_background' allows to avoid paining of the skin's background; in this case background_order should be before_all and the effective custom background rectangle should cover all screen. The 'backgroun_order' allows to specify backround painting order: - before_all: before all other graphics; - before_icons: after glasses, but before icons/captions/focuses. - after_all: after all other graphics. - scroll_path (image URL string, default=unset) - scroll_x (non-negative integer, default=auto) - scroll_y (non-negative integer, default=auto) - scroll_height (positive integer, default=auto) Allows to override default skin scrollbar graphics. - mark_path (image URL string, default=unset) - mark_dx (integer, default=0) - mark_dy (integer, default=0) - mark_scale_factor (double, default=1.0) Allows to override default skin folder element mark icon. The mark_dx and mark_dy: if mark_path is set => offset from the top-left corner of icon; otherwise => offset from the default position near the right-top corner of icon. - paint_path_box (boolean, default=true) - paint_path_box_background (boolean, default=true) NOTE: Available in firmware 130818+ - paint_widget (boolean, default=true) NOTE: Available in firmware 130818+ - paint_widget_background (boolean, default=true) NOTE: Available in firmware 130818+ - paint_content_box_background (boolean, default=true) - paint_scrollbar (boolean, default=true) - paint_icon_selection_box (boolean, default=true) - paint_help_line (boolean, default=true) - paint_details (boolean, default=true) - paint_details_box_background (boolean, default=true) Allows to hide some graphics. - help_line_text_color (integer color index, currently from 0 to 23; default is 23) Color of text in help line. - icon_selection_box_dx (integer, default=auto) - icon_selection_box_dy (integer, default=auto) - icon_selection_box_width (positive integer, default=auto) - icon_selection_box_height (positive integer, default=auto) Allows to adjust the icon_selection_box size and position. By default the selection is painted over content item rectangle. - paint_icon_badge_box (boolean, default=false) Enables badge mode. In badge mode the "badge" cut-image from skin is painted under icon and icons are automatically downscaled and centered into the badge box. - hidden_badge_box (boolean, default=false) When true, the badge is not painted but the additional graphics (marks and stars) are painted in the badge-mode locations. NOTE: Available in firmware 120819+. - icon_badge_box_dx (integer, default=auto) - icon_badge_box_dy (integer, default=auto) - icon_badge_box_width (positive integer, default=auto) - icon_badge_box_height (positive integer, default=auto) - icon_badge_box_sel_dx (integer, default=auto) - icon_badge_box_sel_dy (integer, default=auto) - icon_badge_box_sel_width (positive integer, default=auto) - icon_badge_box_sel_height (positive integer, default=auto) Allow to adjust the badge rectangle location, separately in selected and unselected state. - content_box_x (non-negative integer, default=auto) - content_box_y (non-negative integer, default=auto) - content_box_width (positive integer, default=auto) - content_box_height (positive integer, default=auto) Allow to specify the content block rectangle. - content_box_padding_left (non-negative integer, default=20) - content_box_padding_top (non-negative integer, default=20) - content_box_padding_right (non-negative integer, default=20) - content_box_padding_bottom (non-negative integer, default=20) Allow to specify the content block padding. - extra_content_objects (string, default=null) Allows to paint some fixed graphics in the content block. Currently only text labels in normal font are supported. Example string: label{x=50}{y=600}{text=Text:}{color=7}label{x=70}{y=659}{text=Some text.}{color=15} The x,y are specified relatively to the content block rectangle. Extra content objects normally should not cross the content block bounds. NOTE: Available in firmware 121201+. - paint_item_info_in_details (boolean, default=true) Whether to paint text in details block. If false => only icon is painted in details block. - item_detailed_info_rel_y (non-negative integer, default=auto) Specifies the Y-position of details text relative to the top of the details block, if specified. If not specified, then icon scale_factor is calculated w/o height-limitations and the text is placed just below the icon. If specified, then text is painted at the specified Y-coordinate, and the icon's scale_factor/position are calculated respectively. - zoom_detailed_icon (boolean, default=false) - detailed_icon_scale_factor (double, default=auto) If 'zoom_detailed_icon' is true => the detailed icon is scaled to fit into details block by width (even upscaled if needed). Otherwise, if 'detailed_icon_scale_factor' is specified => the detailed icon is scaled using this factor. Otherwise, the detailed icon scale-factor is calculated automatically to fit into details block width and into 'item_detailed_info_rel_y', if specified. - detailed_icon_valign (top|center|bottom, default=top) Vertical alignment of the detailed icon in case 'item_detailed_info_rel_y' is specified and is greater than actual detailed icon height. PHP constants available: VALIGN_TOP, VALIGN_CENTER, VALIGN_BOTTOM. NOTE: Available in firmware 120606+. - item_detailed_info_font_size (normal|small, default=normal) PHP constants available: FONT_SIZE_NORMAL, FONT_SIZE_SMALL - item_detailed_info_title_color (integer color index 0..23, default=8) - item_detailed_info_text_color (integer color index 0..23, default=7) The text color index for detailed info 'title' and 'text'. See description of ViewItemParams::item_detailed_info for more details. - item_detailed_info_auto_line_break (boolean, default=false) Whether to automatically break detailed info text into lines, when line does not fit into width. Also see the ViewItemParams::item_detailed_info for more details. NOTE: Available in firmware 120605+. - paint_sandwich (boolean, default=false) Whether to paint all item using "sandwich". Sandwich consists of 4 components: Base (icon or cut-image) Mask (icon or cut-image, only alpha channel is used) Cover (icon or cut-image) Icon (icon) Sandwich is painted using following sequence: - first, Base is painted as background into buffer. - next, Icon is painted into buffer; typically centered if smaller or downscaled if bigger. - next, alpha from Mask is merged with alpha from buffer. - finally, cover is painted into buffer. - sandwich_base (string, image URL or cut_icon URL string, default=unset) - sandwich_mask (string, image URL or cut_icon URL string, default=unset) - sandwich_cover (string, image URL or cut_icon URL string, default=unset) Sandwich Base, Mask and Cover components, as images or cut-icons. The following URLs can be used, taken from skin: sandwich_base=gui_skin://special_icons/sandwich_base.aai sandwich_mask=cut_icon://{name=sandwich_mask} sandwich_cover=cut_icon://{name=sandwich_cover} - sandwich_width (non-negative integer, default=0 meaning "auto") - sandwich_height (non-negative integer, default=0 meaning "auto") - sandwich_sel_width (non-negative integer, default=0 meaning "auto") - sandwich_sel_height (non-negative integer, default=0 meaning "auto") Sandwich dimensions in selected and non-selected state. - sandwich_icon_keep_aspect_ratio (boolean, default=true) Whether to keep icon aspect ratio when scaling. - sandwich_icon_upscale_enabled (boolean, default=false) Whether to upscale icon to fit sandwich bounds. NOTE: the downscale is always performed when needed. - sandwich_icon_scale_factor (positive double in range (0..1], default=1) Specifies how to scale icon relative to the sandwich bounds. Can be overridden by ViewItemParams::item_sandwich_icon_scale_factor. List of ViewItemParams properties --------------------------------- - item_paint_icon (boolean, default=true) Whether to paint current item's icon in content block. - item_paint_caption (boolean, default=true) Whether to paint item caption text in content block. - item_paint_unselected_caption (boolean, default=true) Whether to paint captions for currently non-selected items. NOTE: Available in firmware 130818+. - item_caption_font_size (normal|small, default=normal) Item caption font size. PHP constants available: FONT_SIZE_NORMAL, FONT_SIZE_SMALL. - item_paint_caption_within_icon (boolean, default=false) If true, the caption is painted inside icon. This option typically is used together with item_paint_caption=0. - item_caption_within_icon_color (string representing color, the following values allowed: white, black, 0, 1, 2, ... 23; default=white) Specifies color of caption text within icon. - item_padding_top (non-negative integer, default=0) - item_padding_bottom (non-negative integer, default=0) Specifies vertical padding of icon+caption area inside the item block. Normally caption is painted in the bottom and icon is Y-aligned in the rest of vertical space above caption. - icon_path (image URL string, mandatory) - icon_sel_path (image URL string, by default equals to icon_path) Icon URL in selected and non-selected state. - icon_width (non-negative integer, default=0 meaning auto) - icon_height (non-negative integer, default=0 meaning auto) - icon_sel_width (non-negative integer, default=0 meaning auto) - icon_sel_height (non-negative integer, default=0 meaning auto) Icon dimensions in selected and non-selected state. If not specified, the real icon image dimensions will be used. - icon_keep_aspect_ratio (boolean, default=yes) Whether to keep icon aspect ratio when scaling to the predefined dimensions (see ViewItemParams::icon_width and ViewItemParams::icon_height). - icon_scale_factor (positive double, default=1.0) - icon_sel_scale_factor (positive double, default=auto) Icon scale factor in selected and non-selected state. - icon_margin_top (integer, default=0) - icon_margin_bottom (integer, default=0) - icon_margin_left (integer, default=0) - icon_margin_right (integer, default=0) - icon_sel_margin_top (integer, default=0) - icon_sel_margin_bottom (integer, default=0) - icon_sel_margin_left (integer, default=0) - icon_sel_margin_right (integer, default=0) Icon margins in selected and non-selected state. - item_layout (left|center, default=center) The default layout is "center", meaning that icon and caption are horizontally centered, icon is painted above caption. When "left" is chosen, the icon and caption are vertically centered, icon is aligned to the left of rectangle and caption text is painted starting from the left bound of text area block. The text area block is right-aligned but normally it occupies all item rectangle width. So, to avoid painting text over icon, it is needed to change ViewItemParams::item_caption_dx or ViewItemParams::item_caption_width respectively. PHP constants available: HALIGN_CENTER, HALIGN_LEFT. - icon_valign (top|center|bottom, default=top) The method of vertical alignment of icon (between the upper bound of item rectangle from top and the caption from bottom). It is used only when ViewItemParams::item_layout = HALIGN_CENTER. PHP constants available: VALIGN_TOP, VALIGN_CENTER, VALIGN_BOTTOM. - icon_dx (integer, default=0) - icon_dy (integer, default=0) - icon_sel_dx (integer, default=0) - icon_sel_dy (integer, default=0) The additional icon horizontal/vertical offset in selected and non-selected state. - icon_fit_scale_factor (double in range (0..1], default=0.9) Used only when ViewParams::paint_icon_badge_box = true. In badge mode icon is downscaled and centered into badge box, using this scale factor as parameter. NOTE: Available in firmware 120605+. - item_caption_wrap_enabled (boolean, default=false) Allows to show the long captions in 2 rows. If 2 rows are not enough then caption is painted in 1 row with scrolling. The overall content block layout must ensure that 2-row caption does not cross the content block bounds. - item_caption_width (non-negative integer, default=0 meaning auto) Allows to change the default width of caption text block. By default the text block occupies all item rectangle width. - item_caption_dx (integer, default=0) Moves the left bound of caption text block, the right bound remains unchanged. - item_caption_dy (integer, default=0) - item_caption_sel_dy (integer, default=0) Additionally changes the vertical position of caption in selected and non-selected states separately. - item_caption_color (integer color index 0..23, default=auto) Caption text color. By default 15 is used (white). - item_detailed_info (string, default=unset) Structured text to be painted in the details block when current item is selected (focused). It may contain several paragraphs, each paragraph may have separated single-line title and a multiline text. The paragraphs are separated by '||'; the title and text lines are separated by '|'. The auto line breaking can also be used instead of '|' to separate text lines (see ViewParams::item_detailed_info_auto_line_break). Example of item_detailed_info: Title 1|line 1.1|line 1.2|line 1.3||Title 2|line2.1|line2.2 - item_detailed_icon_path (image URL string, default=icon_path) Allows to specify icon to be painted in details block; by default the same icon is used for content block and for details block. - item_badge_icon_path (image URL string, default=unset) Specifies icon to be pained instead of the default skin badge cut image. Affects only badge mode (ViewParams::paint_icon_badge_box=true). This property is ignored in GUI skins having enable_badge_icons=no unless ViewItemParams::item_override_default_badge is set to true. NOTE: Available in firmware 120830+. - item_override_default_badge (boolean, default=false) When true, the ViewItemParams::item_badge_icon_path overrides the default GUI skin badge even for skins with enable_badge_icons=no. NOTE: Available in firmware 131005+. - item_sandwich_icon_scale_factor (double in range (0..1], default=auto) Specifies how to scale icon relative to the sandwich bounds. If not set, the ViewParams::sandwich_icon_scale_factor used instead. Other functionality ------------------- The GComponents framework (gcomp*) is currently unfinished and is currently reserved for internal use only. Porting plugins to SMP87xx platforms ------------------------------------ Please see the following sections: - "Differences between SMP86xx and SMP87xx platforms" - "Including platform-specific files for SMP87xx platforms" Also please see the following: - http://files.dune-hd.com/partners/sdk/smp875x.txt - http://files.dune-hd.com/partners/sdk/dune_devel_info.txt#toolchain_for_smp87xx_arm_platforms Differences between SMP86xx and SMP87xx platforms ------------------------------------------------- All the features PHP plugins framework and the plugins mechanism in general (manifest files, www/ and www/cgi-bin folders, etc) are fully supported on SMP87xx platforms the same way as on SMP86xx platforms. The main differences between SMP86xx and SMP87xx platforms which affect plugins are the following: - SMP87xx platforms do not support outdated FlashLite technology. - SMP87xx plarforms do support HTML applications and Dune STB JS API, but a slightly different version of the web browser engine is used (QtWebkit based), and there may be slight differences in the behavior and supported features of the web browser engine and in the behavior and supported features of Dune STB JS API implementation. So it is recommended to carefully test if HTML application works correctly on SMP87xx platform, and some adaptation/porting may be required. - The playback engine on SMP87xx platform is based on the playback engine of SMP86xx platforms and supports the same streaming protocols and media formats and features (and even more, e.g. DASH streaming protocol and H.265 video codec), but some incompatibilities and slight differences potentially may take place. So it is recommended to carefully test if the media content is played OK on SMP87xx platform, and some adaptation/porting may be required. - If the plugin includes native binary code (such as binary executables or libraries, Linux kernel drivers, or other platform-specific files), the plugin should carry two versions of such platform-specific files -- one version for SMP86xx platform, another version for SMP87xx platform; for more details, see "Including platform-specific files for SMP87xx platforms" section. - SMP87xx platforms support background playback feature -- by pressing TOP MENU RC button, the user can return to the main menu, keeping video or audio playback in background (to return to the playback, TOP MENU RC button can be pressed again, or "Now playing" POP UP MENU item can be used). When navigating the main menu, the user can navigate through the screens of the same plugin which controls the current playback session; to ensure that this works correctly, the plugin should take this use case into account. Including platform-specific files for SMP87xx platforms ------------------------------------------------------- If the plugin includes files specific to SMP86xx platforms which can not be used on SMP87xx platforms (such as executable binary files for MIPS CPU), the following approach should be used to add support for SMP87xx platform. At the top level of the plugin, folder ".platform.87xx" should be created, and for each platform-specific file, the version of the file for SMP87xx platform should be put under this folder. For example: bin/some_exe -- SMP86xx (MIPS) version of "some_exe" www/cgi-bin/cgi_exe -- SMP86xx (MIPS) version of "cgi_exe" .platform.87xx/bin/some_exe -- SMP87xx (ARM) version of "some_exe" .platform.87xx/www/cgi-bin/cgi_exe -- SMP87xx (ARM) version of "cgi_exe" When such a plugin is installed on SMP86xx platform, the content of ".platform.87xx" folder is automatically deleted from the plugin installation directory. When such a plugin is installed on SMP87xx platform, the content of ".platform.87xx" folder is automatically moved to the top level of the plugin installation directory. Toolchain to build native binaries for SMP87xx platforms can be found here: - http://files.dune-hd.com/partners/sdk/dune_devel_info.txt#toolchain_for_smp87xx_arm_platforms Porting plugins to Android platforms ------------------------------------ Please see the following sections: - "Differences between Sigma and Android platforms" - "Including platform-specific files for Android platforms" Also please see the following: - http://files.dune-hd.com/partners/sdk/dune_devel_info.txt#toolchain_for_android_platforms - http://files.dune-hd.com/partners/sdk/dune_devel_info.txt#launching_executables_from_user_storages_on_android_platforms Differences between Sigma and Android platforms ----------------------------------------------- All the features PHP plugins framework and the plugins mechanism in general (manifest files, www/ and www/cgi-bin folders, etc) are fully supported on Android platforms the same way as on Sigma (SMP87xx) platforms. The main differences between Sigma and Android platforms which affect plugins are the following: - Android platforms do not support outdated FlashLite technology. - Android plarforms do support HTML applications and Dune STB JS API, but a slightly different version of the web browser engine is used, and there may be slight differences in the behavior and supported features of the web browser engine and in the behavior and supported features of Dune STB JS API implementation. So it is recommended to carefully test if HTML application works correctly on Android platform, and some adaptation/porting may be required. - The playback engine on Android platform is similar to the playback engine of Sigma platforms and in general supports the same streaming protocols and media formats and features (and even more, e.g. 4Kp60 video, Widevine DRM, etc), but the core part of the playback engine is different and some incompatibilities and slight differences potentially may take place. So it is recommended to carefully test if the media content is played OK on Android platform, and some adaptation/porting may be required. - If the plugin includes native binary code (such as binary executables or libraries, or other platform-specific files), the plugin should carry several versions of such platform-specific files -- one or two version for Sigma SMP86xx/SMP87xx platforms, and another version for Android platform; for more details, see "Including platform-specific files for Android platforms" section. - On Android platforms, user storages are mounted with "noexec" flag, which may complicate the use of "dune_plugins" folder mechanism. See the following for more information and possible workaround: - http://files.dune-hd.com/partners/sdk/dune_devel_info.txt#launching_executables_from_user_storages_on_android_platforms Including platform-specific files for Android platforms ------------------------------------------------------- If the plugin includes files specific to Sigma platforms which can not be used on Android platforms (such as executable binary files), the following approach should be used to add support for Android platform. At the top level of the plugin, folder ".platform.android" should be created, and for each platform-specific file, the version of the file for Android platform should be put under this folder. For example: bin/some_exe -- SMP86xx (MIPS) version of "some_exe" www/cgi-bin/cgi_exe -- SMP86xx (MIPS) version of "cgi_exe" .platform.87xx/bin/some_exe -- SMP87xx (ARM) version of "some_exe" .platform.87xx/www/cgi-bin/cgi_exe -- SMP87xx (ARM) version of "cgi_exe" .platform.android/bin/some_exe -- Android version of "some_exe" .platform.android/www/cgi-bin/cgi_exe -- Android version of "cgi_exe" When such a plugin is installed on Android platform, the content of ".platform.android" folder is automatically deleted from the plugin installation directory. When such a plugin is installed on Android platform, the content of ".platform.87xx" folder is automatically moved to the top level of the plugin installation directory. Toolchain to build native binaries for Android platforms can be found here: - http://files.dune-hd.com/partners/sdk/dune_devel_info.txt#toolchain_for_android_platforms Debugging plugins ----------------- Here are some hints which can be helpful to debug plugins during development. During plugin development/debugging, it is recommended to create convenience scripts for typical repetitive actions which can include some of the below commands (or similar commands). See the logs of the plugin: On Sigma platforms (in telnet session): tail -F /tmp/run/.log On Android platforms (in telnet or ADB session): busybox tail -F /tmp/run/.log On Android platforms (on remote PC via ADB): adb shell busybox tail -F /tmp/run/.log Copy plugin files from PC into STB flash memory via ADB on Android platforms: # local folder should contain files to deploy to the STB adb shell rm -rf /flashdata/plugins/ adb push /flashdata/plugins/ adb shell chmod -R +x /flashdata/plugins//bin adb shell chmod -R +x /flashdata/plugins//www/cgi-bin Restart shell process (to reload all plugins): On Sigma platforms (in telnet session): killall shell On Android platforms (in telnet or ADB session): killall com.dunehd.shell On Android platforms (on remote PC via ADB): adb shell killall com.dunehd.shell Request shell process to reload plugins w/o restarting shell process: Go to the top menu of the shell and press "ANGLE/ROTATE" button on the old Dune HD RCU (or choose "Refresh" action in POP UP MENU), or navigate to the top menu and send "ANGLE/ROTATE" IR code (00 BF 4D B2) via IP Control: curl 'http://dune-ip-address/cgi-bin/do?cmd=main_screen' curl 'http://dune-ip-address/cgi-bin/do?cmd=ir_code&ir_code=B24DBF00'