switchMediaSource method

  1. @override
void switchMediaSource(
  1. ByteArkPlayerConfig config
)
override

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`).
    });