switchMediaSource method
Switches the current media source to the one described by config.
Implementation
@override
void switchMediaSource(ByteArkPlayerConfig config) =>
_withPlayer('switchMediaSource', (p) {
// Refresh state captured from the originating config.
_seekTime = config.seekTime ?? 30;
final item = config.playerItem;
final sources = item?.sources ?? const [];
if (sources.isEmpty) {
throw StateError(
'switchMediaSource requires '
'ByteArkPlayerConfig.playerItem.sources to be non-empty.',
);
}
// Pass the full multi-source array via WebSourcesMapper so the
// SDK can auto-select per browser on switch (Widevine in
// Chromium / Edge / Android browsers, FairPlay in Safari).
//
// Known limitation: `plugins.bytearkShaka` is register-once at
// construction time (see _buildSdkOptions in the view factory).
// If the originating Player was mounted with non-DRM sources and
// the host now switches to DRM sources, Shaka is absent and DRM
// decryption silently fails. Warn the host so the failure isn't
// invisible — the workaround is to mount with a DRM-capable
// config (any DRM source in the initial sources list enables
// Shaka), or accept the limitation and only switch within the
// same DRM regime.
if (WebSourcesMapper.requiresShakaPlugin(sources) &&
!_shakaEnabledAtMount) {
debugPrint(
'ByteArkPlayer[$playerId]: switchMediaSource introduced DRM '
'sources, but the JS player was constructed without the '
'`bytearkShaka` plugin. DRM decryption will likely fail. '
'Mount with a DRM-capable initial config to enable Shaka at '
'construction time.',
);
}
// `src()` is overloaded by JS argument arity (no-arg getter,
// with-arg setter), so the call goes through `callMethod` to keep
// the typed extension-type binding unambiguous — same pattern as
// currentTime / playbackRate in MOB-134.
//
// Pass `item` so Item-level metadata (title / subtitle / videoId /
// poster) reaches every emitted JS source on the switch — mirrors
// the fan-out wired into `_buildSdkOptions` for the initial mount.
// See MOB-167.
final jsSources =
WebSourcesMapper.toJsSources(sources, item: item).jsify();
p.callMethod<JSAny?>('src'.toJS, jsSources);
// The SDK fires `loadstart` + `loadedmetadata` after src() — the
// event subscription wired in MOB-132 translates those to
// `playerLoadingMetadata` / `playerReady` Listener callbacks
// without any additional wiring here. Same for `playlistitem`
// when the new source belongs to a playlist (MOB-132 already
// covers it via `playbackPlaylistItemChanged`).
});