Перейти к содержанию

Приёмы разработки плагинов Dune HD: структура плагина

Часть каталога о том, из чего состоит плагин и как он встраивается в оболочку: манифест и установка, точки входа и жизненный цикл, экраны и ввод, локализация, обновление и совместимость платформ. Это разделы 2–5, 11, 12 и 16 общего каталога; их нумерация сохранена, ссылки на другие части проставлены в тексте.

2. Манифест, упаковка и установка

Объект: dune_plugin.xml, состав пакета и действия при установке и удалении в 50 разобранных плагинах и семействах (code; платформа и прошивка исполнения в большинстве не установлены, исключения названы в строках). Поведение оболочки — по SDK (doc) и tv188b r24/r25 (code, device).

Манифест — единственный обязательный файл пакета: остальные файлы указываются в нём и могут называться как угодно (SDK)1; по SDK PHP-плагин должен содержать программу с hd_create_plugin(), путь к которой задан в манифесте (SDK)2, но на tv188b r25 тестовые плагины test_plugin5 и test_plugin10 работали без неё, с классом-наследником DunePluginFw (устройство r25)3 (см. «Расхождения»). Из манифеста оболочка узнаёт, где показать плагин (точки входа), что делать на системные события (global_actions) и откуда брать обновления (check_update, см. §12). Ниже — как это делают плагины; устройство пакета, .platform.*, подпись и пути установки со стороны прошивки — guide/plugin-packaging.md.

2.1. Где показать плагин: entry_point и parent_media_url

