@property (nonatomic, strong) NSMutableSet<HBAVPlayerRateObserver *> *rateObservers;
@property (nonatomic, strong) NSMutableSet<HBPlayableObverser> *playableObservers;
-@property (nonatomic, readwrite) BOOL playable;
+@property (nonatomic, readwrite, getter=isPlayable) BOOL playable;
+@property (nonatomic, readwrite, getter=isLoaded) BOOL loaded;
@end
if (self)
{
_movie = [AVAsset assetWithURL:url];;
-
- if (!_movie)
- {
- return nil;
- }
-
_player = [[AVPlayer alloc] init];
_layer = [CALayer layer];
- if (!_layer || !_player)
- {
- return nil;
- }
-
_rateObservers = [NSMutableSet set];
_playableObservers = [NSMutableSet set];
// Because we want to access our AVPlayer in our ensuing set-up, we must dispatch our handler to the main queue.
dispatch_async(dispatch_get_main_queue(), ^(void) {
[self _setUpPlaybackOfAsset:_movie withKeys:assetKeysToLoadAndTest];
+ self.loaded = YES;
});
}];
}
}
-- (void)setPlayable:(BOOL)playable
+- (void)setLoaded:(BOOL)loaded
{
- _playable = playable;
+ _loaded = loaded;
for (HBPlayableObverser block in self.playableObservers)
{
- (void)loadPlayableValueAsynchronouslyWithCompletionHandler:(nullable void (^)(void))handler;
{
- if (self.playable)
+ if (self.isLoaded)
{
handler();
}
[self.slider setMinValue:0.0];
[self.slider setMaxValue:self.player.duration];
[self.slider setDoubleValue:0.0];
-
+
+ self.player.volume = self.volumeSlider.floatValue;
+
[self.player play];
}
}
// adjust the preview slider length
self.pictureHUD.pictureCount = generator.imagesCount;
- [self switchStateToHUD:self.pictureHUD];
}
else
{
self.previewView.image = nil;
- self.currentHUD.view.hidden = YES;
self.window.title = NSLocalizedString(@"Preview", nil);
}
+ [self switchStateToHUD:self.pictureHUD];
}
- (void)reloadPreviews
for (NSViewController *controller in huds) {
controller.view.hidden = YES;
}
- hud.view.hidden = NO;
- hud.view.layer.opacity = 1.0;
+ if (self.generator)
+ {
+ hud.view.hidden = NO;
+ hud.view.layer.opacity = 1.0;
+ };
[self.window makeFirstResponder:hud.view];
[self startHudTimer];
}
}
-- (void)setUpPlaybackOfURL:(NSURL *)fileURL;
+- (void)setUpPlaybackOfURL:(NSURL *)fileURL playerClass:(Class)class;
{
- if (self.player.isPlayable && self.currentHUD == self.encodingHUD)
+ NSArray<Class> *availablePlayerClasses = @[[HBAVPlayer class], [HBQTKitPlayer class]];
+
+ self.player = [[class alloc] initWithURL:fileURL];
+
+ if (self.player)
{
- [self switchStateToHUD:self.playerHUD];
+ [self.player loadPlayableValueAsynchronouslyWithCompletionHandler:^{
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (self.player.isPlayable && self.currentHUD == self.encodingHUD)
+ {
+ [self switchStateToHUD:self.playerHUD];
+ }
+ else
+ {
+ // Try to open the preview with the next player class.
+ NSUInteger idx = [availablePlayerClasses indexOfObject:class];
+ if (idx != NSNotFound && (idx + 1) < availablePlayerClasses.count)
+ {
+ Class nextPlayer = availablePlayerClasses[idx + 1];
+ [self setUpPlaybackOfURL:fileURL playerClass:nextPlayer];
+ }
+ else
+ {
+ [self showAlert:fileURL];
+ [self switchStateToHUD:self.pictureHUD];
+ }
+ }
+ });
+
+ }];
}
else
{
- (void)didCreateMovieAtURL:(NSURL *)fileURL
{
- if (fileURL)
- {
- self.player = [[HBAVPlayer alloc] initWithURL:fileURL];
-
- if (self.player)
- {
- [self.player loadPlayableValueAsynchronouslyWithCompletionHandler:^{
-
- dispatch_async(dispatch_get_main_queue(), ^{
- [self setUpPlaybackOfURL:fileURL];
- });
-
- }];
- }
- else
- {
- [self showAlert:fileURL];
- [self switchStateToHUD:self.pictureHUD];
- }
- }
+ [self setUpPlaybackOfURL:fileURL playerClass:[HBAVPlayer class]];
}
#pragma mark - Player mode
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, readwrite, getter=isPlayable) BOOL playable;
+@property (nonatomic, readwrite, getter=isLoaded) BOOL loaded;
@property (nonatomic, strong) NSMutableSet<HBQTKitPlayerPeriodicObserver *> *periodicObservers;
@property (nonatomic, strong) NSMutableSet<HBQTKitPlayerRateObserver *> *rateObservers;
QTMovieAskUnresolvedDataRefsAttribute: @NO,
QTMovieOpenForPlaybackAttribute: @YES,
QTMovieIsSteppableAttribute: @YES,
- QTMovieOpenAsyncRequiredAttribute: @YES,
+ QTMovieOpenAsyncRequiredAttribute: @NO,
+ QTMovieOpenAsyncOKAttribute: @NO,
QTMovieApertureModeAttribute: QTMovieApertureModeClean };
_movie = [[QTMovie alloc] initWithAttributes:attributes error:&outError];
- if (!_movie)
+ if (_movie)
{
- return nil;
- }
-
- _movie.delegate = self;
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(_movieRateDidChange:)
- name:QTMovieRateDidChangeNotification
- object:_movie];
+ _movie.delegate = self;
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(_loadStateChanged:)
- name:QTMovieLoadStateDidChangeNotification
- object:_movie];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(_movieRateDidChange:)
+ name:QTMovieRateDidChangeNotification
+ object:_movie];
- _layer = [QTMovieLayer layerWithMovie:_movie];
-
- if (!_layer)
- {
- return nil;
+ _layer = [QTMovieLayer layerWithMovie:_movie];
}
_periodicObservers = [NSMutableSet set];
_rateObservers = [NSMutableSet set];
_playableObservers = [NSMutableSet set];
+
+ // Can't open things async
+ // because of 23414 QTKit bugs.
+ if (_movie && _layer)
+ {
+ self.playable = YES;
+ [self _enableSubtitles];
+ }
+ else
+ {
+ self.playable = NO;
+ }
+
+ self.loaded = YES;
}
return self;
[self _stopMovieTimer];
}
-- (void)setPlayable:(BOOL)playable
+- (void)setLoaded:(BOOL)loaded
{
- _playable = playable;
+ _loaded = loaded;
for (HBPlayableObverser block in self.playableObservers)
{
[self.playableObservers removeAllObjects];
}
-- (void)_loadStateChanged:(NSNotification *)notification
-{
- int loadState = [[self.movie attributeForKey:QTMovieLoadStateAttribute] intValue];
-
- if (loadState >= QTMovieLoadStateLoaded)
- {
- [self _enableSubtitles];
- self.playable = YES;
- }
-}
-
- (void)_movieRateDidChange:(NSNotification *)notification
{
for (HBQTKitPlayerRateObserver *observer in self.rateObservers)
- (void)loadPlayableValueAsynchronouslyWithCompletionHandler:(nullable void (^)(void))handler;
{
- if (self.playable)
+ if (self.isLoaded)
{
handler();
}