mirror of
https://github.com/StikDebug/StikDebug.git
synced 2026-10-16 04:20:30 +00:00
138 lines
4.1 KiB
Objective-C
138 lines
4.1 KiB
Objective-C
//
|
|
// PiPController.m
|
|
// StikDebug
|
|
//
|
|
// Created by Stossy11 on 10/07/2025.
|
|
//
|
|
|
|
#import "PiPController.h"
|
|
|
|
@interface PiPController ()
|
|
@property (nonatomic, strong, nullable) AVPictureInPictureController *pipController;
|
|
@property (nonatomic, strong, nullable) AVPlayerLayer *playerLayer;
|
|
@property (nonatomic, strong, nullable) UIView *customView;
|
|
@end
|
|
|
|
@implementation PiPController
|
|
|
|
+ (PiPController *)shared {
|
|
static PiPController *sharedInstance = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
sharedInstance = [[self alloc] init];
|
|
});
|
|
return sharedInstance;
|
|
}
|
|
|
|
- (instancetype)init {
|
|
self = [super init];
|
|
if (self) {
|
|
_isPiPActive = NO;
|
|
[self setupAudioSession];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)setupAudioSession {
|
|
NSError *error = nil;
|
|
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
|
|
|
|
if (![audioSession setCategory:AVAudioSessionCategoryPlayback error:&error]) {
|
|
NSLog(@"Audio session setup error: %@", error.localizedDescription);
|
|
return;
|
|
}
|
|
|
|
if (![audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error]) {
|
|
NSLog(@"Audio session setup error: %@", error.localizedDescription);
|
|
}
|
|
}
|
|
|
|
- (void)setupPiPWithPlayerLayer:(AVPlayerLayer *)playerLayer {
|
|
if (![AVPictureInPictureController isPictureInPictureSupported]) {
|
|
NSLog(@"Picture in Picture not supported");
|
|
return;
|
|
}
|
|
|
|
self.playerLayer = playerLayer;
|
|
|
|
self.pipController = [[AVPictureInPictureController alloc] initWithPlayerLayer:playerLayer];
|
|
self.pipController.delegate = self;
|
|
|
|
// Set controls style (equivalent to setValue:forKey: in Swift)
|
|
if ([self.pipController respondsToSelector:@selector(setControlsStyle:)]) {
|
|
[self.pipController setValue:@(1) forKey:@"controlsStyle"];
|
|
}
|
|
}
|
|
|
|
- (void)startPiP {
|
|
if (self.pipController.isPictureInPictureActive) return;
|
|
|
|
[self.pipController startPictureInPicture];
|
|
}
|
|
|
|
- (void)stopPiP {
|
|
if (!self.pipController.isPictureInPictureActive) return;
|
|
|
|
[self.pipController stopPictureInPicture];
|
|
}
|
|
|
|
- (void)togglePiP {
|
|
if (self.isPiPActive) {
|
|
[self stopPiP];
|
|
} else {
|
|
[self startPiP];
|
|
}
|
|
}
|
|
|
|
#pragma mark - AVPictureInPictureControllerDelegate
|
|
|
|
- (void)pictureInPictureControllerWillStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {
|
|
if (!self.customUIView) {
|
|
NSLog(@"Fatal error: customUIView = nil");
|
|
return;
|
|
}
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
self.isPiPActive = YES;
|
|
});
|
|
|
|
self.customView = self.customUIView;
|
|
|
|
UIWindow *window = [UIApplication sharedApplication].windows.firstObject;
|
|
if (window && self.customView) {
|
|
self.customView.backgroundColor = [UIColor clearColor];
|
|
[window addSubview:self.customView];
|
|
|
|
self.customView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
[NSLayoutConstraint activateConstraints:@[
|
|
[self.customView.topAnchor constraintEqualToAnchor:window.topAnchor],
|
|
[self.customView.leadingAnchor constraintEqualToAnchor:window.leadingAnchor],
|
|
[self.customView.trailingAnchor constraintEqualToAnchor:window.trailingAnchor],
|
|
[self.customView.bottomAnchor constraintEqualToAnchor:window.bottomAnchor]
|
|
]];
|
|
}
|
|
}
|
|
|
|
|
|
- (void)pictureInPictureControllerDidStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {
|
|
NSLog(@"PiP started");
|
|
}
|
|
|
|
- (void)pictureInPictureControllerDidStopPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
self.isPiPActive = NO;
|
|
});
|
|
|
|
// Remove custom view
|
|
[self.customView removeFromSuperview];
|
|
self.customView = nil;
|
|
}
|
|
|
|
- (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController failedToStartPictureInPictureWithError:(NSError *)error {
|
|
NSLog(@"Failed to start PiP: %@", error.localizedDescription);
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
self.isPiPActive = NO;
|
|
});
|
|
}
|
|
|
|
@end
|