Самый частый приём — две точки входа: основная в нужном разделе главного меню и вторая в «Настройки → Приложения» (setup://applications), ведущая на экран настроек. Раздел задаёт parent_media_url, открываемый экран — media_url. На tv188b r25 (device) точки входа без icon_url в разделе «Приложения» не появлялись (устройство r25)4, поэтому иконку стоит задавать всегда.

Задача Приём Грабли и ограничения Плагины и claims
Плагин в «Приложениях» и в настройках root://applications → основной экран и setup://applications → setup у Dune BackUp badge_icon_url задан дважды Dune BackUp (код)5; Screenshoter (код)6; Twitch TV (код)7; altSource (код)8; Entware/Wallpaper (код)9
ТВ-плагин в разделе TV root://tv → tv_group_list (или свой экран) плюс setup://applications → setup — AllTV (код)10; Novosib-iptv (код)11; plugtv (код)12; AceStreamSearch (код)13; liteIPTV (код)14; zlostnyi (код)15; Юрта ТВ (код)16; WeburgTV (код)17; заготовки zlostnyi.tech (код)18; shura (код)19; Dune HD TV (код)20
VOD-плагин в разделе Video root://video → main_menu и setup://applications → setup — Smart_* (код)21; Anidub.Com (код)22
Радио в Music & Radio, камеры в Video root://music_and_radio (радио) или root://video (камеры) у второй точки (настройки) только ENTER, без PLAY 101.ru (код)23; surface_* (код)24
Каталог медиатеки в «Источниках» root://sources → свой экран — DunePlexCatalog (код)25; rclone, rmfon.pl (загрузчики) (код)26
Один пакет — разные разделы у разных сборок раздел зашит в манифест каждой сборки у youtube_api/folder_cache 9 пакетов в root://applications, 5 — в root://video youtube_api/folder_cache (код)27
Две точки в одном разделе: ТВ и фильмотека две точки в root://tv с разными media_url: у FREE TV launch_tv и launch_vod, у ProIPTV tv_groups и launch_vod — FREE TV (код)28; ProIPTV (код)29
Только в настройках одна точка setup://applications → setup закомментированная точка не активна Online Movies (TV Series) (код)30
Пункт в разделе «Настройки» главного меню parent_media_url root://setup, exclude_from_merged_parent yes размещение в SETUP подтверждено не полностью (§19) Widget Ext (код)31
Одна точка входа одна entry_point в root://applications — Apple Trailers (код)32; Lampa bridge (код)33
Иконка точки входа из пакета icon_url=plugin_file://…; путь — от корня пакета у surface_* путь зависит от наличия www/: plugin_file://logo/… или plugin_file://www/lib/logo/… WeburgTV (код)34; Lampa bridge (код)35; surface_* (код)36
Второй значок на иконке badge_icon_url у точки входа среди 43 пакетов-загрузчиков — единственный манифест с badge_icon_url liteIPTV (код)37

2.2. Что делают ENTER и PLAY на иконке

Действие клавиши на иконке задаётся в actions точки входа. Три варианта: открыть папку (plugin_open_folder), сразу запустить ТВ (plugin_tv_play) или передать решение своему PHP-обработчику (plugin_handle_user_input с handler_id). Третий нужен, если перед открытием надо что-то проверить (дисклеймер, авторизацию, выбор экрана).

Задача Приём Грабли и ограничения Плагины и claims
Открыть экран плагина key_enter → plugin_open_folder — Twitch TV (код)38; DunePlexCatalog (код)39; загрузчики check_update — 41 из 43 (код)40
ENTER — папка, PLAY — сразу ТВ key_enter → plugin_open_folder, key_play → plugin_tv_play key_play с plugin_tv_play — у 22 из 43 загрузчиков AllTV (код)41; 101.ru (код)42; AceStreamSearch (код)43; загрузчики check_update (код)40
PLAY запускает ТВ, ENTER — свой обработчик key_enter → plugin_handle_user_input, key_play → plugin_tv_play — Dune HD TV (код)44
И ENTER, и PLAY сразу запускают канал key_enter и key_play → plugin_tv_play у surface_* (LSS) точки настроек нет WeburgTV (код)45; surface_* (LSS) (код)46
Решать в PHP, что открыть key_enter/key_play → plugin_handle_user_input с handler_id=entry (и control_id/entry_id) обработчик должен быть зарегистрирован под этим handler_id Screenshoter (код)47; YouTube (Smart_) (код)48; liteIPTV (код)49; rain_ (код)50; Entware/Wallpaper (код)51; Smart_* (Zona.mobi) (код)52
Запуск из ярлыка «Избранного» разбор root_shortcut://… и dune_folder.txt ярлыка путь /persistfs/main_screen_items зашит Cleanup (код)53

Как обработчик ввода устроен в PHP — §3 и guide/input-dialogs.md.

2.3. Видимость иконки и требования к сети

Задача Приём Грабли и ограничения Плагины и claims
Дать пользователю скрыть иконку show_cookie_name (cookie, которую пишет экран настроек) + show_by_default yes имя cookie в манифесте и в коде должны совпадать: у surface_* в манифесте show_application, rmfon.pl и wwcam пишут show_tv, у Radiorecord.ru переключателя нет plugtv (код)54; AceStreamSearch (код)55; liteIPTV (код)56; surface_* (код)57; загрузчики check_update — у 42 из 43 (код)58
Скрыть вторую точку по умолчанию show_by_default no у точки VOD точка управляется cookie show_vod_section FREE TV (код)59
Показывать иконку по языку show_by_default=lang(russian) — Юрта ТВ (код)60
Не запускать без сети ip_address_required yes на точке входа стоит у всех 43 загрузчиков Twitch TV (код)61; 101.ru (код)62; DunePlexCatalog (код)63; загрузчики check_update (код)64

2.4. Контекстное меню на иконке: popup_menu

Пункты popup_menu точки входа вызывают plugin_handle_user_input с разными control_id; так из главного меню без открытия плагина доступны настройки, сброс, выбор плейлиста или выключение.

Задача Приём Грабли и ограничения Плагины и claims
Меню действий на иконке popup_menu/menu_items → plugin_handle_user_input на обработчик entry с control_id пункт, оставленный в XML-комментарии, оболочка не видит; у Bazinga3 — четыре пункта: do_setup, reboot, power_off, newPluginIco altSource — 5 пунктов (код)65; YouTube (код)66; liteIPTV (код)67; ProIPTV — 8 пунктов (код)68; Entware/Wallpaper (код)69; Bazinga3 (код)70
Один пункт «Настройки плагина» popup_menu → open_setup — FREE TV (код)71

2.5. Прочие блоки манифеста: auto_resume, auto_start, operation_timeout, drm_defs, тип plain

auto_resume по SDK выключен по умолчанию и при включении (enable yes) восстанавливает после включения и выхода из standby только live-ТВ, архив и VOD (SDK)72; подробности — guide/playback.md.

Задача Приём Грабли и ограничения Плагины и claims
Восстановить просмотр после standby <auto_resume><enable>yes</enable> значение auto вместо yes — у Юрта ТВ, sunduk, shara-tv; у 21 загрузчика блока нет 101.ru (код)73; AllTV (код)74; rain_* (код)75; WeburgTV (код)76; Юрта ТВ (код)77; загрузчики check_update (код)78; AceStreamSearch (код)79; Dune HD TV (код)80
Восстановление со своим действием и проверкой времени auto_resume с действием (action_id auto_resume, mandatory_playback 1), ip_address_required, valid_time_required — ProIPTV (код)81; FREE TV (код)82
Стартовать плагин при включении плеера auto_start: entry_point_media_url, force_on_start black_screen, force_on_finish main_screen, skip_initial_dialogs yes, действие plugin_tv_play — WeburgTV (код)83
Автозапуск по типу «включение плеера» или «вход в плагин» autostart_remote_name (type 1) или autostartPluginInRemote (type 2), затем bin/rclone_mount.sh с remote и каталогом при принятом дисклеймере и незапущенном mount вход ждёт 3 с и предупреждает о задержке 1–2 мин; скрипт берёт аргументы или файлы настроек и без них завершается ошибкой rclone (код)84
Пункты главного меню в манифесте main_menu с адресами пунктов Setup вынесен и в меню, и в entry_point streamit (код)85
Длинные операции (EPG, ввод) operation_timeout: default, отдельные значения по операциям — ProIPTV: default 300, get_epg_day 30 (код)86; Online Movies (TV Series): default 300 (код)87
Объявить DRM drm_defs/drm_def типа verimatrix параметры — в отдельном ini; у Novosib два описания FREE TV (код)88; Novosib-iptv (код)89
Подменить сервис встроенного ТВ-плагина %ext%-шаблон caption и блок ktv_params (caption, server_address, fixed_osk_id) — Polbox.tv (код)90
Плагин без GUI (только поставщик) type plain; описатель пишется прямо в /tmp/movie_suppliers нет params/movie_suppliers в манифесте Online Movies (rus) (код)91
Метаданные для каталога dune_plugin_metadata.xml: категория, иконка, firmware_features, community_plugin, secure_update — GlobalTV (код)92; Dune HD TV (category, country, expr) (код)93

2.6. Код на системные события: global_actions

SDK поддерживает события boot, install, update, uninstall (SDK)94, boot_end — с 130917_b9 (SDK)95, gui_start — с 130914_b8 (SDK)96; для boot годится только plugin_system (SDK)97, для остальных — любое GUI-действие плагина или plugin_system (SDK)98. На tv188b r25 (device) boot и boot_end не повторяются при следующих стартах приложения (устройство r25)99, а gui_start выполняется при каждом (устройство r25)100; скрипт plugin_system работает под uid 1000 (устройство r25)101. На tv188b r25 (device) строковый id plugin_system в boot-действии выполнен: shell.log пишет action D: exec_all plugin_system и Running system(sh <плагин>/bin/ga.sh boot) (устройство r25)102. Подробно — guide/plugin-packaging.md §3.

Задача Приём Грабли и ограничения Плагины и claims
Запустить скрипт на событие в фоне plugin_system с run_string bin/<имя>.sh & дождаться результата из PHP нельзя; на Android rclone_automount.sh запускает rclone_mount.sh через /system/dunehd/dunehd_service do, если рядом есть fusermount Widget Ext (код)103; Dune BackUp (код)104; rclone (код)105
Удалить за собой синхронно uninstall → скрипт без & — Widget Ext (код)106; DLNA Renderer (код)107
Флаг «система загрузилась» boot → plugin_system с echo > $FS_PREFIX/tmp/<флаг> — Dune BackUp (код)108
Фоновый демон с загрузки boot_end → plugin_system bin/<демон>.sh & у Cleanup в манифесте main.php, которого нет в пакете Cleanup (код)109
Перезапустить свой демон после установки или обновления install/update → bin/gmediarender-ctl restart & — DLNA Renderer (код)110
Ставить и обновлять по условию прошивки boot_end/install/update с if="not(firmware_feature(movie_suppliers_update))" → plugin_system bin/install.sh; uninstall — bin/uninstall.sh без условия установка зависит от фичи прошивки Dune HD TV (код)111
Обработать события в PHP install/update/uninstall → plugin_handle_user_input на свой обработчик (entry_id/control_id) GlobalTV из PHP запускает bin/install.sh через system(), тот чистит кэши GlobalTV (код)112; ProIPTV (и confirm_update) (код)113; Online Movies (TV Series) (код)114
Зарегистрировать поставщика фильмов boot_end/install/update → bin/register_supplier.sh, пишущий описатель в /tmp/movie_suppliers; у ProIPTV — bin/update_suppliers.sh на boot_end описатель в /tmp; Online Movies (TV Series) делает это на boot_end только без feature movie_suppliers_update Online Movies (eng) (код)115; Online Movies (TV Series) (код)116; ProIPTV (код)117
Убрать описатель поставщика при удалении uninstall → /bin/rm -f /tmp/movie_suppliers/<имя>; Online Movies (TV Series) удаляет описатели в PHP-обработчике uninstall — Online Movies (eng) (код)118; Megogo (код)119; Okko (код)120; Online Movies (TV Series) (код)121
Разложить стартовые данные install → plugin_system prepare2.sh & копирует data в plugins_data две зашитые схемы путей /persistfs//flashdata altIPTV (код)122
Остановить свой сервер при удалении bin/uninstall.sh → dunehd_service killall node убивает любой процесс node PeerflixServer (код)123
Откатить системные правки утилиты uninstall → скрипт отката откат Codec_install не удаляет симлинки и строку в profile служебные установщики hdtv (код)124

Поставщики фильмов и их описатели — guide/movie-suppliers.md. Поставщик ТВ для NewUI на boot_end (описатель в /tmp/tv_app_suppliers) — Домашнее ТВ, §4.7 (код)125.

2.7. Состав пакета и сборка

Многие плагины несут в lib/ копию PHP-фреймворка SDK и меняют только свои классы. Копии не совпадают с фреймворком встроенных плагинов r24 целиком (код)126, поэтому сверять поведение нужно с конкретной копией.

Задача Приём Грабли и ограничения Плагины и claims
Связать манифест с кодом params/program → PHP-файл, который подключает lib/default_dune_plugin_fw.php и задаёт DefaultDunePluginFw::$plugin_class_name фреймворк должен лежать в lib/ рядом Apple Trailers (код)127; youtube_api/folder_cache (код)128; служебные установщики hdtv (код)129
Подключать модули-поставщики без списка glob('lib/wox/*.php') → require_once в цикле список не задан в коде: состав определяется содержимым каталога Bazinga3 (код)130
Взять фреймворк SDK копией копия lib/ в пакете копия не совпадает с r24: 27 из 43 файлов совпадают с встроенными плагинами r24 (Moi-Dom, Peers.TV), у Polbox — 40 из 45 AllTV (код)131; Moi-Dom.tv (код)132; Peers.TV (код)133; Polbox.tv (код)134; служебные установщики hdtv (код)135
Начать с демо-каркаса SDK классы Demo* (DemoPlugin, DemoTv) с регистрацией экранов в конструкторе имена Demo* остаются в готовом плагине EvolutionTV (код)136; Kaban.tv (код)137; Peers.TV (код)138
Несколько плагинов на одном коде общий каркас и lib/, различаются конфиг, манифест и иконки копии расходятся: lib/utils.php у youtube_api/folder_cache — 10 вариантов, у itv (zlostnyi) — BOM и CRLF; streamit отличается от mp3tales четырьмя изменёнными файлами и 16 добавленными PHP, а его lib/utils.php не задаёт таймауты pirates_* (код)139; zlostnyi (код)140; rain_* (код)141; youtube_api/folder_cache (код)142; streamit (код)143; служебные установщики hdtv (код)144
Переименовать плагин, не трогая файлы новый name/caption, файлы и классы — от исходного (starnet_*) имя и файлы расходятся zlostnyi (shura) (код)145
Минимальный пакет ZIP с dune_plugin.xml из name, caption, type без точки входа и версии remote-control (код)146
Собрать пакет без сборки в пакете только текст: dune_plugin.xml, README и 18 PHP-файлов в корне и lib/; бинарников и архивов нет README описывает плагин как браузер трейлеров Apple Trailers (код, форум)147
MVC-пакет: index.php и application/bootstrap.php type=php, program=index.php; index.php задаёт EXT, DOCROOT, APPPATH, MODPATH, SYSPATH и подключает application/bootstrap.php в пакете plg-hdtv-1hd — 76 PHP-файлов; logo.png — картинка; только у firstmuzru есть version, dune_plugin_signer_id.txt и __version_info.xml Kohana-канал (код)148
Подставлять версию при сборке шаблон манифеста с заглушками, make_update.php подставляет version, version_index, дату и debug версия в шаблоне не боевая ProIPTV (код)149
Скрипт сборки и релиз по тегу make_package.cmd → make_update.php → zip; GitHub workflow по тегу N.N.N публикует релиз — ProIPTV (код)150
Права файлов в zip build.sh: файлам 644, каталогам 755; build.py: www/cgi-bin/api 0755, прочим 0644 build.sh altIPTV ставит 644 всем файлам без исключений altIPTV (код)151; Lampa bridge (код)152
Воспроизводимый zip фиксированная дата записей ZipInfo(2026,10,10,0,0,0) — Lampa bridge (код)153
Комплект для пользователя отдельный zip: пакет плагина, JS-плагины, README, LICENSE — Lampa bridge (код)154
Хранить версию и дату сборки в VERSION файл VERSION с версией «0.0.19 beta» и датой сборки извлечённый пакет — 123 файла в 9 каталогах, 80 текстовых, без ELF и симлинков RemTor (код)155
Переиспользовать чужой каркас Smart_file_screen.php/Smart_plugin.php и lib/ — копии PeerflixServer и Smart_* в пакете нет VOD-экранов, но Smart_list_screen подключает lib/vod/vod.php rclone (код)156
Android-приложение в составе решения AndroidManifest: queries на com.dunehd.app, usesCleartextTraffic=true, activity exported с excludeFromRecents; подпись release из ANDROID_RELEASE_*, сборка по тегу v* — Jellyfin Bridge (код)157
Не оставлять в пакете чужое — в пакете бывают лишние файлы: Thumbs.db; в Screenshoter — BOM перед <?php загрузчики check_update (код)158; Screenshoter (код)159
Не тащить неиспользуемые файлы и классы — в lib/ лежат невызываемые методы и модули; скопированный экран не подключён; классы Btv* не зарегистрированы; lib/_utils.php побайтно совпадает с utils.php edem 101.ru (код)160; Moidom (код)161; Юрта ТВ (код)162; zlostnyi (shura) (код)163
Ссылаться только на существующие файлы — битые ссылки: logo.png в метаданных, icons/null.png, p_plus/p_minus.png Online Movies (rus) (код)164; plugtv (код)165

2.8. Бинарники под разные платформы

SDK: файлы для SMP87xx (ARM) кладутся в .platform.87xx/, основная копия bin/, www/cgi-bin/ — для SMP86xx (MIPS) (SDK)166. Как установщик применяет .platform.* на Android — guide/plugin-packaging.md §2 и §7.

Задача Приём Грабли и ограничения Плагины и claims
Свой php-cgi для двух архитектур две разные ELF-сборки: в bin/ (или www/cgi-bin/) и в .platform.87xx/ какая копия остаётся — §19 Online Movies (rus) (код)167; Torrent Center (код)168
Свой php-cgi в веб-части ELF www/cgi-bin/php-cgi в пакете в его строках есть libphp5.so; от чего он зависит — §19 Screenshoter (код)169
Запуск своего интерпретатора описатель вызывает <bin>/php-cgi -f <bin>/run.php ключ -c не передан, хотя php.ini рядом Online Movies (rus) (код)170
Утилита под каждую платформу в пакете bin/curl.{864x,865x,867x,87xx}, выбор по platform_kind из versions.txt; на Android — curl прошивки для 864x/867x — curl 7.19.5, для 87xx — 7.36.0; curl.864x совпадает с curl прошивки tv188b r24 Widget Ext (код)171
Не класть ELF в пакет, а скачать при первом запуске platform_kind из /tmp/run/versions.txt → каталог platform.* на своём сервере → wget в bin/ нужен интернет; неизвестный platform_kind → null; перед загрузкой проверяется наличие Content-Length rclone (код)172; PeerflixServer (код)173
Права на скачанный бинарник на Android chmod 777 через /system/dunehd/dunehd_service do, иначе PHP chmod — rclone (код)174
Запуск утилиты на Android exec через dunehd_service do — MegaTorrents (код)175
CGI-обёртка вокруг своего php-cgi обёртки вычисляют PLUGIN_NAME, PLUGIN_INSTALL_DIR_PATH, PLUGIN_TMP_DIR_PATH, PLUGIN_WWW_URL, PLUGIN_CGI_URL и PLUGIN_DATA_DIR_PATH, затем запускают ./php-cgi — liteIPTV (код)176
Сторонний бинарник в пакете bin/gmediarender — ELF, версия 0.0.7-git видна в strings — DLNA Renderer (код)177

2.9. Подпись пакета

SDK: плагины из розничной прошивки и Dune Store подписаны Dune HD и содержат dune_plugin.sign и dune_plugin_signer_id.txt (SDK)178; проверка подписи прошивкой — guide/plugin-packaging.md §5. Среди разобранных пакетов dune_plugin.sign и dune_plugin_signer_id.txt со значением com.dune-hd есть у GlobalTV (код)179, Online services (код)180, Megogo (код)181, Okko (код)182, у amediateka из веб-плагинов (код)183 и у Dune HD TV (код)184. По SDK, на r24+ не подтверждено: собственная подпись (с 150326_r10) делается DSA-ключами 2048 через openssl и утилитой plugin_sign.x86 <dir> <signer_id> <key>, публичный ключ кладётся в прошивку (SDK)185; если прошивка требует только подписанные плагины, сторонний плагин для кастомного каталога Dune Store подписывают собственным ключом, а прошивку настраивают разрешать этот ключ (SDK)186, при этом подписывать могут только приложения Dune HD (SDK)187; для запрета произвольных сторонних плагинов «Secure firmware» рекомендует external_plugins_enabled = signed (SDK)188. Подробнее — publishing.md §2.2 и §2.3.

2.10. Установка внешних компонентов с прогрессом и распространение

Задача Приём Грабли и ограничения Плагины и claims
Показать ход установки скрипт в фоне пишет лог, экран раз в секунду перечитывает его и вырезает ANSI-последовательности — Entware/Wallpaper (код)189
Поставить внешнюю программу только на постоянный носитель bin/inst.sh ставит mpd только при наличии /persistfs: скачивает архив с dune-club.info и распаковывает в bin/ — MPD (код)190
Распаковать архив с прогрессом CGI-обёртка unpack → php-cgi → unpack.php → bin/bar -c 'tar xzf -' пути /flashdata зашиты; bar — сторонняя утилита PeerflixServer (код)191
Поставить Entware на диск выбор ext3-раздела, симлинк /opt на каталог Entware платформа — по строке ARMv7 в /proc/cpuinfo Entware/Wallpaper (код)192
Описать каталог внешних программ в массиве install_script, uninstall_script, install_path, при наличии select_path; установленность — по существованию install_path элемент без ключа текущей platform удаляется Entware/Wallpaper (код)193
Предложить установку codecpack launch_media_url с plugin_installer://…tar.gz и callback refresh — altIPTV (код)194
Распространять без каталога zip во вложении темы форума — rain_* (форум)195 (по сообщениям пользователей); plugtv (форум)196 (по сообщениям пользователей)
Выложить старую версию, остальное — обновлением вложение на форуме + check_update на свой хост по сообщениям пользователей, в первых постах пяти тем версия новее, чем в архиве загрузчики check_update (форум)197; liteIPTV (форум)198
Обновлять Android-приложение APK поверх; по README, при другой подписи Android может вернуть INSTALL_FAILED_UPDATE_INCOMPATIBLE ключ подписи нужно сохранять Jellyfin Bridge (форум)199 (по сообщениям пользователей)

3. Точки входа, жизненный цикл и каркасы

Объект: PHP-каркас плагина (DefaultDunePluginFw, DefaultDunePlugin, UserInputHandlerRegistry) в копиях lib/ сторонних плагинов, точки входа entry, загрузка кода с сервера, поставщики фильмов без GUI и Android-приложения вместо PHP-плагина; уровень code, платформа и прошивка исполнения у плагинов не установлены. Поведение php_server — наблюдения на tv188b r25 (device).

Почти все разобранные PHP-плагины устроены одинаково: файл-программа из манифеста называет класс плагина, адаптер каркаса создаёт его при первом вызове и раскладывает вызовы оболочки по методам, а экраны и обработчики ввода регистрируются в конструкторе. Ниже — приёмы и грабли этого каркаса, затем то, что плагины добавляют поверх: единая точка входа entry, дисклеймер первого запуска, перезапуск, долгие операции, код с сервера и копии SDK в lib/. Как оболочка исполняет вызовы (очередь, тайм-ауты, процесс php_server), — в guide/plugin-operations.md; манифест и точки входа — в §2; ввод и диалоги — в §5.

3.1. Подключить класс плагина: $plugin_class_name, DunePluginFw::$instance, ленивый экземпляр

Схема повторяется в десятке плагинов почти дословно, поэтому её можно брать за образец. На r25 статическая переменная класса плагина живёт, пока жив php_server (устройство r25)200, и начинается заново после каждого его перезапуска (устройство r25)201; SDK прямо запрещает полагаться на глобальные переменные, потому что движок может быть пересоздан между вызовами (SDK)202. Ответ null из call_plugin на r25 оболочка считает сбоем вызова (устройство r25)203.

Задача Приём Грабли и ограничения Плагины и claims
Назвать класс плагина файл-программа подключает lib/default_dune_plugin_fw.php и файл плагина, затем DefaultDunePluginFw::$plugin_class_name = '<Класс>' — Twitch TV (код)204; WeburgTV (код)205; Anidub.Com (код)206; altIPTV (код)207; AllTV (код)208; plugtv (код)209; rain_* (код)210; surface_* (код)211; altSource (код)212; Torrent Center (код)213; Smart_* (код)214
Подгружать классы по имени spl_autoload_register: <class>.php ищется в каталоге плагина, lib, vod, plugin_vod, plugin_api имя класса должно совпадать с именем файла ProIPTV (код)215; Kohana-канал (Rise::auto_load) (код)216
Выбрать реализацию экрана настройкой при загрузке при загрузке подключается lib/vod/movie_screen.php или lib/vod/vod_movie_screen.php по настройке movieViewed — Bazinga3 (код)217
Выбрать реализацию ТВ константой в конструкторе BcuConfig::USE_M3U_FILE ? new BcuM3uTv() : new BcuTv() при true ветка BcuTv остаётся мёртвой, а BcuTv::load_channels читает CHANNEL_LIST_URL, которой в конфиге нет zlostnyi (bcu) (код)218
Зарегистрировать адаптер DunePluginFw::$instance = new DefaultDunePluginFw() в конце файла каркаса (или свой наследник) в Kohana-канале экземпляр создаёт не файл каркаса, а bootstrap.php Torrent Center (код)219; altIPTV (код)220; WeburgTV (код)221; Anidub.Com (код)222; Lampa bridge (код)223; Kohana-канал (код)224
Создать плагин один раз call_plugin_impl держит объект в static $plugin и создаёт его при первом вызове состояние живёт только пока жив процесс (см. выше) Torrent Center (код)225; altIPTV (код)226; WeburgTV (код)227; Anidub.Com (код)228; Apple Trailers (код)229; pirates_* (код)230
Разобрать вызов и упаковать ответ call_plugin: json_decode контекста → call_plugin_impl → json_encode; ответ — PluginOutputData с has_data, data_type, data, plugin_cookies, is_error копия TorrServe возвращает json_encode(...) сразу, без tracing_enabled и без обработки ошибки декодирования Torrent Center (код)231; Anidub.Com (код)232; Lampa bridge (код)233; WeburgTV (код)234; TorrServe (код)235
Вернуть ошибку оболочке DuneException → is_error=true и error_action из исключения; прочее исключение из invoke_operation → show_error; сбой создания плагина → show_error «Can not create PHP plugin instance.» — WeburgTV (код)236; Anidub.Com (код)237
Не принять NULL за ошибку комментарий каркаса: change_tv_favorites() может вернуть NULL и при успехе — Widget Ext (код)238
Встроить хуки до и после вызова копия каркаса подключает внешний impl_dune_plugin_fw.php, если он есть, и вызывает call_plugin_begin/call_plugin_end, если методы определены хуки зависят от файла вне пакета (/persistfs/plugins/history/impl/) Smart_* (MoviesTape) (код)239

3.2. Экраны и обработчики ввода: add_screen, UserInputHandlerRegistry, свой маршрутизатор

Экраны и обработчики регистрируются в конструкторе класса плагина. В r24 DefaultDunePlugin::handle_user_input() выбирает обработчик по handler_id среди зарегистрированных (код r24)240; та же схема у плагинов. Фабрики контролов и create_action разобраны в guide/input-dialogs.md §4.1–§4.2.

Задача Приём Грабли и ограничения Плагины и claims
Подключить набор экранов конструктор плагина вызывает add_screen (или create_screen) для каждого экрана и создаёт объект ТВ/VOD зарегистрированный экран не обязательно пункт меню; в plugtv зарегистрирован TvFavoritesScreen при выключенном ТВ-избранном; у Dune HD TV часть экранов регистрируется только при непустом ID видеоисточника в настройках Online Movies (TV Series) (код)241; Smart_* (код)242; liteIPTV (код)243; DunePlexCatalog (16 экранов) (код)244; AllTV (код)245; plugtv (код)246; ProIPTV (код)247; Dune HD TV (код)248
Не зарегистрировать дубль add_screen бросает Exception на повторный get_id(), get_screen_by_id — на неизвестный id; register_handler перезаписывает обработчик без проверки дубль экрана — исключение, дубль обработчика — молчаливая замена Widget Ext (код)249
Экран с контролами — сам себе обработчик конструктор AbstractControlsScreen регистрирует экран в UserInputHandlerRegistry; ControlsScreen требует get_control_defs() реестр возвращает null при отсутствующем или незарегистрированном handler_id Widget Ext (код)250
Обойтись без экранов-классов класс плагина реализует UserInputHandler, переопределяет get_folder_view/handle_user_input и выбирает меню по префиксу media_url реестр используется только для создания действий, register_handler не вызывается; ТВ- и folder-range-методы пустые и возвращают null Twitch TV (код)251
Маршрутизатор без контроллеров media_url — JSON {"media_url": "Class->method", "params": …}; Screen::findOrCreate находит или создаёт экран по имени класса и вызывает метод через call_user_func_array класс из media_url должен наследовать Screen, иначе исключение Kohana-канал (код)252
MVC-каркас поверх SDK переименованная Kohana 1.0 (Rise) с application/, modules/, system/; модули dune_lib, dune, folder — Kohana-канал (код)253

3.3. Единая точка входа entry и дисклеймер первого запуска

Частый приём — все входы манифеста (ENTER, PLAY, настройки, auto_resume) ведут в один обработчик с handler_id=entry, а он решает, что открыть. Так же делают проверку подписки и согласие с предупреждением при первом входе.

Задача Приём Грабли и ограничения Плагины и claims
Свести все входы в один обработчик один handler_id=entry, различие — в entry_id (tv, setup, auto_resume, account_changed) и action (enter/play) обработчик сам разбирает entry_id; без него возвращает null, а Dune HD TV без входа показывает форму регистрации Polbox.tv (код)254; Dune HD TV (код)255
Не активироваться в чужом плагине того же сервиса сверить settings->kartina_tv_plugin_name с id сервиса при несовпадении — только строка в лог и null, пользователь объяснения не видит Polbox.tv (код)256
Сразу запустить ТВ, без папки обработчик entry возвращает ActionFactory::tv_play() (или PLUGIN_TV_PLAY_ACTION_ID) иной entry_id → null rain_* (код)257; Kohana-канал (код)258
Открыть папку через обработчик key_enter точки входа — plugin_handle_user_input с handler_id=entry, обработчик возвращает open_folder Filmix_API в том же семействе использует прямой plugin_open_folder Smart_* (код)259
Проверить подписку на входе entry на setup/tv вызывает apply_subscription(), при неудаче и пустом логине показывает диалог входа — Юрта ТВ (код)260
Ветки служебных команд в entry control_id reboot, power_off, do_setup, unInstallPlugin в одном обработчике reboot — shell_exec('reboot'), power_off — запись IR-кода в /proc/ir/button altSource (код)261
Показать дисклеймер при первом входе entry проверяет plugin_cookies->disclaimer; если согласия нет — диалог с кнопкой save_yes, она пишет флаг в cookie и открывает папку (Wallpaper — повторным вызовом entry) согласие хранится в cookie; значение флага у плагинов разное (1 или yes) MegaAnime (код)262; MegaTorrents (код)263; PeerflixServer (код)264; Entware/Wallpaper (код)265; Smart_* (Vimeo) (код)266

3.4. Перезапуск плагина и оболочки, лимит времени PHP

Задача Приём Грабли и ограничения Плагины и claims
Перезапустить плагин после смены настроек действие plugin_launcher://<имя плагина> — Novosib-iptv (код)267
Перезапустить GUI после смены темы change_settings с restart_gui=true или RESTART_ACTION_ID с reboot=false; запасной путь — killall shell в Wallpaper выбор между change_settings и reboot/killall shell зависит от HD::get_versions() Entware/Wallpaper (код)268
Жёстко перезапустить оболочку кнопка restart выполняет killall shell в DunePlexCatalog кнопка есть только при файле-флаге /D/dpc_custom_icons/reboot_enable.txt Anidub.Com (код)269; DunePlexCatalog (код)270
Дать PHP больше времени set_time_limit(180) в файле плагина лимит PHP — не тайм-аут операции оболочки, см. guide/plugin-operations.md §2 Novosib-iptv (код)271
Скачать документ без исключений HD::http_get_document: cURL с тайм-аутом 40 с, SSL-проверки выключены; при ошибке печатает текст и возвращает content ошибка HTTP не прерывает выполнение — исключения нет, возвращается content 101.ru (код)272

3.5. Долгие операции и поставщики фильмов без GUI

Поставщик фильмов (movie_suppliers) — это не экран плагина, а команда bin, которую оболочка вызывает по протоколу из guide/movie-suppliers.md §4. Плагины dunemdb показывают, как писать такую команду на Python или PHP и как не держать оболочку на долгом поиске.

Задача Приём Грабли и ограничения Плагины и claims
Не блокировать оболочку на поиске do_file_search сразу отвечает {"status": "active", "files": []}, поиск идёт в фоновом omsearcher.py; цикл пишет res.json и опрашивает cmd-файл с паузой 0,5 с daemonize() делает один fork без setsid/chdir; stop() только ставит флаг, потоки не останавливает Online Movies (eng) (код)273
Не запускать Python на каждый опрос run.sh для get_file_search_state выводит res.json файл читается без проверки существования Online Movies (eng) (код)274
Отдать URL без разбора JSON run.sh для get_stream_url переписывает "fileId": в "url": через sed замена рассчитана на точное написание ключа "fileId":, без пробела Online Movies (eng) (код)275
Единая оболочка команд run.sh для остальных команд делает exec ./run.py "$1"; run.py принимает имя метода первым аргументом, JSON — из stdin, ответ — JSON в stdout run.sh — штатный путь, run.py можно вызвать напрямую Online Movies (eng) (код)276
Принять команду movie_suppliers ровно один аргумент — имя команды, JSON из stdin; при неверном числе аргументов или JSON — error и выход 1 реализованы только get_episodes, do_file_search, get_stream_url; на остальные — unknown command и выход 1 Online Movies (rus) (код)277
Поставщик без сборки на Python скрипты с #!/usr/bin/python на Python 2; для 86xx в метаданных — зависимость от плагина python_86xx нужен Python 2 на устройстве Online Movies (eng) (код)278
Взять результаты из чужой библиотеки подменить методы объекта (sourcesFilter = lambda: None, sources = PatchedSources(callback)) зависит от внутренних имён библиотеки Online Movies (eng) (код)279
Один поставщик — PHP на устройстве и Python на хосте movie_suppliers_update.sh/register_supplier.sh пишут bin: ./run.py при пустом FS_PREFIX, иначе php-cgi -f ./run.php ответы двух реализаций различаются: Python не отдаёт indirect/urls Megogo (код)280; Okko (код)281
Подключить общий код из bin/ run.php подключает ../load_link_api.php и ../link_api.php относительными путями описатель не делает cd в каталог пакета Online Movies (rus) (код)282

Несколько семейств обновляют парсеры и «ядро» плагина, не выпуская новую версию пакета: скачивают PHP-файл с версией в маркере ##…## и подключают его через require. Все такие приёмы (link_api, get_streams, radio_tv, архив CGI-скриптов) собраны в §12.5, рядом с обычным обновлением пакета.

3.7. Копии SDK-каркаса в lib/: чем отличаются

Плагины не получают каркас от прошивки, а везут копию lib/ с собой; копии старые и расходятся с r24 и между собой. Поведение такой копии нельзя считать равным каркасу прошивки, а при замене lib/ надо сверять сигнатуры.

Задача Приём Грабли и ограничения Плагины и claims
Взять каркас из SDK-примера копия lib/ старого SDK-примера (dune_plugin_demo2.2011_12_22, фреймворк 2012 года, 43–45 файлов) нет properties.php/text_utils.php из r24; в plugtv 5 из 34 общих файлов отличаются, рядом лежат .bak двух фабрик plugtv (код)283; pirates_* (код)284; rain_* (код)285
Что изменено в копиях каркаса без text_utils.php: жёсткие строки «System error», «Can not create PHP plugin instance.»; DefaultDunePlugin делегирует ТВ/VOD объектам $tv/$vod; MediaURL::encode = json_encode ActionFactory копии surface_* уже r24 (нет open_folder_ext, launch_ext_app, restart и др.), зато ControlFactory шире altSource (код)286; surface_* (код)287
Не падать на старых прошивках ActionFactorySafe добавляет необязательные поля действий только при defined() константы без константы поле молча не добавляется 101.ru (код)288; FREE TV (код)289
Расширенная ActionFactory общая копия с tv_play(media_url, caption), show_dialog($attrs), launch_m3u, update_epg копии в родственных пакетах различаются: DI.FM и 101.ru; LSS новее SomaFM и Radiopotok.ru 101.ru (DI.FM) (код)290; surface_* (LSS) (код)291
Общая копия в нескольких плагинах lib/ MPD и DunePlexServer совпадает с TorrServe, кроме расширенного utils.php в копии TorrServe conf::__get без isset MPD (код)292; DunePlexServer (код)293; TorrServe (код)294
Урезанная копия ТВ-методы DefaultDunePlugin закомментированы или заглушка из 38 строк; классы приходят автозагрузчиком дубли ActionFactory/Action DunePlexCatalog (код)295; Kohana-канал (код)296
Заменить lib/ без поломки вызовов сверить позиционные аргументы фабрик (ControlFactory::add_button, RowsFactory::pane, gcomps_row, vgap_row) с копией r24 в GlobalTV add_button не передаёт тайм-ауты, pane принимает headers вместо focus, gcomps_row пропускает ui_level, vgap_row всегда пишет inactive_height GlobalTV (код r24)297
Строить GComp-компоненты фабрикой GCompsFactory::get_label_def, label/label_v2 всегда пишут id/geom_def/kind/specific_def и подставляют свои умолчания (цвет, размер шрифта) умолчания — это умолчания фабрики, а не контракт оболочки GlobalTV (код)298

3.8. Android-приложение вместо PHP-плагина

Объект: Jellyfin Bridge 0.3.3, watch-sync 0.1.0 и dune-voice (code, у dune-voice — README); это не PHP-плагины, а внешние приложения и утилиты.

Когда нужно принять видео от чужого Android-приложения или синхронизировать историю, плагин не обязателен. Jellyfin Bridge — приложение без dune_plugin.xml: оно принимает intent и само запускает плеер Dune, а состояние читает через IP Control.

Задача Приём Грабли и ограничения Плагины и claims
Принять видео из другого приложения BridgeActivity exported=true, singleTop, пустой taskAffinity, excludeFromRecents=true; intent-filter VIEW + BROWSABLE/DEFAULT для video/* и схем content, file, http, https — Jellyfin Bridge (код)299
Запустить плеер Dune копия входящего intent с компонентом com.dunehd.app/com.dunehd.shell.PlayerProxyActivity — Jellyfin Bridge (код)300
Получить право рисовать поверх других приложений при SDK >= Q и !Settings.canDrawOverlays — Toast, ACTION_MANAGE_OVERLAY_PERMISSION для своего пакета и cancelAndFinish(); если в прошивке нет такого экрана, разрешение выдаётся adb appops set … SYSTEM_ALERT_WINDOW allow без разрешения запуск не продолжается Jellyfin Bridge (код, форум)301 (по README)
Не перезапустить плеер при пересоздании activity при savedInstanceState != null — запись в лог и cancelAndFinish() — Jellyfin Bridge (код)302
Прочитать позицию и вернуть результат вход — int extra position, выход — позиция в мс в оба extra, один раз (compareAndSet) на входе int extra position, на выходе — позиция в мс в position и extra_position Jellyfin Bridge (код)303
Дождаться запуска плеера grace-период 5000 мс; onResume откладывает deliverResult на max(1000 мс, остаток) и вызывает его только при фокусе окна; onPause снимает вызов grace-период покрыт тестом Jellyfin Bridge (код)304
Следить за плеером, не мешая просмотру частый опрос — HTTP cmd=status (порт 80, без root); чтение и запись истории — только через adb с root — Jellyfin Bridge (код)305; watch-sync (код)306
Обойтись без root и ADB accessibility-служба перехватывает кнопки по README, root и ADB не нужны, содержимое экрана служба не считывает Lampa bridge (dune-voice) (форум)307 (по сообщениям авторов)

4. Экраны, папки и оформление

Объект: экраны PHP-плагинов: регулярные папки, control-папки, карточка фильма, rows- и GComps-экраны, меню, иконки, скины и обои. Источник — код около 40 плагинов и семейств (code; платформа и прошивка исполнения, как правило, не установлены). Это факты кода плагинов, а не проверенное поведение оболочки.

Экран плагина — это ответ на операции get_folder_view, get_regular_folder_items и get_next_folder_view. Модель видов папок, свойства ViewParams и действия обновления описаны в guide/gui-screens.md §1–§3; здесь — как плагины собирают из них приложение. Клавиши и диалоги — §5, хранение выбранного вида и настроек — §10, переводы подписей — §11.

4.1. Каркас: регистрация экранов и маршрутизация по screen_id в MediaURL

Самый распространённый каркас — набор экранов, зарегистрированных в конструкторе плагина, и адрес папки media_url в виде JSON с полем screen_id. Его используют плагины разных авторов; там, где адрес задан не JSON, ниже показаны альтернативы.

Задача Приём Грабли и ограничения Плагины и claims
Собрать приложение из нескольких экранов конструктор плагина регистрирует экраны через add_screen(); операции оболочки уходят в экран, выбранный по media_url неизвестный id в ProIPTV приводит к исключению Screen not found GlobalTV (код)308; altIPTV (код)309; WeburgTV (код)310; altSource (код)311; pirates_* (код)312; Torrent Center (код)313; ProIPTV (код)314
Передать параметры экрана в адресе папки MediaURL::encode кодирует карту в JSON; экран выбирается по screen_id, а без поля — по сырой строке media_url decode разбирает JSON только у строк, начинающихся с {; MediaURL::__get возвращает null для отсутствующего ключа, поэтому опечатка в имени поля не видна GlobalTV (код)315; altIPTV (код)316; WeburgTV (код)317; Online Movies (TV Series) (код)318; Torrent Center (код)319; Smart_* (код)320; Widget Ext (код)321
Связать экран и его обработчик ввода при регистрации экрана, реализующего User_Input_Handler, регистрируется и его обработчик; create_screen_action ищет обработчик экрана обработчик с неизвестным handler_id даёт null ProIPTV (код)322
Склеить адрес и данные без MediaURL HD::encode_user_data() склеивает media_url, \|\| и json_encode(user_data); decode_user_data() делит по первому \|\| разбор в get_folder_view() — цепочка условий; нераспознанный media_url у ForumHouseTV получает папку с элементами загрузки youtube_api/folder_cache (код)323
Обойтись без классов экранов get_folder_view выбирает меню по префиксам media_url (search_games:, streams:, movie:, genre: …) и точным строкам порядок проверок важен; любой неизвестный адрес молча открывает главное меню Twitch TV (код)324; Apple Trailers (код)325
Пункт поиска как группа в истории группа на каждый запрос с id = base64_encode(запрос); адрес результатов несёт group_id в base64 — AceStreamSearch (код)326
Отдать список и следующий вид через базовый класс DefaultDunePlugin::get_regular_folder_items делегирует get_folder_range экрана, get_next_folder_view — одноимённому методу экрана TV- и VOD-методы бросают исключение, если провайдер не задан Widget Ext (код)327
Плагин без экранов манифест только с name, caption, type; весь код — CGI в www/cgi-bin/, вызывается по HTTP в меню GUI-точек входа нет remote-control (код)328
Выбрать стартовый экран по сохранённому режиму обработчик входа по cookie start_tv/group_tv: при start_tv=1 — tv_play, при group_tv=4 — список каналов, иначе список групп ActionFactory::tv_play() объявлен без параметров и не переносит media_url в действие altIPTV (код)329
Выбрать экран по типу библиотеки PL::select_screen: для movie, artist, show, episodes, photo, home — свой экран; при непустом $check и вторичном атрибуте — DPC_FilterListScreen_a для firstCharacter/year/decade, иначе DPC_FilterListScreen; экран фильтров для вложенных фильтров открывает следующий список, для листовых — экран по типу библиотеки — DunePlexCatalog (код)330
Открыть папку своим экраном по её типу тип папки хранится в foldersTypes по basename; выбранный класс (SmartVideoScreen, SmartAudioScreen) формирует media_url тип привязан к basename, а не к пути: одноимённые папки делят настройку altSource (код)331
Добавить экран списка и сохранить сортировку Vimeo регистрирует SmartVodItemsScreen (show_list) и SmartVodSimpleListScreen (vod_simplelist); сортировка по genre_id/category_id — в sort_page_settings при save_sort_page и заданном video_sorting сортировка сохраняется и сбрасывает кэш Smart_* (Vimeo) (код)332
Подменить список каналов своим экраном подкласс TvChannelListScreen с GetScreenID() = surface_tv_channel_list, зарегистрированный в UserInputHandlerRegistry у Radiorecord.ru в начало того же списка добавляются пункты меню surface_* (код)333
Открыть вложенную папку по ENTER BaseMenu по умолчанию вешает на GUI_EVENT_KEY_ENTER действие $this->action (PLUGIN_OPEN_FOLDER_ACTION_ID) у TrailerMenu действие переопределено на VOD Apple Trailers (код)334
Убрать экран и пункт из сборки в sharavoz и tvteam нет файла *_search_screen.php и пункта поиска в медиатеке; в shura нет ещё *_m3u_tv.php и *_tv_channel_list_screen.php TV-экраны shura регистрируются напрямую (TvChannelListScreen и Starnet_MainScreen) zlostnyi (код)335

Узнать, в каком плагине сейчас пользователь, служебный плагин Cleanup пытается по файлу /tmp/run/nav_state.txt: из первых двух строк он извлекает тип и элемент, а для plugin:// — имя плагина и его pid (код)336.

4.2. Регулярная папка: виды, сетка и переключение вида

Вид регулярной папки задаёт сетку (num_cols/num_rows), иконки и фон через ViewParams (guide/gui-screens.md §2.1, §2.3). Плагины держат несколько видов одной папки и переключают их по get_next_folder_view.

Задача Приём Грабли и ограничения Плагины и claims
Несколько раскладок одной папки массив видов в функциях-константах (GET_*_FOLDER_VIEWS, FolderViews) — сетки и списки, async_icon_loading у GlobalTV у категорий и каналов задана заглушка loading_channel.png; DPC объявляет 12 функций видов, одна не вызывается; у WeburgTV группы 2×7, каналы 2×8; у torrent-center 1×10 и постерная 5×2; у rain_* VOD 5×4 и 1×12 GlobalTV (код)337; surface_* (код)338; Smart_* (код)339; zlostnyi (код)340; DunePlexCatalog (код)341; Torrent Center (код)342; WeburgTV (код)343; Apple Trailers (код)344; AceStreamSearch (код)345; rain_* (код)346
Запомнить выбранный вид индекс вида в plugin_cookies под ключом screen.<id>.view_idx; get_next_folder_view циклически увеличивает его без ключа берётся 0 GlobalTV (код)347; altIPTV (код)348; altSource (код)349; Torrent Center (код)350
То же со своим ключом cookie view_type с кругом 1→2→3→1 у streamit задан вид для view_type 4, но круг 1→2→3→1 его не достигает; у Anidub по умолчанию 2 youtube_api/folder_cache (код)351; Anidub.Com (код)352
Общий реестр видов для всех экранов init_screen_view_parameters собирает имена видов → параметры; экран перечисляет свои виды в $folder_view_ids; индекс — в настройке или параметре multiple_views_supported=1 ставится только при числе видов больше одного ProIPTV (код)353
Разные виды по прошивке два файла видов (nSmartViews/oSmartviews), выбор по HD::get_versions() в новых видах YouTube иконка-заглушка mov_unset.png, а в пакете есть только mov_unset2.png MegaAnime (код)354; YouTube (Smart_*) (код)355
Анимация прокрутки там, где она есть ViewParams::scroll_animation_enabled только на Android и только если константа определена — GlobalTV (код)356
Простое меню списком BaseMenu::create_folder_view: пункты {caption, url} → PluginRegularFolderItem, 1×11, иконка и действие ENTER из свойств меню все элементы в initial_range, more_items_available=false — подгрузки нет Twitch TV (код)357; Apple Trailers (код)358
Карточка фильма view_kind=view_movie с movie из 17 ключей, пустые поля — пустыми строками мост требует полный набор полей SDK Lampa bridge (код)359
Показать версию плагина в заголовке вида extra_content_objects с label, текст — HD::plugin_version() из поля version манифеста версию читает simplexml_load_file по dune_plugin.xml пакета, а не константа кода Bazinga (код)360
Не падать на старых прошивках без новых полей вида перед полем ViewItemParams — defined('ViewItemParams::…') на старых прошивках константы нет — поле не добавляется Bazinga (код)361
Два варианта интерфейса для 720 и 1080 отдельный манифест ott_play_1920 с путём /dunehd/1920 и osd_size=1920x1080; у остальных пяти фактических URL osd_size=1280x720 у пяти из шести пакетов есть закомментированный альтернативный URL, у itv комментария нет ott-play (код)362

Свойства видов — guide/gui-screens.md §3.2–§3.3, карточка фильма — там же §2.9.

4.3. Длинные списки: диапазоны, ленивая подгрузка и обновление открытой папки

Ленивая папка отдаёт элементы порциями через PluginRegularFolderRange (guide/gui-screens.md §2.2), а обновлять открытый экран можно целиком или по одному элементу (там же §2.7).

Задача Приём Грабли и ограничения Плагины и claims
Собрать диапазон элементов HD::create_regular_folder_range: при total=-1 (GlobalTV) или по умолчанию (Widget Ext) total = from_ndx + count(items); лишние элементы обрезаются при from_ndx >= total GlobalTV отдаёт пустой items GlobalTV (код)363; Widget Ext (код)364
Подгружать список по мере прокрутки первый диапазон — один элемент «Загрузка...» с more_items_available=1; Folder берёт следующий чанк у Cursor, а в конце ставится «Больше ничего не найдено» служебный элемент сдвигает индексы: при from_ndx > 0 индекс уменьшается на 1 Anidub.Com (код)365; youtube_api/folder_cache (код)366
Кэшировать загруженные папки singleton FolderCache (media_url → Folder), устаревание через час после последнего обращения или set_expired(); VideoCache по video_id кэш живёт в памяти процесса Anidub.Com (код)367; youtube_api/folder_cache (код)368
Отдавать весь список сразу get_folder_range строит элементы из всего массива и не использует from_ndx ошибка — один элемент ERROR: … RemTor (код)369
Перерисовать один элемент get_sel_item_update_action: диапазон из одного элемента по sel_ndx и update_regular_folder(range, false) — altIPTV (код)370; WeburgTV (код)371
Обновить соседнюю папку после действия таймер 100 мс в списке каналов и по событию timer — инвалидация папки групп — AceStreamSearch (код)372
Открыть папку действием ActionFactory::open_folder(media_url, caption) → PluginOpenFolderActionData оба аргумента по умолчанию null Widget Ext (код)373
Обновить открытую папку целиком или по элементу invalidate_folders(media_urls, post_action) или update_regular_folder(range, need_refresh, sel_ndx) sel_ndx приводится к int; need_refresh и индекс задаёт вызывающий код Widget Ext (код)374; Torrent Center (код)375
Сменить поведение экрана действием ActionFactory::change_behaviour(actions, timer, post_action) → CHANGE_BEHAVIOUR_ACTION_ID таймер и список действий задаёт вызывающий экран Widget Ext (код)376
Периодически обновлять папку таймер 500 мс у корня и файловых экранов; у Dune BackUp вид main_menu с таймером 900 мс, обработчик timer выполняет timer_actions и возвращает change_behaviour; у RemTor — refresh_interval*1000 и invalidate_folders у video_screen и audio_screen таймера нет; по сообщениям пользователей, у RemTor период по умолчанию 5 с, 0 отключает обновление altSource (код)349; Dune BackUp (код)377; RemTor (код, форум)378
Показать прогресс долгой операции диалог с ActionFactory::timer(1000); по GUI_EVENT_TIMER — close_dialog_and_run самого себя, выход по маркеру в логе или по исчезновению файла лога нужен вариант lib/action_factory.php с timer; в варианте LTU_install его нет служебные установщики hdtv (код)379

Размер страницы в коде и число строк вида могут не совпадать: BaseListScreen Online Movies задаёт вид 1×11 и PAGE_SIZE = 9 (код)380.

4.4. Экран настроек и контролы: AbstractControlsScreen и ControlFactory

Как экран сохраняет значения и применяет их к открытым спискам — §10.1.

Экран настроек — control-папка (guide/gui-screens.md §2.8); поля контролов и диалоги — §5 и guide/controls-reference.md §3.5–§3.6. Плагины собирают её фабрикой и перестраивают после каждого ввода.

Задача Приём Грабли и ограничения Плагины и claims
Вернуть экран контролов AbstractControlsScreen::get_folder_view → PluginFolderView вида CONTROLS с defs, initial_sel_ndx=-1, params в копии GlobalTV params всегда пустой массив, а в r24 — из get_folder_view_params GlobalTV (код)381; служебные установщики hdtv (код)382
Собрать поля фабрикой ControlFactory::add_vgap, add_multiline_label (max_lines по умолчанию 2), add_text_field с numeric/password/has_osk — Widget Ext (код)383; altIPTV (код)384
Кнопка, вызывающая обработчик add_button строит push_action через UserInputHandlerRegistry::create_action с action_type = apply; add_button_close оборачивает его в close_dialog_and_run — Widget Ext (код)385; altIPTV (код)386
Перестроить экран после действия обработчик по умолчанию возвращает reset_controls(do_get_control_defs()); набор контролов зависит от состояния системы (наличия путей) — служебные установщики hdtv (код)387
Вернуться в родительский экран на ту же позицию make_return_action закрывает экран и шлёт окну-источнику действие с initial_sel_ndx; RETURN и TOP_MENU направлены в обработчик экрана — ProIPTV (код)388
Сначала отправить в настройки без токена ENTER, PLAY и B_GREEN открывают настройки, а список — одна группа-подсказка — zlostnyi (код)389
Дисклеймер перед настройками пока plugin_cookies->disclaimer != 'yes', показывается предупреждение с кнопкой согласия — rclone (код)390
Свой контрол в копии фреймворка add_progressbar из cut_images скина; add_img_label со smart=1 это локальные правки копии ControlFactory, в других копиях их нет PeerflixServer (код)391; Smart_* (код)392
Собрать defs диалога фабрикой add_vgap, add_label, add_button, add_custom_button, add_text_field, add_combobox; у кнопок, поля и combobox общие ключи name/title/kind/specific_def/params params — переданный gui_params; need_apply/need_confirm по умолчанию false и оставляют действия null GlobalTV (код)393
Кнопки закрытия и применения add_close_dialog_button, add_close_dialog_and_apply_button, add_custom_close_dialog_and_apply_button; действие close_dialog_and_run у кнопок title=null, подпись центрируется по умолчанию; add_custom_* не добавляет action_type GlobalTV (код)394
Метки и кнопки, которых нет в прикладном коде add_smart_label (smart=1), add_img_label (max_lines/lines_vgab/pars_vgab), add_multiline_label (max_lines, lines=2), add_button_close, add_close_dialog_and_apply_button_title вызовов этих методов в прикладном коде пакета не найдено GlobalTV (код)395
Группы и подразделы настроек активная группа и подраздел — в файлах settings/group и settings/chapter; диалог группы — combobox из Group_arr, диалог подраздела — кнопки do_chapter_run<chapter> при смене группы подраздел сбрасывается, папка открывается заново; диалог подраздела строится только при более чем одном chapter Dune BackUp (код)396
Сменить библиотеку из настроек экран читает music_directory из mpd.conf и показывает статус по pidof; file_list с save_data music_folder переписывает четыре пути и перезапускает mpd, если он запущен — MPD (код)397
Подписи автора внизу экрана настроек две метки: представитель услуги «Общество Любителей Халявы» и разработчик zlostnyi с forum.hdtv.ru — pirates_* (код)398
Сменить настройки экрана действием ActionFactory::change_settings(settings, reboot, restart_gui, post_action) → CHANGE_SETTINGS_ACTION_ID флаги reboot и restart_gui передаются в действие Widget Ext (код)399
Экран настроек с неполным набором контролов контролы show_main_icon, use_osk, buf_time, skin, кнопки pin_dialog и restart контролов для video_quality и skip_details в do_get_control_defs() нет streamit (код)400

Расхождение между объявленным и показанным: в 101.ru обработчик пишет настройку b_ground, а контрола для неё в do_get_control_defs нет (код)401.

4.5. Меню, контекстное меню, скрытие и порядок пунктов

Пункты главного меню плагина, их порядок, скрытие и защита PIN — повторяющийся набор приёмов семейства Smart_* и его наследников. Карту клавиш экрана и popup-меню строят через действия SDK (guide/input-dialogs.md §2.1).

Задача Приём Грабли и ограничения Плагины и claims
Контекстное меню списка ActionFactory::show_popup_menu / GuiMenuItemDef с пунктами-действиями обработчика; пункты зависят от состояния у liteIPTV меню канала — около двадцати пунктов; у RemTor set_location — только при rpc_version > 5 и без отметок liteIPTV (код)402; RemTor (код)403; rclone (код)404; Dune BackUp (код)405; Widget Ext (код)406
Вернуться на главный экран ActionFactory::show_main_screen(post_action) → SHOW_MAIN_SCREEN_ACTION_ID — Widget Ext (код)407
Собрать главное меню из модулей для каждого класса из SmartConfig::getWox() вызывается getMainMenuInfo(): ответ с name даёт одну категорию, массив без name — несколько категорий с mUrl, name, descr и ico — Bazinga (код)408
Пользовательский пункт с постером и бейджем элементы mainMenuItems с ключом — закодированный MediaURL; при poster_url иконка и бейдж mmFilmBadge (mmFilmBadge2 при shape=rectangle), иначе SmartConfig::getPluginIco — Bazinga (код)409
Пункты в меню значка плагина popup_menu точки входа с plugin_handle_user_input (перезагрузка, выключение, настройки) у Dune BackUp блок цветных кнопок не добавляется при flag_apk, flag_new или прошивке от 240619 Screenshoter (код)410; Smart_* (Vimeo) (код)411; Dune BackUp (код)412
Свои кнопки экрана карта действий экрана: зелёная — настройки, жёлтая — информация о версии; INFO и жёлтая — панель управления — youtube_api/folder_cache (код)413; RemTor (код)414
Скрыть пункт меню ключ пункта в hide_id (Smart_* и наследники) или в сериализованном hideMmCat; проверка перед выдачей элемента в Bazinga hideCat вне режима «все источники» пропускает категорию, а в нём показывает серым color=17, стикер hide — только при defined('ViewItemParams::item_sticker') и view_idx != 2; lockCat даёт стикер s_lock только при defined('ViewItemParams::item_sticker') Smart_* (код)415; MegaRadio (код)416; Entware/Wallpaper (код)417; Torrent Center (код)418; Bazinga (код)419
Дать пользователю менять порядок up_portal переносит ключ в начало массива порядка (portals_link, n_link) и инвалидирует меню; reset_portal очищает порядок порядок без сохранённого значения — индекс от 1000, затем ksort; в Bazinga порядок — сериализованный nbrCat (media_url → номер), при расхождении набора категорий он пересчитывается Smart_* (код)420; MegaRadio (код)421; Bazinga (код)422
Добавить свои пункты в корень пункты в main_menu_manually (MegaRadio) или в mmItems с ключом md5(media_url) (altSource) у altSource ключ — md5 от media_url MegaRadio (код)423; altSource (код)424
Служебный пункт в начале списка add_special_groups вставляет первым «[новый поиск]» или «Медиатека» с адресом другого экрана — AceStreamSearch (код)425; zlostnyi (код)426
Всегда показывать «все каналы» экран списка подменяет group_id на группу всех каналов перед вызовом родителя — plugtv (Новый Мир, Трофей HD) (код)427
Массовый выбор и перенос LEFT/RIGHT двигают выбранные на один, страницу или к краю, RED меняет шаг, ENTER отмечает; отметки liteIPTV — в select_id с подсветкой цветом — ProIPTV (код)428; liteIPTV (код)429
Меню из внешних скриптов без правки PHP список пунктов — файлы *.sh из нескольких каталогов; имя, описание, группа, иконка и условия — директивы #<name>, #<info>, #<grup>, #<logo>, #<test> в самом скрипте слишком длинный путь скрипта прерывает разбор списка Dune BackUp (код)430
Настроить кнопку запуска директивами скрипта #<start.txt>, #<stop.txt>, #<autostart>, #<update>, #<no$1>, #<rmLG>, #<LGrv>, #<LG%%>, #<run.choice>, #<mode_full> #<mode_full> не скрывает пункт: он показывает ход выполнения и остановку в полном диалоге вместо лёгкого окна Dune BackUp (код)431
Скрыть раздел, если сервис недоступен при первом входе обработчик ставит cookie show_vod_ep и show_vod_section; при launch_vod проверяет MEDIATEKA_AVAILABLE и показывает диалог «фильмотека недоступна» MEDIATEKA_INPUT_SHOW и MEDIATEKA_AVAILABLE объявлены в скачиваемом ядре: обе равны 0 при branch_num < 11 и 1 при branch_num >= 11 FREE TV (код)432
Вызвать функциональность встроенного плагина run_builtin с id kartina_tv_root_shown, kartina_tv_open, kartina_tv_play, kartina_tv_auto_resume, kartina_tv_clear_cache; пункт очистки кэша показывается по результату kartina_tv_has_cache — Polbox.tv (код)433

4.6. Оформление элемента: иконки, логотипы, индикаторы, стикеры, QR-код

Форматы и схемы URL картинок (plugin_file://, gui_skin://) и асинхронная загрузка — guide/gui-screens.md §2.4, §2.6.

Задача Приём Грабли и ограничения Плагины и claims
Иконка пункта с цепочкой запасных вариантов get_plugin_ico: сохранённая пользователем → install/icons → DATA/icons → запасная → gui_skin (Smart_*); рядом со скриптом → icons → data → default.png (Dune BackUp); в Bazinga — DATA/icons, затем icons пакета файлы проверяются на существование; у Bazinga для имени с _bg — <data>/icons/<имя>.jpg, иначе gui_skin://images/bg.jpg; для userFav_ — userFavFolder.png Smart_* (код)434; Dune BackUp (код)435; Bazinga (код)436
Пользователь задаёт свою иконку или фон пункта file_list с save_file, путь сохраняется в plugin_ico иконка — PNG, фон — JPG MegaRadio (код)437; Smart_* (код)438; surface_* (код)439; liteIPTV (код)440
Логотип канала DATA/logo/<id>.png → plugin_file://logo/<id>.png → 0.png/00.png — liteIPTV (код)441
Иконка по типу объекта plugin_file://icons/<type>.png, автозапуск — starred, запущенное — цветом у AceStreamSearch константа ALL_CHANNEL_GROUP_ICON_PATH — plugin_file://icons/all.png, а по умолчанию в списке каналов — channel_unset.png rclone (код)442; altIPTV (код)443; AceStreamSearch (код)444
Индикатор просмотра по viewCount/viewOffset/duration — seen, halfseen с процентом или unseen; вид значка зависит от вида экрана при show_seen=hide всегда seen DunePlexCatalog (код)445
Пометить элемент стикером ViewItemParams::item_detailed_info_sticker и item_sticker, только если константа определена — Smart_* (knigavuhe) (код)446
Внешние обложки через свой CGI do_img?img=<url>: CGI скачивает картинку и отдаёт с Content-Type по расширению картинка идёт через CGI плагина, а не напрямую MegaAnime (код)447; Entware/Wallpaper (код)448
QR-код в диалоге картинка у api.qrserver.com с кэшем в tmp; вставка через smart label с <icon> внешний сервис ProIPTV (код)449
Разметка подписи add_smart_label со smart=1; ссылки gui_skin:// на части textfield_*selected и пиктограммы пульта ресурсы gui_skin:// зависят от скина Widget Ext (код)450
Статус и прогресс в иконке элемента иконка и подробности зависят от tr_status: verifying — get_icon_by_progress из plugin_file://icons/verify/ по recheckProgress*100, downloading — из plugin_file://icons/downloading/ по проценту готовности только при sizeWhenDone != 0, seeding — plugin_file://icons/seeding.aai, для статусов из icon_set — соответствующий, иначе gui_skin://small_icons/torrent_file.aai; в item_detailed_info — downloadDir, totalSize, tr_status, errorString (при непустом), а для downloading — eta и скорости иконки .aai не удалось посмотреть RemTor (код)451

4.7. Rows- и GComps-экраны, EPF: GlobalTV и Домашнее ТВ

Объект: GlobalTV 260130_1351 (таблица ниже) и Домашнее ТВ 3.5.4 с forum.mydune.ru (второй образец, после неё); оба — code; платформа плагинов в claims не установлена (кроме проверки ext_epg на r25 tv188b — «Не проверено»). SDK называет GComponents незавершёнными и внутренними (SDK)452; что это и где работает — guide/gui-screens.md §2.10, §3.8–§3.9.

Задача Приём Грабли и ограничения Плагины и claims
Включать rows только там, где они есть проверка class_exists("PluginRowsFolderView"); плагин использует виды REGULAR, GCOMPS, ROWS и CONTROLS у Dune HD TV от этой проверки зависит и создание TvRowsScreen с EpfsHandler, у Домашнего ТВ — признак NEWGUI_FEAUTURES_AVAILABLE и подключение EpfsHandler GlobalTV (код)453; Dune HD TV (код)454; Домашнее ТВ (код)455
Вернуть rows-папку AbstractRowsScreen кладёт в PluginRowsFolderView pane, sel_state, actions, timer; view_kind=PLUGIN_FOLDER_VIEW_ROWS обычный get_folder_view передаёт null вместо sel_state GlobalTV (код)456
Собрать pane и ряды RowsFactory::pane (rows, focus, bg, заголовки); фокус по умолчанию GCOMP_FOCUS_SYSTEM/GCOMP_FOCUS_NONE поля fade у title-ряда добавляются только при наличии констант GlobalTV (код)457
Кластеры с заголовками при defined(PluginRowsPane::headers) категория получает header с first_in_cluster без headers экран строится иначе: VGAP и строка избранного в начале GlobalTV (код)458
Обновить информационную панель событие PLUGIN_ROWS_INFO_UPDATE → update_rows_info с PluginRowsInfo (folder_key, item_id, info_defs, фон, маска) без item_id/folder_key или для неизвестного канала — null GlobalTV (код)459
Заранее подготовить экран (EPF) folder_view целиком в <epf_id>.json через <path>.tmp и rename; отдельная заглушка <epf_id>.no_internet.json при ошибке кэша пишется EPF products GlobalTV (код)460
Не пересобирать EPF без нужды пересборка только при холодном старте, отсутствии или устаревании метки или смене тега <язык>-<страна>; избранное — отдельным EPF — GlobalTV (код)461
Геометрия GComponents GCompGeom::geom всегда пишет w/h; GCompGeom::align пишет каждое поле только при истинном значении x=0 и y=0 в массив не попадают GlobalTV (код)462
GComps-папка и её состояние PLUGIN_FOLDER_VIEW_GCOMPS с window_def, sel_state, actions, timer; состояние выбора — через json_encode/json_decode — GlobalTV (код)463
Разложить GComp относительно соседа top/bottom/left/right/center задают role; place_* строят align_def: place_center центрирует, place_top_left не задаёт выравнивание, place_below_* ставят base_to_prev=true, place_next_right_align_top — halign=LEFT/valign=TOP при base_halign=RIGHT/base_valign=TOP place_same_size включает use_base_width и use_base_height GlobalTV (код)464
Задать четыре отступа GComp GCompMargins::all пишет left/top/right/bottom get_rect_def этой копии включает margins_def всегда, а в r24 он добавляется только при истинном margins GlobalTV (код)465
Собрать элементы rows-панели add_regular_item пишет обязательные id/icon_url и опциональные caption/sticker_urls; item_params задаёт состояния def/sel/inactive, variable_params — размеры и сдвиги; шаблон common хранится в regular_item_params_templates id канала — icon:<row_name>:<channel_id>; у шаблона common размеры 246×230, 189×230 и 189×190 GlobalTV (код)466
Заполнить информационную панель программы на time() берутся начало/конец с timezone_diff_secs, title_and_subtitle, описание, год, возраст, жанр, страна и main_icon; панель info_inf_dimmed получает alpha=64 и GCOMP_OPT_PREPAINT данные есть только при найденной программе GlobalTV (код)467
Выбрать фон и маску информационной панели fanart текущей программы либо plugin_file://%shell_ext%/icons/bg<индекс>.jpg с (channel.id+1)%4; mask_url — icons/mask.png, nl_bg_url=null — GlobalTV (код)468
Собрать rows-menu из разделов rows_menu_config.json с ключом rows_menu_items: обычный пункт — type=plugin, name, epf_id, caption, small_icon_url, left=5; избранное — caption=MY, left=0 (только при MainHelper::with_favorites()) protected=1 только для раздела xxx; отсутствующие разделы пропускаются; без list-config избранное идёт первым, с list-config — на позиции fav GlobalTV (код)469
Обновлять EPF главного меню по событию embeddable_plugin_folders.update_action → entry_id=update_epfs; обработчик вызывает EpfsHandler::update_all_epfs(interface_language, first_run) и возвращает ActionFactory::status(0) обработчик работает только при HD::with_rows_api(), иначе возвращает null; пересборка (если не GlobalSettings::WITHOUT_EPFS_AND_CACHE) — только при холодном старте, смене timestamp или языка; при неудаче загрузки пишется EPF products; ensure_no_internet_epfs_created использует неопределённую $plugin_cookies Dune HD TV (код)470

Домашнее ТВ 3.5.4: второй образец EPF и NewUI. Плагин, по первому посту автора, поддерживает New GUI (форум)471; EPF-механизм, по истории версий, появился в нём в v3.2.0 от 30.01.2022 (форум)472. Ниже — то, что он делает иначе, чем GlobalTV и Dune HD TV, и чего нет в таблице выше: свой id EPF, запись только при изменении, ряд истории, свой экран передачи ProgramScreen и поставщик ТВ на boot_end. Платформа и прошивка в claims плагина не установлены, на устройстве приёмы не проверены. Грабли этого кода — в guide/pitfalls.md, «Rows-экраны, EPF и история просмотра»; подробности — в claims этого плагина.

Задача Приём Грабли и ограничения Claims
Свой id EPF вместо tv embeddable_plugin_folders/mapping задаёт tv → htv; EpfsHandler::init читает id из своего манифеста: get_plugin_info('embeddable_plugin_folders') → [0]['mapping']['tv'] id не равен ни tv, ни имени плагина; при пустом tv или epg init ничего не делает (код)473
Не переписывать EPF без изменений update_all_epfs перезаписывает файл, только если json_encode нового folder_view отличается от текущего файла; при холодном старте создаёт маркер epfs_warmed_up меток времени и тега языка, как у GlobalTV, нет; EPF лежит на флеше — /flashdata/plugins_epfs/home_tv/htv.json, заглушка htv.no_internet.json рядом; отдельного tmp_epfs_path (/tmp/plugins/<p>/epfs) в этой копии нет (код)474
Обновить ТВ-раздел после правки каналов EpfsHandler::invalidate_folders всегда ставит id EPF (htv) первым в media_urls действия invalidate_folders; вызов — после выхода из экрана групп с флагом need_update_epf, перестановки избранного, сохранения локации в настройках, стопа воспроизведения, корзины и редактора каналов без NewUI те же места вызывают invalidate_folders или close_and_run (код)475
Обработать update_epfs ветка pf_checked лаунчера: если плагин не только что установлен или обновлён и есть NewUI — update_all_epfs и invalidate_folders(), иначе null first_run — isset полей first_run_after_boot/restore_from_sleep, а не их значение (shell_ext r25 и DUNE-HD.TV берут значение) (код)476
Ряд «Продолжить просмотр» при class_exists('PlaybackPoints') и не взведённом clear_playback_points — до 7 разных каналов из истории, кроме неизвестных и взрослых; при прогрессе и картинке передачи элемент получает её картинку, логотип канала стикером и полосу прогресса высотой 8; если элементов меньше 7, они добираются из прежнего EPF, пока передача в окне архива; ряд вставляется перед рядами групп история ведётся только при branch_num прошивки ≥ 9; «Удалить» — см. guide/pitfalls.md (код)477
ENTER на ряду — сразу смотреть ENTER на элементе или на ряду группы → SplashScreen::open_and_run с действием plugin_entry лаунчера и resume_mode=1, resume_tv_group, resume_tv_channel, resume_tv_archive_tm (−1 без архива), resume_tv_is_favorite запуск по ENTER на колонке группы, по истории версий, добавлен в v3.2.1 (код, форум)478
Предпросмотр канала в инфо-панели на GUI_EVENT_PLUGIN_ROWS_INFO_UPDATE при наличии item_id и folder_key — update_rows_info с playback_urls = [plugin_tv://<plugin_name>/<item_id>], фон — фанарт передачи или images/bg.jpg без item_id или folder_key — null (код)479
Свой экран передачи ProgramScreen вместо встроенного ext_epg GComps-экран ProgramScreen (epg_event_screen) сам регистрируется через create_screen; лаунчер на control_id=recent берёт событие из своего EPG (get_program_event) и возвращает get_update_epg_action с open_folder; файл /tmp/ext_epg/<channel>-<day>.json экран не читает экран подключается только при EXT_EPG_AVAILABLE = defined('PluginTvInfo::ext_epg_enabled') (код)480
Перенаправить встроенный ext_epg в свой экран мод ext_epg на control_id=open при plugin_name=home_tv и определённых PLUGIN_HANDLE_USER_INPUT_ACTION_ID и GuiAction::plugin_name возвращает plugin_handle_user_input с handler_id=plugin_launcher, control_id=recent и plugin_name=home_tv; при невыполнении любого условия ведёт себя как встроенный параметры совпадают с обработчиком recent Домашнего ТВ; мод, по сообщению автора на форуме (2025-09-07), — «немного модифицированный плагин ext_epg» для проверки в Домашнем ТВ; кто шлёт recent без мода — «Не проверено» (код, форум r24)481
Обратиться к встроенному ext_epg один раз за процесс PHP к change_behaviour воспроизведения добавляется handle_user_input с handler_id=main, control_id=init и GuiAction::plugin_name=ext_epg зачем — «Не проверено» (код)482
Зарегистрировать поставщика ТВ для NewUI boot_end → bin/register_supplier: без newgui2021 в /tmp/firmware_features.txt — выход; иначе JSON /tmp/tv_app_suppliers/home_tv с tv_app {type: plugin, plugin_name: home_tv, update_url}, метка в /config/htv_timestamp и флаг /tmp/plugins/home_tv/update_epfs_if_needed_flag вариант .platform.android/bin/register_supplier ставит $FS_PREFIX перед путями и пишет в update_url порт $HD_HTTP_LOCAL_PORT (по умолчанию 80), а /config/htv_timestamp не пишет; /config/htv_timestamp PHP-код плагина не читает; DUNE-HD.TV пишет свой описатель в $FS_PREFIX/tmp/tv_app_suppliers/dune-hd.tv (код)483

4.8. Скины, темы, обои и прозрачность диалогов

Плагины меняют оформление и вне своего каталога: создают пользовательский скин оболочки, подменяют обои и логотип. Эти приёмы пишут в системные пути и требуют перезапуска оболочки.

Задача Приём Грабли и ограничения Плагины и claims
Сделать пользовательский скин оболочки копия активного скина (путь из /tmp/dune_skin_dir.txt) в /persistfs/dune_skin или /flashdata/dune_skin — симлинки, копия bg.jpg и dune_skin_config.xml; gui_skin = custom в /config/settings.properties; затем CHANGE_SETTINGS_ACTION_ID, иначе RESTART_ACTION_ID, иначе killall shell пишет системные настройки напрямую; Widget Ext перед копированием удаляет содержимое каталога скина и показывает кнопку только при gui_skin = alt:Silver; Bazinga в save_skin копирует только dune_skin_config.xml и images/bg.jpg, остальное — симлинками altSource (код)484; Entware/Wallpaper (код)485; Widget Ext (код)486; Bazinga (код)487
Исправить палитру скина Silver и производных проверка dune_skin_config.xml активного скина по таблице из 16 цветов и патч с резервной копией; подробно — guide/gui-screens.md §4 патч скина из firmware идёт через копию в dune_skin и gui_skin=custom Домашнее ТВ (код)488
Заменить иконку плагина PNG в dune_skin/plugins/icons/<plugin_name>/icons/logo.png нужен gui_skin=custom; предлагается перезапуск оболочки altSource (код)489; Bazinga (код)490
Сменить логотип внутри пакета копирование skins/<skin>/icons/logo.png в skins/, затем reboot или killall shell у streamit путь зашит с чужим именем плагина CinemaHD.ru; у Anidub shell_exec копирует logo.png и no_cover.png, а combobox выбора скина закомментирован youtube_api/folder_cache (код)491; Anidub.Com (код)492
Темы иконок плагина выгрузка DATA/icons в <plugin>IconTheme.zip, загрузка — удалить DATA/icons, распаковать, перезагрузить; тема по умолчанию — копия каталога, не ZIP — altSource (код)493
Сменный скин самого плагина skins/<name>/plugin_skin.xml + PHP-файл раскладок; выбор skin_vote читается из cookie-файла до создания плагина; установка скина из ZIP ZIP распаковывается в skins/<name> по имени из архива целиком EvolutionTV (код)494
Обои главного меню запись dune_skin/images/bg.jpg с резервной копией .bak; случайный или следующий файл из папки; Wallpaper при gui_start запускает bin/boot.sh, который запрашивает локальный http://127.0.0.1/cgi-bin/plugins/Wallpaper/do3; SomaFM и Radiopotok.ru при bg_path не no берут случайную страницу wallpaperscraft и картинку по индексу файл больше 1 000 000 байт отбрасывается; по описанию автора, новые обои применяются после следующего включения плеера или «обновить»; у SomaFM/Radiopotok.ru при ошибке curl или HTTP-коде не 200 возвращается пустая строка; локальный HTTP должен быть готов Entware/Wallpaper (код)495; описание автора на форуме (форум)496; surface_* (код)497
Прозрачность диалогов как настройка локальный ActionFactory::show_dialog ставит или снимает dialog_params.frame_style по настройке правка копии фреймворка PeerflixServer (код)498; YouTube (Smart_*) (код)499
Оформить системную папку накопителя переписать dune_folder.txt: подписи «[просмотрено]», item_detailed_info, icon_path; папка «История» в /persistfs/main_screen_items/History; имя диска — storage_name плагин перезаписывает dune_folder.txt в чужих каталогах; имя диска — после перезагрузки служебные установщики hdtv (код)500

4.9. Экраны-каталоги: пункты, группировка и сортировка

Объект: экраны, которые строят пункты из своей базы, а не из ответа сервера: Apple Trailers, Twitch TV и список плагинов Dune BackUp (code; платформа и прошивка исполнения не установлены). Ниже — приёмы этих трёх плагинов: пункт-группа, фильтр по её ключу, сортировка подписей.

Задача Приём Грабли и ограничения Плагины и claims
Показать все объекты по алфавиту обойти всю базу, caption = title, url = 'movie:<location>', затем CompareCaption база грузится при каждом создании меню, если глобальной ещё нет Apple Trailers (код)501
Сгруппировать по дате уникальные timestamp полуночи из getDates, rsort, пункт strftime('%Y-%m-%d') с url = 'date:<timestamp>' полночь задаётся DateTime::setTime(0, 0, 0) Apple Trailers (код)502
Сгруппировать по жанру getGenres → array_unique и sort; пункт genre:<жанр>, фильтр — in_array по массиву genre — Apple Trailers (код)503
Показать файлы объекта MovieMenu перечисляет типы трейлеров, TrailerMenu — файлы с индексом и действием PLUGIN_VOD_PLAY_ACTION_ID индекс — позиция в массиве файлов; у TrailerMenu действие переопределено на VOD Apple Trailers (код)504
Отсортировать пункты по подписи usort по BaseMenu::CompareCaption без учёта регистра сортировка только по подписи: повторяющиеся имена не различить Twitch TV (код)505
Обработать пустой результат $items не инициализируется, первый элемент создаёт только $items[] при отсутствии совпадений переменная не создана; что из этого следует для usort и create_folder_view — в «Не проверено» Apple Trailers (код)506
Собрать список из чужих манифестов plugins_list обходит /persistfs/plugins, иначе /flashdata/plugins, читает caption и version из dune_plugin.xml, переводит %tr% по переводам плагина; data/plugins_rename.txt переводит внутренние имена в подписи встроенные префиксы tv_, dunemdb_supplier_, test_php-cgi, node, bluray, dunestore, smotreshka.tv исключены; plugins_rename.txt используют 19 one in all upload.sh и for_plugins.mydune.ru.sh Dune BackUp (код)507

4.10. Файловый браузер и запуск из папки

Объект: экраны, которые показывают содержимое каталогов накопителя и запускают файлы: altSource, DuneArc из служебных установщиков и файловый экран Smart_* (code; платформа и прошивка исполнения не установлены). Это не каталог сервиса, а обзор локальной файловой системы; запуск идёт через URL-схемы прошивки.

Задача Приём Грабли и ограничения Плагины и claims
Показать содержимое папки scandir; по умолчанию скрыть имена с точкой, lost+found, dune_folder.txt, Thumbs.db; тип — filetype, для симлинков — test -d скрытие и проверка симлинков выполняются при построении списка altSource (код)508
Искать по текущей папке shell_exec('cd "<path>" && find \| grep -iF "<keyword>"'), результат фильтруется по вхождению подстроки в имя без учёта регистра — altSource (код)509
Слайд-шоу из картинок папки собрать m3u из всех image_file в <tmp_dir_path>/tmp.m3u, запомнить start_index и запустить file://…/tmp.m3u через launch_media_url файл называется одинаково для любой папки altSource (код)510
Открыть системный файловый браузер SmartFileSystemScreen по control_id=open_folder открывает embedded_app file_browser с путём, преобразованным через launch_media_url; do_mkdir создаёт каталог с mode 0777 и инвалидирует родителя — Smart_* (код)511
Показать файловый экран и запустить файл DuneArc регистрирует единственный экран fsScreen; локальный путь /tmp/mnt/storage/… переводится в storage_name://…, SMB — в smb://user:password@<ip>/… или smb:<ip>/…, NFS — в nfs-tcp:// или nfs-udp://<ip>:/… и запускается launch_media_url setup_screen.php и settings_manager.php в пакете нет служебные установщики hdtv (код)512

5. Ввод и диалоги

Объект: обработка пульта, текстовый ввод и экранные клавиатуры в плагинах (Torrent Center, altIPTV, WeburgTV, Anidub.Com, altSource, Smart_*, ProIPTV, GlobalTV, 101.ru, zlostnyi, MegaAnime, YouTube, Widget Ext и др.) и внешние источники ввода (IP Control, Android-приложения); уровень code, платформа и прошивка исполнения не установлены.

Модель ввода платформы — действие HANDLE_USER_INPUT, карта actions с клавишами GuiEventKind, диалоги и контролы — описана в guide/input-dialogs.md. Там же, в §4, разобраны фабрики контролов shell_ext, Widget Ext и GlobalTV, диалог-список с RETURN как «применить», диалог поиска GlobalTV, клавиатура AdvKeyboard в Widget Ext и перехват клавиш accessibility-сервисом dune-voice. Здесь — то, что к этому добавляют другие плагины: как они разводят клавиши по обработчикам, как просят текст и PIN, как распространена AdvKeyboard и как подают ввод снаружи. Регистрация обработчиков в каркасе — §3.2.

5.1. Развести клавиши по обработчикам: handler_id, control_id, get_action_map

Типовая схема: экран возвращает карту клавиш из get_action_map, каждое действие создаётся UserInputHandlerRegistry::create_action с handler_id и control_id, а реестр передаёт ввод зарегистрированному обработчику. Идентификаторы control_id — внутренний контракт плагина, оболочка их не знает.

Задача Приём Грабли и ограничения Плагины и claims
Привязать клавишу к своей функции create_action → PLUGIN_HANDLE_USER_INPUT_ACTION_ID с handler_id/control_id в params; реестр направляет ввод обработчику по handler_id — Torrent Center (код)513; altIPTV (код)514; WeburgTV (код)515; Online Movies (TV Series) (код)516; Smart_* (код)517
Не потерять клавиши базового экрана подкласс, переопределивший handle_user_input, должен сам вызвать parent::handle_user_input для чужих control_id в WeburgTV подкласс обрабатывает только add_favorite и для остальных возвращает null, не вызывая родителя WeburgTV (код)518
Один обработчик на весь плагин один handle_user_input со switch ($control_id); get_handler_id() возвращает id класса при отсутствии control_id или неизвестном значении открывается папка selected_media_url Anidub.Com (код)519
Карта клавиш главного меню ENTER/PLAY → add_actions, SETUP и жёлтая → настройки, зелёная → whats_new, POPUP_MENU → popup_menu — Smart_* (код)517; Torrent Center (код)520
Цветные клавиши в списке файлов зелёная — «просмотрено/не просмотрено», жёлтая — фильтр, синяя — избранное (в истории — удаление), SETUP — настройки — altSource (код)521
Клавиши в списке каналов ENTER/PLAY — воспроизведение, SETUP — настройки, REC — фоновая запись, зелёная/жёлтая — поиск прокси, POPUP_MENU — меню — altIPTV (код)522
Дополнительные настройки по цветной клавише GUI_EVENT_KEY_D_BLUE открывает диалог — служебные установщики hdtv (код)523
Скрытый раздел по серии нажатий семь нажатий CLEAR, когда скрипт не работает и выбран не users, или семь SELECT в полном режиме вне main_menu открывают раздел users; fast_group_to_users включает группу и запускает run семь SELECT в базовом режиме дают диалог смены режима, а не users Dune BackUp (код)524
Клавиши, зависящие от состояния экрана get_action_map всегда назначает POPUP_MENU, INFO, SELECT, D_BLUE и TIMER; ENTER/PLAY и CLEAR — только при непустом Script_arr, A_RED — при файле автостарта, B_GREEN — в полном режиме при более чем одной группе, C_YELLOW — при более чем одном подразделе ENTER/PLAY, CLEAR, A_RED, B_GREEN и C_YELLOW в остальных состояниях не назначаются Dune BackUp (код)525
Вернуть отложенное действие после логина если в user_input есть callback_action и предыдущие ветки обработчика не вернули действие, оно возвращается как действие после json_decode — Dune HD TV (код)526
Вызвать обработчик ввода готовым действием ActionFactory::handle_user_input(params) кладёт params в GuiAction::params; data и caption — null — Widget Ext (код)527

5.2. Запросить текст, ключ и PIN: текстовое поле, поиск, родительский контроль

Поле ввода строится add_text_field; поля GuiTextFieldDef и экранная клавиатура has_osk — в guide/input-dialogs.md §2.5 и guide/controls-reference.md §3.6.

Задача Приём Грабли и ограничения Плагины и claims
Текстовое поле с флагами add_text_field с numeric, password, has_osk, always_active, шириной и необязательными apply/confirm в Widget Ext apply_action/confirm_action остаются null, пока не включены need_apply/need_confirm ProIPTV (код)528; Widget Ext (код)529
Поиск с запоминанием запроса поле поиска заполняется последним запросом из cookie; непустой запрос сохраняется обратно GlobalTV не сохраняет запрос для раздела xxx ProIPTV (PARAM_LAST_TV_SEARCH) (код)528; GlobalTV (last_search_channels_text) (код)530
Потребовать ключ при входе ENTER/PLAY → add_actions; при пустом ключе — диалог с полем и кнопкой «применить», ключ сохраняется в plugin_cookies без ключа папка не открывается 101.ru (DI.FM, listenKey) (код)531
Родительский контроль каналы «для взрослых» помечаются при разборе плейлиста; get_tv_playback_url отдаёт пустой URL, если код не совпал с cookie pass_sex (по умолчанию 0000); смена пароля — диалог «старый/новый» при неверном коде — пустой URL, а не сообщение об ошибке zlostnyi (код)532
Защитить каналы кодом в get_tv_playback_url для защищённого канала при need_password_sextv = yes и родительском коде не 0000 поток выдаётся только при совпадении protect_code иначе для не-passive канала возвращается строка "protected", для passive — matras.mp4 Dune HD TV (код)533
PIN на отдельные разделы $plugin_cookies->pin (по умолчанию 0000); в parent_dialog код спрашивается, только если subcategory_ref целиком равен http://streamit.ws/c/porn/ или /Porn мастер-код 9876 подменяет проверку и открывает раздел без PIN; остальные разделы не защищены streamit (код)534
Показать диалог с произвольными контролами ActionFactory::show_dialog(title, defs, close_by_return, width, attrs) собирает ShowDialogActionData, включая max_height; старый show_dialog_old его не заполняет при transparency_dialogs, сравниваемом с 0, удаляется attrs[dialog_params][frame_style]; это loose comparison PHP, фактическая прозрачность не доказана Widget Ext (код)535
Передать параметры диалога локальный show_dialog принимает attrs.max_height и attrs.dialog_params и передаёт их в ShowDialogActionData::max_height и params имена полей отличаются от варианта android_apps r24 Smart_* (код)536
Диалог с одной кнопкой OK show_title_dialog строит кнопку apply_subscription с подписью OK, шириной 300 и post_action через add_custom_close_dialog_and_apply_buffon имя метода buffon — опечатка исходника, вызывающий код использует именно его Widget Ext (код)537
Закрыть диалог и выполнить действие close_dialog_and_run кладёт post_action в CloseDialogAndRunActionData; close_dialog — частный случай с null; close_and_run — без диалога отдельного действия закрытия нет; для кнопок нужен add_close_dialog_and_apply_button или add_custom_close_dialog_and_apply_buffon Widget Ext (код)538
Показать файл в диалоге shell-скрипт пишет ход работы в /tmp/service_result_message, кнопка info_log показывает файл построчно в диалоге «Лог установки» приём повторяется в LTU_install, Codec_install и ExtendRC_install служебные установщики hdtv (код)539
Диалог условий сервиса регистрация на www.jurt.tv, тестовый логин, годовой сбор $25, контакты по e-mail — Юрта ТВ (код)540
Диалог выбора значения add_id позволяет выбрать vsetvID из похожих, по первой букве или из полного списка; флаг HD добавляет суффикс _HD, id сохраняется в my_channels_id для id > 2999 id пишется ещё и в vsetv_list, а логотип ищется в /D/<id>.png и копируется в DATA/logo liteIPTV (код)541
Поиск через отдельный CGI search_items, use_osk, отдельный диалог /suche.php; запрос — HOST_API_URL + /suche.php?s=<urlencode>, следующая страница — page=N или &page=N по сообщениям пользователей, поиск на сайте находит только фильмы в flv, которые в этом плагине на Dune не воспроизводятся streamit (код, форум)542

5.3. Своя экранная клавиатура AdvKeyboard в разных плагинах

AdvKeyboard — сторонний класс с пометкой «As is. It is free. q2100 forum.hdtv.ru» в шапке, он встречается в нескольких плагинах (код)543; его устройство описано в guide/input-dialogs.md §4.5. Ниже — как её встраивают и настраивают.

Задача Приём Грабли и ограничения Плагины и claims
Взять готовую клавиатуру с подсказками копия adv_keyboards/adv_keyboard.php с handler_id adv_text_keyboard и раскладками из txt-файлов в altSource подсказки — Google Suggest, Kinopoisk Suggest и поиск по файлам altSource (код)544; MegaAnime (код)545; YouTube (Smart_*) (код)546
Включать её настройкой на экране поиска use_osk == 2 (и нет open_normal_search) — AdvKeyboard, иначе стандартное текстовое поле; в YouTube у use_osk три значения, по умолчанию 1 — MegaAnime (код)547; YouTube (код)548
Встроить в свой экран конструктор принимает media_url, plugin_cookies, родительский обработчик и postActionCtrlId (по умолчанию run_search); параметры minLengthForSuggestions (3), searchAndSelectMode (false), searchTextActionParamKey для выбора из списка (город Gismeteo) — порог 2 и searchAndSelectMode = true со своим поставщиком подсказок Widget Ext (код)549; YouTube (do_search в списках) (код)550
Подсказки от YouTube запрос к suggestqueries.google.com/complete/search?client=toolbar… — YouTube (код)551
Раскладки в текстовых файлах adv_keyboard_<язык>.txt: пять строк на страницу, пары «символ|параметры|», служебные BackSpace, Shift, Alt, __ (пробел), Enter, Conf; список языков — обход файлов каталога нет файла — english; ошибка загрузки — встроенная раскладка с ERR; нераспознанная команда в позиции (0,0) переключает раскладку Widget Ext (код)552; YouTube (код)553
Переключать языки и страницы change_keyboard — по кругу три слота userKbrds, пропуская -; alt_onoff — следующие пять строк раскладки ровно три слота Widget Ext (код)554
Язык по умолчанию — язык оболочки interface_language из /config/settings.properties, при неудаче english — YouTube (код)555
Курсор в строке ввода цифры вставляются в позицию курсора; LEFT/RIGHT на строке ввода переходят между началом и концом — Widget Ext (код)556
Перерисовать клавиатуру без перезапуска screen_render перестраивает подписи через highlight_selected и add_screen_labels, screen_refresh отдаёт defs в ActionFactory::reset_controls defs собираются заново на каждое действие, состояние строки хранится в полях объекта Widget Ext (код)557
Развести клавиши клавиатуры карта get_action_map: CLEAR → clear_left, красная → clear_all, зелёная → alt_onoff, жёлтая → shift_onoff, синяя и AUDIO → change_keyboard; TOP_MENU → open_normal_search, PLAY → do_search, ENTER → selection_enter, SELECT → пробел, SETUP → config_lang, TIMER → timed_startup для каждой клавиши — отдельный control_id; карта не описывает поведение вне диалога Widget Ext (код)558
Вводить и удалять UTF-8 собственные mb_insert_str и mb_delete_chr на mb_strlen/mb_substr; на односимвольной клавише регистр выбирается через mb_strtoupper/mb_strtolower по флагу shift регистр зависит от shift, вставка идёт в cursPos Widget Ext (код)559
Очистить и восстановить строку clear_all при cursPos != 0 очищает строку и сбрасывает курсор, при нуле восстанавливает strRed strRed хранится в объекте: повторное нажатие красной кнопки возвращает удалённый текст Widget Ext (код)560
Отправить введённую строку родителю обычный do_search передаёт str под ключом searchTextActionParamKey через close_dialog_and_run; open_normal_search шлёт search_actions = keyboard, restart_kbrd — search_actions = open, doSearchBySuggestion — фиксированный adv_kbrd_str_to_find_q21 обычный поиск использует настраиваемый ключ, а отправка подсказки — фиксированный Widget Ext (код)561
Режим обязательного выбора подсказки в searchAndSelectMode обычная отправка строки через do_search, строка поиска, Enter раскладки и open_normal_search возвращают null; do_search на выбранной подсказке обрабатывается раньше этой проверки произвольный текст отправить нельзя; ENTER на подсказке вызывает doSearchBySuggestion, если режим включён или поставщик вернул isSearchBySuggestionOnly, иначе переносит текст в строку ввода Widget Ext (код)562
Обновлять подсказки по мере ввода getSuggestions вызывается только при длине строки не меньше minLengthForSuggestions; highlight_selected смотрит первые шесть подсказок и пишет scrBuff при непустом представлении что происходит со старыми подсказками после сокращения строки — в «Не проверено» Widget Ext (код)563

5.4. Ввод снаружи: ИК-коды через IP Control, публичные действия, голос

Команда IP Control cmd=ir_code описана в guide/ip-control.md §5; плагины пользуются ею, чтобы «нажать» кнопку пульта из своего кода.

Задача Приём Грабли и ограничения Плагины и claims
Нажать кнопку пульта из плагина wget на http://127.0.0.1:<port>/cgi-bin/do?cmd=ir_code&ir_code=<код>, проверка command_status = ok по комментарию автора, это работает на ATV, где /proc/ir/button не работает ProIPTV (код)564
Перезагрузить плеер кнопкой питания reboot.bash раз в секунду шлёт в /firmware/ext_command/cgi-bin/do cmd=ir_code с DISCRETE_POWER_OFF, пока плеер не уйдёт в standby, затем DISCRETE_POWER_ON, пока не выйдет helper exec_do для других команд закомментирован remote-control (код)565
Запуск по ENTER и внешним вызовом actions/key_enter и публичное действие play — оба plugin_handle_user_input с command=play обе ветки обрабатываются одним кодом Lampa bridge (код)566
Голосовая команда в предыдущее приложение после распознавания VoiceActivity делает finish() и только через 250 мс выполняет команду иначе BACK и команды плеера уйдут в собственный экран Lampa bridge (dune-voice) (код)567

5.5. Диалог-редактор списка: EditListConfigActionData и EditListDialog

Объект: штатный редактор списка GlobalTV 260130_1351 (code; прошивка и поведение на устройстве не проверялись). Это диалог с группами и отметками: так плагин даёт пользователю включить, снять и переставить разделы главного меню, не рисуя собственный экран контролов.

Задача Приём Грабли и ограничения Плагины и claims
Показать штатный редактор списка ActionFactory::edit_list_config всегда пишет в data config_id, title, all_items и post_action; checked_ids, groups и options — только при истинном аргументе без defined(EditListConfigActionData::config_id) фабрика возвращает null; close_item_params и sel_id добавляются по defined и isset GlobalTV (код)568
Сбросить или заменить порядок без редактора change_list_config_reset_to_default передаёт set_default=true и null для остальных полей; replace_order — set_default=false, заданный order и null обе фабрики не заполняют списки изменений GlobalTV (код)569
Построить редактор без list config старая ветка configure_sections строит EditListDialog шириной 870 из всех разделов, текущего get_enabled_sections_idset(false), групп default/other и callback apply_sections; show_dialog получает close_by_return=false, max_height=870, page_size=11 max_height пишется только при defined его константы; пустой all_by_id очищает состояние и возвращает null GlobalTV (код)570
Отметить группы и элементы get_group_checked кодирует состояние: 4 — смешанное, 3 — все, 2 — снято, 1 — пусто; полная группа снимается, прочая отмечается; элемент инвертируется; ответ — reset_controls с новыми defs changed=true ставится при любом переключении, даже при возврате к исходному набору; в defs порядок apply, group:<gid>, item:<id>, подпись кнопки — JSON с иконкой 48×48 GlobalTV (код)571
Применить или отменить синяя клавиша и RETURN вызывают собственное действие apply; пустой набор отклоняется через show_error, иначе close_dialog_and_run(do_apply); в params уходят JSON checked_idset и initial_checked_idset cancel только закрывает диалог без cleanup и apply_action; без переключений do_apply после cleanup возвращает null GlobalTV (код)572
Обработать результат редактора apply_list_config читает list_config_changed и list_config_id: при ложном changed — null, id разделов уходят в apply_edit_sections, остальные — в обработку категорий apply_edit_sections перечитывает lcfg, пишет CFG_TS, вызывает update_all_epfs(false) и возвращает reread_all_epfs(true); удалённые категории снимаются через change_tv_favorites_categories(REMOVE, id), изменённые — через force_update_section GlobalTV (код)573

11. Локализация

Объект: переводы подписей и выбор языка в PHP-плагинах — около 30 плагинов и семейств (code; платформа и прошивка исполнения, как правило, не установлены). Одно утверждение о числе языков RemTor — сообщение автора на форуме.

У платформы есть штатный механизм: файлы translations/dune_language_<lang>.txt плагина загружаются в глобальную таблицу переводов при старте устройства или смене языка интерфейса (SDK)574; где они лежат в пакете и как оболочка ищет запасной английский файл — guide/plugin-packaging.md. Большинство плагинов пользуются им через ключи %tr%<key>, часть читает язык оболочки сама и переводит в своём коде.

11.1. Штатные переводы: %tr%<key> и translations/dune_language_<lang>.txt

Задача Приём Грабли и ограничения Плагины и claims
Перевести подпись плагина в манифесте caption — ключ %tr%title_plugin; у поставщиков dunemdb ещё title_supplier, title_supplier_category — Online Movies (eng/TV Series) (код)575; Online services / Megogo (dunemdb) (код)576; Okko (dunemdb) (код)577; Online Movies (rus) (код)578
Перевести подписи popup-меню и экранов ключи %tr%tNN в манифесте и коде, словари ключ = текст одни и те же ключи t39 («Перезагрузить плеер») и t77 («Выключить Dune») встречаются в разных плагинах Screenshoter (SDK)579; TorrServe (код)580; DunePlexServer (код)581; YouTube (Smart_*) (код)582; liteIPTV (код)583; MPD (код)584
Словари на два языка dune_language_english.txt и dune_language_russian.txt в формате ключ = текст у surface_* словари трёх пакетов одинаковы (24 ключа); у 101.ru русский словарь задаёт ключи show_tv_main, ip_ac_inf, ip_access, mode_grounds, save_bg_path, save_mode_path GlobalTV (код)585; AceStreamSearch (код)586; youtube_api/folder_cache (код)587; surface_* (код)588; служебные установщики hdtv (код)589; altIPTV (код)590; 101.ru (код)591
Получить ключ из PHP-кода T::t($key) возвращает '%tr%' . $key; фреймворк так оформляет и свои сообщения об ошибках в Apple Trailers T::t — заглушка локализации AceStreamSearch (код)592; Twitch TV (код)593; Apple Trailers (код)594
Строка с параметрами %ext%<key_local>…</key_local> и %ext%<key_global>…</key_global> с параметрами в <p> (классы T, TR) — GlobalTV (код)595; ProIPTV (код)596
Подписи на нескольких языках прямо в манифесте caption по умолчанию плюс caption lang="russian" и caption lang="ukrainian" у плагина и точки входа — Kohana-канал (код)597

Ключи-сироты остаются при копировании плагина: в DI.FM-варианте 101.ru часть ключей 101.ru в коде не используется (код)598. Наличие словарей ещё не значит, что перевод работает: в EvolutionTV есть четыре файла translations/ и 82 строки с %tr%, но кода подстановки или загрузки переводов в пакете нет (код)599.

11.2. Свой перевод: язык оболочки из /config/settings.properties

Когда строку нужно перевести в самом PHP (не через оболочку), плагины читают язык интерфейса из файла настроек оболочки и загружают словарь сами.

Задача Приём Грабли и ограничения Плагины и claims
Узнать язык интерфейса прочитать interface_language из /config/settings.properties (PHP-разбор или shell_exec с grep); без ключа — english — Widget Ext (код)600; RemTor (код)601; Anidub.Com (код)602; DunePlexCatalog (код)603
Загрузить словарь по языку TR::load / TR::set_tr_table читают translations/dune_language_<язык>.txt с запасным английским, подставляют параметры через vsprintf у ProIPTV отсутствующий ключ возвращает сам ключ ProIPTV (код)596; DunePlexCatalog (код)603
Свой формат словарей lang/<язык>.php с массивом $LANG (Widget Ext, пять языков); отдельные файлы для строк скриптов (scripts_language_*, ключи sc_) у Dune BackUp Widget Ext проверяет язык, но подключает файл по сырому interface_language — для неподдерживаемого языка файла нет Widget Ext (код)604; Dune BackUp (код)605
Двуязычные подписи без словарей русский или украинский по точному сравнению строки языка — русские подписи, иначе английские при смене языка плагин очищает FolderCache Anidub.Com (код)606; youtube_api/folder_cache (код)607
Справка на языке интерфейса help_russian.txt при russian, иначе help_english.txt — служебные установщики hdtv (код)608
Язык для внешнего сервиса russian → ru, ukrainian → ua, german → de, иначе en остальные языки уходят в en Widget Ext (код)609

По сообщению автора RemTor на форуме, язык плагина берётся из настроек Dune и на 0.0.19 поддержано 13 языков (форум)610; в пакете — translations/dune_language_english.txt с ключами tr_* (код)611.

11.3. Кодировки и локаль: русские данные

Задача Приём Грабли и ограничения Плагины и claims
Включить русскую локаль PHP setlocale(LC_ALL, 'ru_RU.UTF-8') в точке входа — altIPTV (код)612; WeburgTV (код)613
Принять плейлист в WINDOWS-1251 перекодировать невалидную UTF-8 строку из WINDOWS-1251 режим cod_type=2 перекодирует без проверки altIPTV (код)614
Работать с сайтом в WINDOWS-1251 iconv запроса в WINDOWS-1251 и ответа в UTF-8 в адаптере сайта — Smart_* (код)615; pirates_* (EPG vsetv.com) (код)616

12. Обновление плагина

Объект: check_update, дескрипторы update.txt/update_info.xml, события обновления и самообновление кода в 35 разобранных плагинах и семействах (code; платформа и прошивка исполнения в большинстве не установлены). Поведение оболочки — по SDK (doc), коду APK r24 и наблюдениям на tv188b r25 (device).

Плагин обновляет оболочка: SDK задаёт в манифесте version_index (растёт с каждой версией), version (подпись для UI) и блок check_update (SDK)617; timeout — минимальный интервал между проверками, 0 — проверять при каждом запуске точки входа (SDK)618; auto включает фоновую автопроверку (SDK)619. Схема 1 в SDK названа устаревшей, рекомендована schema = 2 (SDK)620, но код APK r24 по-прежнему читает url для схем 1 и 2 (код r24)621. Как идёт проверка, диалог и что сохраняется при обновлении — guide/online-upgrade.md. Ниже — как это настраивают плагины и что они делают сверх штатного механизма: подкачивают код с сервера, обновляют внешние бинарники, мигрируют настройки.

12.1. Блок check_update в манифесте

Схема 1 с update.txt на собственном хосте встречается чаще всего: её задают 42 из 43 загрузчиков (код)622; схему 2 с update_info.xml используют GlobalTV, поставщики фильмов, ProIPTV и Kohana-канал (таблица ниже). Пустой url отключает обновление: код APK r24 без url проверку не запускает (код r24)621.

Задача Приём Грабли и ограничения Плагины и claims
Обновляться по update.txt (схема 1) check_update: schema 1, url …/update.txt, timeout 0 все 43 URL загрузчиков — http://; 42 из 43 — timeout 0 загрузчики check_update (код)623; Twitch TV (код)624; AllTV (код)625; Юрта ТВ (код)626; FREE TV (код)627; 101.ru (код)628; Anidub.Com (код)629; surface_* (код)630; zlostnyi (код)631; Smart_* (код)632; Bazinga3 (timeout 7200) (код)633
Схема 1 с ненулевым интервалом timeout 5, 20 или 86400 — altSource — 5 (код)634; Screenshoter — 20, auto yes (код)635; liteIPTV — 20 (код)636; rclone — 20 (код)637; RemTor — 86400, required no (код)638; Widget Ext — 0, auto yes (код)639
Обновляться по update_info.xml (схема 2) schema 2, timeout 86400, auto yes — GlobalTV (код)640; Online Movies (eng) (код)641; Online services (код)642; ProIPTV — timeout 0, auto false (код)643; Kohana-канал (код)644; загрузчики (sunduk) (код)645; Dune HD TV — условие country(ru) и prefer_builtin_if_url_differ (код)646
Самообновление браузерного плагина check_update schema 1 с timeout 0 у шести ott-play и xsmart; schema 2 с timeout 86400 у amediateka задано только в 8 манифестах; по словам автора, XSMART 3.0 — браузерный плагин с самообновлением веб-загрузчики (код)647; XSMART 3.0 (форум)648 (по словам автора)
Обновлять встраиваемые папки (EPFS) embeddable_plugin_folders с update_action → plugin_handle_user_input update_epfs, show_dialog_delay 10000; обработчик перестраивает EPFS и пишет заглушку no_internet только при включённом NewUI ProIPTV (код)649
Обновлять без вопроса пользователю dont_ask_confirmations yes на r25 (device) confirm_update при этом всё равно вызывается, диалога нет GlobalTV (код)650; платформа (устройство r25)651
Сделать обновление обязательным required yes код APK r24 при ошибке проверки и required=yes запрещает запуск плагина загрузчики (sunduk, ottclub) (код)652; платформа (код r24)653
Предпочесть встроенную копию prefer_builtin_if_url_differ yes — Online services (код)642
Не обновлять вовсе check_update с пустым url или без блока — Novosib-iptv (код)654; plugtv (код)655; pirates_* (gold) (код)656; Smart_* (BestKino) (код)657; Kohana-канал (3 пакета) (код)658; remote-control (код)659
Разложить пакеты по хостам дескриптор и .tar.gz на хосте автора: dune-club.info, zlostnyi.tech, ddaaff.mydune.ru путь в URL не всегда совпадает с name (у четырёх манифестов) загрузчики check_update (код)660

12.2. Дескрипторы update.txt (схема 1) и update_info.xml (схема 2)

Код APK r24 читает из update.txt ключи version_index, last_critical_version_index, version, download_url, space_needed, next_check_update_timeout и confirm_dialog_line* (код r24)661 и считает обновление доступным, только если version_index больше установленного (код r24)662. В 41 дескрипторе загрузчиков ровно пять строк ключ=значение в одном порядке: version_index, version, download_url, space_needed, last_critical_version_index (код)663; download_url ведёт на .tar.gz по http:// (код)664. Пример в составе пакета — update.txt Twitch TV с теми же полями (код)665. Срез 23 дескрипторов серверов обновления, снятых 2026-11-01, даёт тот же состав: все 23 — ровно пять строк ключ=значение в том же порядке, без других ключей, пустых строк и комментариев (код)666.

Задача Приём Грабли и ограничения Плагины и claims
Номер версии для сравнения version_index — целое положительное число; version — произвольная строка в 23 файлах среза version_index от 1 до 2021062000, у xsmart — 022, нуля нет; version — 13 номеров с датой в скобках, 2 десятизначные даты и 8 номеров версии дескрипторы (код)667; загрузчики check_update (код)668
Порог критического обновления last_critical_version_index в 23 файлах среза — целые 1 у 19, 8 у Entware, 43 у hdrezka и 0 у обоих ott-play; у 9 из 41 дескриптора загрузчиков там строка версии вместо целого (у 8 — «1.0.0», у smile — «1.0.1») дескрипторы (код)669; загрузчики check_update (код)670
Место под установку space_needed в байтах в 23 файлах среза — от 800000 до 20000000; у обоих дескрипторов ott-play нечисловое 1-400000 дескрипторы (код)671; загрузчики check_update (код)672
Переводы строк — в 23 update.txt среза 17 в CRLF и 6 в LF; у 41 дескриптора загрузчиков 37 в CRLF и 4 в LF; все 6 update_info.xml — LF дескрипторы (код)673; загрузчики check_update (код)674
Завершающий перевод строки — 19 из 23 update.txt среза не заканчиваются переводом строки; завершающий есть только у kinolist и moi-dom (LF), Screenshoter и widget_ext (CRLF); все 6 update_info.xml заканчиваются \n дескрипторы (код)675
Пробел после = download_url= http://… у moi-dom после = стоит пробел; у остальных 22 файлов среза — нет дескрипторы (код)676
Отдать пакет другого плагина download_url на пакет другого плагина у Radiopotok.ru — пакет RadioRecord, при этом манифест Radiopotok.ru ссылается на свой update.txt в каталоге Radiopotok.ru дескрипторы (код)677
Гарантировать, что загрузчик обновится version_index в манифесте ниже, чем в дескрипторе у 39 манифестов загрузчиков version_index 0 загрузчики check_update (код)678

Схема 2 — XML-файл update_info.xml: у всех шести снятых файлов корень dune_plugin_update_info со <schema>2</schema>; кроме массива plugin_version_descriptor, в корне только schema и name, а redirect и next_check_update_timeout не встречаются ни в одном файле (код)679. В шести файлах 73 дескриптора: globaltv — 20, dunemdb_supplier_movies_rus — 13, dune-hd.tv — 16, dunemdb_supplier_generic — 10, amediateka — 8, first_muz_ru — 6 (код)680. В каждом файле version_index возрастает, но часть номеров пропущена: movies-rus — 10, globaltv — 37 и 41, amediateka — 9, dune-hd.tv — 80–85, 89, 97 и 98, dunemdb_supplier_generic — 13 и 14; у first_muz_ru идут 2–7 без пропусков (код)681.

Задача Приём Грабли и ограничения Плагины и claims
Описать одну версию восемь базовых элементов в порядке version_index, version, beta, critical, url, md5, size, caption — дескрипторы (код)682
Закодировать версию version — YYMMDD_HHMM — дескрипторы (код)683
Сверить целостность пакета md5 — 32 строчные шестнадцатеричные цифры, size — целое число байт в 23 дескрипторах схемы 1 полей md5 и size нет; в 73 дескрипторах size от 49152 до 4206592 дескрипторы (код)684
Пометить бету и критичность beta и critical во всех 73 дескрипторах — no; значения yes нет ни в одном файле дескрипторы (код)685
Потребовать функцию прошивки require/api_version или required_firmware_features сверх восьми базовых элементов require с 1.1.0 — только у 4 из 73 (первые два amediateka и первые два first_muz_ru); required_firmware_features — у 26 из 73 (dunemdb_supplier_plugin_api_v6 у 16 из 20 globaltv, newgui2021 у 10 dunemdb_supplier_generic) дескрипторы (код)686

12.3. Пакет, который дозаливается обновлением

Приём для форумного распространения: в архив кладут только манифест с check_update, значок и PHP-заглушку, а рабочий код приходит первым обновлением. В 22 пакетах лежит один и тот же PHP из 11 строк, который подключает фреймворк и starnet_plugin.php (код)687; в 18 заготовках zlostnyi.tech PHP-файл из params/program не содержит исполняемого кода (код)688; в 37 из 43 пакетов ровно три файла (код)158. Карточка-загрузчик MegaAnime 0.0.1 тоже неполная, с одной точкой входа и check_update (код)689. Запустится ли такой пакет без сети — §19.

12.4. События обновления и как отключить автообновление

На r25 (device) перед диалогом обновления оболочка вызывает confirm_update установленной версии (устройство r25)690, а новая версия после установки получает update, но не install (устройство r25)691; cookies и data_dir_path при этом сохраняются (устройство r25)692. Код APK r24 трактует результат confirm_update как 0 — обновить, 1 — пропустить, 2 — «обновлено действием» (код r24)693.

Задача Приём Грабли и ограничения Плагины и claims
Выключатель «не обновлять плагин» confirm_update → обработчик возвращает !disabled по cookie ProIPTV возвращает логическое значение, а не код 0/1/2 (§18) ProIPTV (код)694
Выключить обновление правкой манифеста настройка use_update заменяет URL check_update прямо в установленном dune_plugin.xml меняется файл установки altIPTV (код)695
Действия после установки и обновления install/update → один и тот же обработчик (entry_id=install) при обновлении на r25 приходит update, а не install (устройство r25)691 GlobalTV (код)696; Online Movies (TV Series) (код)114
Перезапустить свой демон на обновлении update → bin/gmediarender-ctl restart & — DLNA Renderer (код)697

Семейство Smart_* и родственные плагины берут парсеры сайтов из общего PHP-файла link_api, который скачивают с dune-club.info, записывают в /tmp/plugins/link_api.php и подключают через require (код)698. Версия — число в маркере ##N##: файл перезаписывается, если локального нет или удалённая версия больше (код)699. Так парсеры меняются без выпуска пакета, но скачанный PHP исполняется без проверки подписи: Online Movies (rus) перед записью проверяет только подстроку <?php (код)700.

Задача Приём Грабли и ограничения Плагины и claims
Резервная копия в пакете скачанный файл, если он есть, иначе require 'link_api.php' из пакета у MegaTorrents пакетной копии нет, а код зовёт mUrl, которого в пакете нет; у YouTube резервной копии нет altIPTV (код)701; MegaTorrents (код)702; YouTube (код)703
Хранить скачанное не в /tmp путь /tmp/plugins/link_api.php заменяется на /persistfs/plugins_data/… при его наличии — Smart_* (BestKino) (код)704; YouTube (код)705
Обновление парсеров по кнопке экран настроек показывает кнопку, если удалённая версия новее; parser_update записывает файл — MegaAnime (код)706; Bazinga3 (parser_update/parser_del) (код)707
Ядро плагина целиком с сервера radio_tv.txt → /tmp/plugins/radio_tv.php → require в пакете 101.ru файла ядра нет; в DI.FM ядро входит в пакет 101.ru (код)708; 101.ru (DI.FM) (код)709
Обновлять парсер ссылок link_api() скачивает link_api.txt с dune-club, сравнивает версию ##…## и пишет /tmp/plugins/link_api.php, затем подключает его без скачанного файла подключается локальный link_api.php, которого в пакете LSS нет liteIPTV (код)710; altIPTV (код)701; surface_* (LSS) (код)711
Обновлять «ядро» каналов get_streams.txt (PHP-код с маркером ##653##) → сравнение версии → get_streams.php → require, если файл есть каталог копии зависит от прошивки: /tmp/plugins, /persistfs/plugins_data или /flashdata/plugins_data (по /system/dunehd/init) FREE TV (код)712
Обновлять CGI-скрипты scripts.tar.gz распаковывается в www/cgi-bin; версия — в cookie ver_scripts, повторная загрузка и при пустом peers.sh версия пишется в cookie только при коде возврата 0 FREE TV (код)713
Добавить хостинг в link_api generic-ветка: текст перед EpisodId_ — имя класса, вызывается <класс>::getIframe нужен класс с методом getIframe; кроме generic-ветки, в get_link есть явные else if для 17 хостингов Smart_* (link_api) (код)714
Выбрать качество в link_api getIframe($iUrl, $arg, $vQuality); номер качества 0–6 переводится шкалой 6→2160 … 0→240 с понижением до существующего — Smart_* (link_api) (код)715
Логировать версии hd_print версии плагина, старой и новой версии парсера и versions.txt — YouTube (код)716

12.6. Обновить внешний бинарник отдельно от плагина

Задача Приём Грабли и ограничения Плагины и claims
Проверить новую версию демона удалённый файл ver сравнивается с ответом демона /echo и локальным bin/ver; при новой версии экран показывает кнопку установки — TorrServe (код)717
Удалить старый файл после установки имя старого файла — в строке с индексом 2 удалённого ver — TorrServe (код)718
Поставить свою сборку вручную остановить демон (/shutdown), выбрать файл через file_list с фильтром имени имя файла зашито в фильтр TorrServe (код)719

12.7. «Что нового» и номер версии в интерфейсе

Задача Приём Грабли и ограничения Плагины и claims
Показать список изменений кнопка whats_new скачивает info.txt с сервера и выводит текст в диалоге нужна сеть; Bazinga3 пропускает текст через strip_tags Screenshoter (код)720; Smart_* (код)721; PeerflixServer (код)722; Bazinga3 (код)723
«Что нового» и справка из языкового файла translations/Info_language_<язык>.txt делится по <+>: в базовом режиме средняя часть опускается, в полном показывается целиком в полном режиме с русским языком по INFO открывается info_script Dune BackUp (код)724
Изменения по версии из update_info.xml найти элемент version с номером, равным версии в коде, и показать его строки версия дублируется в коде (PluginVersion) и манифесте zlostnyi (код)725
Changelog в дескрипторе схемы 2 plugin_version_descriptor с описанием изменений первый дескриптор RemTor — 0.0.2 alpha RemTor (код)726
Показать версию сборки файл VERSION в пакете читается экраном настроек; 101.ru читает version и caption из dune_plugin.xml и добавляет к версии ответ release_data.txt VERSION расходится с version манифеста у Anidub.Com и pirates_* (gold); у streamit манифест и VERSION дают 0.0.34, имя архива — 0.0.35, а экран показывает 0.0.4; у 101.ru при открытии настроек идёт сетевой запрос Anidub.Com (код)727; youtube_api/folder_cache (код)728; pirates_* (код)729; remote-control (код)730; 101.ru (код)731
Скопировать VERSION в данные при смене версии сравнить VERSION в каталоге установки и данных, при различии скопировать новый — remote-control (код)732

12.8. Миграция данных при переходе на новую версию

Онлайн-обновление сохраняет cookies и data_dir_path (§12.4), поэтому старые настройки новая версия должна уметь прочитать сама.

Задача Приём Грабли и ограничения Плагины и claims
Перенести старый файл настроек в новый формат при первом запуске: если старый файл есть, а нового нет, скопировать содержимое если новый файл уже есть, миграция не выполняется GlobalTV (код)733
Предложить бэкап при переходе со старой major-версии флаг upgrade.flag: нет новой БД, но есть старые настройки → создать флаг и показать диалог «бэкап / пропустить» флаг удаляется при следующем входе ProIPTV (код)734
Сбросить кэши при установке и обновлении install/update → bin/install.sh удаляет кэши в plugins_data — GlobalTV (код)735

16. Совместимость платформ и версий

Объект: проверки платформы, оболочки и версии прошивки в коде плагинов GlobalTV, ProIPTV, Widget Ext, Screenshoter, liteIPTV, MegaTorrents, FREE TV, Torrent Center, Smart_*, Entware/Wallpaper, Dune BackUp, поставщиков dunemdb и сторонних Android-проектов (Jellyfin Bridge, Lampa bridge, watch-sync); уровень code, у сторонних проектов часть фактов — заявления README (forum). Платформа и прошивка исполнения плагинов, как правило, не установлены; где плагин ссылается на прошивку платформы, это сказано в строке.

Один пакет плагина обычно ставится и на Sigma (SMP86xx/87xx), и на Android-прошивки Dune, и в APK-оболочку, а возможности PHP-фреймворка различаются от прошивки к прошивке. Плагины решают это тремя способами: определяют платформу и оболочку по файлам и переменным окружения (§16.1–16.2), сравнивают номер ревизии прошивки (§16.3) или проверяют наличие нужного класса или константы фреймворка (§16.4). Сводка различий платформ и прошивок — guide/versions.md и guide/compat-matrix.md; ограничения установки в манифесте — guide/plugin-packaging.md. Гипотезы по этой области — в §19.

16.1. Определить платформу: Android или Sigma, platform_kind, чипсет

На tv188b r25 (device) файл /tmp/run/versions.txt — шесть строк key=value, среди них platform_kind (устройство r25)736; на его разборе построено большинство проверок ниже.

Задача Приём Грабли и ограничения Плагины и claims
Свести платформу к семейству HD::get_platform_kind() читает /tmp/run/versions.txt через parse_ini_file и сводит platform_kind к 87xx, 864x, 867x, 865x или android; при HD_APK возвращает apk одна и та же копия HD в разных пакетах; проверки версии прошивки в этом методе нет Screenshoter (код)737; liteIPTV (код)738; MegaTorrents (код)739; Bazinga3 (код)740
Отличить платформу с DASH HD::get_dash_platform_kind → true при platform_kind 8758, android — при Android, иначе false — MegaTorrents (код)741
Отсечь не-Android вне APK вне APK get_platform_info() читает $FS_PREFIX/tmp/run/versions.txt; нет файла или platform_kind не android — платформа unsupported Sigma этот плагин не поддерживает ProIPTV (код)742
Отличить custom-прошивку is_custom_firmware(): нет /firmware/config/base_firmware_info.txt — «не custom»; нет product_id или product_id.txt — «custom»; иначе сравниваются product_id из двух файлов на custom-прошивке load_link_api() сразу возвращает false, и подключается упакованная копия link_api.php Online Movies (rus) (код)743
Признать Android по файлу наличие /system/dunehd/init разные плагины проверяют разные файлы, см. §18; Dune HD TV признаёт Android ещё и по HD_APK=1 GlobalTV (код)744; FREE TV (код)745; Bazinga3 (код)746; Dune HD TV (код)747
Признать Android в shell-скрипте HD_APK=1 или наличие /system/dunehd_init; привилегированные команды на не-APK Android — через /system/dunehd/dunehd_service do — Widget Ext (код)748
Узнать чипсет Android /firmware/config/android_platform.txt; Amlogic — строка начинается с s905 вычисленный $is_amlogic дальше не используется GlobalTV (код)749
Выбрать сборку бинарника под CPU по умолчанию mipsel, ARMv7 — при этой строке в /proc/cpuinfo; при уже установленном /opt/bin/opkg — поиск каталога Entware-ng/Entware-3x различаются только ARMv7 и mipsel Entware/Wallpaper (код)750
Скрыть пункты меню не своей платформы маркеры в скрипте: на Android исключаются #<sigm> (всегда), #<apk->, #<new-> (по флагам); на не-Android — #<andr> (всегда) и #<b9-> (при before_r11) условия задаёт автор скрипта, а не прошивка Dune BackUp (код)751
Узнать IP плеера HD::get_ip_address() берёт первый адрес из вывода ifconfig, если он не 127.0.0.1; если оба адреса loopback — null — 101.ru (код)752

16.2. Определить оболочку: APK и HD_APK/HD_FW_APK

Фреймворк APK-оболочки r24 сам определяет is_apk() как getenv("HD_APK"), is_fw_apk() — как getenv("HD_FW_APK"), а is_limited_apk() — как is_apk() && !is_fw_apk() (код r24)753. На собственной Android-прошивке tv188b r24 в окружении процессов есть и HD_APK=1, и HD_FW_APK=1 (устройство r24)754, поэтому одна HD_APK ещё не означает стороннюю APK-оболочку; урезанный режим — это комбинация «HD_APK без HD_FW_APK».

Задача Приём Грабли и ограничения Плагины и claims
Различить три режима is_apk()/is_fw_apk()/is_limited_apk() по тем же переменным, что во фреймворке — ProIPTV (код)755
Обойти ограничения урезанной APK при is_limited_apk() скрыть «внешний плеер» и «media info» в меню серий, в выборе папок передать PARAM_ALLOW_NETWORK = false сетевые папки в этом режиме не предлагаются ProIPTV (код)756
Выбрать способ системного действия без HD_APK, HD_APK без HD_FW_APK (скриншот IR-кодом, без лога) и HD_APK с HD_FW_APK (screencap через dunehd_service do) — три ветки в урезанном режиме CGI-лог не пишется Screenshoter (код)757

16.3. Узнать версию прошивки и отсечь старые

Задача Приём Грабли и ограничения Плагины и claims
Получить номер ревизии firmware_version: из $FS_PREFIX/tmp/sysinfo.txt → разбор → число rev_number; is_r22_or_higher() — > 21, is_r24_or_higher() — > 22, is_r25_or_higher() — > 24 неразобранная версия даёт rev_number = 0 ProIPTV (код)758
Не запускаться на старой прошивке entry handler: rev_number ≤ 21 → диалог err_too_old_player, нет класса SQLite3 → err_no_sqlite; дальше вход не обрабатывается confirm_update проверяется раньше этих условий ProIPTV (код)759
Отличить r10 от r11+ HD::get_versions() возвращает false для firmware_version с r10; файловый экран добавляет replace_path только при true; YouTube сравнивает с подстрокой r1 после проверки r10, 101.ru — с r\d\d на r10 replace_path не предлагается liteIPTV (код)760; MegaTorrents (код)761; 101.ru (код)762; YouTube (код)763
Проверить Android и ветку перед ТВ /system/dunehd/init и branch_num >= 21 → встроенное действие pf_check с текстом про Dune Extra и продолжением по успеху/неудаче — FREE TV (код)745
Проверить, что по адресу Dune с нужным API ответ status IP Control: product_id/player_state — строки, product_name непуст, protocol_version ≥ 5; порты 80, затем 11080 версия прошивки не проверяется Lampa bridge (код)764
Не проверять ничего в коде нет firmware_version, platform_kind, branch_num, get_parsed_firmware_ver поведение на других прошивках ничем не страхуется; в 101.ru проверок версии прошивки в radio_*.php, radio_setup_screen.php и CGI-файлах нет plugtv (код)765; 101.ru (код)766

16.4. Проверять возможность, а не версию: class_exists, defined, firmware features

Самый переносимый приём — проверять наличие нужного класса или константы dune_api.php прямо перед использованием и иметь запасной путь. Так плагин не зависит от того, на какой ревизии появилась возможность.

Задача Приём Грабли и ограничения Плагины и claims
Включить rows API class_exists('PluginRowsFolderView') — GlobalTV (код)767; ProIPTV (код)768; Домашнее ТВ (код)769
Включить list config, встроенный родительский контроль class_exists('EditListConfigActionData') и defined('EDIT_LIST_CONFIG_OPT_REMOVE_UNCHECKED'); defined('PluginTvInfo::builtin_pcontrol_enabled') — GlobalTV (код)770
Включить внешний EPG defined полей ext_epg_* плюс наличие /firmware_ext/plugins/ext_epg/dune_plugin.xml; у Домашнего ТВ — defined('PluginTvInfo::ext_epg_enabled') GlobalTV при этом всё равно ставит ext_epg_enabled = false GlobalTV (код)771; ProIPTV (код)768; Домашнее ТВ (код)772
Выбор файла, отложенная загрузка каналов defined('ChooseFileActionData::filter') → choose_file; defined('PluginUpdateTvInfoActionData::channel_changes'); close_item_params в edit_list_config — только при определённой константе комментарии в коде связывают их с r24 ProIPTV (код)773
Поля вида и таймера epg_text_size → размеры текста и страниц EPG; scroll_animation_enabled — только на Android и при определённой константе; reset_on_keypress таймера — при определённой константе — GlobalTV (код)774
Запасное действие при отсутствии API нет PLUGIN_REPLACE_PATH_ACTION_ID → plugin_launcher вместо replace_path; GUI_EVENT_PLAYBACK_GOING_TO_SWITCH регистрируется только при наличии константы — Torrent Center (код)775
Перезапуск оболочки после смены настроек defined('CHANGE_SETTINGS_ACTION_ID') → restart_gui, иначе RESTART_ACTION_ID, иначе killall shell; по SDK ChangeSettingsAction есть с 140905_r10 AdvKeyboard при этом пишет gui_skin прямо в /config/settings.properties Widget Ext (код, SDK)776; Bazinga3 (код)777
Читать флаги прошивки построчно /tmp/firmware_features.txt и /tmp/ro_features.txt; проверки lcfg_v2 и whale_tv при whale_tv плагин удаляет из кэша раздел xxx GlobalTV (код)778
Писать свою копию ActionFactory осторожно необязательные поля добавлять только при defined (так делают копии GlobalTV и YouTube, а r24 пишет их без проверки) побайтовое тождество интерфейсов экранов с r24 не означает тождества: в r24 Screen объявляет больше методов и DEFAULT_CATEGORY GlobalTV (код r24)779; YouTube (код)780
Учесть сигнатуры r25 get_timer в r25 принимает нетипизированный media_url, в копии плагина и r24 — MediaURL $media_url другие различия r25 в этой единице не разбирались GlobalTV (код r24, r25)781

16.5. Ограничить установку и обновление в манифесте

Ограничения на уровне манифеста срабатывают до запуска кода; их семантика описана в guide/plugin-packaging.md и guide/online-upgrade.md.

Задача Приём Грабли и ограничения Плагины и claims
Ставить только при нужном API поставщиков expr = and(firmware_feature(dunemdb_supplier_plugin_api_v2),not(firmware_feature(dunemdb_supplier_plugin_api_v6))) — Megogo (код)782; Okko (код)783
Ограничить обновление страной check_update с условием country(...) условие записано у check_update, а не у установки Megogo (код)784; Okko (код)785
Ограничить по модели и стране strict_country с отрицанием списка стран и expr с product(<модели>) — Online Movies (eng) (код)786
Потребовать другой плагин для product 86xx — плагин python_86xx для других платформ Python не объявлен Online Movies (eng) (код)787
Потребовать проверку подписи params/strict_verify_needed = yes и pf_allowed = yes — Dune HD TV (код)788

16.6. Выбрать бинарник, путь и ресурсы по платформе

Задача Приём Грабли и ограничения Плагины и claims
Взять системный ffmpeg, если есть при is_r25_or_higher() и наличии $FS_PREFIX/firmware/bin/ffmpeg — он, иначе своя сборка bin/ffmpeg-7.1.3 — ProIPTV (код)789
Поднять лимит памяти PHP при is_r22_or_higher() memory_limit из cookie (256M по умолчанию, в настройках 256M/384M/512M) — ProIPTV (код)790
Найти каталог данных в PHP — data_dir_path от оболочки; в shell — /persistfs/plugins_data/<плагин>, иначе $FS_PREFIX/flashdata/plugins_data/<плагин> boot.sh проверяет /flashdata без $FS_PREFIX; совпадение путей PHP и shell не доказано Widget Ext (код)791
Запустить скрипт при загрузке прошивки исполняемые (-x) файлы из $FS_PREFIX/config/boot прошивка запускает при старте; на tv188b — по очереди, на tv175u — в фоне — Widget Ext (код r22, r24)792
Встроиться в расписание прошивки init_cron_apps.sh прошивки при widget_enabled=yes и исполняемом /firmware/scripts/run_widget.sh добавляет в crontab run_widget.sh (10 */2 * * *) вызывается ли init_cron_apps.sh на tv188b/tv175u — не установлено Widget Ext (код r24)793
Поднять Android-приложение-сервис на android при неудачном get_version AceStream — найти пакет в /tmp/applications/app_data.json, am start, ждать 15 с, повторить запрос — liteIPTV (код)794
Узнать, установлено ли приложение читать $FS_PREFIX/tmp/applications/app_data.json и искать applications[].package_name файла может не быть, JSON может не разобраться — тогда «не установлено» Online services (код)795
Снизить нагрузку на слабом CPU если в /tmp/sysinfo.txt нет solo4k и _r11, к dune_params добавляется lower_cpu_load:1 — Dune HD TV (код)796
Настроить буферизацию и HLS-движок по платформе вне Android и на Amlogic — buffering_ms:300, на Amlogic ещё frame_rate:25000; на s905l2 к HLS-URL добавляется engine:1 — Dune HD TV (код)747
Обойти баг SMB-каталогов на 8672 get_bug_platform_kind по platform_kind; для «багованной» платформы — test -d вместо is_dir списки «багованных» платформ в копиях различаются, см. §18 Smart_* (код)797; Screenshoter (код)798
Поправить палитру скина color_palette_patch меняет цвета в dune_skin_config.xml активного скина с бэкапом по md5; color_palette_restore возвращает бэкап и перезапускает оболочку правка системного скина — обратимая, но с перезапуском ProIPTV (код)799

