AVMovieEditor/AVMovieEditor/AAPLDocument.m
/* |
Copyright (C) 2015 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
The 'AAPLDocument' provides a way for documents to be opened and backed by AVMovie. This document does work to ensure that the documents that are saved and opened are compatible with the underlying AVMovie. |
*/ |
@import AVFoundation; |
#import "AAPLDocument.h" |
#import "AAPLMovieMutator.h" |
#import "AAPLMovieViewController.h" |
@interface AAPLDocument() <AAPLMovieViewControllerDelegate> |
#pragma mark - Properties |
@property AAPLMovieMutator *movieMutator; |
@property AAPLMovieViewController *movieViewController; |
@end |
@implementation AAPLDocument |
#pragma mark - Window setup |
- (void)makeWindowControllers { |
NSStoryboard *storyboard = [NSStoryboard storyboardWithName:@"Main" bundle:nil]; |
NSWindowController* windowController = [storyboard instantiateControllerWithIdentifier:@"Document Window Controller"]; |
[self addWindowController:windowController]; |
self.movieViewController = (AAPLMovieViewController *)windowController.contentViewController; |
self.movieViewController.delegate = self; |
self.movieViewController.playerView.player = [AVPlayer playerWithPlayerItem:[self.movieMutator makePlayerItem]]; |
// Add an observer for the MovieMutator to know if data has been pasted into it or cut out of it, and then update accordingly. |
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(underlyingMovieWasMutated) name:movieWasMutated object:self.movieMutator]; |
windowController.window.backgroundColor = [NSColor blackColor]; |
} |
- (void)underlyingMovieWasMutated { |
self.movieViewController.playerView.player = [AVPlayer playerWithPlayerItem:[self.movieMutator makePlayerItem]]; |
[self.movieViewController updateMovieTimeline]; |
self.movieViewController.view.needsDisplay = YES; |
} |
- (BOOL)readFromURL:(nonnull NSURL *)url ofType:(nonnull NSString *)typeName error:(NSError * __nullable __autoreleasing * __nullable)outError{ |
NSString *fileType = [self UTIFromPathExtension:url.pathExtension]; |
// If the UTI is not one of AVMovie.movieTypes() then this movie is not supported by AVMovie and should not be opened. |
if (![[AVMovie movieTypes] containsObject:fileType]) { |
return false; |
} |
AVMovie *currentMovie = [AVMovie movieWithURL:url options:nil]; |
self.movieMutator = [[AAPLMovieMutator alloc] initWithMovie:currentMovie]; |
return true; |
} |
- (BOOL)cutMovieTimeRange:(CMTimeRange)timeRange error:(NSError *)error { |
return [self.movieMutator cutTimeRange:timeRange error:error]; |
} |
- (BOOL)copyMovieTimeRange:(CMTimeRange)timeRange error:(NSError *)error { |
return [self.movieMutator copyTimeRange:timeRange error:error]; |
} |
- (BOOL)pasteMovieAtTime:(CMTime)time error:(NSError *)error { |
return [self.movieMutator pasteAtTime:time error:error]; |
} |
- (void)movieViewController:(AAPLMovieViewController *)movieViewController needsNumberOfImages:(NSUInteger)numberOfImages completionHandler:(ImageGenerationCompletionHandler)completionHandler { |
[self.movieMutator generateImages:numberOfImages withCompletionHandler:completionHandler]; |
} |
- (CMTime)timeAtPercentage:(float)percentage { |
return [self.movieMutator timePercentageThroughMovie:percentage]; |
} |
#pragma mark - File -> Save |
- (void)saveDocument:(nullable id)sender { |
NSSavePanel *savePanel = [NSSavePanel savePanel]; |
// The only UTIs that AVMovie can write to are in AVMovie.movieTypes() |
savePanel.allowedFileTypes = [AVMovie movieTypes]; |
[savePanel beginWithCompletionHandler:^(NSInteger result) { |
if (result == 1) { |
NSURL *url = savePanel.URL; |
NSString *fileType = [self UTIFromPathExtension:url.pathExtension]; |
NSError *error = nil; |
BOOL didSucceed = [self.movieMutator writeMovieToURL:url fileType:fileType error:error]; |
if (!didSucceed || error) { |
NSLog(@"There was a problem saving the movie."); |
} |
} |
}]; |
} |
#pragma mark - Cleanup |
- (void)canCloseDocumentWithDelegate:(nonnull id)delegate shouldCloseSelector:(nullable SEL)shouldCloseSelector contextInfo:(nullable void *)contextInfo { |
[[NSNotificationCenter defaultCenter] removeObserver:self name:movieWasMutated object:self.movieMutator]; |
[super canCloseDocumentWithDelegate:delegate shouldCloseSelector:shouldCloseSelector contextInfo:contextInfo]; |
} |
- (NSString *)UTIFromPathExtension:(NSString *)pathExtension { |
// Figure out the correct UTI from the path extension. |
NSString *fileType = AVFileTypeQuickTimeMovie; |
if ([pathExtension.lowercaseString isEqualToString:@"mp4"]) |
fileType = AVFileTypeMPEG4; |
else if ([pathExtension.lowercaseString isEqualToString:@"m4v"]) |
fileType = AVFileTypeAppleM4V; |
else if ([pathExtension.lowercaseString isEqualToString:@"m4a"]) |
fileType = AVFileTypeAppleM4A; |
return fileType; |
} |
@end |
Copyright © 2015 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2015-09-16