/* HBSummaryViewController.m $
This file is part of the HandBrake source code.
Homepage: .
It may be used under the terms of the GNU General Public License. */
#import "HBSummaryViewController.h"
#import "HBPreviewViewController.h"
#import "HBPreviewGenerator.h"
#import "HBPreferencesKeys.h"
@import HandBrakeKit;
static void *HBSummaryViewControllerContainerContext = &HBSummaryViewControllerContainerContext;
static void *HBSummaryViewControllerVideoContext = &HBSummaryViewControllerVideoContext;
static void *HBSummaryViewControllerPictureContext = &HBSummaryViewControllerPictureContext;
static void *HBSummaryViewControllerFiltersContext = &HBSummaryViewControllerFiltersContext;
static void *HBSummaryViewControllerAudioContext = &HBSummaryViewControllerAudioContext;
static void *HBSummaryViewControllerSubsContext = &HBSummaryViewControllerSubsContext;
static void *HBSummaryViewControllerPreferencesContext = &HBSummaryViewControllerPreferencesContext;
@interface HBSummaryViewController ()
@property (nonatomic, strong) IBOutlet NSTextField *tracksLabel;
@property (nonatomic, strong) IBOutlet NSTextField *filtersLabel;
@property (nonatomic, strong) IBOutlet NSTextField *dimensionLabel;
@property (nonatomic, strong) IBOutlet NSView *previewView;
@property (nonatomic, strong) HBPreviewViewController *previewViewController;
@property (nonatomic) BOOL tracksReloadInQueue;
@property (nonatomic) BOOL filtersReloadInQueue;
@property (nonatomic) BOOL pictureReloadInQueue;
@property (nonatomic, readwrite) NSColor *labelColor;
@end
@implementation HBSummaryViewController
- (instancetype)init
{
self = [super initWithNibName:@"HBSummaryViewController" bundle:nil];
if (self)
{
_labelColor = [NSColor disabledControlTextColor];
_previewViewController = [[HBPreviewViewController alloc] init];
[NSUserDefaultsController.sharedUserDefaultsController addObserver:self forKeyPath:@"values.HBShowSummaryPreview"
options:0 context:HBSummaryViewControllerPreferencesContext];
}
return self;
}
- (void)dealloc
{
self.job = nil;
[NSUserDefaultsController.sharedUserDefaultsController removeObserver:self forKeyPath:@"values.HBShowSummaryPreview" context:HBSummaryViewControllerPreferencesContext];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.previewViewController.view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
self.previewViewController.view.frame = NSMakeRect(0, 0, self.previewView.frame.size.width, self.previewView.frame.size.height);
[self.previewView addSubview:self.previewViewController.view];
[self resetLabels];
}
- (void)setGenerator:(HBPreviewGenerator *)generator
{
_generator = generator;
self.previewViewController.generator = [NSUserDefaults.standardUserDefaults boolForKey:HBShowSummaryPreview] ? generator : nil;
}
- (void)setJob:(HBJob *)job
{
if (job)
{
self.labelColor = [NSColor controlTextColor];
[self removeJobObservers];
_job = job;
[self addJobObservers];
[self updateTracksLabel];
[self updateFiltersLabel];
[self updatePictureLabel];
}
else
{
self.labelColor = [NSColor disabledControlTextColor];
[self removeJobObservers];
[self resetLabels];
_job = job;
}
}
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == HBSummaryViewControllerAudioContext)
{
if ([change[NSKeyValueChangeKindKey] integerValue] == NSKeyValueChangeInsertion)
{
[self addAudioTracksObservers:change[NSKeyValueChangeNewKey]];
}
else if ([change[NSKeyValueChangeKindKey] integerValue]== NSKeyValueChangeRemoval)
{
[self removeAudioTracksObservers:change[NSKeyValueChangeOldKey]];
}
[self updateTracks:nil];
}
else if (context == HBSummaryViewControllerSubsContext)
{
if ([change[NSKeyValueChangeKindKey] integerValue] == NSKeyValueChangeInsertion)
{
[self addSubtitlesTracksObservers:change[NSKeyValueChangeNewKey]];
}
else if ([change[NSKeyValueChangeKindKey] integerValue]== NSKeyValueChangeRemoval)
{
[self removeSubtitlesTracksObservers:change[NSKeyValueChangeOldKey]];
}
[self updateTracks:nil];
}
else if (context == HBSummaryViewControllerContainerContext)
{
[self updateTracks:nil];
}
else if (context == HBSummaryViewControllerVideoContext)
{
[self updateTracks:nil];
}
else if (context == HBSummaryViewControllerFiltersContext)
{
[self updatePicture:nil];
}
else if (context == HBSummaryViewControllerPreferencesContext)
{
self.generator = self.generator;
}
else
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)addAudioTracksObservers:(NSArray *)tracks
{
for (HBAudioTrack *track in tracks)
{
[track addObserver:self forKeyPath:@"encoder" options:0 context:HBSummaryViewControllerAudioContext];
[track addObserver:self forKeyPath:@"mixdown" options:0 context:HBSummaryViewControllerAudioContext];
}
}
- (void)removeAudioTracksObservers:(NSArray *)tracks
{
for (HBAudioTrack *track in tracks)
{
[track removeObserver:self forKeyPath:@"encoder" context:HBSummaryViewControllerAudioContext];
[track removeObserver:self forKeyPath:@"mixdown" context:HBSummaryViewControllerAudioContext];
}
}
- (void)addSubtitlesTracksObservers:(NSArray *)tracks
{
for (HBSubtitlesTrack *track in tracks)
{
[track addObserver:self forKeyPath:@"burnedIn" options:0 context:HBSummaryViewControllerSubsContext];
}
}
- (void)removeSubtitlesTracksObservers:(NSArray *)tracks
{
for (HBSubtitlesTrack *track in tracks)
{
[track removeObserver:self forKeyPath:@"burnedIn" context:HBSummaryViewControllerSubsContext];
}
}
- (void)addJobObservers
{
if (_job)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePicture:) name:HBPictureChangedNotification object:_job.picture];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateFilters:) name:HBFiltersChangedNotification object:_job.filters];
[_job addObserver:self forKeyPath:@"container" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:HBSummaryViewControllerContainerContext];
[_job addObserver:self forKeyPath:@"chaptersEnabled" options:0 context:HBSummaryViewControllerVideoContext];
[_job addObserver:self forKeyPath:@"video.encoder" options:0 context:HBSummaryViewControllerVideoContext];
[_job addObserver:self forKeyPath:@"video.frameRate" options:0 context:HBSummaryViewControllerVideoContext];
[_job addObserver:self forKeyPath:@"video.frameRateMode" options:0 context:HBSummaryViewControllerVideoContext];
[_job addObserver:self forKeyPath:@"filters.deinterlace" options:0 context:HBSummaryViewControllerFiltersContext];
[_job addObserver:self forKeyPath:@"filters.rotate" options:0 context:HBSummaryViewControllerFiltersContext];
[_job addObserver:self forKeyPath:@"filters.flip" options:0 context:HBSummaryViewControllerFiltersContext];
[_job addObserver:self forKeyPath:@"audio.tracks" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:HBSummaryViewControllerAudioContext];
[_job addObserver:self forKeyPath:@"subtitles.tracks" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:HBSummaryViewControllerSubsContext];
[self addAudioTracksObservers:_job.audio.tracks];
[self addSubtitlesTracksObservers:_job.subtitles.tracks];
}
}
- (void)removeJobObservers
{
if (_job)
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:HBPictureChangedNotification object:_job.picture];
[[NSNotificationCenter defaultCenter] removeObserver:self name:HBFiltersChangedNotification object:_job.filters];
[_job removeObserver:self forKeyPath:@"container" context:HBSummaryViewControllerContainerContext];
[_job removeObserver:self forKeyPath:@"chaptersEnabled" context:HBSummaryViewControllerVideoContext];
[_job removeObserver:self forKeyPath:@"video.encoder" context:HBSummaryViewControllerVideoContext];
[_job removeObserver:self forKeyPath:@"video.frameRate" context:HBSummaryViewControllerVideoContext];
[_job removeObserver:self forKeyPath:@"video.frameRateMode" context:HBSummaryViewControllerVideoContext];
[_job removeObserver:self forKeyPath:@"filters.deinterlace" context:HBSummaryViewControllerFiltersContext];
[_job removeObserver:self forKeyPath:@"filters.rotate" context:HBSummaryViewControllerFiltersContext];
[_job removeObserver:self forKeyPath:@"filters.flip" context:HBSummaryViewControllerFiltersContext];
[_job removeObserver:self forKeyPath:@"audio.tracks" context:HBSummaryViewControllerAudioContext];
[_job removeObserver:self forKeyPath:@"subtitles.tracks" context:HBSummaryViewControllerSubsContext];
[self removeAudioTracksObservers:_job.audio.tracks];
[self removeSubtitlesTracksObservers:_job.subtitles.tracks];
}
}
- (void)updateTracks:(NSNotification *)notification
{
if (self.tracksReloadInQueue == NO)
{
[[NSRunLoop mainRunLoop] performSelector:@selector(updateTracksLabel) target:self argument:nil order:0 modes:@[NSDefaultRunLoopMode]];
self.tracksReloadInQueue = YES;
}
}
- (void)updateFilters:(NSNotification *)notification
{
if (self.filtersReloadInQueue == NO)
{
[[NSRunLoop mainRunLoop] performSelector:@selector(updateFiltersLabel) target:self argument:nil order:0 modes:@[NSDefaultRunLoopMode]];
self.filtersReloadInQueue = YES;
}
}
- (void)updatePicture:(NSNotification *)notification
{
// Enqueue the reload call on the main runloop
// to avoid reloading the same image multiple times.
if (self.pictureReloadInQueue == NO)
{
[[NSRunLoop mainRunLoop] performSelector:@selector(updatePictureLabel) target:self argument:nil order:0 modes:@[NSDefaultRunLoopMode]];
self.pictureReloadInQueue = YES;
}
}
- (void)resetLabels
{
self.tracksLabel.stringValue = @"";
self.filtersLabel.stringValue = @"";
self.dimensionLabel.stringValue = @"";
self.tracksReloadInQueue = NO;
self.filtersReloadInQueue = NO;
self.pictureReloadInQueue = NO;
}
- (void)updateTracksLabel
{
self.tracksLabel.stringValue = self.job.shortDescription;
self.tracksReloadInQueue = NO;
}
- (void)updateFiltersLabel
{
self.filtersLabel.stringValue = self.job.filtersShortDescription;
self.filtersReloadInQueue = NO;
}
- (void)updatePictureLabel
{
self.pictureReloadInQueue = NO;
self.dimensionLabel.stringValue = self.job.picture.shortInfo;
[self.previewViewController update];
}
@end