16.7. PHP старых прошивок и заявленная проверка сторонних проектов

На tv188b r25 (device) PHP_VERSION — 5.3.6 (устройство r25)800; ограничения этой версии — guide/pitfalls.md. Плагины zlostnyi передают cookies по ссылке на месте вызова (load_channels(&$plugin_cookies)) (код)801 — конструкция, судьба которой в разных версиях PHP вынесена в §19. По сообщениям автора, bridge.php Lampa bridge совместим с PHP 5.3 (форум)802.

Сторонние Android-проекты проверку версий в коде не делают и заявляют проверенные конфигурации в README; это сообщения авторов, а не наблюдения базы.

Проект Заявлено автором Claims
Jellyfin Bridge Dune HD 8K Pro Plus, 250815_1012_r22, Jellyfin for Android TV 0.19.9; сборка — minSdk 21, targetSdk 36 (code) (код, форум r22)803
Lampa bridge Pro Vision 4K (tv184a), Android 11, 250815_1012_r22, Lampa 1.13.1; нужны IP Control с JSON (протокол 5+) и порты 80/11080 (форум r22)804
watch-sync Solo 8K и Pro 8K Plus, 250815_1012_r22 (userdebug); adb root работает из-за userdebug и сохраняется при выключении пультом; выключенный пультом плеер остаётся в сети (форум r22)805
liteIPTV минимальная прошивка 150721_0135_B9 (первый пост темы) (форум)806

