Releases: empyfi/FBC-ChannelSpeedChange
v0.5.3 - NEAR detection + anchor alignment
Measurement-correctness release on top of v0.5.2. Two items
from the 2026-06-23 field-test (own and FCC-Extender 0.2 author Oberhesses CSV + log shared
via forum). No new feature surface, no config keys added, no
C-binding additions.
Added
NEARresult label for the intra-TP channel-share case.
When a bypass zap targets a service whose transponder is
already locked by a sibling pool slot (different service id
on the same MUX),pool.lookupcorrectly misses at the
service level buteDVBResourceManagerchannel-shares at
the transponder level - the demod is already there, so the
zap lands in the ~100-300 ms PMT-switch regime instead of
the ~700-900 ms cold-tune regime. Previously these zaps were
labelledEXTand dragged the EXT-bucket median artificially
low; they now report asNEARwith their own OSD bucket-
colour (teal#80ffc0). Wrapper-MISS paths get the same
upgrade when a TP-share is available. Addspool.tp_match(ref)
as the transponder-level partner of the existingpool.lookup
and a_tp_keyhelper alongside the existing_keyin
predictor.py.
Changed
- Wrapper-path zap timing now anchors on
evStart(same as
the bypass path) instead of at the top of the wrapper
closure. The wrapper sets_zap_attr/_zap_hitup front
so the metadata is known by the timeplayServicedispatches
evStart; the timing anchor itself is set by
_on_nav_event(evStart)for every path. Net effect:
zapUp/zapDown HITandext HITmeasurements now cover
the sameevStart -> evTunedInspan, eliminating the ~50 ms
measurement gap where wrapper-HIT looked artificially slower
than bypass-HIT in v0.5.2.
Field-test grounding
Oberhesses CSV from v0.5.2 contained two ext EXT rows at 154
and 153 ms - way too fast for cross-transponder cold tunes
(~700-900 ms hardware-bound). The corresponding LOOKUP
blocks in his log showed that a sibling slot was armed on the
same transponder as the target service (ZDF on 3F3 for the
ZDF Neo zap, ZDF Neo on 3F3 for the ZDF zap). pool.lookup
correctly missed at the service level but eDVBResourceManager
channel-shared at the transponder. v0.5.3 labels these as
NEAR; removing them from the EXT bucket makes Oberhesses
field-test factor (was 2x) line up with the on-hardware factor
(~5x), and removing the wrapper pre-work measurement gap makes
his wrapper-HIT vs bypass-HIT comparison directly meaningful.
Test suite: 144 -> 156 (12 new cases: pool.tp_match positive
and negative, NEAR classification on evStart, HIT priority
over NEAR, wrapper-MISS NEAR upgrade).
v0.5.2 - OSD honesty + code polish
Polish release on top of v0.5.1. Four code-polish items from the
v0.4.1 audit / v0.5.0 rc1 smoke test plus one OSD-honesty bug fix.
No new feature surface, no config keys added, no C-binding additions.
Fixed
- OSD overlay and timing CSV now label pool-delivered external
zaps honestly. Previously every bypass zap (history selector /
Last-Channel button, EPG OK, NumberZap OK, FCC-Extender-driven
api zap) was tagged as a neutral cyanEXTregardless of whether
the pool's channel-share path had actually delivered the speedup.
OnevStartthe interceptor now probes the pool for the live
ref and, on a match, classifies the zap asHIT- so the overlay
bucket-colours the same 50-60 ms recall green instead of cyan,
andzap_stats.pyaggregates the(ext, HIT)combo as a genuine
hit. Bypass zaps without a pool match still surface asEXTso
the two cases can be told apart.
Changed
controller startedlog line reports the three
prewarm_descrambler_*flags alongside the threepretune_*
flags. On a fresh boot the descrambler-prewarm state is visible
in/tmp/fbc_csc.logwithout grepping/etc/enigma2/settings.- Single canonical implementation of the serviceref-key normaliser:
fbc_pretune_poolimports_keyfrompredictorinstead of
carrying its own duplicate. A future change to the normalisation
rule can no longer drift between modules. _release_slotrestructured so each cleanup stage (reclaim
timer, recordable stop, file unlink, slot state reset) runs in
its own try/except. A fault in any one stage no longer skips the
others. In particular, the throwaway pre-tune file is now
unlinked unconditionally; previously a leaked.tscould hold
tmpfs RAM until reboot./tmp/fbc_csc_timing.csvis now size-capped at 256 KB with three
rotated backups (.csv.1/.csv.2/.csv.3), mirroring the
existinglogger.pyrotation. Each rotated segment carries the
canonical CSV header so off-box analysis tooling does not have
to special-case post-rotation segments.
Added
- Startup sweep at
FBCPreTunePoolinit removes leftover
/tmp/fbc_csc_pretune_*.ts*files from a prior controller that
died (e.g.init 4SIGKILL'd the Python process) before
completing_release_slot. The pool is singleton with exclusive
ownership of this filename pattern, so any matching file at init
time is unreachable garbage by definition.
Field-test result
Verified on the GigaBlue UHD Quad 4K Pro running parallel to
FCC-Extender 0.2: of 32 bypass zaps (history recall, EPG OK,
NumberZap OK), 28 now classify as HIT with median 94 ms; the
remaining 4 stay EXT with median 920 ms - exactly the cold-tune
profile. Before v0.5.2 all 32 reported undifferentiated as EXT.
Test suite: 130 -> 144 (new pool/CSV/interceptor cases).
v0.5.1 — Native FCC-Extender shortcut
v0.5.1 — Native yellow-button shortcut to FCC-Extender
Polish release on top of v0.5.0. The companion-plugin integration is now bidirectional and natively owned on each side.
Added
- Yellow-button shortcut from the Settings screen straight into the FCC-Extender's own settings screen. The button appears only when the companion plugin is detected (same opkg-status check that powers the existing "FCC-Extender: installed (v...)" presence indicator); on every other box it stays out of the action map entirely so any host-skin yellow binding is untouched.
- This is the native replacement for the runtime monkey-patch that the FCC-Extender plugin used to inject into
FBCChannelSpeedChangeSetup.__init__in earlier releases. Each plugin now owns its own settings surface; the FCC-Extender's matching v0.2 release drops its monkey-patch in the same cycle.
Changed
_classify_fccextender_contentis now a thin wrapper around a new low-level_parse_fccextender_statushelper that returns a(state, version)tuple. The boolean detector used by the new button gate and the existing label formatter share one parser. No behaviour change to the presence-indicator label.
Tests
- 6 new cases pin the parser and the boolean detector contracts (
FccExtenderParserTests+FccExtenderInstalledDetectorTests). All existing label tests stay green. 130 / 130 total.
Notes
- No new C-binding surface, no new
recordServiceorprepare()call shapes. Pure UI / presence-detection work. - Field-verified 2026-06-22 against the FCC-Extender rc2 (v0.2) on the GigaBlue UHD Quad 4K Pro: yellow button appears, opens the FCC-Extender settings, both plugins coexist without crashes.
- On boxes without the FCC-Extender installed the new code path is dormant - no UI change, no startup cost.
Full v0.5.0 release notes (which introduce the underlying public api, EXTERNAL slot, TTL safety net and presence indicator): https://github.com/empyfi/FBC-ChannelSpeedChange/releases/tag/v0.5.0.
v0.5.0 — Public API for companion plugins (FCC-Extender integration)
v0.5.0 — FCC-Extender Integration
Public Python API at Plugins.Extensions.FBCChannelSpeedChange.api for companion plugins (FCC-Extender etc.) that want to feed a service reference into the pre-tune pool.
Highlights
- Two entry points, both returning
None:PreTuneSingleChannel(service_ref)— arm or refresh the EXTERNAL pool slotReleaseSingleChannel(service_ref=None)— release the slot (race-safe with optional ref)
- Accepts either an
eServiceReferenceinstance or a canonical DVB broadcast serviceref string ("1:0:<stype>:<sid>:<tsid>:<onid>:<ns>:..."). String input is shape-whitelisted before any SWIG construction. - New
Role.EXTERNALpool slot — capacity 1, never competes with the internal NEXT / PREV / HISTORY predictor. - TTL safety net (
cfg.external_slot_ttl_min, default 5 min) catches the case where the companion plugin's explicit release never lands. evNewProgramInfolistener releases the EXTERNAL slot when the live service changes to the armed ref (covers shortcut-zap paths).- Defense-in-depth: input validation, watchdog isolation (external-caller failures do NOT count toward 3-failure self-disable), rate limiter (100 ms same-ref debounce + 10 distinct refs / sec cap), always-on traceback on exception.
- Forensic diagnostics: caller-frame in
debug_logmode, 60-second stats heartbeat.
Settings UI
- New
External pretune (FCC-Extender)group with three toggles:accept_external_pretune(default True — paired companion plugin just works)external_slot_ttl_min(default 5, limits 1..30)prewarm_descrambler_external(default False, Pay-TV opt-in)
FCC-Extender presence indicatorinjected at Setup-screen open time — reads/var/lib/opkg/status, displaysinstalled (v...)/not detected/status unknown.
Notes
- No new C-binding surface — the EXTERNAL slot reuses the existing
recordService → prepare(9-arg) → start()path proven in v0.4.0 onwards. - Public API designed for and verified against Oberhesse's FCC-Extender (rc1 field-tested 2026-06-21 on the GigaBlue UHD Quad 4K Pro test bench, 60-66 ms median HIT latency vs ~900 ms cold cross-transponder).
- On VU+ boxes the OpenATV FCC system plugin remains the native fast-zap path. The FCC-Extender routes to FCC there.
Full public API reference: docs/api.md.
v0.4.4 - version visible in plugin browser
The Plugin Browser entry now prefixes its description with the version string [v0.4.4] so the OpenATV feed maintainer and forum users can identify the installed build at a glance without opening the Settings UI.
Added
__version__constant exposed by the plugin package (Plugins.Extensions.FBCChannelSpeedChange.__version__) as the single runtime source of truth for the version string.tools/bump_release_urls.py --checkenforces thatCONTROL/control,Makefileand__init__.pyall agree before a release goes out, so the three version sources cannot drift.
Notes
- Pure presentation-layer change. Controller, pool, predictor, arbiter, interceptor and config behaviour are untouched.
- Tests 56/56 green.
See the CHANGELOG for full release history.
v0.4.3 - fix green-button save on settings screen
Summary
Bug-fix release. The settings screen introduced in v0.4.2 looked
correct on every skin but had a broken Save path: pressing the
green button did not close the screen, and the live controller
was not notified of the change. The values themselves were still
written to /etc/enigma2/settings (so a subsequent enigma2
restart picked them up), but from the user's point of view the
green button appeared to do nothing.
v0.4.3 fixes the override that swallowed the close path. No
other changes; layout, descriptions, group headers, and the 13
underlying toggles are identical to v0.4.2.
What was wrong
Components.ConfigList.ConfigListScreen.saveAll() returns an
empty tuple () on a normal successful save (and a
(QUIT_RESTART, ...) / (QUIT_REBOOT, ...) tuple when a
restart-marked item changed), not a boolean. The v0.4.2
keySave override read it as if not self.saveAll(): return,
short-circuited on the empty tuple, and never reached the close
path or the controller.on_config_changed() hook.
The fix runs the controller hook first and delegates the save +
close + restart-prompt logic to the parent Setup.keySave().
That picks up the standard restart confirmation flow for free,
even though no current setup.xml row needs it.
Install
wget https://github.com/empyfi/FBC-ChannelSpeedChange/releases/download/v0.4.3/enigma2-plugin-extensions-fbc-channelspeedchange_0.4.3_all.ipk -O /tmp/fbc-csc.ipk
opkg install --force-reinstall /tmp/fbc-csc.ipk
init 4 && init 3
Changelog
See CHANGELOG.md.
v0.4.2 - settings screen layout polish
Summary
Pure presentation-layer rebuild of the plugin's settings screen.
The previous version pinned an inline 600x400 skin block onto the
plugin browser entry; on FHD and 4K image skins (Metrix HD,
Gradient FHD, ...) that produced a tiny floating window with
truncated labels and skin-incompatible button graphics.
The new setup screen inherits whatever Setup skin the active image
provides: title bar, scrollable config list on the left, blue
description panel on the right, button row at the bottom. Layout-
correct from default skin up to 4K skin builds. Each toggle now
has an in-screen help text that surfaces in the right-hand panel.
No behaviour changes. config.py is unchanged, the 13
ConfigYesNo toggles persist identically to v0.4.1.
What you see
- Three-line plugin intro at the top of the settings list.
- Five visual group headers (Plugin / Resource release / Zap
acceleration / Pay-TV / Diagnostics) rendered via the official
Setup separator pattern (<item text="..."></item>with no
inner config binding). - Per-toggle description in the right-hand panel for every entry.
- DE labels of the three Pay-TV descrambler toggles renamed from
"Descrambler beim ... aktivieren" to "Entschluesselung
aktivieren beim ..." for better end-user vocabulary.
Install
wget https://github.com/empyfi/FBC-ChannelSpeedChange/releases/download/v0.4.2/enigma2-plugin-extensions-fbc-channelspeedchange_0.4.2_all.ipk -O /tmp/fbc-csc.ipk
opkg install --force-reinstall /tmp/fbc-csc.ipk
init 4 && init 3
Changelog
See CHANGELOG.md.
v0.4.1 — pool: collapse HISTORY when target converges with NEXT or PREV
What's changed
During linear bouquet walking the just-departed channel ends up on
both the HISTORY slot and the opposite-direction neighbour slot
(PREV when walking Channel ↑, NEXT when walking Channel ↓). The pool
would then hold two recordables on the same service — the dvbapi
side sees two demuxer subscriptions, which on softcam / cardsharing
setups with descrambler-prewarm enabled means a redundant continuous
ECM stream above the live one.
The controller now detects this collision at arm time and drops
HISTORY when its target matches NEXT or PREV. A recall after a
skipped HISTORY still HITs because the pool's lookup walks all
armed slots and returns the first key-matching one — PREV / NEXT
answers the recall via channel-sharing.
Measured impact
On the test bench (GigaBlue UHD Quad 4K Pro, HD+ Nagra Aladin via
OSCam, all three prewarm_descrambler_* toggles on):
| Metric | Without skip | With skip | Δ |
|---|---|---|---|
| Card ECM rate | 20.3/min | 18.8/min | −7 % |
| ECM round-trip p95 | 923 ms | 722 ms | −22 % |
| Card-stress events (RTT > 500 ms) | 44.7 % | 32.6 % | −27 % |
| Walk HIT rate | 100 % | 100 % | unchanged |
| Recall HIT rate | 100 % | 100 % | unchanged |
Median RTT stays at the hardware-bound ~376 ms; the gain is
concentrated in the tail.
Who benefits
Specifically cardsharing setups and single-decode CAMs with one or
more Activate descrambler in … pay-TV pre-tune toggles enabled —
where the redundant ECM stream was real card load. For everyone
else the optimisation is silent (no descrambler engaged on the
pre-tune means nothing on the wire to save).
Install
Drop the IPK on the receiver and:
opkg install --force-reinstall enigma2-plugin-extensions-fbc-channelspeedchange_0.4.1_all.ipkRestart enigma2 to pick up the controller change. Existing settings
are preserved.
Full change log in CHANGELOG.md.
v0.4.0 — pay-TV-safe pre-tune by default
What changed
Pre-tune of scrambled channels no longer engages the CA descrambler by default. The pool now uses the canonical 9-arg iRecordableService.prepare() (signature verified against openatv/enigma2 7.6) and passes descramble=False, so the FBC tuner locks the transponder without adding ECM / decoder load to the user's softcam, OSCam dvbapi, cardsharing or CI+ CAM path. Safe for cardsharing accounts (no anti-share ECM heat), single-decode CAMs (no contention with live), CI+ modules.
User-visible effect: scrambled HIT zaps show a brief black frame (~400 ms, the descrambler's first ECM round-trip) between tuner lock and clear picture. Free-to-air channels are unaffected.
New per-direction opt-in toggles
Three separate settings restore the v0.3.7-style behaviour where the descrambler engages during pre-tune, one toggle per pre-tune slot. UI labels:
- Activate descrambler in NEXT pay-TV pre-tune — engages the descrambler on the NEXT slot (bouquet position immediately below live). HITs a Channel ↓ press.
- Activate descrambler in PREVIOUS pay-TV pre-tune — engages the descrambler on the PREVIOUS slot (bouquet position immediately above live). HITs a Channel ↑ press.
- Activate descrambler in LAST pay-TV pre-tune (history) — engages the descrambler on the HISTORY slot (most recent non-live channel). HITs the last-channel button and the top entry of the history selector.
All three default off. The three slots are mechanically symmetric: all three re-arm on every successful zap, and each enabled toggle holds exactly one continuous descrambler session above the live consumer regardless of zap activity. Per-zap ECM bursts and parallel-decode count are identical across the three directions; card / softcam load scales with how many toggles are on, not with which one. Pick the direction that matches the user's primary zap action.
For cardsharing setups whose anti-share heuristic looks at long-window service diversity (rather than raw ECM rate), HISTORY's target set stays small for recall-heavy viewing while NEXT/PREV move with the live channel through the bouquet.
Provider coverage
All empirical numbers in these notes (ECM rates, ~400 ms black-frame, three-parallel-decode capacity) come from a single test bench: HD+ Nagravision (CAID 1843) on OSCam-smod through the GigaBlue UHD Quad 4K Pro's internal smartcard reader. The descramble=False mechanic itself sits above the CA layer and is provider-agnostic — Sky DE / UK / IT (Videoguard, NagraMA), ORF (Cryptoworks, Irdeto), M7 Group, Vodafone GigaTV, freenet TV / Diveo via CI+ CAM should all see the same architecture-level behaviour. The specific numbers will vary: black-frame duration is typically 200–700 ms depending on CA system and pairing, and consumer cards / CAMs often handle only one or two parallel decode sessions reliably. NCam, CCcam, mgcamd and mainline OSCam may also handle the enigma2-restart dvbapi-desync below differently.
Other improvements
ZAP_TIMINGlog line and/tmp/fbc_csc_timing.csvcarry the target service reference, so off-box analysis can classify FTA vs scrambled per zap.- CSV header migrate-on-first-write: a pre-0.4.0 timing CSV is rewritten in place on first launch so column counts stay consistent across the whole file. Idempotent.
- New "Descrambler behaviour and pay-TV channels" section in
docs/architecture.md.
Install
ssh root@<your-box>
wget https://github.com/empyfi/FBC-ChannelSpeedChange/releases/download/v0.4.0/enigma2-plugin-extensions-fbc-channelspeedchange_0.4.0_all.ipk -O /tmp/fbc.ipk
opkg install /tmp/fbc.ipk
init 4 && sleep 2 && init 3After enigma2 comes back, if pay-TV channels are black, restart the softcam manager once (/etc/init.d/softcam stop && /etc/init.d/softcam start) — see README "Operational note" for details.
Full release notes: CHANGELOG.md
v0.3.7 — startup sanity check + log rotation
Added
- Startup sanity check across the interceptor, pool and arbiter. Before wrapping anything the plugin verifies the critical enigma2 surface it depends on (
InfoBar.zapUp/zapDown/servicelist,NavigationInstance.recordService/playService). A missing critical interface makes the plugin refuse to start with a clear log line + one-shot popup instead of failing piecemeal at the first zap. Missing optional interfaces (historyBack/historyNext,servicelist.setCurrentSelection,RecordTimer.on_state_change) log a degraded-mode warning and the plugin keeps running.
Changed
- Log rotation in
logger.py: whenfbc_csc.logpasses 256 KB it shifts to.1/.2/.3(oldest dropped) instead of being wiped, so the minutes leading up to a recent crash survive for post-mortems.
Fixed
- The IPK no longer ships
__pycache__/*.pyc. Both build paths prune host-built bytecode before packaging; enigma2 compiles its own on first import. The package is noticeably smaller.
Off-box test suite grew 29 → 42. Verified on the GigaBlue UHD Quad 4K Pro: installs cleanly, sanity passes, controller and interceptor start, no tracebacks.