summaryrefslogtreecommitdiffstats
path: root/macosx/HBAudio.m
diff options
context:
space:
mode:
authorDamiano Galassi <[email protected]>2016-09-03 18:11:11 +0200
committerDamiano Galassi <[email protected]>2016-09-03 18:11:11 +0200
commit85d5fb9e66e6568b055b8350dfed3e044206c4a8 (patch)
tree6f415c375eab50026432ba1948525eec7fe8d61d /macosx/HBAudio.m
parent29c7a63c2ae91fc557f5586587a3a3e949ca8843 (diff)
MacGui: rework HBAudioTrack to use less NSDictionary.
Diffstat (limited to 'macosx/HBAudio.m')
-rw-r--r--macosx/HBAudio.m455
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;
}