Расхождения

Объект: места, где плагины делают одно и то же по-разному или где код плагина расходится с документацией и кодом платформы; плагины (code, платформа и прошивка исполнения не установлены), SDK плагинов (doc) и прошивки, если на них есть ссылка. Связь conflicts_with указана там, где она заведена; где её нет — это кандидат для lead.

Манифест

  • Программа с hd_create_plugin(). SDK требует от PHP-плагина программу с этой функцией (SDK)2; на tv188b r25 тестовые плагины test_plugin5 и test_plugin10 без неё, с классом-наследником DunePluginFw, работали, и handle_user_input выполнялся (устройство r25)3. Стороны связаны conflicts_with; подробнее — guide/plugin-packaging.md.
  • Значение auto_resume/enable. SDK описывает включение как <auto_resume><enable>yes (SDK)72; Юрта ТВ задаёт enable = auto (код)77, так же sunduk и shara-tv, а у ottclub два блока — yes и auto (код)78. Что оболочка делает со значением auto, в базе не описано. Связи conflicts_with нет.
  • Регистрация поставщика на boot_end. Online Movies (eng) запускает register_supplier.sh на boot_end, install и update без условий (код)807; Online Movies (TV Series) на boot_end делает это только при отсутствии feature movie_suppliers_update (код)116. Это разные поколения механизма, а не противоречие; подробности — guide/movie-suppliers.md. Связи conflicts_with нет.
  • Cookie видимости иконки. В манифестах surface_* show_cookie_name = show_application (код)808, а плагины эту cookie не пишут: rmfon.pl и wwcam пишут show_tv (код)809. Расхождение внутри плагина; следствие — в §19. Связи conflicts_with нет.

