diff options
author | Damiano Galassi <[email protected]> | 2016-09-03 18:11:11 +0200 |
---|---|---|
committer | Damiano Galassi <[email protected]> | 2016-09-03 18:11:11 +0200 |
commit | 85d5fb9e66e6568b055b8350dfed3e044206c4a8 (patch) | |
tree | 6f415c375eab50026432ba1948525eec7fe8d61d /macosx/HBAudio.m | |
parent | 29c7a63c2ae91fc557f5586587a3a3e949ca8843 (diff) |
MacGui: rework HBAudioTrack to use less NSDictionary.
Diffstat (limited to 'macosx/HBAudio.m')
-rw-r--r-- | macosx/HBAudio.m | 455 |
1 files changed, 218 insertions, 237 deletions
diff --git a/macosx/HBAudio.m b/macosx/HBAudio.m index 8f8872777..81936d790 100644 --- a/macosx/HBAudio.m +++ b/macosx/HBAudio.m @@ -15,13 +15,11 @@ #include "hb.h" +#define NONE_TRACK_INDEX 0 + NSString *HBAudioChangedNotification = @"HBAudioChangedNotification"; @interface HBAudio () <HBAudioTrackDataSource, HBAudioTrackDelegate> - -@property (nonatomic, readonly, strong) NSDictionary *noneTrack; -@property (nonatomic, readonly, strong) NSArray *masterTrackArray; // the master list of audio tracks from the title - @end @implementation HBAudio @@ -33,192 +31,172 @@ NSString *HBAudioChangedNotification = @"HBAudioChangedNotification"; { _container = HB_MUX_MP4; + _sourceTracks = [title.audioTracks mutableCopy]; _tracks = [[NSMutableArray alloc] init]; _defaults = [[HBAudioDefaults alloc] init]; - _noneTrack = @{keyAudioTrackIndex: @0, - keyAudioTrackName: NSLocalizedString(@"None", @"None"), - keyAudioInputCodec: @0}; - - NSMutableArray *sourceTracks = [NSMutableArray array]; - [sourceTracks addObject:_noneTrack]; - [sourceTracks addObjectsFromArray:title.audioTracks]; - _masterTrackArray = [sourceTracks copy]; - - [self switchingTrackFromNone: nil]; // this ensures there is a None track at the end of the list + // Add the none and foreign track to the source array + NSDictionary *none = @{keyAudioTrackName: NSLocalizedString(@"None", nil)}; + [_sourceTracks insertObject:none atIndex:0]; } return self; } -- (void)addAllTracks +#pragma mark - Data Source + +- (NSDictionary<NSString *, id> *)sourceTrackAtIndex:(NSUInteger)idx; { - [self addTracksFromDefaults:YES]; + return self.sourceTracks[idx]; } -- (void)removeAll +- (NSArray<NSString *> *)sourceTracksArray { - [self _clearAudioArray]; - [self switchingTrackFromNone:nil]; + NSMutableArray *sourceNames = [NSMutableArray array]; + + for (NSDictionary *track in self.sourceTracks) + { + [sourceNames addObject:track[keyAudioTrackName]]; + } + + return sourceNames; } -- (void)reloadDefaults +#pragma mark - Delegate + +- (void)track:(HBAudioTrack *)track didChangeSourceFrom:(NSUInteger)oldSourceIdx; { - [self addTracksFromDefaults:NO]; + // If the source was changed to None, remove the track + if (track.sourceTrackIdx == NONE_TRACK_INDEX) + { + NSUInteger idx = [self.tracks indexOfObject:track]; + [self removeObjectFromTracksAtIndex:idx]; + } + // Else add a new None track + else if (oldSourceIdx == NONE_TRACK_INDEX) + { + [self addNoneTrack]; + } } -- (void)_clearAudioArray +- (void)addNoneTrack +{ + HBAudioTrack *track = [self trackFromSourceTrackIndex:NONE_TRACK_INDEX]; + [self addTrack:track]; +} + +#pragma mark - Public methods + +- (void)addAllTracks { - while (0 < [self countOfTracks]) + while (self.countOfTracks) { - [self removeObjectFromTracksAtIndex: 0]; + [self removeObjectFromTracksAtIndex:0]; + } + + // Add the remainings tracks + for (NSUInteger idx = 1; idx < self.sourceTracksArray.count; idx++) { + [self addTrack:[self trackFromSourceTrackIndex:idx]]; } + + [self addNoneTrack]; } -/** - * Uses the templateAudioArray from the preset to create the audios for the specified trackIndex. - * - * @param templateAudioArray the track template. - * @param trackIndex the index of the source track. - * @param firstOnly use only the first track of the template or all. - */ -- (void)_processPresetAudioArray:(NSArray *)templateAudioArray forTrack:(NSUInteger)trackIndex firstOnly:(BOOL)firstOnly +- (void)removeAll { - for (HBAudioTrackPreset *preset in templateAudioArray) + while (self.countOfTracks) { - BOOL fallenBack = NO; - HBAudioTrack *newAudio = [[HBAudioTrack alloc] init]; - [newAudio setDataSource:self]; - [newAudio setDelegate:self]; - [self insertObject: newAudio inTracksAtIndex: [self countOfTracks]]; - [newAudio setContainer:self.container]; - [newAudio setTrackFromIndex: (int)trackIndex]; - [newAudio setUndo:self.undo]; + [self removeObjectFromTracksAtIndex:0]; + } + [self addNoneTrack]; +} - const char *name = hb_audio_encoder_get_name(preset.encoder); - NSString *audioEncoder = nil; +- (void)reloadDefaults +{ + [self addTracksFromDefaults]; +} - // Check if we need to use a fallback - if (name) +- (void)setContainer:(int)container +{ + _container = container; + if (!(self.undo.isUndoing || self.undo.isRedoing)) + { + for (HBAudioTrack *track in self.tracks) { - audioEncoder = @(name); - if (preset.encoder & HB_ACODEC_PASS_FLAG && - ![newAudio setCodecFromName:audioEncoder]) - { - int passthru, fallback; - fallenBack = YES; - passthru = hb_audio_encoder_get_from_name([audioEncoder UTF8String]); - fallback = hb_audio_encoder_get_fallback_for_passthru(passthru); - name = hb_audio_encoder_get_name(fallback); - - // If we couldn't find an encoder for the passthru format - // fall back to the selected encoder fallback - if (name == NULL) - { - name = hb_audio_encoder_get_name(self.defaults.encoderFallback); - } - } - else - { - name = hb_audio_encoder_sanitize_name([audioEncoder UTF8String]); - } - audioEncoder = @(name); + track.container = container; } - // If our preset wants us to support a codec that the track does not support, instead - // of changing the codec we remove the audio instead. - if ([newAudio setCodecFromName:audioEncoder]) - { - const char *mixdown = hb_mixdown_get_name(preset.mixdown); - if (mixdown) - { - [newAudio setMixdownFromName: @(mixdown)]; - } + // Update the Auto Passthru Fallback Codec Popup + // lets get the tag of the currently selected item first so we might reset it later + [self.defaults validateEncoderFallbackForVideoContainer:container]; - const char *sampleRateName = hb_audio_samplerate_get_name(preset.sampleRate); - if (!sampleRateName) - { - [newAudio setSampleRateFromName: @"Auto"]; - } - else - { - [newAudio setSampleRateFromName: @(sampleRateName)]; - } - if (!fallenBack) - { - [newAudio setBitRateFromName: [NSString stringWithFormat:@"%d", preset.bitRate]]; - } - [newAudio setDrc:preset.drc]; - [newAudio setGain:preset.gain]; - } - else - { - [self removeObjectFromTracksAtIndex: [self countOfTracks] - 1]; - } + //[self validatePassthru]; + } +} - if (firstOnly) - { - break; - } +- (void)setUndo:(NSUndoManager *)undo +{ + _undo = undo; + for (HBAudioTrack *track in self.tracks) + { + track.undo = undo; + } + self.defaults.undo = undo; +} + +- (void)setDefaults:(HBAudioDefaults *)defaults +{ + if (defaults != _defaults) + { + [[self.undo prepareWithInvocationTarget:self] setDefaults:_defaults]; } + _defaults = defaults; + _defaults.undo = self.undo; } /** - * Matches the source audio tracks with the specific language iso code. + * Convenience method to add a track to tracks array. * - * @param isoCode the iso code to match. - * @param selectOnlyFirst whether to match only the first track for the iso code. - * - * @return a NSIndexSet with the index of the matched tracks. + * @param track the track to add. */ -- (NSIndexSet *)_tracksWithISOCode:(NSString *)isoCode selectOnlyFirst:(BOOL)selectOnlyFirst +- (void)addTrack:(HBAudioTrack *)newTrack { - NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet]; - - // We search for the prefix noting that our titles have the format %d: %s where the %s is the prefix - [self.masterTrackArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - if (idx) // Note that we skip the "None" track - { - if ([isoCode isEqualToString:@"und"] || [obj[keyAudioTrackLanguageIsoCode] isEqualToString:isoCode]) - { - [indexes addIndex:idx]; - - if (selectOnlyFirst) - { - *stop = YES; - } - } - } - }]; - - return indexes; + [self insertObject:newTrack inTracksAtIndex:[self countOfTracks]]; } -- (void)_processPresetAudioArray:(NSArray *)templateAudioArray forTracks:(NSIndexSet *)trackIndexes firstOnly:(BOOL)firstOnly +/** + * Creates a new track dictionary from a source track. + * + * @param index the index of the source track in the sourceTracks array + */ +- (HBAudioTrack *)trackFromSourceTrackIndex:(NSInteger)index { - __block BOOL firsTrack = firstOnly; - [trackIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { - // Add the track - [self _processPresetAudioArray: self.defaults.tracksArray forTrack:idx firstOnly:firsTrack]; - firsTrack = self.defaults.secondaryEncoderMode ? YES : NO; - }]; + HBAudioTrack *track = [[HBAudioTrack alloc] initWithTrackIdx:index container:self.container dataSource:self delegate:self]; + track.undo = self.undo; + return track; } -- (void)addTracksFromDefaults:(BOOL)allTracks +#pragma mark - Defaults + +- (void)addTracksFromDefaults { BOOL firstTrack = NO; + BOOL allTracks = NO; NSMutableIndexSet *tracksAdded = [NSMutableIndexSet indexSet]; NSMutableIndexSet *tracksToAdd = [NSMutableIndexSet indexSet]; // Reinitialize the configured list of audio tracks - [self _clearAudioArray]; + while (self.countOfTracks) + { + [self removeObjectFromTracksAtIndex:0]; + } if (self.defaults.trackSelectionBehavior != HBAudioTrackSelectionBehaviorNone) { // Add tracks of Default and Alternate Language by name for (NSString *languageISOCode in self.defaults.trackSelectionLanguages) { - NSMutableIndexSet *tracksIndexes = [[self _tracksWithISOCode: languageISOCode - selectOnlyFirst: self.defaults.trackSelectionBehavior == HBAudioTrackSelectionBehaviorFirst] mutableCopy]; + NSMutableIndexSet *tracksIndexes = [[self _tracksWithISOCode:languageISOCode + selectOnlyFirst:self.defaults.trackSelectionBehavior == HBAudioTrackSelectionBehaviorFirst] mutableCopy]; [tracksIndexes removeIndexes:tracksAdded]; if (tracksIndexes.count) { @@ -229,7 +207,7 @@ NSString *HBAudioChangedNotification = @"HBAudioChangedNotification"; } // If no preferred Language was found, add standard track 1 - if (tracksAdded.count == 0 && self.masterTrackArray.count > 1) + if (tracksAdded.count == 0 && self.sourceTracks.count > 1) { [tracksToAdd addIndex:1]; } @@ -238,7 +216,7 @@ NSString *HBAudioChangedNotification = @"HBAudioChangedNotification"; // If all tracks should be added, add all track numbers that are not yet processed if (allTracks) { - [tracksToAdd addIndexesInRange:NSMakeRange(1, self.masterTrackArray.count - 1)]; + [tracksToAdd addIndexesInRange:NSMakeRange(1, self.sourceTracks.count - 1)]; [tracksToAdd removeIndexes:tracksAdded]; } @@ -248,119 +226,131 @@ NSString *HBAudioChangedNotification = @"HBAudioChangedNotification"; } // Add an None item - [self switchingTrackFromNone: nil]; + [self addNoneTrack]; } -- (BOOL)anyCodecMatches:(int)codec +/** + * Uses the templateAudioArray from the preset to create the audios for the specified trackIndex. + * + * @param templateAudioArray the track template. + * @param trackIndex the index of the source track. + * @param firstOnly use only the first track of the template or all. + */ +- (void)_processPresetAudioArray:(NSArray *)templateAudioArray forTrack:(NSUInteger)trackIndex firstOnly:(BOOL)firstOnly { - BOOL retval = NO; - NSUInteger audioArrayCount = [self countOfTracks]; - for (NSUInteger i = 0; i < audioArrayCount && !retval; i++) + for (HBAudioTrackPreset *preset in templateAudioArray) { - HBAudioTrack *anAudio = [self objectInTracksAtIndex: i]; - if ([anAudio enabled] && codec == [[anAudio codec][keyAudioCodec] intValue]) - { - retval = YES; - } - } - return retval; -} - -- (void)addNewAudioTrack -{ - HBAudioTrack *newAudio = [[HBAudioTrack alloc] init]; - [newAudio setDataSource:self]; - [newAudio setDelegate:self]; - [self insertObject:newAudio inTracksAtIndex:[self countOfTracks]]; - [newAudio setContainer:self.container]; - [newAudio setTrack: self.noneTrack]; - [newAudio setUndo:self.undo]; -} + HBAudioTrack *newAudio = [[HBAudioTrack alloc] initWithTrackIdx:trackIndex + container:self.container + dataSource:self + delegate:self]; + [newAudio setUndo:self.undo]; -#pragma mark - -#pragma mark Notification Handling + [self insertObject:newAudio inTracksAtIndex:[self countOfTracks]]; -- (void)settingTrackToNone:(HBAudioTrack *)newNoneTrack -{ - // If this is not the last track in the array we need to remove it. We then need to see if a new - // one needs to be added (in the case when we were at maximum count and this switching makes it - // so we are no longer at maximum. - NSUInteger index = [self.tracks indexOfObject: newNoneTrack]; + int inputCodec = [self.sourceTracks[trackIndex][keyAudioInputCodec] intValue]; + int outputCodec = preset.encoder; - if (NSNotFound != index && index < [self countOfTracks] - 1) - { - [self removeObjectFromTracksAtIndex: index]; - } - [self switchingTrackFromNone: nil]; // see if we need to add one to the list -} + // Check if we need to use a fallback + if (preset.encoder & HB_ACODEC_PASS_FLAG && !(preset.encoder & inputCodec & HB_ACODEC_PASS_MASK)) + { + outputCodec = hb_audio_encoder_get_fallback_for_passthru(outputCodec); + + // If we couldn't find an encoder for the passthru format + // fall back to the selected encoder fallback + if (outputCodec == HB_ACODEC_INVALID) + { + outputCodec = self.defaults.encoderFallback; + } + } + + int supportedMuxers = hb_audio_encoder_get_from_codec(outputCodec)->muxers; + + // If our preset wants us to support a codec that the track does not support, + // instead of changing the codec we remove the audio instead. + if (supportedMuxers & self.container) + { + newAudio.drc = preset.drc; + newAudio.gain = preset.gain; + newAudio.mixdown = preset.mixdown; + newAudio.sampleRate = preset.sampleRate; + newAudio.bitRate = preset.bitRate; + newAudio.encoder = outputCodec; + } + else + { + [self removeObjectFromTracksAtIndex:[self countOfTracks] - 1]; + } -- (void)switchingTrackFromNone:(HBAudioTrack *)noLongerNoneTrack -{ - NSUInteger count = [self countOfTracks]; - BOOL needToAdd = NO; - // If there is no last track that is None we add one. - if (0 < count) - { - HBAudioTrack *lastAudio = [self objectInTracksAtIndex: count - 1]; - if ([lastAudio enabled]) + if (firstOnly) { - needToAdd = YES; + break; } } - else - { - needToAdd = YES; - } - - if (needToAdd) - { - [self addNewAudioTrack]; - } } -// This gets called whenever the video container changes. -- (void)setContainer:(int)container +/** + * Matches the source audio tracks with the specific language iso code. + * + * @param isoCode the iso code to match. + * @param selectOnlyFirst whether to match only the first track for the iso code. + * + * @return a NSIndexSet with the index of the matched tracks. + */ +- (NSIndexSet *)_tracksWithISOCode:(NSString *)isoCode selectOnlyFirst:(BOOL)selectOnlyFirst { - _container = container; + NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet]; - if (!(self.undo.isUndoing || self.undo.isRedoing)) - { - // Update each of the instances because this value influences possible settings. - for (HBAudioTrack *audioObject in self.tracks) + [self.sourceTracks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + if (idx) // Note that we skip the "None" track { - audioObject.container = container; + if ([isoCode isEqualToString:@"und"] || [obj[keyAudioTrackLanguageIsoCode] isEqualToString:isoCode]) + { + [indexes addIndex:idx]; + + if (selectOnlyFirst) + { + *stop = YES; + } + } } + }]; - // Update the Auto Passthru Fallback Codec Popup - // lets get the tag of the currently selected item first so we might reset it later - [self.defaults validateEncoderFallbackForVideoContainer:container]; - } + return indexes; } -- (void)setUndo:(NSUndoManager *)undo +- (void)_processPresetAudioArray:(NSArray<HBAudioTrackPreset *> *)templateAudioArray forTracks:(NSIndexSet *)trackIndexes firstOnly:(BOOL)firstOnly { - _undo = undo; - for (HBAudioTrack *track in self.tracks) - { - track.undo = undo; - } - self.defaults.undo = undo; + __block BOOL firstTrack = firstOnly; + [trackIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { + // Add the track + [self _processPresetAudioArray: self.defaults.tracksArray forTrack:idx firstOnly:firstTrack]; + firstTrack = self.defaults.secondaryEncoderMode ? YES : NO; + }]; } -- (void)setDefaults:(HBAudioDefaults *)defaults +- (BOOL)anyCodecMatches:(int)codec { - if (defaults != _defaults) + BOOL retval = NO; + NSUInteger audioArrayCount = [self countOfTracks]; + for (NSUInteger i = 0; i < audioArrayCount && !retval; i++) { - [[self.undo prepareWithInvocationTarget:self] setDefaults:_defaults]; + HBAudioTrack *anAudio = [self objectInTracksAtIndex: i]; + if (anAudio.isEnabled && codec == anAudio.encoder) + { + retval = YES; + } } - _defaults = defaults; - _defaults.undo = self.undo; + return retval; } -- (void)mixdownChanged +#pragma mark - +#pragma mark Notification Handling + +- (void)encoderChanged { - [[NSNotificationCenter defaultCenter] postNotificationName: HBAudioChangedNotification object: self]; + [[NSNotificationCenter defaultCenter] postNotificationName:HBAudioChangedNotification object:self]; } #pragma mark - NSCopying @@ -372,17 +362,13 @@ NSString *HBAudioChangedNotification = @"HBAudioChangedNotification"; if (copy) { copy->_container = _container; - - copy->_noneTrack = [_noneTrack copy]; - copy->_masterTrackArray = [_masterTrackArray copy]; + copy->_sourceTracks = [_sourceTracks mutableCopy]; copy->_tracks = [[NSMutableArray alloc] init]; [_tracks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if (idx < _tracks.count) { - HBAudioTrack *trackCopy = [obj copy]; - trackCopy.dataSource = copy; - trackCopy.delegate = copy; + id trackCopy = [obj copy]; [copy->_tracks addObject:trackCopy]; } }]; @@ -402,14 +388,11 @@ NSString *HBAudioChangedNotification = @"HBAudioChangedNotification"; - (void)encodeWithCoder:(NSCoder *)coder { - [coder encodeInt:1 forKey:@"HBAudioVersion"]; + [coder encodeInt:2 forKey:@"HBAudioVersion"]; encodeInt(_container); - - encodeObject(_noneTrack); - encodeObject(_masterTrackArray); + encodeObject(_sourceTracks); encodeObject(_tracks); - encodeObject(_defaults); } @@ -418,9 +401,7 @@ NSString *HBAudioChangedNotification = @"HBAudioChangedNotification"; self = [super init]; decodeInt(_container); - - decodeObject(_noneTrack, NSDictionary); - decodeObject(_masterTrackArray, NSArray); + decodeObject(_sourceTracks, NSMutableArray); decodeObject(_tracks, NSMutableArray); for (HBAudioTrack *track in _tracks) @@ -444,13 +425,13 @@ NSString *HBAudioChangedNotification = @"HBAudioChangedNotification"; - (void)applyPreset:(HBPreset *)preset { [self.defaults applyPreset:preset]; - [self addTracksFromDefaults:NO]; + [self addTracksFromDefaults]; } #pragma mark - #pragma mark KVC -- (NSUInteger) countOfTracks +- (NSUInteger)countOfTracks { return self.tracks.count; } |