/* HBRange.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 "HBRange.h" #import "HBTitle+Private.h" #import "HBCodingUtilities.h" NSString *HBRangeChangedNotification = @"HBRangeChangedNotification"; @implementation HBRange #pragma mark - NSCoding - (instancetype)initWithTitle:(HBTitle *)title { self = [super init]; if (self) { _title = title; _chapterStart = 0; _chapterStop = (int)title.chapters.count - 1; _secondsStart = 0; _secondsStop = title.duration; _frameStart = 0; _frameStop = title.frames; } return self; } - (void)postChangedNotification { [[NSNotificationCenter defaultCenter] postNotificationName:HBRangeChangedNotification object:self]; } - (void)setType:(HBRangeType)type { if (type != _type) { [[self.undo prepareWithInvocationTarget:self] setType:_type]; } _type = type; } - (void)setChapterStart:(int)chapterStart { if (chapterStart != _chapterStart) { [[self.undo prepareWithInvocationTarget:self] setChapterStart:_chapterStart]; } if (chapterStart > self.chapterStop) { self.chapterStop = chapterStart; } _chapterStart = chapterStart; [self postChangedNotification]; } - (void)setChapterStop:(int)chapterStop { if (chapterStop != _chapterStop) { [[self.undo prepareWithInvocationTarget:self] setChapterStop:_chapterStop]; } if (chapterStop < self.chapterStart) { self.chapterStart = chapterStop; } _chapterStop = chapterStop; [self postChangedNotification]; } - (void)setFrameStart:(int)frameStart { if (frameStart != _frameStart) { [[self.undo prepareWithInvocationTarget:self] setFrameStart:_frameStart]; } _frameStart = frameStart; } - (void)setFrameStop:(int)frameStop { if (frameStop != _frameStop) { [[self.undo prepareWithInvocationTarget:self] setFrameStop:_frameStop]; } _frameStop = frameStop; } - (void)setSecondsStart:(int)secondsStart { if (secondsStart != _secondsStart) { [[self.undo prepareWithInvocationTarget:self] setSecondsStart:_secondsStart]; } _secondsStart = secondsStart; } - (void)setSecondsStop:(int)secondsStop { if (secondsStop != _secondsStop) { [[self.undo prepareWithInvocationTarget:self] setSecondsStop:_secondsStop]; } _secondsStop = secondsStop; } - (NSString *)duration { if (self.type == HBRangeTypeChapters) { hb_title_t *title = self.title.hb_title; hb_chapter_t *chapter; int64_t duration = 0; for (int i = self.chapterStart; i <= self.chapterStop; i++ ) { chapter = (hb_chapter_t *) hb_list_item(title->list_chapter, i); duration += chapter->duration; } duration /= 90000; // pts -> seconds return [NSString stringWithFormat: @"%02lld:%02lld:%02lld", duration / 3600, ( duration / 60 ) % 60, duration % 60]; } else if (self.type == HBRangeTypeSeconds) { int duration = self.secondsStop - self.secondsStart; return [NSString stringWithFormat:@"%02d:%02d:%02d", duration / 3600, (duration / 60) % 60, duration % 60]; } else if (self.type == HBRangeTypeFrames) { hb_title_t *title = self.title.hb_title; int duration = (int) ((self.frameStop - self.frameStart) / (title->vrate.num / (double)title->vrate.den)); return [NSString stringWithFormat: @"%02d:%02d:%02d", duration / 3600, ( duration / 60 ) % 60, duration % 60]; } return @"00:00:00"; } + (NSSet *)keyPathsForValuesAffectingDuration { return [NSSet setWithObjects:@"type", @"chapterStart", @"chapterStop", @"frameStart", @"frameStop", @"secondsStart", @"secondsStop",nil]; } - (void)setNilValueForKey:(NSString *)key { [self setValue:@0 forKey:key]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { HBRange *copy = [[[self class] alloc] init]; if (copy) { copy->_type = _type; copy->_chapterStart = _chapterStart; copy->_chapterStop = _chapterStop; copy->_secondsStart = _secondsStart; copy->_secondsStop = _secondsStop; copy->_frameStart = _frameStart; copy->_frameStop = _frameStop; } return copy; } #pragma mark - NSCoding + (BOOL)supportsSecureCoding { return YES; } - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeInt:1 forKey:@"HBRangeVersion"]; encodeInt(_type); encodeInt(_chapterStart); encodeInt(_chapterStop); encodeInt(_secondsStart); encodeInt(_secondsStop); encodeInt(_frameStart); encodeInt(_frameStop); } - (instancetype)initWithCoder:(NSCoder *)decoder { self = [super init]; decodeInt(_type); if (_type < HBRangeTypeChapters || _type > HBRangePreviewIndex) { goto fail; } decodeInt(_chapterStart); if (_chapterStart < 0) { goto fail; } decodeInt(_chapterStop); if (_chapterStop < _chapterStart) { goto fail; } decodeInt(_secondsStart); decodeInt(_secondsStop); decodeInt(_frameStart); decodeInt(_frameStop); return self; fail: return nil; } @end