Жизненный цикл

  • Один поставщик — два ответа. В Megogo и Okko bin запускает ./run.py при пустом FS_PREFIX и run.php через php-cgi иначе (код)810; ответ Python-версии беднее PHP-версии: в Megogo нет indirect и urls (код)811. Это расхождение реализаций внутри пакета, а не claims; conflicts_with нет.

Экраны

  • GComponents и rows-вид: SDK против GlobalTV. SDK называет фреймворк GComponents незавершённым и зарезервированным для внутреннего использования (SDK)452 и не включает rows-вид в перечень видов папок (SDK)812; GlobalTV возвращает и GComps-папку (код)813, и rows-папку (код)814. Claim rows-папки связан conflicts_with с SDK; между (SDK)452 и (код)813 связи нет. Подробнее — guide/gui-screens.md §5.
  • Пользовательский скин: условие записи gui_skin=custom. altSource и Wallpaper пишут gui_skin = custom только при наличии /config/settings.properties (код)815; AdvKeyboard из Widget Ext пишет его прямо в этот файл, без упомянутой проверки (код)816. Это разная реализация одного приёма, не противоречие; связи conflicts_with нет.
  • Переключение вида view_type в streamit. Круг view_type 1→2→3→1 (код)817 не достигает вида для view_type 4, который задан в get_folder_view() (код)818. Это несогласованность внутри кода, а не расхождение источников; связи conflicts_with нет.

Ввод

  • Эмуляция кнопки питания: /proc/ir/button или IP Control. altSource выключает плеер записью A15EBF00 в /proc/ir/button (код)261; ProIPTV шлёт ИК-коды через cmd=ir_code и в комментарии пишет, что /proc/ir/button на ATV не работает (код)564. Это не противоречие claims (комментарий автора, платформы не установлены), связи conflicts_with нет; на какой платформе работает каждый путь, в базе не проверено.

Обновление

  • Результат confirm_update. Код APK r24 трактует результат глобального действия confirm_update как код: 0 — обычное обновление, 1 — пропустить, 2 — «обновлено действием» (код r24)693; на r25 (device) ответ null означает обычное обновление (устройство r25)690. ProIPTV возвращает логическое !disabled (код)819; как прошивка понимает false, не проверено (§19). Связи conflicts_with нет.
  • Схема 1 против рекомендации SDK. SDK называет схему 1 устаревшей и требует schema = 2 (SDK)620; её задают 42 из 43 загрузчиков (код)622, а код APK r24 продолжает читать update.txt схемы 1 (код r24)661. Это не противоречие поведения, а расхождение практики с документацией. Связи conflicts_with нет.
  • Два способа выключить обновление. altIPTV переписывает URL check_update в установленном манифесте (код)695; ProIPTV оставляет манифест и отвечает на confirm_update по cookie (код)819. Связи conflicts_with нет.

