about summary refs log tree commit diff
path: root/patches
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-09-03 08:33:21 -0700
committerGitHub <noreply@github.com>2024-09-03 08:33:21 -0700
commit05e61346b8c20b242edf748d2d84a66aefa390f6 (patch)
treeb70b284013ba22f2b680057ad81ba8eeefe82e6a /patches
parent0e1de199030e4106c791978c8a6bf52a90bbc269 (diff)
downloadvoidsky-05e61346b8c20b242edf748d2d84a66aefa390f6.tar.zst
[Video] Say No to Audio (Disable `expo-video` `AudioSession` management) (#5101)
Diffstat (limited to 'patches')
-rw-r--r--patches/expo-video+1.2.4.patch146
-rw-r--r--patches/expo-video+1.2.4.patch.md3
2 files changed, 121 insertions, 28 deletions
diff --git a/patches/expo-video+1.2.4.patch b/patches/expo-video+1.2.4.patch
index 0364dd63a..f9e91a439 100644
--- a/patches/expo-video+1.2.4.patch
+++ b/patches/expo-video+1.2.4.patch
@@ -5,7 +5,7 @@ index 473f964..f37aff9 100644
 @@ -41,6 +41,11 @@ sealed class PlayerEvent {
      override val name = "playToEnd"
    }
-
+ 
 +  data class PlayerTimeRemainingChanged(val timeRemaining: Double): PlayerEvent() {
 +    override val name = "timeRemainingChange"
 +    override val arguments = arrayOf(timeRemaining)
@@ -32,10 +32,10 @@ index 9905e13..47342ff 100644
    setTimeBarInteractive(requireLinearPlayback)
 +  setShowSubtitleButton(true)
  }
-
+ 
  @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
 @@ -27,7 +28,8 @@ internal fun PlayerView.setTimeBarInteractive(interactive: Boolean) {
-
+ 
  @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
  internal fun PlayerView.setFullscreenButtonVisibility(visible: Boolean) {
 -  val fullscreenButton = findViewById<android.widget.ImageButton>(androidx.media3.ui.R.id.exo_fullscreen)
@@ -93,7 +93,7 @@ index ec3da2a..5a1397a 100644
 +        "onEnterFullscreen",
 +        "onExitFullscreen"
        )
-
+ 
        Prop("player") { view: VideoView, player: VideoPlayer ->
 diff --git a/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoPlayer.kt b/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoPlayer.kt
 index 58f00af..5ad8237 100644
@@ -101,7 +101,7 @@ index 58f00af..5ad8237 100644
 +++ b/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoPlayer.kt
 @@ -1,5 +1,6 @@
  package expo.modules.video
-
+ 
 +import ProgressTracker
  import android.content.Context
  import android.view.SurfaceView
@@ -111,18 +111,18 @@ index 58f00af..5ad8237 100644
      .setLooper(context.mainLooper)
      .build()
 +  var progressTracker: ProgressTracker? = null
-
+ 
    val serviceConnection = PlaybackServiceConnection(WeakReference(player))
-
+ 
    var playing by IgnoreSameSet(false) { new, old ->
      sendEvent(PlayerEvent.IsPlayingChanged(new, old))
 +    addOrRemoveProgressTracker()
    }
-
+ 
    var uncommittedSource: VideoSource? = source
 @@ -141,6 +144,9 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
    }
-
+ 
    override fun close() {
 +    this.progressTracker?.remove()
 +    this.progressTracker = null
@@ -133,7 +133,7 @@ index 58f00af..5ad8237 100644
 @@ -228,7 +234,7 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
      listeners.removeAll { it.get() == videoPlayerListener }
    }
-
+ 
 -  private fun sendEvent(event: PlayerEvent) {
 +  fun sendEvent(event: PlayerEvent) {
      // Emits to the native listeners
@@ -173,7 +173,7 @@ index a951d80..3932535 100644
    val onPictureInPictureStop by EventDispatcher<Unit>()
 +  val onEnterFullscreen by EventDispatcher()
 +  val onExitFullscreen by EventDispatcher()
-
+ 
    var willEnterPiP: Boolean = false
    var isInFullscreen: Boolean = false
 @@ -154,6 +156,7 @@ class VideoView(context: Context, appContext: AppContext) : ExpoView(context, ap
@@ -183,7 +183,7 @@ index a951d80..3932535 100644
 +    onEnterFullscreen(mapOf())
      isInFullscreen = true
    }
-
+ 
 @@ -162,6 +165,7 @@ class VideoView(context: Context, appContext: AppContext) : ExpoView(context, ap
      val fullScreenButton: ImageButton = playerView.findViewById(androidx.media3.ui.R.id.exo_fullscreen)
      fullScreenButton.setImageResource(androidx.media3.ui.R.drawable.exo_icon_fullscreen_enter)
@@ -191,9 +191,9 @@ index a951d80..3932535 100644
 +    this.onExitFullscreen(mapOf())
      isInFullscreen = false
    }
-
+ 
 diff --git a/node_modules/expo-video/build/VideoPlayer.types.d.ts b/node_modules/expo-video/build/VideoPlayer.types.d.ts
-index a09fcfe..65fe29a 100644
+index a09fcfe..5eac9e5 100644
 --- a/node_modules/expo-video/build/VideoPlayer.types.d.ts
 +++ b/node_modules/expo-video/build/VideoPlayer.types.d.ts
 @@ -128,6 +128,8 @@ export type VideoPlayerEvents = {
@@ -219,6 +219,96 @@ index cb9ca6d..ed8bb7e 100644
  }
  //# sourceMappingURL=VideoView.types.d.ts.map
 \ No newline at end of file
+diff --git a/node_modules/expo-video/ios/VideoManager.swift b/node_modules/expo-video/ios/VideoManager.swift
+index 094a8b0..412fd0c 100644
+--- a/node_modules/expo-video/ios/VideoManager.swift
++++ b/node_modules/expo-video/ios/VideoManager.swift
+@@ -51,45 +51,45 @@ class VideoManager {
+   // MARK: - Audio Session Management
+ 
+   internal func setAppropriateAudioSessionOrWarn() {
+-    let audioSession = AVAudioSession.sharedInstance()
+-    var audioSessionCategoryOptions: AVAudioSession.CategoryOptions = []
+-
+-    let isAnyPlayerPlaying = videoPlayers.allObjects.contains { player in
+-      player.isPlaying
+-    }
+-    let areAllPlayersMuted = videoPlayers.allObjects.allSatisfy { player in
+-      player.isMuted
+-    }
+-    let needsPiPSupport = videoViews.allObjects.contains { view in
+-      view.allowPictureInPicture
+-    }
+-    let anyPlayerShowsNotification = videoPlayers.allObjects.contains { player in
+-      player.showNowPlayingNotification
+-    }
+-    // The notification won't be shown if we allow the audio to mix with others
+-    let shouldAllowMixing = (!isAnyPlayerPlaying || areAllPlayersMuted) && !anyPlayerShowsNotification
+-    let isOutputtingAudio = !areAllPlayersMuted && isAnyPlayerPlaying
+-    let shouldUpdateToAllowMixing = !audioSession.categoryOptions.contains(.mixWithOthers) && shouldAllowMixing
+-
+-    if shouldAllowMixing {
+-      audioSessionCategoryOptions.insert(.mixWithOthers)
+-    }
+-
+-    if isOutputtingAudio || needsPiPSupport || shouldUpdateToAllowMixing || anyPlayerShowsNotification {
+-      do {
+-        try audioSession.setCategory(.playback, mode: .moviePlayback)
+-      } catch {
+-        log.warn("Failed to set audio session category. This might cause issues with audio playback and Picture in Picture. \(error.localizedDescription)")
+-      }
+-    }
+-
+-    // Make sure audio session is active if any video is playing
+-    if isAnyPlayerPlaying {
+-      do {
+-        try audioSession.setActive(true)
+-      } catch {
+-        log.warn("Failed to activate the audio session. This might cause issues with audio playback. \(error.localizedDescription)")
+-      }
+-    }
++//    let audioSession = AVAudioSession.sharedInstance()
++//    var audioSessionCategoryOptions: AVAudioSession.CategoryOptions = []
++//
++//    let isAnyPlayerPlaying = videoPlayers.allObjects.contains { player in
++//      player.isPlaying
++//    }
++//    let areAllPlayersMuted = videoPlayers.allObjects.allSatisfy { player in
++//      player.isMuted
++//    }
++//    let needsPiPSupport = videoViews.allObjects.contains { view in
++//      view.allowPictureInPicture
++//    }
++//    let anyPlayerShowsNotification = videoPlayers.allObjects.contains { player in
++//      player.showNowPlayingNotification
++//    }
++//    // The notification won't be shown if we allow the audio to mix with others
++//    let shouldAllowMixing = (!isAnyPlayerPlaying || areAllPlayersMuted) && !anyPlayerShowsNotification
++//    let isOutputtingAudio = !areAllPlayersMuted && isAnyPlayerPlaying
++//    let shouldUpdateToAllowMixing = !audioSession.categoryOptions.contains(.mixWithOthers) && shouldAllowMixing
++//
++//    if shouldAllowMixing {
++//      audioSessionCategoryOptions.insert(.mixWithOthers)
++//    }
++//
++//    if isOutputtingAudio || needsPiPSupport || shouldUpdateToAllowMixing || anyPlayerShowsNotification {
++//      do {
++//        try audioSession.setCategory(.playback, mode: .moviePlayback)
++//      } catch {
++//        log.warn("Failed to set audio session category. This might cause issues with audio playback and Picture in Picture. \(error.localizedDescription)")
++//      }
++//    }
++//
++//    // Make sure audio session is active if any video is playing
++//    if isAnyPlayerPlaying {
++//      do {
++//        try audioSession.setActive(true)
++//      } catch {
++//        log.warn("Failed to activate the audio session. This might cause issues with audio playback. \(error.localizedDescription)")
++//      }
++//    }
+   }
+ }
 diff --git a/node_modules/expo-video/ios/VideoModule.swift b/node_modules/expo-video/ios/VideoModule.swift
 index c537a12..e4a918f 100644
 --- a/node_modules/expo-video/ios/VideoModule.swift
@@ -232,16 +322,16 @@ index c537a12..e4a918f 100644
 +        "onEnterFullscreen",
 +        "onExitFullscreen"
        )
-
+ 
        Prop("player") { (view, player: VideoPlayer?) in
 diff --git a/node_modules/expo-video/ios/VideoPlayer.swift b/node_modules/expo-video/ios/VideoPlayer.swift
-index 3315b88..f482390 100644
+index 3315b88..733ab1f 100644
 --- a/node_modules/expo-video/ios/VideoPlayer.swift
 +++ b/node_modules/expo-video/ios/VideoPlayer.swift
 @@ -185,6 +185,10 @@ internal final class VideoPlayer: SharedRef<AVPlayer>, Hashable, VideoPlayerObse
      safeEmit(event: "sourceChange", arguments: newVideoPlayerItem?.videoSource, oldVideoPlayerItem?.videoSource)
    }
-
+ 
 +  func onPlayerTimeRemainingChanged(player: AVPlayer, timeRemaining: Double) {
 +    safeEmit(event: "timeRemainingChange", arguments: timeRemaining)
 +  }
@@ -250,7 +340,7 @@ index 3315b88..f482390 100644
      if self.appContext != nil {
        self.emit(event: event, arguments: repeat each arguments)
 diff --git a/node_modules/expo-video/ios/VideoPlayerObserver.swift b/node_modules/expo-video/ios/VideoPlayerObserver.swift
-index d289e26..de9a26f 100644
+index d289e26..ea4d96f 100644
 --- a/node_modules/expo-video/ios/VideoPlayerObserver.swift
 +++ b/node_modules/expo-video/ios/VideoPlayerObserver.swift
 @@ -21,6 +21,7 @@ protocol VideoPlayerObserverDelegate: AnyObject {
@@ -259,7 +349,7 @@ index d289e26..de9a26f 100644
    func onPlayerItemStatusChanged(player: AVPlayer, oldStatus: AVPlayerItem.Status?, newStatus: AVPlayerItem.Status)
 +  func onPlayerTimeRemainingChanged(player: AVPlayer, timeRemaining: Double)
  }
-
+ 
  // Default implementations for the delegate
 @@ -33,6 +34,7 @@ extension VideoPlayerObserverDelegate {
    func onItemChanged(player: AVPlayer, oldVideoPlayerItem: VideoPlayerItem?, newVideoPlayerItem: VideoPlayerItem?) {}
@@ -267,14 +357,14 @@ index d289e26..de9a26f 100644
    func onPlayerItemStatusChanged(player: AVPlayer, oldStatus: AVPlayerItem.Status?, newStatus: AVPlayerItem.Status) {}
 +  func onPlayerTimeRemainingChanged(player: AVPlayer, timeRemaining: Double) {}
  }
-
+ 
  // Wrapper used to store WeakReferences to the observer delegate
 @@ -91,6 +93,7 @@ class VideoPlayerObserver {
    private var playerVolumeObserver: NSKeyValueObservation?
    private var playerCurrentItemObserver: NSKeyValueObservation?
    private var playerIsMutedObserver: NSKeyValueObservation?
 +  private var playerPeriodicTimeObserver: Any?
-
+ 
    // Current player item observers
    private var playbackBufferEmptyObserver: NSKeyValueObservation?
 @@ -152,6 +155,9 @@ class VideoPlayerObserver {
@@ -285,16 +375,16 @@ index d289e26..de9a26f 100644
 +      player?.removeTimeObserver(playerPeriodicTimeObserver)
 +    }
    }
-
+ 
    private func initializeCurrentPlayerItemObservers(player: AVPlayer, playerItem: AVPlayerItem) {
 @@ -270,6 +276,7 @@ class VideoPlayerObserver {
-
+ 
      if isPlaying != (player.timeControlStatus == .playing) {
        isPlaying = player.timeControlStatus == .playing
 +      addPeriodicTimeObserverIfNeeded()
      }
    }
-
+ 
 @@ -310,4 +317,28 @@ class VideoPlayerObserver {
        }
      }
@@ -329,12 +419,12 @@ index f4579e4..10c5908 100644
 --- a/node_modules/expo-video/ios/VideoView.swift
 +++ b/node_modules/expo-video/ios/VideoView.swift
 @@ -41,6 +41,8 @@ public final class VideoView: ExpoView, AVPlayerViewControllerDelegate {
-
+ 
    let onPictureInPictureStart = EventDispatcher()
    let onPictureInPictureStop = EventDispatcher()
 +  let onEnterFullscreen = EventDispatcher()
 +  let onExitFullscreen = EventDispatcher()
-
+ 
    public override var bounds: CGRect {
      didSet {
 @@ -163,6 +165,7 @@ public final class VideoView: ExpoView, AVPlayerViewControllerDelegate {
@@ -344,7 +434,7 @@ index f4579e4..10c5908 100644
 +    onEnterFullscreen()
      isFullscreen = true
    }
-
+ 
 @@ -179,6 +182,7 @@ public final class VideoView: ExpoView, AVPlayerViewControllerDelegate {
          if wasPlaying {
            self.player?.pointer.play()
@@ -364,7 +454,7 @@ index aaf4b63..f438196 100644
 +
 +  timeRemainingChange(timeRemaining: number): void;
  };
-
+ 
  /**
 diff --git a/node_modules/expo-video/src/VideoView.types.ts b/node_modules/expo-video/src/VideoView.types.ts
 index 29fe5db..e1fbf59 100644
diff --git a/patches/expo-video+1.2.4.patch.md b/patches/expo-video+1.2.4.patch.md
index 689cf9a92..6dd85308b 100644
--- a/patches/expo-video+1.2.4.patch.md
+++ b/patches/expo-video+1.2.4.patch.md
@@ -4,3 +4,6 @@
 
 This patch adds two props to `VideoView`: `onEnterFullscreen` and `onExitFullscreen` which do exactly what they say on
 the tin.
+
+This patch also removes the audio session management that Expo does on its own, as we handle audio session management
+ourselves.