From d8648b552dadfa40c619c243ed18343904142004 Mon Sep 17 00:00:00 2001
From: Maxime Chapelet <umxprime@videolabs.io>
Date: Wed, 8 Jan 2025 22:05:22 +0100
Subject: [PATCH] Observe Picture in Picture state changes and update UI
 control accordingly

---
 .../NewPlayer/pip.exit.imageset/Contents.json |  23 ++++++++++++++++++
 .../pip.exit.imageset/pip.exit.24x24.png      | Bin 0 -> 467 bytes
 .../pip.exit.imageset/pip.exit.24x24@2x.png   | Bin 0 -> 847 bytes
 .../pip.exit.imageset/pip.exit.24x24@3x.png   | Bin 0 -> 1182 bytes
 Sources/Playback/Control/VLCPlaybackService.h |   2 ++
 Sources/Playback/Control/VLCPlaybackService.m |  11 ++++++++-
 .../Player/PlayerViewController.swift         |   4 +++
 .../Subviews/MediaNavigationBar.swift         |   5 ++++
 8 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100644 Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/Contents.json
 create mode 100644 Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/pip.exit.24x24.png
 create mode 100644 Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/pip.exit.24x24@2x.png
 create mode 100644 Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/pip.exit.24x24@3x.png

diff --git a/Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/Contents.json b/Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/Contents.json
new file mode 100644
index 000000000..3fa4daf20
--- /dev/null
+++ b/Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "pip.exit.24x24.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "pip.exit.24x24@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "pip.exit.24x24@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/pip.exit.24x24.png b/Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/pip.exit.24x24.png
new file mode 100644
index 0000000000000000000000000000000000000000..ec1a859567ebb61d1a8e16d889c3dbcab9612113
GIT binary patch
literal 467
zcmV;^0WAKBP)<h;3K|Lk000e1NJLTq000;O000;W1^@s6;CDUv00009a7bBm000id
z000id0mpBsWB>pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10bof)
zK~zYIwbr|8R8bhk@!uJzP{b>mU|}O@E5X7lh+63@L{QKtu&}byQn0erLP?_tK0rWy
z35_I(LJ&tmNJ?*67ITDn$joeZoCO;`SRdbiv-dieCW&dPH`VFrx9bMZ<8Z}{?|6&*
z7<A1h$z9yWCN?Snd$1eJIE|nGxJlk686=rWqGIhzvY4Ufx_%F{c!RIFikrBMlgjSs
zH(s^%v98%i(;g38$NU!m8Xgxw{zkFs8r>bPY^k5)Nx|^38U^@>i<tZ0fY-Q(Q&_^{
zP63jvCt2Di9la#S+xkF~he<xAOoKLANBU#fn^<e>JB9%$)hrh9tMpYdKe=UFoht<#
ztOOkD;fLYlJ{9$`inF+d4<q{a)&iO&7w`i6Yln={M$>+9j^YgVjc9y;nVkS8={-(V
z0M<)W^rd1rd@cn%tpq$PJ)#CzaLMq#Cg~eq;!!D}T2ue4_yf@4;}zm)Ibr|+002ov
JPDHLkV1ma^&29hy

literal 0
HcmV?d00001

diff --git a/Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/pip.exit.24x24@2x.png b/Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/pip.exit.24x24@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..cec3107133bb3a1fab07991e22c54398d0f18221
GIT binary patch
literal 847
zcmV-V1F-ywP)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm00009a7bBm0013_
z0013_0gvVJWdHyG8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10^CVN
zK~!jg?U}u66hRoqf4k&M)QG2|5{PIK3lYRpt>Onl3LC*B2tmb4TZ>?4{sEgbieO=r
z_=N~oDu_YRAXq4p1k|8nXA+WVVm=;=xy8wm?9ScJ-FlKA49x8Ay!Sk_AM@T!Ac<-w
z%vwNNRt;oLO+mW}I0S418Y-w`68H!V08>Tvl!T<5q&`Ut%9aU9-I4+sU5N!rb&_6X
zp*Dsqax@S~>H=;S+?ZM5n~!J1fm+O?Yrl`Pz)s+MVsA-zEa&r*PD=`1N5E5AC+T{@
zT{z>?Hw0QNKX-v!z@onac47*+2#j0DT2{Dr2_dlFYQMMY0kAo>G<Rl!VXNKf(y0a`
zG-A%G_W+lHX<#HDJSsyNv(u&PU6$WgJy`K7i^6%pCK~;<z`lI3`3f`xnI=<lGx2cD
zIe=$mEFR(wjKrLK1f27%r6l4E46Sf{4CutXbeR)p;1f$<>WGcNZD37V6ctIFfjNwc
zh=;(NeEleJkIE)|%aW8%M~~5c;3RMa7|b6#4qPjfE@zSq^Z=KDQ<!h`IB*Pjoj<>)
zeA3*An+L#*_F%!Wao{k}0X$u%Pcv`<XwBDai_l|d1!sYFtG$RxFrNdxzy|;%eYO&)
z?vzPct4vN`Ze}EPM#-En8i9TsbC{IW12=$OJ`HpLn>@x#q5(MX)4&0bv0ORm)4&#w
zv0T~e(?FfaSgzDp{kl-00jEC^{}Lha(`xU?N=T`Mz!$6C4(!fIOG(rKPcZonm`Ug@
zW{GdC$XI(l>T)KKlmp%Y+p`dmlF<<O0kp9+_pcfP{oSFd15RL8r<;HcMaJ3><oro<
zV$?Q}mdBVhyONClcN19}vREUMPXm)4W4SWn(?HTnUO5=@Y2bm!SkAxc)4)rh&ttqK
zUI6{Rzd~KWRba+*T$=^VCQKVJ?{glo$zdkMX3X-u4}M|x%m%Rb&dOz=VysSNSyS}}
Z{s4bsAe)rbQx5<D002ovPDHLkV1g_RcGLg>

literal 0
HcmV?d00001

diff --git a/Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/pip.exit.24x24@3x.png b/Resources/iOS/Images.xcassets/NewPlayer/pip.exit.imageset/pip.exit.24x24@3x.png
new file mode 100644
index 0000000000000000000000000000000000000000..584494155a18fdc850bab01f45af1348cadec1f0
GIT binary patch
literal 1182
zcmV;P1Y!G$P)<h;3K|Lk000e1NJLTq002k;002k`1^@s6RqeA!00009a7bBm001mX
z001mX0e5<IO#lD@8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H11S?5I
zK~#90?c7bsR8<_u@z0EpJ|(?qSQeCSA_{evg_^xs5Jf^QqFPiCz0g8i)}~EC%gCrU
zxd=)()uJ|0v?we~A}E7Ot*{qKg~~@0eM&nm&O9+r_j&G}d&e_(^nPKOnRD*^|Nr^T
zz2}~n|Cv?@LBsU4haEuOX#~ol5h#a7pd1>3au}PTZWb0|9?nb?PHB$f0QTY7APx5l
zGzWL%UR;f{2k9&Uhw&LU;WbgXO0>HAL6_l8EUjv^Cj5vyMZrolCD29qyz_i2aR^u8
z+p-3x8tIKrJ#mOl#LHC-v_c3=@D*Cq9P=A~!ar3UokUu=1n19i%nE#3#`qX+kuA<9
zJb_=z7#;!_;we0oQFp770=30!w3jWo&*+E)d+{*d$*9Zvj)iFBf{gOb>U&A$@oGld
z!m`HNI5(qwXIX<aAS?E)?^uX2*~5)PJ@4n@N%1=0)d^x}=k<}Y&QB5tGs<R_H8#^w
zqnrE12D_Ia-r>4M+kr2{Heuu`D$wj{%3E06dEC@hehjza-SVN;gQBDPU47ae!?Hd<
zQ%i~p)NiBxAztkBGqt3sK)W$n@Ys*BR{a|9QWO>FIDRN_+*Yw?-g_4uS^Ak#EOME>
z?i3P-!3*>(9xWM5Eg6JB-7AkRynqKvM^rPa3bYl=v8Tu8Mm$m>uG&yVpe?vroQYiH
zM3Gu}33pVAt_JiY&|ZAgdHsQSxB9d5ekX2l;`B%xk5`Ou==8fTwg$J0XU^fCx?Q*)
zKX;YwE*n@~C^{CKVlUpBq5gZU6bH7GcqYf*Ik*R_#i7Z3oYiMcy=4997vuMg@}u|z
z-{B*19&FDEM}!c*4F6|&2*F8yJQhNj$nZT({t6*%2qBDzPMpJ9dVU_yiDyuqn2q(~
zEW~Vvvo?Ph)(ydLKU{~WNiR@KoS7U2)?q<vftF!OVxMK1i?yi*TAA2iRaT`IXi;K+
zRaul;pm~Y?Rb_r^fu@`MuPbw!6ucZ7fpTaB%AqYg>G8bOfz*|@m>t^7<*5UyD{cIm
zQT`y#NE}NoY0J*MT8j6?LEEVHT?R@kgs@ngFq&!dY{Fm?s^(&R0CrNbeN4<J-Yllv
zO-Jbjq)}(;HosoX>uKm=N}vf`BRc`|w5EG2!W1jSy&9`<sn~9uu58Z|sF!hr6KR7e
z{;06M$g<C*;<-UZY>gDnSS*J|pd3;QG-}!V$5RV5k=S2V4x|=ne`0@C*`HdVZHfI=
zWm}Pc&>$HXw=QJuFsd5?SEN3JCdI^sQQ&RtNPPwomww*IwW%HV!CqX6J;Ue+{VitV
zzcB>gMfe&w>LgMP;|%I%jhGF)+HiMWAH*kkMf~CZTgVu;K;0}5S5s2{+rtqt1#h2e
wI<a*UsFpNiu^bwKa%cp~p%EyDMxY%21*zb}H3{%^P5=M^07*qoM6N<$f-RLOI{*Lx

literal 0
HcmV?d00001

diff --git a/Sources/Playback/Control/VLCPlaybackService.h b/Sources/Playback/Control/VLCPlaybackService.h
index f4fc636e2..a1a144014 100644
--- a/Sources/Playback/Control/VLCPlaybackService.h
+++ b/Sources/Playback/Control/VLCPlaybackService.h
@@ -50,6 +50,8 @@ currentMediaHasTrackToChooseFrom:(BOOL)currentMediaHasTrackToChooseFrom
               nextMedia:(VLCMedia *)media;
 - (void)playModeUpdated;
 - (void)reloadPlayQueue;
+- (void)pictureInPictureStateDidChange:(BOOL)isEnabled
+NS_SWIFT_NAME(pictureInPictureStateDidChange(enabled:));
 @end
 
 NS_SWIFT_NAME(PlaybackService)
diff --git a/Sources/Playback/Control/VLCPlaybackService.m b/Sources/Playback/Control/VLCPlaybackService.m
index 362b6de28..381d18763 100644
--- a/Sources/Playback/Control/VLCPlaybackService.m
+++ b/Sources/Playback/Control/VLCPlaybackService.m
@@ -87,6 +87,7 @@ NSString *const VLCPlaybackServicePlaybackDidMoveOnToNextItem = @"VLCPlaybackSer
 }
 
 @property (weak, atomic) id<VLCPictureInPictureWindowControlling> pipController;
+@property (atomic) BOOL isPipEnabled;
 @property (atomic) id<VLCPictureInPictureMediaControlling> mediaController;
 
 @end
@@ -1856,11 +1857,19 @@ NSString *const VLCPlaybackServicePlaybackDidMoveOnToNextItem = @"VLCPlaybackSer
     __weak typeof(self) drawable = self;
     return ^(id<VLCPictureInPictureWindowControlling> pipController){
         drawable.pipController = pipController;
+        drawable.pipController.stateChangeEventHandler = ^(BOOL isEnabled) {
+            drawable.isPipEnabled = isEnabled;
+            if ([drawable.delegate respondsToSelector:@selector(pictureInPictureStateDidChange:)])
+                [drawable.delegate pictureInPictureStateDidChange:isEnabled];
+        };
     };
 }
 
 - (void)togglePictureInPicture {
-    [self.pipController startPictureInPicture];
+    if (self.isPipEnabled)
+        [self.pipController stopPictureInPicture];
+    else
+        [self.pipController startPictureInPicture];
 }
 
 @end
diff --git a/Sources/Playback/Player/PlayerViewController.swift b/Sources/Playback/Player/PlayerViewController.swift
index 4ef3750d1..29c7523ea 100644
--- a/Sources/Playback/Player/PlayerViewController.swift
+++ b/Sources/Playback/Player/PlayerViewController.swift
@@ -910,6 +910,10 @@ class PlayerViewController: UIViewController {
 // MARK: - VLCPlaybackServiceDelegate
 
 extension PlayerViewController: VLCPlaybackServiceDelegate {
+    func pictureInPictureStateDidChange(enabled: Bool) {
+        mediaNavigationBar.updatePictureInPictureButton(enabled: enabled)
+    }
+
     func playbackPositionUpdated(_ playbackService: PlaybackService) {
         mediaScrubProgressBar.updateInterfacePosition()
     }
diff --git a/Sources/Playback/Player/VideoPlayer-iOS/Subviews/MediaNavigationBar.swift b/Sources/Playback/Player/VideoPlayer-iOS/Subviews/MediaNavigationBar.swift
index 8962a0fb9..9d9075b9a 100644
--- a/Sources/Playback/Player/VideoPlayer-iOS/Subviews/MediaNavigationBar.swift
+++ b/Sources/Playback/Player/VideoPlayer-iOS/Subviews/MediaNavigationBar.swift
@@ -254,6 +254,11 @@ private enum RendererActionSheetContent: Int, CaseIterable {
         closePlaybackButton.accessibilityLabel = accessibility.0
         closePlaybackButton.accessibilityHint = accessibility.1
     }
+
+    func updatePictureInPictureButton(enabled:Bool) {
+        let image = UIImage(named: enabled ? "pip.exit" : "pip.enter")
+        pictureInPictureButton.setImage(image, for: .normal)
+    }
 }
 
 extension MediaNavigationBar: ActionSheetDelegate, ActionSheetDataSource {
-- 
GitLab