Совместимость

  • Признак Android в разных плагинах. GlobalTV и FREE TV проверяют файл /system/dunehd/init (код)820; crontask.sh Widget Ext — HD_APK=1 или файл /system/dunehd_init (код)748. Это разные пути; какой из них есть на каких прошивках, в базе не сопоставлено. Связи conflicts_with нет.
  • «Багованные» платформы SMB. Копия smbtree::get_bug_platform_kind() в CGI Screenshoter считает такими platform_kind 8672, 8673 и 8758 (код)821, копия в его же Smart_file_screen.php — только 8672 (код)822, как и эталон Smart_* (код)823. Одна функция разошлась при копировании; какая версия верна для устройства, не проверено. Связи conflicts_with нет.
  • HD_APK как признак сторонней оболочки. ProIPTV считает урезанным режим HD_APK без HD_FW_APK (код)755, а crontask.sh Widget Ext признаёт Android уже по HD_APK=1 (код)748; на собственной прошивке tv188b r24 выставлены обе переменные (устройство r24)754. Противоречия нет, но смысл HD_APK в плагинах разный. Связи conflicts_with нет.

Не проверено

Объект: гипотезы (inference) и оспоренные утверждения (disputed) из разборов плагинов, относящиеся к приёмам этой главы; платформа и прошивка — как в scope claim. Это кандидаты на проверку в коде или на устройстве; в разделах выше они не цитируются.

Утверждение Уровень, статус Claim Раздел
Точка входа с parent_media_url root://setup помещает пункт Widget Ext в раздел «Настройки» главного меню code, disputed (код r24)824 §2
Установщик оставляет одну из двух сборок php-cgi: .platform.87xx/bin/ — для SMP87xx, bin/ — для SMP86xx inference (вывод)825 §2
php-cgi из описателя Online Movies (rus) не обязательно читает bin/php.ini (ключ -c не передан); причина своего php-cgi — не зависеть от прошивки inference (вывод)826 §2
php-cgi Screenshoter — сборка PHP 5 под ARM, использующая системную libphp5.so inference, verified (вывод)827 §2, §15
Без main.php PHP-часть Cleanup не откроется, работает только boot_end-скрипт inference (вывод)828 §2
Переключатель «Показать на главном экране» в rmfon.pl и wwcam не влияет на видимость иконки (пишется show_tv, читается show_application) inference (вывод)829 §2
Откат LTU не возвращает правки системы (/etc/inittab, /etc/profile, /sbin) inference (вывод)830 §2
update_info.txt в пакете WeburgTV относится к altIPTV 5.2.9 — артефакт чужой сборки inference (вывод)831 §2
Асинхронный поиск Online Movies (eng) совместим с контрактом r24: без actx оболочка опрашивает res.json каждые 0,5 с до DO_FILE_SEARCH_TIMEOUT, с actx — по таймеру экрана 500 мс inference (вывод r24)832 §3
Для 86xx /usr/bin/python, вероятно, даёт плагин python_86xx из required_plugins; для других продуктов источник Python не указан inference (вывод)833 §3
Относительный require "../load_link_api.php" в Online Movies (rus) может не найти файл: путь зависит от текущего каталога процесса (на r25 у стороннего поставщика cwd был /) inference (вывод)834 §3
При вызове через run.sh ветки run.py для get_file_search_state и get_stream_url недостижимы: эти команды run.sh обрабатывает сам, до запуска Python inference (вывод)835 §3
Пункты «перезагрузить» и «выключить» в меню значка Screenshoter: запись IR-кода в /proc/ir/button, вероятно, эмулирует нажатие кнопки пульта inference (вывод)836 §4
A15EBF00, который пишет пункт «Выключить Dune», вероятно, — IR-код кнопки питания inference (вывод)837 §4
На экране каналов WeburgTV клавиши info и popup_menu из базовой карты действий не обрабатываются: подкласс перехватывает handle_user_input и возвращает null inference (вывод)838 §5, §6
Пакеты 22 каркасов неполные (нет lib/ и starnet_plugin.php) и без обновления не запустятся inference (вывод)839 §12
В 21 заготовке функциональность появляется только из update-файла check_update inference (вывод)840 §12
Без check_update/auto фоновая автопроверка у 43 загрузчиков не включена inference (вывод)841 §12
Прошивка r24 трактует false из confirm_update как отказ от обновления inference (вывод)842 §12
На tv188b r25 обновление TorrServe возвращает поставляемый bin/boot.sh с exit 0 и сбрасывает включённый автозапуск inference (вывод r25)843 §12
Класс mUrl для MegaTorrents приходит из скачиваемого link_api.txt; источник parse_acestream_page неизвестен inference (вывод)844 §12
YouTube (Smart_*) получает класс Youtube только из скачиваемого link_api; версия 2022 г. могла отличаться inference (вывод)845 §12
Из HD::get_versions следует, что nSmartViews выбирается на прошивках r11 и выше (r1x, кроме r10), а oSmartviews — на r10 и более старых без r1 в firmware_version inference (вывод)846 §16
data_dir_path, который PHP-часть Widget Ext получает от оболочки, — вероятно, тот же каталог, что находят её shell-скрипты (/persistfs/plugins_data/<плагин> или $FS_PREFIX/flashdata/plugins_data/<плагин>) inference, disputed (вывод)847 §16
Старое решение fix_widget, по-видимому, работало как загрузочный скрипт /config/boot/fix_widget.sh inference (вывод)848 §16
Наличие константы RESTART_ACTION_ID, возможно, тоже зависит от версии прошивки inference (вывод)849 §16
HD::get_entware_ver MegaTorrents при любом установленном Entware вернёт Entware, потому что /Entware/ совпадает и с Entware-ng, и с Entware-3x inference (вывод)850 §16
Передача по ссылке на месте вызова (&$plugin_cookies) в PHP 5.3 — предупреждение deprecated, в 5.4+ — ошибка разбора inference (вывод)851 §16
После сокращения или очистки строки в AdvKeyboard старые подсказки, вероятно, остаются доступными: короткая строка не обновляет suggestions, а рендер не очищает отсутствующие элементы scrBuff inference (вывод)852 §5.3
Пустой результат в меню Apple Trailers: в GenreMenu, MovieMenu и OnDateMenu usort получает неопределённую переменную — в PHP 8 это TypeError, в DateMenu, GenresMenu и TrailerMenu — предупреждение и пустая папка inference (вывод)853 §4.9
Домашнее ТВ пишет EPF на флеш при каждом изменении списка; читает ли оболочка EPF стороннего плагина из /flashdata/plugins_epfs/<plugin>/<epf_id>.json или из /tmp/plugins/<plugin>/epfs/, из кода плагина не следует inference (вывод)854 §4.7
Инвалидация «папки» с media_url, равным epf_id (htv), вероятно, заставляет оболочку перечитать EPF ТВ-раздела после перезаписи inference (вывод)855 §4.7
На Android .platform.android/bin/register_supplier, вероятно, при установке заменяет bin/register_supplier, вариант без $FS_PREFIX работает на прочих платформах inference (вывод)856 §4.7
control_id=recent Домашнему ТВ, вероятно, посылает оболочка (нативный ext_epg или браузер каналов) либо мод ext_epg: в коде плагина отправителя нет, а мод при plugin_name=home_tv шлёт recent сам inference (код, вывод)857 §4.7
Вероятно, действие init Домашнего ТВ встроенному ext_epg нужно, чтобы оболочка заранее загрузила плагин ext_epg: PHP-обработчик main ext_epg r25 tv188b на init возвращает null inference (вывод r25)858 §4.7
Вероятно, ветка tv_play с action_origin в TvRowsScreen Домашнего ТВ завершилась бы фатальной ошибкой PHP (вызов неопределённого EpfsHandler::update_tv_epf) inference (вывод)859 §4.7, guide/pitfalls.md
Похоже, условие таймера TvRowsScreen инвертировано: флаг ставит только need_update_epf_mapping, которую никто не вызывает, поэтому таймер всегда пересобирает EPF inference (вывод)860 guide/pitfalls.md
Вероятно, «Удалить» в ряду истории Домашнего ТВ стирает всю историю точек, а остальные элементы держатся в ряду только добором из прежнего EPF inference (вывод)861 guide/pitfalls.md
Вероятно, на устройствах с cenc_drm_support() EPF после загрузки или выхода из сна пересобирается с first_run=false, и заглушка «нет интернета» не создаётся inference (вывод)862 guide/pitfalls.md

  1. doc-sdk-plugins.c025 · doc · any-documented; прошивка — · dune_plugin.xml — единственный файл, обязательный для загрузки плагина; остальные файлы указываются в манифесте и могут называться как угодно ↩

  2. doc-sdk-plugins.c026 · doc · any-documented; прошивка — · PHP-плагин обязан содержать PHP-программу с функцией hd_create_plugin(); путь к ней задаётся в dune_plugin.xml ↩↩

  3. fw-tv188b-261021-0117-r25.c372 · device · tv188b, android-dune-fw; прошивка 261021_0117_r25 · На tv188b r25 тестовые PHP-плагины test_plugin5 и test_plugin10 работали без hd_create_plugin(): их main.php объявляет класс, унаследованный от DunePluginFw, и handle_user_input выполнялся. ↩↩

  4. fw-tv188b-261021-0117-r25.c213 · device · tv188b, android-dune-fw; прошивка 261021_0117_r25 · На tv188b r25 точки входа плагина test_plugin5 (root://applications), заданные без icon_url, в разделе «Приложения» не появлялись. ↩

    • plg-dc-dune-backup.c009 · code · unknown; прошивка — · Первая точка входа манифеста открывается из root://applications по media_url main_menu.
    • plg-dc-dune-backup.c010 · code · unknown; прошивка — · Вторая точка входа манифеста открывается из setup://applications по media_url setup.
    • plg-dc-dune-backup.c014 · code · unknown; прошивка — · В первой точке входа элемент badge_icon_url задан дважды — plugin_file://icons/badge1.png и затем plugin_file://icons/transparent.aai.

    ↩

    • plg-dc-screenshoter.c011 · code · unknown; прошивка — · Первая точка входа: parent_media_url = root://applications, media_url = setup_app
    • plg-dc-screenshoter.c012 · code · unknown; прошивка — · Вторая точка входа: parent_media_url = setup://applications, media_url = setup

    ↩

    • plg-gh-aspel-twitch-dune-plugin.c003 · code · unknown; прошивка — · Первая точка входа размещена в root://applications (parent_media_url).
    • plg-gh-aspel-twitch-dune-plugin.c010 · code · unknown; прошивка — · Вторая точка входа размещена в setup://applications (parent_media_url).

    ↩

    • plg-hdtv-altsource.c004 · code · unknown; прошивка — · Первая точка входа — root://applications, ставится после section:applications, не является разделом по умолчанию, открывает media_url root_file_system_screen с подписью «Источники 2.0» и иконками plugin_file://icons/logo.png и plugin_file://icons/default.png.
    • plg-hdtv-altsource.c008 · code · unknown; прошивка — · Вторая точка входа — setup://applications, media_url setup, подпись «Источники 2.0»; клавиша ENTER открывает папку действием plugin_open_folder.

    ↩

  5. plg-hdtv-smart-apps.c011 · code · unknown; прошивка — · Первый entry_point обоих манифестов задаёт parent_media_url root://applications, второй — setup://applications. ↩

    • plg-hdtv-altv.c002 · code · unknown; прошивка — · Первая точка входа манифеста — parent_media_url root://tv, media_url tv_group_list, подпись AllTV; key_enter — plugin_open_folder, key_play — plugin_tv_play; ip_address_required=yes, show_cookie_name=show_tv, show_by_default=yes.
    • plg-hdtv-altv.c003 · code · unknown; прошивка — · Вторая точка входа манифеста — parent_media_url setup://applications, media_url setup, подпись AllTV; key_enter — plugin_open_folder.

    ↩

    • plg-hdtv-novosib-iptv.c002 · code · unknown; прошивка — · Первая точка входа манифеста — parent_media_url root://tv, media_url tv_group_list, подпись Novosib-iptv-2; key_enter — plugin_open_folder, key_play — plugin_tv_play; ip_address_required=yes, show_cookie_name=show_tv, show_by_default=yes.
    • plg-hdtv-novosib-iptv.c003 · code · unknown; прошивка — · Вторая точка входа манифеста — parent_media_url setup://applications, media_url setup, подпись Novosib-iptv-2; key_enter — plugin_open_folder.

    ↩

    • plg-hdtv-plugtv.c003 · code · unknown; прошивка — · В обоих манифестах ТВ-точка входа размещена в root://tv с media_url tv_channel_list и иконкой plugin_file://icons/logo.png; key_enter — plugin_open_folder, key_play — plugin_tv_play; требуются IP-адрес, cookie show_tv и показ по умолчанию.
    • plg-hdtv-plugtv.c004 · code · unknown; прошивка — · В обоих манифестах вторая точка входа размещена в setup://applications с media_url setup, иконкой plugin_file://icons/logo.png и key_enter plugin_open_folder.

    ↩

    • plg-gh-valerievitch-dune-plugin-acestreamsearch.c004 · code · unknown; прошивка — · Первая точка входа манифеста помещена в root://tv (entry_points/entry_point[1]/parent_media_url).
    • plg-gh-valerievitch-dune-plugin-acestreamsearch.c005 · code · unknown; прошивка — · Первая точка входа открывает media_url tv_group_list (entry_points/entry_point[1]/media_url).

    ↩

    • plg-hdtv-liteiptv.c004 · code · unknown; прошивка — · Первая точка входа обоих манифестов задаёт parent_media_url = root://tv и media_url = tv_group_list.
    • plg-hdtv-liteiptv.c015 · code · unknown; прошивка — · Вторая точка входа обоих манифестов задаёт parent_media_url = setup://applications и media_url = setup.

    ↩

  6. plg-hdtv-zlostnyi-iptv.c008 · code · unknown; прошивка — · У всех 12 полных пакетов одинаковая форма манифеста: две точки входа (root://tv → tv_group_list с plugin_open_folder/plugin_tv_play и setup://applications → setup), type php и check_update на zlostnyi.tech; различаются name, caption, значок, program, version/version_index и путь update-URL. ↩

    • plg-hdtv-jurt.c002 · code · unknown; прошивка — · Первая точка входа манифеста — parent_media_url root://tv, media_url tv_group_list, подпись Юрта ТВ; key_enter — plugin_handle_user_input (handler_id entry, entry_id tv), key_play — plugin_tv_play; ip_address_required=yes, show_cookie_name=show_tv, show_by_default=lang(russian).
    • plg-hdtv-jurt.c003 · code · unknown; прошивка — · Вторая точка входа манифеста — parent_media_url setup://applications, media_url setup, подпись Юрта ТВ; key_enter — plugin_handle_user_input с handler_id entry и entry_id setup.

    ↩

    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c004 · code · unknown; прошивка — · В манифесте WeburgTV элемент entry_points/entry_point[1]/parent_media_url имеет значение «root://tv».
    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c005 · code · unknown; прошивка — · В манифесте WeburgTV элемент entry_points/entry_point[1]/media_url имеет значение «tv_group_list».
    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c006 · code · unknown; прошивка — · В манифесте WeburgTV элемент entry_points/entry_point[1]/caption имеет значение «Weburg TV».
    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c007 · code · unknown; прошивка — · В манифесте WeburgTV элемент entry_points/entry_point[1]/icon_url имеет значение «plugin_file://icons/WeburgTV.png».

    ↩

  7. plg-hdtv-update-bootstrap.c006 · code · unknown; прошивка — · У 18 IPTV-заготовок zlostnyi.tech (1cent, 1usd, antifriz, bcu, cbilling, edem, fox, glanz, great, ilook, itv, lightiptv, shara-club, smile, tvteam, viplime, sharavoz, ottclub) манифест задаёт две точки входа — root://tv → tv_group_list с key_enter plugin_open_folder и key_play plugin_tv_play и setup://applications → setup с key_enter plugin_open_folder (у ottclub — plugin_handle_user_input, c013), — а также auto_resume/enable yes, ip_address_required yes, show_cookie_name show_tv и show_by_default yes. ↩

  8. plg-hdtv-update-bootstrap.c010 · code · unknown; прошивка — · shura — единственный каркас из 22 с манифестом IPTV-типа: root://tv → tv_group_list с key_play plugin_tv_play, вторая точка setup://applications → setup, auto_resume/enable yes, show_tv, version 2.0.5, version_index 5, program starnet.php и check_update schema 1 на http://zlostnyi.tech/dune/shura/shura_update.txt; PHP при этом — та же 11-строчная заглушка. ↩

    • plg-ds-dune-hd-tv.c005 · code · unknown; прошивка — · Первая точка входа: parent_media_url root://tv, media_url top_list; key_enter — plugin_handle_user_input с handler_id=entry, entry_id=top; key_play — plugin_tv_play.
    • plg-ds-dune-hd-tv.c006 · code · unknown; прошивка — · Вторая точка входа: parent_media_url setup://applications, media_url setup, key_enter — plugin_handle_user_input с handler_id=entry, entry_id=setup.

    ↩

    • plg-hdtv-smart-vod.c003 · code · unknown; прошивка — · Манифест HdKinoTeatr.Com, Futbik.Net, KinoKrad.Co, KinoProfi.Org, MegaMult.Net, Mosfilm, BestKino, Indiakino.net, KinoHold.Com, HDrezka.ag, Zona.mobi, KinoFrance задаёт dune_plugin/entry_points/entry_point[1]/parent_media_url = «root://video».
    • plg-hdtv-smart-vod.c004 · code · unknown; прошивка — · Манифест HdKinoTeatr.Com, Futbik.Net, KinoKrad.Co, KinoProfi.Org, MegaMult.Net, Mosfilm, BestKino, Indiakino.net, KinoHold.Com, HDrezka.ag, Zona.mobi, KinoFrance задаёт dune_plugin/entry_points/entry_point[1]/media_url = «main_menu».
    • plg-hdtv-smart-vod.c013 · code · unknown; прошивка — · Манифест HdKinoTeatr.Com, Futbik.Net, KinoKrad.Co, KinoProfi.Org, MegaMult.Net, Mosfilm, BestKino, Indiakino.net, KinoHold.Com, HDrezka.ag, Zona.mobi, KinoFrance задаёт dune_plugin/entry_points/entry_point[2]/parent_media_url = «setup://applications».
    • plg-hdtv-smart-vod.c014 · code · unknown; прошивка — · Манифест HdKinoTeatr.Com, Futbik.Net, KinoKrad.Co, KinoProfi.Org, MegaMult.Net, Mosfilm, BestKino, Indiakino.net, KinoHold.Com, HDrezka.ag, Zona.mobi, KinoFrance задаёт dune_plugin/entry_points/entry_point[2]/media_url = «setup».

    ↩

    • plg-gh-rpervykh-dune-plugin-anidub-com.c003 · code · unknown; прошивка — · В манифесте anidub первая точка входа имеет parent_media_url «root://video».
    • plg-gh-rpervykh-dune-plugin-anidub-com.c011 · code · unknown; прошивка — · В манифесте anidub вторая точка входа имеет parent_media_url «setup://applications».

    ↩

    • plg-hdtv-101-ru.c003 · code · unknown; прошивка — · Первая точка входа: parent_media_url root://music_and_radio, media_url tv_group_list, подпись 101.ru, icon_url plugin_file://icons/logo.png, badge_icon_url plugin_file://icons/default.png.
    • plg-hdtv-101-ru.c006 · code · unknown; прошивка — · Вторая точка входа — parent_media_url setup://applications, media_url setup, подпись 101.ru, icon_url logo.png, badge_icon_url default.png, key_enter plugin_open_folder; блока key_play нет.

    ↩

    • plg-hdtv-surface-family.c009 · code · unknown; прошивка — · Точка входа Radiorecord.ru и rmfon.pl стоит в root://music_and_radio, wwcam — в root://video; у всех media_url surface_tv_channel_list, key_enter = plugin_open_folder, key_play = plugin_tv_play.
    • plg-hdtv-surface-family.c010 · code · unknown; прошивка — · Вторая точка входа всех трёх плагинов стоит в setup://applications, media_url setup и реагирует на key_enter действием plugin_open_folder (key_play нет).

    ↩

    • plg-hdtv-duneplexcatalog.c003 · code · unknown; прошивка — · Первая точка входа размещена в root://sources, открывает media_url plex_library_list, подписана DunePlexCatalog и использует иконку plugin_file://icons/dpc_new.png.
    • plg-hdtv-duneplexcatalog.c006 · code · unknown; прошивка — · Вторая точка входа размещена в setup://applications, открывает media_url setup_screen, подписана DPC Setup и использует ту же иконку dpc_new.png.

    ↩

  9. plg-hdtv-update-bootstrap.c003 · code · unknown; прошивка — · Два каркаса dune-club отличаются от остальных 19 родительской точкой входа: rclone и rmfon-pl задают parent_media_url root://sources (остальные элементы те же — main_menu, plugin_open_folder, show_vod, start.php, version 0.0.1, version_index 0). ↩

    • plg-hdtv-folder-cache-vod.c009 · code · unknown; прошивка — · В каждом манифесте два entry_point: основной (media_url main_menu) и setup (setup://applications/setup); действие key_enter у обоих — plugin_handle_user_input; у Fussball есть третий entry_point root://tv.
    • plg-hdtv-folder-cache-vod.c010 · code · unknown; прошивка — · Плагины прописываются в разные разделы меню: 9 — в root://applications, 5 — в root://video (karas-avadim, gozlan, kinolist, seretil, veterok), mp3tales — в root://music_and_radio; Fussball дополнительно в root://tv.

    ↩

    • plg-hdtv-freetv.c002 · code · unknown; прошивка — · Первая точка входа манифеста — parent_media_url root://tv, media_url launch_tv, подпись FREE TV; key_enter — plugin_handle_user_input (handler_id main_handler, control_id plugin_entry, action_id launch_tv), key_play — plugin_tv_play; ip_address_required=yes.
    • plg-hdtv-freetv.c004 · code · unknown; прошивка — · Вторая точка входа манифеста — parent_media_url root://tv, media_url launch_vod, подпись «Фильмотека»; key_enter — plugin_handle_user_input с action_id launch_vod; show_cookie_name=show_vod_section, show_by_default=no.

    ↩

    • plg-gh-kocourkuba-proiptv.c007 · code · unknown; прошивка — · Первая точка входа манифеста — parent_media_url root://tv, media_url tv_groups; key_enter и key_play вызывают entry_handler/plugin_entry с action_id launch и mandatory_playback 0 и 1 соответственно; ip_address_required=yes, show_cookie_name=show_tv, show_by_default=yes.
    • plg-gh-kocourkuba-proiptv.c009 · code · unknown; прошивка — · Вторая точка входа — root://tv, media_url launch_vod, подпись %tr%plugin_vod, key_enter → entry_handler/plugin_entry action_id launch_vod; show_cookie_name=show_vod_icon, show_by_default=no. Третья — setup://applications, media_url plugin_setup с key_enter типа plugin_open_folder.

    ↩

    • plg-dc-dunemdb-supplier-online-movies.c005 · code · unknown; прошивка — · В /dune_plugin/entry_points объявлена одна активная точка входа setup://applications с media_url setup и подписью %tr%title_plugin.
    • plg-dc-dunemdb-supplier-online-movies.c008 · code · unknown; прошивка — · В entry_points есть закомментированная точка входа downloads (parent root://applications, show_by_default no), которая не активна.

    ↩

  10. plg-dc-widget-ext.c007 · code · unknown; прошивка — · Точка входа: parent_media_url root://setup, exclude_from_merged_parent yes, media_url setup_screen, icon_url plugin_file://icon.png, badge_icon_url plugin_file://default.png ↩

  11. plg-gh-sndpl-apple-trailers-dune-plugin.c008 · code · unknown; прошивка — · Манифест задаёт одну точку входа entry_points/entry_point в root://applications с media_url main_menu. ↩

    • plg-gh-vladikshkwok-lampa-dune-plugins.c006 · code · android; прошивка — · Манифест объявляет точку входа в разделе entry_points/entry_point.
    • plg-gh-vladikshkwok-lampa-dune-plugins.c007 · code · android; прошивка — · Точка входа помещена в раздел root://applications (parent_media_url).
    • plg-gh-vladikshkwok-lampa-dune-plugins.c008 · code · android; прошивка — · media_url точки входа — play.
    • plg-gh-vladikshkwok-lampa-dune-plugins.c009 · code · android; прошивка — · Подпись точки входа — «Lampa: последнее видео», иконка — plugin_file:///icon.png.

    ↩

  12. plg-gh-mikhail-ilin-dune-plugin-weburgtv.c007 · code · unknown; прошивка — · В манифесте WeburgTV элемент entry_points/entry_point[1]/icon_url имеет значение «plugin_file://icons/WeburgTV.png». ↩

  13. plg-gh-vladikshkwok-lampa-dune-plugins.c009 · code · android; прошивка — · Подпись точки входа — «Lampa: последнее видео», иконка — plugin_file:///icon.png. ↩

  14. plg-hdtv-surface-family.c014 · code · unknown; прошивка — · Иконки точек входа Radiorecord.ru и rmfon.pl лежат под plugin_file://www/lib/logo/, а wwcam — под plugin_file://logo/ (без каталога www). ↩

  15. plg-hdtv-update-bootstrap.c005 · code · unknown; прошивка — · Среди 43 пакетов-загрузчиков liteiptv — единственный с timeout 20 и единственный манифест с badge_icon_url: version 0.0.0, version_index 0, program Smart.php, точка входа root://tv → tv_group_list с key_enter plugin_open_folder и key_play plugin_tv_play, badge_icon_url plugin_file://icons/default.png, check_update schema 1 на http://dune-club.info/plugins/update/liteIPTV/update.txt. ↩

  16. plg-gh-aspel-twitch-dune-plugin.c007 · code · unknown; прошивка — · В первой точке входа ENTER назначен на действие plugin_open_folder. ↩

  17. plg-hdtv-duneplexcatalog.c005 · code · unknown; прошивка — · Обе точки входа назначают клавише Enter действие plugin_open_folder; первая открывает экран plex_library_list, вторая — setup_screen. ↩

  18. plg-hdtv-update-bootstrap.c025 · code · unknown; прошивка — · key_enter с plugin_open_folder есть у 41 плагина (все, кроме sunduk и shara-tv; у ottclub — только в TV-точке), key_play с plugin_tv_play — у 22 (18 zlostnyi, shura, liteiptv, sunduk, shara-tv), key_enter с plugin_handle_user_input — у sunduk (обе точки), shara-tv (обе) и ottclub (setup). ↩↩

  19. plg-hdtv-altv.c002 · code · unknown; прошивка — · Первая точка входа манифеста — parent_media_url root://tv, media_url tv_group_list, подпись AllTV; key_enter — plugin_open_folder, key_play — plugin_tv_play; ip_address_required=yes, show_cookie_name=show_tv, show_by_default=yes. ↩

  20. plg-hdtv-101-ru.c004 · code · unknown; прошивка — · В первой точке входа key_enter задаёт plugin_open_folder, key_play — plugin_tv_play. ↩

    • plg-gh-valerievitch-dune-plugin-acestreamsearch.c008 · code · unknown; прошивка — · Первая точка входа на key_enter выполняет действие plugin_open_folder (entry_points/entry_point[1]/actions/key_enter/type).
    • plg-gh-valerievitch-dune-plugin-acestreamsearch.c009 · code · unknown; прошивка — · Первая точка входа на key_play выполняет действие plugin_tv_play (entry_points/entry_point[1]/actions/key_play/type).

    ↩

  21. plg-ds-dune-hd-tv.c005 · code · unknown; прошивка — · Первая точка входа: parent_media_url root://tv, media_url top_list; key_enter — plugin_handle_user_input с handler_id=entry, entry_id=top; key_play — plugin_tv_play. ↩

    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c008 · code · unknown; прошивка — · В манифесте WeburgTV действие key_enter точки входа имеет тип «plugin_tv_play».
    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c009 · code · unknown; прошивка — · В манифесте WeburgTV действие key_play точки входа имеет тип «plugin_tv_play».

    ↩

  22. plg-hdtv-surface-family.c098 · code · unknown; прошивка — · Единственная точка входа LSS стоит в root://music_and_radio → surface_tv_channel_list и реагирует и на key_enter, и на key_play действием plugin_tv_play; иконки — plugin_file://icons/logo.png и plugin_file://icons/default.png. ↩

  23. plg-dc-screenshoter.c014 · code · unknown; прошивка — · В обеих точках входа клавиши key_enter и key_play вызывают действие plugin_handle_user_input с handler_id = entry ↩

    • plg-hdtv-youtube.c008 · code · unknown; прошивка — · Манифест YouTube задаёт entry_point[1]/actions/key_enter/type = «plugin_handle_user_input» (в эталоне HdKinoTeatr — plugin_open_folder).
    • plg-hdtv-youtube.c009 · code · unknown; прошивка — · Манифест YouTube задаёт entry_point[1]/actions/key_enter/params/handler_id = «entry».
    • plg-hdtv-youtube.c010 · code · unknown; прошивка — · Манифест YouTube задаёт entry_point[1]/actions/key_play/type = «plugin_handle_user_input» с params/handler_id = «entry».
    • plg-hdtv-youtube.c035 · code · unknown; прошивка — · SmartEntryHandler (handler_id entry) при control_id=save_yes записывает plugin_cookies->disclaimer='yes' и открывает папку; при do_setup открывает SmartSetupScreen с заголовком %tr%t1; иначе при handler_id=entry возвращает ActionFactory::open_folder() без аргументов.

    ↩

    • plg-hdtv-liteiptv.c007 · code · unknown; прошивка — · ENTER в первой точке входа обоих пакетов обрабатывается действием plugin_handle_user_input с handler_id = entry и control_id = entry_enter.
    • plg-hdtv-liteiptv.c008 · code · unknown; прошивка — · PLAY в первой точке входа обоих пакетов обрабатывается действием plugin_handle_user_input с handler_id = entry и control_id = entry_play.

    ↩

    • plg-hdtv-rain-tv.c003 · code · unknown; прошивка — · key_enter и key_play точки входа 43Kanal отправляют действие plugin_handle_user_input с params handler_id=entry и entry_id=rain.
    • plg-hdtv-rain-tv.c010 · code · unknown; прошивка — · RainEntryHandler реализует UserInputHandler, в конструкторе регистрируется в синглтоне UserInputHandlerRegistry, get_handler_id() возвращает 'entry'.
    • plg-hdtv-rain-tv.c011 · code · unknown; прошивка — · RainEntryHandler::handle_user_input при entry_id == 'rain' возвращает ActionFactory::tv_play(), иначе null; входные данные и полный user_input пишутся в лог через hd_print/print_r.

    ↩

    • plg-hdtv-smart-apps.c014 · code · unknown; прошивка — · Первый entry_point Entware назначает ENTER и PLAY действию plugin_handle_user_input с handler_id entry.
    • plg-hdtv-smart-apps.c016 · code · unknown; прошивка — · Первый entry_point Wallpaper назначает ENTER и PLAY действию plugin_handle_user_input с handler_id entry.

    ↩

  24. plg-hdtv-smart-vod.c087 · code · unknown; прошивка — · Манифест Zona.mobi задаёт dune_plugin/entry_points/entry_point[1]/actions/key_enter/type = «plugin_handle_user_input». ↩

  25. plg-hdtv-cleanup.c011 · code · unknown; прошивка — · Если тип в nav_state.txt — path = root:favorites, parse_nav берёт элемент root_shortcut://…, читает /persistfs/main_screen_items//dune_folder.txt и извлекает имя плагина из media_url = plugin_launcher://{name=...}, затем читает его pid. ↩

    • plg-hdtv-plugtv.c003 · code · unknown; прошивка — · В обоих манифестах ТВ-точка входа размещена в root://tv с media_url tv_channel_list и иконкой plugin_file://icons/logo.png; key_enter — plugin_open_folder, key_play — plugin_tv_play; требуются IP-адрес, cookie show_tv и показ по умолчанию.
    • plg-hdtv-plugtv.c031 · code · unknown; прошивка — · Экран настроек DemoSetupScreen содержит комбобоксы show_tv (Показать/Спрятать), epg_server (Внешний источник/От провайдера), epg_shift (от -12 до 12 часов), epg_font (Нормальный/Мелкий, хранится в set_font), buf_time (0…10000 мс), кнопки информации о плагине и канале и перезагрузки.

    ↩

  26. plg-gh-valerievitch-dune-plugin-acestreamsearch.c011 · code · unknown; прошивка — · Видимость первой точки входа привязана к cookie show_tv (entry_points/entry_point[1]/show_cookie_name). ↩

  27. plg-hdtv-liteiptv.c014 · code · unknown; прошивка — · Первая точка входа обоих манифестов задаёт ip_address_required = yes, show_cookie_name = show_vod и show_by_default = yes. ↩

    • plg-hdtv-surface-family.c011 · code · unknown; прошивка — · У первой точки входа всех трёх манифестов ip_address_required = yes, show_cookie_name = show_application, show_by_default = yes.
    • plg-hdtv-surface-family.c046 · code · unknown; прошивка — · Ни один из трёх плагинов не записывает cookie show_application, указанный в манифесте как show_cookie_name; rmfon.pl и wwcam пишут cookie show_tv, а Radiorecord.ru переключателя show_tv не имеет.

    ↩

  28. plg-hdtv-update-bootstrap.c024 · code · unknown; прошивка — · show_cookie_name задан в 42 манифестах: show_vod — у 21 каркаса dune-club, show_tv — у 21 IPTV-плагина (18 zlostnyi, shura, liteiptv, shara-tv); у sunduk элемента нет. ↩

  29. plg-hdtv-freetv.c004 · code · unknown; прошивка — · Вторая точка входа манифеста — parent_media_url root://tv, media_url launch_vod, подпись «Фильмотека»; key_enter — plugin_handle_user_input с action_id launch_vod; show_cookie_name=show_vod_section, show_by_default=no. ↩

  30. plg-hdtv-jurt.c002 · code · unknown; прошивка — · Первая точка входа манифеста — parent_media_url root://tv, media_url tv_group_list, подпись Юрта ТВ; key_enter — plugin_handle_user_input (handler_id entry, entry_id tv), key_play — plugin_tv_play; ip_address_required=yes, show_cookie_name=show_tv, show_by_default=lang(russian). ↩

  31. plg-gh-aspel-twitch-dune-plugin.c008 · code · unknown; прошивка — · Первая точка входа требует IP-адрес — ip_address_required = yes. ↩

  32. plg-hdtv-101-ru.c005 · code · unknown; прошивка — · Первая точка входа задаёт ip_address_required yes, show_cookie_name show_application и show_by_default yes. ↩

  33. plg-hdtv-duneplexcatalog.c004 · code · unknown; прошивка — · Первая точка входа требует IP-адрес (ip_address_required yes), показывает иконку по cookie show_dpc (show_cookie_name) и включена по умолчанию (show_by_default yes). ↩

  34. plg-hdtv-update-bootstrap.c027 · code · unknown; прошивка — · Все 43 манифеста задают ip_address_required yes и show_by_default yes; у shara-tv ip_address_required и show_cookie_name дополнительно повторены внутри auto_resume. ↩

  35. plg-hdtv-altsource.c006 · code · unknown; прошивка — · Контекстное меню первой точки входа содержит пять пунктов, каждый — действие plugin_handle_user_input обработчика entry: «Настройки Источники 2.0» (do_setup), «Перезагрузить плеер» (reboot), «Выключить плеер» (power_off), «Задать иконку плагина» (newPluginIco) и «Удалить плагин» (unInstallPlugin). ↩

    • plg-hdtv-youtube.c011 · code · unknown; прошивка — · Манифест YouTube задаёт в entry_point[1]/popup_menu пункт %tr%t1 с иконкой gui_skin://small_icons/setup.aai и действием plugin_handle_user_input handler_id=entry, control_id=do_setup; в эталоне HdKinoTeatr popup_menu нет.
    • plg-hdtv-youtube.c012 · code · unknown; прошивка — · Манифест YouTube задаёт в popup_menu пункт %tr%t2 с иконкой gui_skin://small_icons/service_file.aai и control_id=do_hard_reset.
    • plg-hdtv-youtube.c013 · code · unknown; прошивка — · Манифест YouTube задаёт в popup_menu пункт %tr%t3 с иконкой gui_skin://small_icons/power.aai и control_id=power_off.

    ↩

    • plg-hdtv-liteiptv.c009 · code · unknown; прошивка — · Первый пункт popup_menu первой точки входа обоих манифестов: caption %tr%t160, icon gui_skin://small_icons/tv.aai, действие entry/entry_play.
    • plg-hdtv-liteiptv.c013 · code · unknown; прошивка — · Пятый пункт popup_menu с caption %tr%t288 и действием power_off присутствует в обоих манифестах только в XML-комментарии и оболочкой не используется.

    ↩

  36. plg-gh-kocourkuba-proiptv.c008 · code · unknown; прошивка — · popup_menu первой точки входа содержит 8 пунктов plugin_handle_user_input на entry_handler с control_id call_plugin_setup, call_playlist_settings, call_backup, force_open, call_playlists_setup, call_clear_all_epg, call_send_log, call_reboot; подписи — ключи перевода с префиксом %tr%. ↩

    • plg-hdtv-smart-apps.c017 · code · unknown; прошивка — · Манифест Entware задаёт popup_menu второго входа с пунктами «%tr%t39» → control_id do_hard_reset и «%tr%t77» → control_id power_off; оба действия — plugin_handle_user_input с handler_id entry.
    • plg-hdtv-smart-apps.c018 · code · unknown; прошивка — · Манифест Wallpaper задаёт popup_menu первого входа из пяти пунктов: случайный (do_random), по порядку (do_next), настройки (do_setup), перезагрузка плеера (do_hard_reset), выключение плеера (power_off).

    ↩

    • plg-dc-bazinga3.c007 · code · unknown; прошивка — · Popup-меню первой точки входа содержит четыре пункта с plugin_handle_user_input, handler_id entry и control_id do_setup, reboot, power_off и newPluginIco.
    • plg-dc-bazinga3.c020 · code · unknown; прошивка — · SmartEntryHandler (handler_id entry) на reboot выполняет shell_exec('reboot'), на power_off пишет код A15EBF00 в /proc/ir/button, на do_setup открывает папку setup.

    ↩

  37. plg-hdtv-freetv.c003 · code · unknown; прошивка — · Первая точка входа содержит popup_menu с пунктом «Настройки плагина»: action_id open_setup через main_handler/plugin_entry. ↩

  38. doc-sdk-plugins.c090 · doc · any-documented; прошивка — · Auto-resume (выключен по умолчанию, включается yes) при включении/выходе из standby восстанавливает только live-ТВ, архив ТВ и VOD; позиция в иерархии папок не восстанавливается ↩↩

  39. plg-hdtv-101-ru.c002 · code · unknown; прошивка — · Манифест включает auto_resume/enable со значением yes. ↩

  40. plg-hdtv-altv.c005 · code · unknown; прошивка — · Манифест включает auto_resume (auto_resume/enable = yes). ↩

  41. plg-hdtv-rain-tv.c004 · code · unknown; прошивка — · Манифест 43Kanal включает auto_resume (yes), то есть стандартное восстановление live-ТВ после standby. ↩

  42. plg-gh-mikhail-ilin-dune-plugin-weburgtv.c003 · code · unknown; прошивка — · В манифесте WeburgTV элемент auto_resume/enable имеет значение «yes». ↩

  43. plg-hdtv-jurt.c005 · code · unknown; прошивка — · Манифест задаёт auto_resume/enable = auto (не yes, а значение auto). ↩↩

  44. plg-hdtv-update-bootstrap.c026 · code · unknown; прошивка — · auto_resume/enable задан у 22 плагинов: yes у 20 (18 zlostnyi, shura, liteiptv), auto у sunduk и shara-tv; у ottclub два блока auto_resume — yes и auto; у 21 каркаса dune-club блока auto_resume нет. ↩↩

  45. plg-gh-valerievitch-dune-plugin-acestreamsearch.c003 · code · unknown; прошивка — · Манифест включает auto_resume (элемент auto_resume/enable = yes). ↩

  46. plg-ds-dune-hd-tv.c004 · code · unknown; прошивка — · В манифесте включено auto_resume (enable = yes) с ip_address_required = yes. ↩

  47. plg-gh-kocourkuba-proiptv.c010 · code · unknown; прошивка — · Манифест включает auto_resume (enable=yes): действие entry_handler/plugin_entry с action_id auto_resume и mandatory_playback 1; ip_address_required=yes, valid_time_required=yes. ↩

  48. plg-hdtv-freetv.c007 · code · unknown; прошивка — · auto_resume манифеста включает enable=yes, ip_address_required=yes и valid_time_required=yes. ↩

    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c012 · code · unknown; прошивка — · В манифесте WeburgTV элемент auto_start/run_action_before_auto_resume имеет значение «yes».
    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c013 · code · unknown; прошивка — · В манифесте WeburgTV элемент auto_start/entry_point_media_url имеет значение «tv_group_list».
    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c014 · code · unknown; прошивка — · В манифесте WeburgTV элемент auto_start/force_on_start имеет значение «black_screen».
    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c015 · code · unknown; прошивка — · В манифесте WeburgTV элемент auto_start/force_on_finish имеет значение «main_screen».
    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c016 · code · unknown; прошивка — · В манифесте WeburgTV элемент auto_start/skip_initial_dialogs имеет значение «yes».
    • plg-gh-mikhail-ilin-dune-plugin-weburgtv.c017 · code · unknown; прошивка — · В манифесте WeburgTV действие auto_start/action имеет тип «plugin_tv_play».

    ↩

    • plg-hdtv-rclone.c068 · code · unknown; прошивка — · При наличии /persistfs или platform_kind android экран настроек при заданном автозапуске показывает его тип («Включение плеера» для type 1, «Вход в плагин» для type 2) и кнопку отмены, а при непустом config без автозапуска — кнопку добавления автозапуска.
    • plg-hdtv-rclone.c042 · code · unknown; прошивка — · Если дисклеймер принят, rclone_mount() не вернул разобранный запущенный mount и в настройках задан autostartPluginInRemote, entry при входе запускает bin/rclone_mount.sh с этим remote и путём fuse_mount_dir_path(), ждёт 3 с и, если rclone_mount() снова разбирается регуляркой, при warning != 'yes' показывает предупреждение о задержке 1–2 мин, иначе сразу открывает remote; без найденного mount открывает папку setup.
    • plg-hdtv-rclone.c106 · code · unknown; прошивка — · bin/rclone_mount.sh берёт имя remote и каталог монтирования из аргументов 1–2, иначе из файлов autostart_remote_name и autostart_fuse_mount_dir_path, иначе завершает с ошибкой REMOTE_NAME/FUSE_MOUNT_DIR_PATH not found.

    ↩

    • plg-hdtv-folder-cache-vod.c114 · code · unknown; прошивка — · Главное меню streamit — четыре пункта: «Категории» (main_menu:videos), «Поиск» (main_menu:search), «Избранное» (main_menu:fav) и «Настройки» (setup); у ForumHouseTV, Stopham и SexyFilmWorld пунктов три (c023).
    • plg-hdtv-folder-cache-vod.c107 · code · unknown; прошивка — · В манифесте два entry_point: main_menu в root://applications и setup в setup://applications; у обоих key_enter = plugin_handle_user_input, иконка plugin_file://skins/logo.png, а у основного ещё ip_address_required=yes, show_cookie_name=main_icon и show_by_default=yes.

    ↩

  49. plg-gh-kocourkuba-proiptv.c012 · code · unknown; прошивка — · operation_timeout манифеста: default 300, get_epg_day 30, handle_user_input 300. ↩

  50. plg-dc-dunemdb-supplier-online-movies.c009 · code · unknown; прошивка — · Тайм-аут операций по умолчанию — 300 секунд (/dune_plugin/operation_timeout/default). ↩

    • plg-hdtv-freetv.c006 · code · unknown; прошивка — · Манифест объявляет DRM-описание rostelecom типа verimatrix (drm_defs/drm_def).
    • plg-hdtv-freetv.c034 · code · unknown; прошивка — · rostelecom_verimatrix.ini задаёт COMPANY=Rostelecom, SERVERADDRESS=vmx.svc.iptv.rt.ru, PREFERRED_VKS=vmx.svc.iptv.rt.ru/12699, SERVERPORT=12697, TIMEOUT=15, ROOTCERT=rootcert.pem.

    ↩

  51. plg-hdtv-novosib-iptv.c005 · code · unknown; прошивка — · Манифест объявляет два DRM-описания типа verimatrix: domolink и rostelecom (drm_defs/drm_def). ↩

  52. plg-hdtv-polsky-tv.c002 · code · unknown; прошивка — · Заголовок точки входа и caption манифеста — шаблон %ext% с ключом kartina_tv_title; блок ktv_params задаёт caption PolBox, server_address online.polbox.tv и fixed_osk_id polish. ↩

    • plg-dc-dunemdb-supplier-movies-rus.c003 · code · unknown; прошивка — · Тип плагина в манифесте — plain.
    • plg-dc-dunemdb-supplier-movies-rus.c023 · code · unknown; прошивка — · Плагин регистрируется старым путём: пишет описатель прямо в /tmp/movie_suppliers/movies_rus; элемента params/movie_suppliers в манифесте нет, файла bin/movie_suppliers_update.sh в пакете нет.

    ↩

    • plg-dc-globaltv.c021 · code · unknown; прошивка — · Файл dune_plugin_metadata.xml указывает категорию плагина tv и путь иконки img/app_icon.png.
    • plg-dc-globaltv.c022 · code · unknown; прошивка — · dune_plugin_metadata.xml требует firmware_features = dunemdb_supplier_plugin_api_v6.
    • plg-dc-globaltv.c023 · code · unknown; прошивка — · dune_plugin_metadata.xml помечает плагин как community_plugin = yes и secure_update = yes.

    ↩

  53. plg-ds-dune-hd-tv.c013 · code · unknown; прошивка — · dune_plugin_metadata.xml: category tv, country Russian Federation,Ru, expr not(firmware_feature(dunemdb_supplier_plugin_api_v6)), extension_v2 yes, interface_language Russian. ↩

  54. doc-sdk-plugins.c143 · doc · any-documented; прошивка — · Global plugin actions поддерживают системные события boot, install, update и uninstall ↩

  55. doc-sdk-plugins.c144 · doc · any-documented; прошивка — · Событие boot_end (в самом конце холодной загрузки) доступно с прошивки 130917_b9 ↩

  56. doc-sdk-plugins.c145 · doc · any-documented; прошивка — · Событие gui_start (при старте родного GUI Dune) доступно с прошивки 130914_b8 ↩

  57. doc-sdk-plugins.c146 · doc · any-documented; прошивка — · Для события boot поддерживается только действие plugin_system ↩

  58. doc-sdk-plugins.c147 · doc · any-documented; прошивка — · Глобальным действием может быть любое стандартное GUI-действие плагина или plugin_system, запускающее исполняемый файл из состава плагина (в примере — через run_string) ↩

  59. fw-tv188b-261021-0117-r25.c077 · device · tv188b, android-dune-fw; прошивка 261021_0117_r25 · На tv188b r25 при следующих стартах приложения (после am force-stop и после restart_gui) boot и boot_end плагина test_plugin5 не выполнялись повторно — в shell.log «[plugin] test_plugin5: boot action already executed» и «[plugin] test_plugin5: GUI boot action already executed». ↩

  60. fw-tv188b-261021-0117-r25.c079 · device · tv188b, android-dune-fw; прошивка 261021_0117_r25 · На tv188b r25 gui_start плагина test_plugin5 выполнялся при каждом старте приложения Dune в прогоне — 13:24:29, 13:35:32, 13:40:55 (после am force-stop) и 13:45:18 (после restart_gui); строки «already executed» для него нет. ↩

  61. fw-tv188b-261021-0117-r25.c081 · device · tv188b, android-dune-fw; прошивка 261021_0117_r25 · На tv188b r25 скрипт global_action plugin_system (boot, boot_end, gui_start) работает под uid 1000(system) с SELinux-контекстом u:r:system_app:s0, текущим каталогом / и переменной окружения FS_PREFIX=/data/data/com.dunehd.app; $0 — абсолютный путь скрипта. ↩

  62. fw-tv188b-261021-0117-r25.c340 · device · tv188b, android-dune-fw; прошивка 261021_0117_r25 · На tv188b r25 строковый id plugin_system в boot-действии выполнен: shell.log пишет action D: exec_all plugin_system и Running system(sh <плагин>/bin/ga.sh boot). ↩

  63. plg-dc-widget-ext.c005 · code · unknown; прошивка — · Манифест задаёт global_actions install, update, boot и gui_start с type plugin_system и data/run_string — запуск shell-скрипта плагина в фоне (bin/<имя>.sh &) ↩

    • plg-dc-dune-backup.c007 · code · unknown; прошивка — · global_actions/gui_start и global_actions/install с типом plugin_system запускают bin/gui_start.sh &.
    • plg-dc-dune-backup.c008 · code · unknown; прошивка — · global_actions/update и global_actions/uninstall с типом plugin_system запускают bin/uninstall_test_php-cgi.sh &.

    ↩

    • plg-hdtv-rclone.c005 · code · unknown; прошивка — · Глобальное действие boot имеет тип plugin_system (global_actions/boot/type).
    • plg-hdtv-rclone.c006 · code · unknown; прошивка — · Глобальное действие boot запускает строку «bin/rclone_automount.sh &» (global_actions/boot/data/run_string), то есть монтирование при старте плеера.
    • plg-hdtv-rclone.c063 · code · android; прошивка — · bin/rclone_automount.sh при наличии fusermount рядом со скриптом запускает rclone_mount.sh через /system/dunehd/dunehd_service do, иначе — напрямую.

    ↩

  64. plg-dc-widget-ext.c006 · code · unknown; прошивка — · global_actions/uninstall вызывает bin/uninstall.sh без «&», в отличие от остальных global_actions ↩

    • plg-hdtv-dlna-renderer.c005 · code · unknown; прошивка — · global_actions/uninstall объявляет plugin_system с run_string bin/gmediarender-ctl cleanup — без завершающего &, то есть команда запускается синхронно.
    • plg-hdtv-dlna-renderer.c014 · code · unknown; прошивка — · Cleanup останавливает рендерер, если он работает, удаляет файлы из /tmp/plugins/dlna_renderer и вызывает sync.

    ↩

  65. plg-dc-dune-backup.c006 · code · unknown; прошивка — · global_actions/boot с типом plugin_system выполняет run_string echo > $FS_PREFIX/tmp/Dune_backup_Flag_boot. ↩

    • plg-hdtv-cleanup.c002 · code · unknown; прошивка — · global_actions/boot_end объявляет plugin_system с run_string bin/cleanup_daemon.sh & — демон очистки запускается в конце загрузки в фоне.
    • plg-hdtv-cleanup.c006 · code · unknown; прошивка — · В пакете нет main.php, объявленного в params/program; в дереве только bin/cleanup_daemon.sh и dune_plugin.xml.

    ↩

    • plg-hdtv-dlna-renderer.c003 · code · unknown; прошивка — · global_actions/install объявляет plugin_system с run_string bin/gmediarender-ctl restart &.
    • plg-hdtv-dlna-renderer.c004 · code · unknown; прошивка — · global_actions/update объявляет plugin_system с run_string bin/gmediarender-ctl restart &.

    ↩

  66. plg-ds-dune-hd-tv.c009 · code · unknown; прошивка — · global_actions boot_end, install и update с условием if="not(firmware_feature(movie_suppliers_update))" выполняют plugin_system с run_string bin/install.sh; uninstall — plugin_system bin/uninstall.sh без условия. ↩

    • plg-dc-globaltv.c011 · code · unknown; прошивка — · Глобальные действия install и update в манифесте оба ведут на plugin_handle_user_input с entry_id=install.
    • plg-dc-globaltv.c027 · code · unknown; прошивка — · Скрипт bin/install.sh удаляет tv_cache_*.json из $FS_PREFIX/flashdata/plugins_data/globaltv, файлы tv_timestamp и fav_timestamp из $FS_PREFIX/flashdata/plugins_epfs/globaltv и создаёт флаг $FS_PREFIX/tmp/plugins/globaltv/update_epfs_if_needed_flag.
    • plg-dc-globaltv.c028 · code · unknown; прошивка — · При entry_id=install обработчик запускает через system() скрипт /bin/install.sh, где install_dir_path берётся из DuneSystem::$properties.

    ↩

  67. plg-gh-kocourkuba-proiptv.c005 · code · unknown; прошивка — · global_actions install, uninstall, update и confirm_update манифеста — действия plugin_handle_user_input на handler_id entry_handler, control_id plugin_entry с action_id, равным имени события (install, uninstall, update, confirm_update). ↩

  68. plg-dc-dunemdb-supplier-online-movies.c011 · code · unknown; прошивка — · Установка и обновление плагина вызывают обработчик entry с control_id install, удаление — control_id uninstall. ↩↩

    • plg-dc-dunemdb-supplier-movies-eng.c004 · code · unknown; прошивка — · global_actions boot_end, install и update выполняют plugin_system bin/register_supplier.sh.
    • plg-dc-dunemdb-supplier-movies-eng.c018 · code · unknown; прошивка — · register_supplier.sh создаёт каталог /tmp/movie_suppliers (если его нет) и пишет описатель movies_eng через heredoc.

    ↩

  69. plg-dc-dunemdb-supplier-online-movies.c010 · code · unknown; прошивка — · На boot_end при отсутствии firmware feature movie_suppliers_update манифест запускает plugin_system с командой bin/register_supplier.sh. ↩↩

  70. plg-gh-kocourkuba-proiptv.c004 · code · unknown; прошивка — · global_actions/boot_end манифеста — действие plugin_system с run_string bin/update_suppliers.sh. ↩

  71. plg-dc-dunemdb-supplier-movies-eng.c005 · code · unknown; прошивка — · global_action uninstall удаляет описатель поставщика командой /bin/rm -f /tmp/movie_suppliers/movies_eng. ↩

  72. plg-ds-dunemdb-supplier-megogo.c005 · code · android; прошивка — · global_actions/uninstall (type plugin_system) удаляет описатель командой /bin/rm -f /tmp/movie_suppliers/megogo. ↩

  73. plg-ds-dunemdb-supplier-okko.c005 · code · android; прошивка — · global_actions/uninstall (type plugin_system) удаляет описатель командой /bin/rm -f /tmp/movie_suppliers/okko. ↩

  74. plg-dc-dunemdb-supplier-online-movies.c065 · code · unknown; прошивка — · run_uninstall при пустом ext_torrserver останавливает запущенный TorrServer и очищает кэш, затем удаляет /tmp/movie_suppliers/online_movies и /tmp/movie_suppliers/online_movies_manual. ↩

  75. plg-gh-mdpuma-dune-plugin-altiptv.c093 · code · unknown; прошивка — · prepare2.sh выбирает /persistfs/plugins/altiptv либо /flashdata/plugins/altiptv по наличию bin и копирует data в соответствующий plugins_data/altiptv/altiptv_data. ↩

  76. plg-hdtv-peerflixserver.c046 · code · unknown; прошивка — · bin/uninstall.sh при наличии любого процесса node выполняет через dunehd_service killall node и завершается с кодом 0. ↩

    • plg-hdtv-utility-family.c033 · code · unknown; прошивка — · Откат LTU: bin/ltu_uninstall.sh при наличии /persistfs/ltu/rc выполняет rc remove (func_stop останавливает smartd, microdc2, ftpd, aria, transmission, nfsd, nut; func_remove ставит boot/.disabled, удаляет /config/boot/ltubd и симлинк /ltu), затем rm -rf /persistfs/ltu и просит перезагрузить плеер.
    • plg-hdtv-utility-family.c054 · code · unknown; прошивка — · Откат Codec_install (dune_service_codecs_uninstall.sh): тот же выбор /persistfs|/flashdata|/D, rm -rf /codecpack, kill по строке ps с httpd и 81 и удаление /config/boot/rtmpboot.sh.
    • plg-hdtv-utility-family.c056 · code · unknown; прошивка — · Codec_install не откатывает прочие правки системы: uninstall-скрипт не удаляет симлинки /codecpack и /lib/libmcrypt.so.4 и строку подключения /codecpack/profile в /etc/profile (grep по скрипту — нет ни одного из этих путей).

    ↩

  77. plg-mydune-home-tv.c158 · code · unknown; прошивка — · bin/register_supplier (boot_end) завершается, если в /tmp/firmware_features.txt нет newgui2021; иначе пишет /tmp/tv_app_suppliers/home_tv — JSON с plugin home_tv, caption «Домашнее ТВ v3» и tv_app {"type":"plugin", "plugin_name":"home_tv","update_url":"http://127.0.0.1/cgi-bin/plugins/home_tv/update"}, затем date +%s в /config/htv_timestamp и touch /tmp/plugins/home_tv/update_epfs_if_needed_flag. ↩

    • plg-hdtv-moidom.c026 · code · unknown; прошивка — · lib/ — копия SDK-фреймворка: 27 из 43 файлов lib побайтно совпадают с файлами встроенных плагинов r24; 16 файлов (default_archive, media_url, conf, action_factory, default_dune_plugin, utils, default_dune_plugin_fw, abstract_preloaded_regular_screen, control_factory, tv_channel_list_screen, vod/*) — другая версия SDK-копии.
    • plg-hdtv-utility-family.c007 · code · unknown; прошивка — · lib/ пакетов — копия старого SDK-фреймворка, а не фреймворка прошивки r24: lib/default_dune_plugin_fw.php отличается от sdk demo2 (2011-12-22) только удалёнными строками-разделителями комментариев, а с файлами прошивки tv188b r24 по md5 совпадают лишь archive.php, archive_cache.php и vod/movie.php.

    ↩

    • plg-gh-sndpl-apple-trailers-dune-plugin.c005 · code · unknown; прошивка — · apple_trailers.php подключает lib/default_dune_plugin_fw.php и apple_trailers_plugin.php и задаёт DefaultDunePluginFw::$plugin_class_name = 'AppleTrailersPlugin'.
    • plg-gh-sndpl-apple-trailers-dune-plugin.c015 · code · unknown; прошивка — · Манифест задаёт тип движка php и главную программу params/program = apple_trailers.php.

    ↩

  78. plg-hdtv-folder-cache-vod.c007 · code · unknown; прошивка — · В конце main-файла каждый плагин присваивает DefaultDunePluginFw::$plugin_class_name имя своего класса; это единственная регистрация плагина в пакете. ↩

  79. plg-hdtv-utility-family.c001 · code · unknown; прошивка — · main.php всех 9 пакетов одинаков (md5): подключает lib/default_dune_plugin_fw.php и plugin.php и задаёт DefaultDunePluginFw::$plugin_class_name = 'BTPlugin'. ↩

  80. plg-dc-bazinga3.c016 · code · unknown; прошивка — · Smart_plugin.php подключает все PHP-файлы lib/wox по списку SmartConfig::getWox(), который строится glob по /lib/wox/*.php. ↩

  81. plg-hdtv-altv.c031 · code · unknown; прошивка — · В lib/ лежит копия PHP-фреймворка Dune: default_dune_plugin_fw.php определяет класс DefaultDunePluginFw extends DunePluginFw. ↩

  82. plg-hdtv-moidom.c026 · code · unknown; прошивка — · lib/ — копия SDK-фреймворка: 27 из 43 файлов lib побайтно совпадают с файлами встроенных плагинов r24; 16 файлов (default_archive, media_url, conf, action_factory, default_dune_plugin, utils, default_dune_plugin_fw, abstract_preloaded_regular_screen, control_factory, tv_channel_list_screen, vod/*) — другая версия SDK-копии. ↩

  83. plg-hdtv-peerstv.c019 · code · unknown; прошивка — · lib/ — копия SDK-фреймворка: 27 из 43 файлов lib побайтно совпадают с файлами встроенных плагинов r24; остальные 16 (action_factory, conf, control_factory, default_dune_plugin, default_dune_plugin_fw, utils, abstract_preloaded_regular_screen, abstract_tv, default_channel, tv_channel_list_screen, tv_favorites_screen, vod/*) — другая версия SDK-копии (см. notes.md §2.1). ↩

  84. plg-hdtv-polsky-tv.c022 · code · unknown; прошивка — · lib/ — копия PHP-фреймворка SDK (DefaultDunePluginFw, DefaultDunePlugin, ActionFactory, ControlFactory, TV/VOD-экраны); 40 из 45 файлов lib побайтно совпадают с файлами встроенных плагинов r24 (android_apps, dunestore, radiotime, bt_setup), а action_factory.php, control_factory.php, default_dune_plugin.php, utils.php и abstract_preloaded_regular_screen.php отличаются от ближайших копий. ↩

    • plg-hdtv-utility-family.c006 · code · unknown; прошивка — · Каталог lib/ — общий фреймворк пакетов (47 файлов у LTU_install): 42 PHP-файла совпадают во всех 9 пакетах по md5; различаются только lib/action_factory.php (3 варианта), lib/control_factory.php (5) и lib/utils.php (4).
    • plg-hdtv-utility-family.c007 · code · unknown; прошивка — · lib/ пакетов — копия старого SDK-фреймворка, а не фреймворка прошивки r24: lib/default_dune_plugin_fw.php отличается от sdk demo2 (2011-12-22) только удалёнными строками-разделителями комментариев, а с файлами прошивки tv188b r24 по md5 совпадают лишь archive.php, archive_cache.php и vod/movie.php.

    ↩

  85. plg-hdtv-evolutiontv.c007 · code · unknown; прошивка — · Конструктор DemoPlugin создаёт DemoM3uTv и регистрирует экраны списка каналов, избранного и групп с layout-ами из DemoSkin, а также экран настроек. ↩

  86. plg-hdtv-kaban.c007 · code · unknown; прошивка — · Конструктор DemoPlugin подключает экраны групп, избранного, списка каналов и настроек; VOD-экранов в нём нет. ↩

  87. plg-hdtv-peerstv.c006 · code · unknown; прошивка — · Конструктор DemoPlugin создаёт DemoTv и DemoVod, регистрирует экраны групп, каналов, избранного, настроек, VOD-категорий, VOD-списка, фильма, серий и избранных фильмов. ↩

  88. plg-hdtv-pirates-radio.c001 · code · unknown; прошивка — · Оба пакета собраны из одного PHP-каркаса pirates_: 9 из 10 файлов pirates_.php и все 45 файлов lib/ совпадают байт-в-байт; diff -rq даёт только VERSION, dune_plugin.xml, pirates_config.php и файл списка станций (list_fm.xml / list_fm.txt). ↩

    • plg-hdtv-zlostnyi-iptv.c008 · code · unknown; прошивка — · У всех 12 полных пакетов одинаковая форма манифеста: две точки входа (root://tv → tv_group_list с plugin_open_folder/plugin_tv_play и setup://applications → setup), type php и check_update на zlostnyi.tech; различаются name, caption, значок, program, version/version_index и путь update-URL.
    • plg-hdtv-zlostnyi-iptv.c114 · code · unknown; прошивка — · Копия lib/ в itv совпадает с копией остальных пакетов по коду, но файлы сохранены с UTF-8 BOM и переводами строк CRLF — отсюда расхождение md5 всех файлов lib/.

    ↩

  89. plg-hdtv-rain-tv.c032 · code · unknown; прошивка — · Из 52 PHP-файлов пакетов 50 совпадают побайтно; различаются config.php (имя канала, stream_url, icon_url) и rain_tv.php (иконка группы). Кроме них отличаются dune_plugin.xml и icons/high.png; в 43Kanal есть icons/43Kanal140.png, в CTPK — icons/STRK-log.png. ↩

    • plg-hdtv-folder-cache-vod.c002 · code · unknown; прошивка — · Файлы folder.php, folder_cache.php, video_cache.php, playback_url_cache.php и compat/dune_plugin_fw.php побайтово одинаковы во всех 15 пакетах.
    • plg-hdtv-folder-cache-vod.c003 · code · unknown; прошивка — · 11 из 12 общих файлов lib/ побайтово одинаковы во всех 15 пакетах, а lib/utils.php отличается от пакета к пакету (10 вариантов).

    ↩

    • plg-hdtv-folder-cache-vod.c111 · code · unknown; прошивка — · Против mp3tales 1.4.0 у streamit 20 одноимённых файлов: 16 совпадают побайтово, изменены dune_plugin.xml, cursor.php, lib/utils.php и utils.php, а 16 PHP-файлов добавлены (streamit.php, decoder.php, streams/*.php, compat/kinokiste_decoder.php, tools/parser.php).
    • plg-hdtv-folder-cache-vod.c128 · code · unknown; прошивка — · Копия lib/utils.php в streamit отличается от mp3tales: http_get_document() отключает проверку SSL, включает CURLOPT_HEADER=1 (ответ приходит вместе с заголовками) и не задаёт таймауты; require_once 'utils.php' из файла убран.

    ↩

  90. plg-hdtv-utility-family.c002 · code · unknown; прошивка — · plugin.php объявляет BTPlugin extends DefaultDunePlugin, конструктор которого регистрирует единственный экран BTSetupScreen (с SettingManager и BTLocalization) — так в LTU_install, Codec_install, ExtendRC_install, Platform_install, SleepWake и mark.it (plugin.php одинаков по md5). ↩

    • plg-hdtv-zlostnyi-iptv.c134 · code · unknown; прошивка — · shura: манифест задаёт name ShuraTV, caption «Шура ТВ», program starnet.php, version 2.1.19, version_index 19 и update-URL http://zlostnyi.tech/dune/shura/shura_update.txt.
    • plg-hdtv-zlostnyi-iptv.c141 · code · unknown; прошивка — · shura — ветка C: starnet_plugin.php создаёт DemoTv и DemoVod, регистрирует TvChannelListScreen, Starnet_MainScreen, DemoSetupScreen() без аргумента и Demo-экраны медиатеки; M3uTv не используется.

    ↩

    • plg-dune-remote-control.c001 · code · unknown; прошивка — · Манифест задаёт имя плагина name = remote-control.
    • plg-dune-remote-control.c003 · code · unknown; прошивка — · Тип плагина в манифесте — php.
    • plg-dune-remote-control.c004 · code · unknown; прошивка — · Манифест не задаёт версию, точку входа, настройки, обновление и автозапуск: в файле только name, caption и type.

    ↩

    • plg-gh-sndpl-apple-trailers-dune-plugin.c001 · code · unknown; прошивка — · Пакет плагина — 20 текстовых файлов: dune_plugin.xml, README.md и 18 PHP-файлов в корне и lib/; бинарников, изображений и вложенных архивов нет.
    • plg-gh-sndpl-apple-trailers-dune-plugin.c002 · forum · unknown; прошивка — · README описывает плагин как браузер и просмотрщик кинотрейлеров с trailers.apple.com на медиаплеерах Dune HD.

    ↩

    • plg-hdtv-kohana-channel.c001 · code · unknown; прошивка — · В каждом из 12 пакетов dune_plugin.xml объявляет тип php и программу index.php (элементы dune_plugin/type и dune_plugin/params/program).
    • plg-hdtv-kohana-channel.c040 · code · unknown; прошивка — · index.php определяет EXT, DOCROOT, APPPATH, MODPATH, SYSPATH от каталога плагина и подключает application/bootstrap.php; кроме этого задаёт error_reporting(E_ALL | E_STRICT) и сбрасывает временные переменные $application, $modules и $system.
    • plg-hdtv-kohana-channel.c039 · code · unknown; прошивка — · Пакет plg-hdtv-1hd по MANIFEST.yaml содержит 78 записей (26 каталогов, 77 текстовых файлов скопировано, 187217 байт), из них 76 PHP-файлов на 6235 строк; logo.png (image, 15953 B) остаётся только в tree.tsv и в files/ не копируется.
    • plg-hdtv-kohana-channel.c033 · code · unknown; прошивка — · Только в plg-hdtv-firstmuzru кроме общих файлов есть version (имя архива dune_plugin_first_muz_ru_2013_08_27.zip и строка name = first_muz_ru), dune_plugin_signer_id.txt (com.dune-hd) и __version_info.xml (version/check_update).

    ↩

  91. plg-gh-kocourkuba-proiptv.c003 · code · unknown; прошивка — · В шаблоне манифеста version=0.0.0, version_index=0, release_date=2023.08.01, debug=false — заглушки; build/make_update.php при сборке подставляет version «<версия>.<номер сборки>», version_index, текущую дату release_date, а для отладочной сборки — debug=true, и пишет результат в dune_plugin/dune_plugin.xml. ↩

    • plg-gh-kocourkuba-proiptv.c016 · code · unknown; прошивка — · Пакет плагина собирается из каталога dune_plugin/: make_package.cmd берёт версию из build/version.txt (9.1), номер сборки — git rev-list --count HEAD, вызывает build/make_update.php и упаковывает dune_plugin/ в dune_plugin_proiptv.zip.
    • plg-gh-kocourkuba-proiptv.c018 · code · unknown; прошивка — · Workflow .github/workflows/release.yml на каждый тег вида N.N.N собирает пакет make_update.php и публикует dune_plugin_proiptv.<тег>.zip как GitHub Release.

    ↩

  92. plg-gh-mdpuma-dune-plugin-altiptv.c092 · code · unknown; прошивка — · build.sh переходит в dune_plugin_altiptv_5.2.8, выставляет файлам 644/каталогам 755 и создаёт dune_plugin_altiptv_latest.zip, исключая .zip и data/logo/. ↩

  93. plg-gh-vladikshkwok-lampa-dune-plugins.c048 · code · android; прошивка — · build.py собирает dune_plugin_lampa_dune_bridge.zip из семи файлов и ставит www/cgi-bin/api права 0755, остальным — 0644. ↩

  94. plg-gh-vladikshkwok-lampa-dune-plugins.c113 · code · android; прошивка — · build.py задаёт записям ZIP фиксированную дату ZipInfo (2026, 10, 10, 0, 0, 0), поэтому метки времени в архиве плагина не зависят от времени сборки. ↩

    • plg-gh-vladikshkwok-lampa-dune-plugins.c049 · code · android; прошивка — · build.py дополнительно собирает lampa-dune-kit.zip с нативным плагином, двумя JS-плагинами, README и LICENSE; комментарий модуля говорит, что локальная конфигурация и учётные данные исключаются.
    • plg-gh-vladikshkwok-lampa-dune-plugins.c012 · code · android; прошивка — · Репозиторий и пакет распространяются по лицензии GPL-2.0.

    ↩

    • plg-hdtv-remtor.c043 · code · unknown; прошивка — · Файл VERSION задаёт версию «0.0.19 beta» и дату сборки «04.05.14 8:30».
    • plg-hdtv-remtor.c104 · code · unknown; прошивка — · Извлечённый пакет содержит 123 файла в 9 каталогах, 80 текстовых файлов, 0 ELF, 0 символических ссылок и 0 вложенных архивов.

    ↩

    • plg-hdtv-rclone.c086 · code · unknown; прошивка — · Smart_file_screen.php и Smart_plugin.php этого пакета байт-в-байт совпадают с plg-hdtv-peerflixserver-upd (sha256 e1ff292e… и 1da24956…).
    • plg-hdtv-rclone.c087 · code · unknown; прошивка — · Локальный lib/ — копия того же упрощённого каркаса, что в пакете Smart_* (hdkinoteatr): 21 общий файл, 17 из них совпадают байт-в-байт, отличаются action_factory.php, control_factory.php, utils.php и vod/vod.php.
    • plg-hdtv-rclone.c094 · code · unknown; прошивка — · SmartListScreen подключает lib/vod/vod.php, хотя VOD-экранов и моделей в пакете нет; интерфейс Vod в копии объявляет try_load_movie с пятью параметрами и get_search_media_url_str($pattern, $q).

    ↩

    • plg-gh-infinitygp-dune-jellyfin-bridge.c006 · code · android; прошивка — · Манифест объявляет в queries видимость пакета com.dunehd.app.
    • plg-gh-infinitygp-dune-jellyfin-bridge.c007 · code · android; прошивка — · Элемент application задаёт allowBackup=false, правила dataExtractionRules и fullBackupContent, usesCleartextTraffic=true, supportsRtl=true, иконку, подпись и тему.
    • plg-gh-infinitygp-dune-jellyfin-bridge.c008 · code · android; прошивка — · Единственная activity BridgeActivity объявлена exported=true с launchMode=singleTop, пустым taskAffinity и excludeFromRecents=true.
    • plg-gh-infinitygp-dune-jellyfin-bridge.c057 · code · android; прошивка — · build.gradle.kts берёт путь к keystore и пароли из переменных окружения ANDROID_RELEASE_* (пароли можно передать файлом), а задача validateReleaseSigning перед packageRelease проверяет наличие всех значений и файла keystore.
    • plg-gh-infinitygp-dune-jellyfin-bridge.c058 · code · android; прошивка — · Release-workflow запускается по тегу v[0-9]*, сверяет его с versionName из задачи printVersionName, собирает подписанный APK из секретов, проверяет его apksigner verify и zipalign -c 4 и публикует APK с SHA-256.

    ↩

  95. plg-hdtv-update-bootstrap.c021 · code · unknown; прошивка — · В 37 из 43 пакетов ровно три файла — dune_plugin.xml, один PHP и один значок; у liteiptv четыре файла (два значка), ещё у edem, glanz, ilook, itv и smile — три файла и icons/Thumbs.db. ↩↩

  96. plg-dc-screenshoter.c098 · code · unknown; прошивка — · Файл Smart_entry_handler.php начинается с UTF-8 BOM (ef bb bf) перед <?php; влияние BOM на вывод не проверено. ↩

    • plg-hdtv-101-ru.c045 · code · unknown; прошивка — · В копии HD есть не используемые плагином методы get_vsetv_epg (загрузка EPG с vsetv.com и кэш в tmp_dir_path/channel__) и get_dash_platform_kind (проверка platform_kind == 8758).
    • plg-hdtv-101-ru.c046 · code · unknown; прошивка — · lib/dune_stb_api.php — модуль Dune STB API авторства Brigadir с последним обновлением 25-10-2019; radio_plugin.php подключает его, но вне самого lib/dune_stb_api.php функции модуля в пакете не вызываются.

    ↩

  97. plg-hdtv-moidom.c024 · code · unknown; прошивка — · В пакете есть newrus_setup_screen.php (352 строки) с вызовами login_newrus, но moidom_plugin.php его не подключает; в moidom_tv.php остались закомментированные обращения к login_newrus/newrus_group. Это неиспользуемый остаток другого плагина. ↩

  98. plg-hdtv-jurt.c033 · code · unknown; прошивка — · Файлы btv_tv_group_list_screen.php и btv_tv_channel_list_screen.php определяют классы BtvTvGroupListScreen/BtvTvChannelListScreen, но BtvPlugin регистрирует вместо них стандартные TvGroupListScreen/TvChannelListScreen. ↩

  99. plg-hdtv-zlostnyi-iptv.c167 · code · unknown; прошивка — · Копия lib/ в shura ближе к edem: 41 из 43 общих файлов совпадают по md5, отличаются utils.php (http_get_document с DuneHD/1.0 и 40 с) и tv/default_channel.php (560 дней EPG вместо 360); дополнительно в lib/ лежит _utils.php, побайтно совпадающий с lib/utils.php edem. ↩

  100. plg-dc-dunemdb-supplier-movies-rus.c054 · code · unknown; прошивка — · Метаданные ссылаются на icon_path = logo.png, но в пакете файла logo.png нет (в tree.tsv 12 строк файлов, logo.png среди них отсутствует). ↩

  101. plg-hdtv-plugtv.c045 · code · unknown; прошивка — · В пакетах нет иконок icons/null.png (ссылка из list.xml), icons/p_plus.png и icons/p_minus.png (ссылки из plugtv_tvg_screen.php); в tree.tsv перечислены только auto, down, high, left, logo, low, medium, return, right и up. ↩

  102. doc-sdk-plugins.c132 · doc · sigma-smp86xx, sigma-smp87xx; прошивка — · Платформенные файлы для SMP87xx (ARM) кладутся в .platform.87xx/ в корне плагина; основная копия (bin/, www/cgi-bin/) — для SMP86xx (MIPS) ↩

  103. plg-dc-dunemdb-supplier-movies-rus.c014 · code · unknown; прошивка — · В пакете две разные сборки ELF php-cgi: bin/php-cgi размером 55889 байт и .platform.87xx/bin/php-cgi размером 51724 байта. ↩

  104. plg-dc-torrent-center.c116 · code · unknown; прошивка — · tree.tsv содержит два различных ELF php-cgi: основной www/cgi-bin/php-cgi (55889 байт) и .platform.87xx/www/cgi-bin/php-cgi (51724 байта). ↩

  105. plg-dc-screenshoter.c057 · code · unknown; прошивка — · Пакет несёт собственный ELF www/cgi-bin/php-cgi (51724 байта); в его строках есть libphp5.so, /lib/ld-linux.so.3 и секции .ARM.exidx ↩

    • plg-dc-dunemdb-supplier-movies-rus.c019 · code · unknown; прошивка — · Описатель указывает bin = «<каталог bin плагина>/php-cgi -f <каталог bin>/run.php», то есть запускает собственный php-cgi из пакета, а не php-cgi прошивки.
    • plg-dc-dunemdb-supplier-movies-rus.c020 · code · unknown; прошивка — · Команда в описателе не передаёт php-cgi ключ -c, хотя php.ini лежит в том же каталоге bin/.

    ↩

    • plg-dc-widget-ext.c065 · code · sigma-smp86xx, sigma-smp87xx, android; прошивка — · Скрипт gismeteo выбирает curl по platform_kind из $FS_PREFIX/tmp/run/versions.txt: android → $FS_PREFIX/firmware/bin/curl; 87.., 864., 867., 865. → собственные bin/curl.87xx, curl.864x, curl.867x, curl.865x; при любом другом platform_kind CURL остаётся пустым
    • plg-dc-widget-ext.c067 · code · sigma-smp86xx, sigma-smp87xx; прошивка — · Вложенные бинарники curl: curl.864x и curl.867x — curl 7.19.5 (mipsel-unknown-linux-gnu), curl.87xx — curl 7.36.0 (arm-buildroot-linux-gnueabi) из sigma-buildroot_2014.05 (bdk8756)
    • plg-dc-widget-ext.c068 · code · unknown; прошивка — · bin/curl.864x плагина побайтно совпадает (sha256 917d95cf…611a, 85377 байт) с shell_ext/bin/curl встроенного плагина прошивки tv188b 260827_0003_r24

    ↩

    • plg-hdtv-rclone.c031 · code · unknown; прошивка — · В ветке handler_id=entry, если (есть /persistfs или platform_kind == android) и файла bin/rclone нет, плагин запускает действие dload_rclone с counter=0.
    • plg-hdtv-rclone.c032 · code · unknown; прошивка — · По умолчанию (platform_kind не 87xx и не android) dload_rclone выбирает каталог platform.mips для загрузки исполняемого файла rclone.
    • plg-hdtv-rclone.c033 · code · sigma-smp87xx; прошивка — · При platform_kind 87xx dload_rclone выбирает каталог platform.87xx.
    • plg-hdtv-rclone.c034 · code · android; прошивка — · При platform_kind android dload_rclone выбирает каталог platform.android.
    • plg-hdtv-rclone.c035 · code · unknown; прошивка — · Бинарник rclone скачивается по адресу http://dune-club.info/plugins/update/rclone/<платформенный каталог>/rclone.
    • plg-hdtv-rclone.c036 · code · unknown; прошивка — · При counter=0 dload_rclone проверяет Content-Length через get_headers и запускает фоновый wget в /bin/rclone с логом /WgetLog.txt.
    • plg-hdtv-rclone.c091 · code · unknown; прошивка — · HD::get_platform_kind читает /tmp/run/versions.txt и сводит platform_kind к 87xx (87\d\d), 864x, 867x, 865x или android; при несовпадении возвращает null.

    ↩

    • plg-hdtv-peerflixserver.c030 · code · unknown; прошивка — · HD::is_android возвращает true, если существует файл /system/dunehd/init; HD::get_platform_kind читает /tmp/run/versions.txt и относит platform_kind к 87xx, 864x, 867x, 865x или android.
    • plg-hdtv-peerflixserver.c031 · code · unknown; прошивка — · На Android в первом тике загрузки (counter=0) адрес архива termux_node.tar.gz выбирается по android_platform из /tmp/run/versions.txt: для rtd1295_android7 и rtd1619_android9 — realtek, для остальных — amlogic; оба адреса начинаются с http://dune-club.info/plugins/update/PeerflixServer/.
    • plg-hdtv-peerflixserver.c032 · code · unknown; прошивка — · На Android в первом тике загрузки (counter=0) выполняется get_headers(url): без Content-Length показывается «Загрузка не удалась»; иначе wget пишет архив в /termux_node.tar.gz, а диалог раз в секунду читает /WgetLog.txt, показывает процент и остаток и после 90 секунд закрывается.

    ↩

  106. plg-hdtv-rclone.c037 · code · unknown; прошивка — · После завершения загрузки на android плагин делает chmod 777 файла bin/rclone через /system/dunehd/dunehd_service do, на остальных платформах — PHP-функцией chmod(0777). ↩

  107. plg-hdtv-megatorrents.c022 · code · android; прошивка — · При HD::get_platform_kind() == android SmartConfig::bytesToHuman запускает bin/bytesToHumanAndroid (а при заданном time — bin/bytesToHumanSpeed) через exec("/system/dunehd/dunehd_service do /bin/…"). ↩

  108. plg-hdtv-liteiptv.c089 · code · unknown; прошивка — · CGI-обёртки index, link, arhive, playlists, file.php, do_img и vsetv_modal вычисляют PLUGIN_NAME и PLUGIN_INSTALL_DIR_PATH из $PWD, задают PLUGIN_TMP_DIR_PATH, PLUGIN_WWW_URL и PLUGIN_CGI_URL и выбирают PLUGIN_DATA_DIR_PATH из /persistfs/plugins_data/ или /flashdata/plugins_data/, после чего запускают ./php-cgi. ↩

  109. plg-hdtv-dlna-renderer.c015 · code · unknown; прошивка — · В пакете лежит ELF bin/gmediarender; его strings сообщают версию «gmediarender 0.0.7-git; 2016-02-04_f9be94c». ↩

  110. doc-sdk-plugins.c115 · doc · any-documented; прошивка — · Встроенные в розничную прошивку и распространяемые через Dune Store плагины подписаны Dune HD; подписанный плагин содержит dune_plugin.sign и dune_plugin_signer_id.txt ↩

  111. plg-dc-globaltv.c026 · code · unknown; прошивка — · Пакет содержит файл подписи dune_plugin.sign (бинарный, 48 байт) и dune_plugin_signer_id.txt со значением com.dune-hd. ↩

  112. plg-ds-dunemdb-supplier-generic.c013 · code · unknown; прошивка — · В пакете есть dune_plugin.sign (46 байт, sha256 e1c2a4207fdf5f756ee522a11b15c551a1da20f0a33257284082449f24c5fd4d) и dune_plugin_signer_id.txt с содержимым com.dune-hd; сам .sign в базу не копировался (извлечение только текстовых файлов), поэтому его содержимое недоступно. ↩

  113. plg-ds-dunemdb-supplier-megogo.c014 · code · android; прошивка — · В пакете есть dune_plugin.sign (47 байт, sha256 606f5a7ec786ff7239b59770eb08d8d0e4539e0af0a24006f1ef4ff8de46c64c) и dune_plugin_signer_id.txt с содержимым com.dune-hd; сам .sign в базу не копировался (извлечение только текстовых файлов), поэтому его содержимое недоступно. ↩

  114. plg-ds-dunemdb-supplier-okko.c014 · code · android; прошивка — · В пакете есть dune_plugin.sign (47 байт, sha256 e94dd19c6f576666b5aeef9c2423cf98d59b934707e24bcf059d2c9489fd609d) и dune_plugin_signer_id.txt с содержимым com.dune-hd; сам .sign в базу не копировался (извлечение только текстовых файлов), поэтому его содержимое недоступно. ↩

  115. plg-hdtv-web-launchers.c025 · code · unknown; прошивка — · В пакете amediateka есть dune_plugin.sign размером 47 байт и dune_plugin_signer_id.txt со значением com.dune-hd. ↩

  116. plg-ds-dune-hd-tv.c014 · code · unknown; прошивка — · dune_plugin_signer_id.txt содержит идентификатор подписанта com.dune-hd; в пакете есть dune_plugin.sign. ↩

  117. doc-sdk-plugins.c119 · doc · any-documented; прошивка — · Собственная подпись (150326_r10+): DSA-ключи 2048 через openssl, подпись утилитой plugin_sign.x86

    , публичный ключ кладётся в прошивку как /firmware/config/plugin_key.pem ↩

  118. doc-sdk-dune-store.c053 · doc · any-documented; прошивка — · Сторонние плагины можно добавить в кастомный каталог Dune Store; если прошивка требует только подписанные плагины, их подписывают собственным ключом подписи плагинов, а прошивку настраивают разрешать этот ключ. ↩

  119. doc-sdk-dune-store.c049 · doc · any-documented; прошивка — · Добавлять сторонние приложения в кастомный каталог Dune Store потенциально можно, но они не будут подписаны, так как сейчас подписывать могут только приложения, выпускаемые и поддерживаемые Dune HD. ↩

  120. doc-sdk-dune-custom-firmware.c005 · doc · any-documented; прошивка — · В разделе «Secure firmware» для запрета установки и запуска произвольных сторонних плагинов рекомендуется выставить external_plugins_enabled = signed в /firmware/config/ro_config.properties. ↩

    • plg-hdtv-smart-apps.c034 · code · unknown; прошивка — · install_app и uninstall_app Entware запускают bin/