diff options
Diffstat (limited to 'macosx/HBAudio.m')
-rw-r--r-- | macosx/HBAudio.m | 640 |
1 files changed, 640 insertions, 0 deletions
diff --git a/macosx/HBAudio.m b/macosx/HBAudio.m new file mode 100644 index 000000000..8d226d33e --- /dev/null +++ b/macosx/HBAudio.m @@ -0,0 +1,640 @@ +// +// HBAudio.m +// HandBrake +// +// Created on 2010-08-30. +// + +#import "HBAudio.h" +#import "HBAudioController.h" +#import "hb.h" + +NSString *keyAudioCodecName = @"keyAudioCodecName"; +NSString *keyAudioMP4 = @"keyAudioMP4"; +NSString *keyAudioMKV = @"keyAudioMKV"; +NSString *keyAudioSampleRateName = @"keyAudioSampleRateName"; +NSString *keyAudioBitrateName = @"keyAudioBitrateName"; +NSString *keyAudioMinimumBitrate = @"keyAudioMinimumBitrate"; +NSString *keyAudioMaximumBitrate = @"keyAudioMaximumBitrate"; +NSString *keyAudioMinimumBitrate6Channel = @"keyAudioMinimumBitrate6Channel"; +NSString *keyAudioMaximumBitrate6Channel = @"keyAudioMaximumBitrate6Channel"; +NSString *keyAudioMustMatchTrack = @"keyAudioMustMatchTrack"; +NSString *keyAudioMixdownName = @"keyAudioMixdownName"; +NSString *keyAudioMixdownLimitsToTrackBitRate = @"keyAudioMixdownLimitsToTrackBitRate"; +NSString *keyAudioMixdownCanBeDefault = @"keyAudioMixdownCanBeDefault"; + +NSString *keyAudioCodec = @"codec"; +NSString *keyAudioMixdown = @"mixdown"; +NSString *keyAudioSamplerate = @"samplerate"; +NSString *keyAudioBitrate = @"bitrate"; + +static NSMutableArray *masterCodecArray = nil; +static NSMutableArray *masterSampleRateArray = nil; +static NSMutableArray *masterBitRateArray = nil; +static NSDictionary *defaultBitRate = nil; +static NSDictionary *bitRate384 = nil; + +@interface NSArray (HBAudioSupport) +- (NSDictionary *) dictionaryWithObject: (id) anObject matchingKey: (NSString *) aKey; +- (NSDictionary *) lastDictionaryWithObject: (id) anObject matchingKey: (NSString *) aKey; +@end +@implementation NSArray (HBAudioSupport) +- (NSDictionary *) dictionaryWithObject: (id) anObject matchingKey: (NSString *) aKey reverse: (BOOL) reverse + +{ + NSDictionary *retval = nil; + NSEnumerator *enumerator = reverse ? [self reverseObjectEnumerator] : [self objectEnumerator]; + NSDictionary *dict; + id aValue; + + while (nil != (dict = [enumerator nextObject]) && nil == retval) { + if (nil != (aValue = [dict objectForKey: aKey]) && YES == [aValue isEqual: anObject]) { + retval = dict; + } + } + return retval; +} +- (NSDictionary *) dictionaryWithObject: (id) anObject matchingKey: (NSString *) aKey +{ return [self dictionaryWithObject: anObject matchingKey: aKey reverse: NO]; } +- (NSDictionary *) lastDictionaryWithObject: (id) anObject matchingKey: (NSString *) aKey +{ return [self dictionaryWithObject: anObject matchingKey: aKey reverse: YES]; } + +@end + +@implementation HBAudio + +#pragma mark - +#pragma mark Object Setup + ++ (void) load + +{ + if ([HBAudio class] == self) { + int i; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSDictionary *dict; + + masterCodecArray = [[NSMutableArray alloc] init]; // knowingly leaked + [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedString(@"AAC (CoreAudio)", @"AAC (CoreAudio)"), keyAudioCodecName, + [NSNumber numberWithInt: HB_ACODEC_CA_AAC], keyAudioCodec, + [NSNumber numberWithBool: YES], keyAudioMP4, + [NSNumber numberWithBool: YES], keyAudioMKV, + [NSNumber numberWithBool: NO], keyAudioMustMatchTrack, + [NSNumber numberWithInt: 64], keyAudioMinimumBitrate, + [NSNumber numberWithInt: 320], keyAudioMaximumBitrate, + [NSNumber numberWithInt: 128], keyAudioMinimumBitrate6Channel, + [NSNumber numberWithInt: 768], keyAudioMaximumBitrate6Channel, + nil]]; + [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedString(@"AAC (faac)", @"AAC (faac)"), keyAudioCodecName, + [NSNumber numberWithInt: HB_ACODEC_FAAC], keyAudioCodec, + [NSNumber numberWithBool: YES], keyAudioMP4, + [NSNumber numberWithBool: YES], keyAudioMKV, + [NSNumber numberWithBool: NO], keyAudioMustMatchTrack, + [NSNumber numberWithInt: 32], keyAudioMinimumBitrate, + [NSNumber numberWithInt: 320], keyAudioMaximumBitrate, + [NSNumber numberWithInt: 192], keyAudioMinimumBitrate6Channel, + [NSNumber numberWithInt: 768], keyAudioMaximumBitrate6Channel, + nil]]; + [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedString(@"MP3 (lame)", @"MP3 (lame)"), keyAudioCodecName, + [NSNumber numberWithInt: HB_ACODEC_LAME], keyAudioCodec, + [NSNumber numberWithBool: YES], keyAudioMP4, + [NSNumber numberWithBool: YES], keyAudioMKV, + [NSNumber numberWithBool: NO], keyAudioMustMatchTrack, + [NSNumber numberWithInt: 32], keyAudioMinimumBitrate, + [NSNumber numberWithInt: 320], keyAudioMaximumBitrate, + [NSNumber numberWithInt: 32], keyAudioMinimumBitrate6Channel, + [NSNumber numberWithInt: 320], keyAudioMaximumBitrate6Channel, + nil]]; + [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedString(@"AC3 Passthru", @"AC3 Passthru"), keyAudioCodecName, + [NSNumber numberWithInt: HB_ACODEC_AC3], keyAudioCodec, + [NSNumber numberWithBool: YES], keyAudioMP4, + [NSNumber numberWithBool: YES], keyAudioMKV, + [NSNumber numberWithBool: YES], keyAudioMustMatchTrack, + [NSNumber numberWithInt: 32], keyAudioMinimumBitrate, + [NSNumber numberWithInt: 384], keyAudioMaximumBitrate, + [NSNumber numberWithInt: 32], keyAudioMinimumBitrate6Channel, + [NSNumber numberWithInt: 384], keyAudioMaximumBitrate6Channel, + nil]]; + [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedString(@"DTS Passthru", @"DTS Passthru"), keyAudioCodecName, + [NSNumber numberWithInt: HB_ACODEC_DCA], keyAudioCodec, + [NSNumber numberWithBool: NO], keyAudioMP4, + [NSNumber numberWithBool: YES], keyAudioMKV, + [NSNumber numberWithBool: YES], keyAudioMustMatchTrack, + [NSNumber numberWithInt: 32], keyAudioMinimumBitrate, + [NSNumber numberWithInt: 384], keyAudioMaximumBitrate, + [NSNumber numberWithInt: 32], keyAudioMinimumBitrate6Channel, + [NSNumber numberWithInt: 384], keyAudioMaximumBitrate6Channel, + nil]]; + [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedString(@"Vorbis (vorbis)", @"Vorbis (vorbis)"), keyAudioCodecName, + [NSNumber numberWithInt: HB_ACODEC_VORBIS], keyAudioCodec, + [NSNumber numberWithBool: NO], keyAudioMP4, + [NSNumber numberWithBool: YES], keyAudioMKV, + [NSNumber numberWithBool: NO], keyAudioMustMatchTrack, + [NSNumber numberWithInt: 48], keyAudioMinimumBitrate, + [NSNumber numberWithInt: 384], keyAudioMaximumBitrate, + [NSNumber numberWithInt: 192], keyAudioMinimumBitrate6Channel, + [NSNumber numberWithInt: 384], keyAudioMaximumBitrate6Channel, + nil]]; + + // Note that for the Auto value we use 0 for the sample rate because our controller will give back the track's + // input sample rate when it finds this 0 value as the selected sample rate. We do this because the input + // sample rate depends on the track, which means it depends on the title, so cannot be nicely set up here. + masterSampleRateArray = [[NSMutableArray alloc] init]; // knowingly leaked + [masterSampleRateArray addObject: [NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedString(@"Auto", @"Auto"), keyAudioSampleRateName, + [NSNumber numberWithInt: 0], keyAudioSamplerate, + nil]]; + for (i = 0; i < hb_audio_rates_count; i++) { + [masterSampleRateArray addObject: [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithUTF8String: hb_audio_rates[i].string], keyAudioSampleRateName, + [NSNumber numberWithInt: hb_audio_rates[i].rate], keyAudioSamplerate, + nil]]; + } + + masterBitRateArray = [[NSMutableArray alloc] init]; // knowingly leaked + int defaultRate = hb_audio_bitrates[hb_audio_bitrates_default].rate; + for (i = 0; i < hb_audio_bitrates_count; i++) { + int rate = hb_audio_bitrates[i].rate; + dict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithUTF8String: hb_audio_bitrates[i].string], keyAudioBitrateName, + [NSNumber numberWithInt: rate], keyAudioBitrate, + nil]; + if (rate == defaultRate) { + defaultBitRate = [dict retain]; // knowingly leaked + } + if (384 == rate) { + bitRate384 = [dict retain]; // knowingly leaked + } + [masterBitRateArray addObject: dict]; + } + + [pool release]; + } + return; +} + +// Ensure the list of codecs is accurate +// Update the current value of codec based on the revised list +- (void) updateCodecs + +{ + NSMutableArray *permittedCodecs = [NSMutableArray array]; + unsigned int count = [masterCodecArray count]; + NSDictionary *dict; + NSString *keyThatAllows = nil; + + // Determine which key we use to see which codecs are permitted + switch ([videoContainerTag intValue]) { + case HB_MUX_MP4: + keyThatAllows = keyAudioMP4; + break; + case HB_MUX_MKV: + keyThatAllows = keyAudioMKV; + break; + default: + keyThatAllows = @"error condition"; + break; + } + + // First get a list of the permitted codecs based on the internal rules + if (nil != track && YES == [self enabled]) { + BOOL goodToAdd; + + for (unsigned int i = 0; i < count; i++) { + dict = [masterCodecArray objectAtIndex: i]; + + // First make sure only codecs permitted by the container are here + goodToAdd = [[dict objectForKey: keyThatAllows] boolValue]; + + // Now we make sure if DTS or AC3 is not available in the track it is not put in the codec list, but in a general way + if (YES == [[dict objectForKey: keyAudioMustMatchTrack] boolValue]) { + if ([[dict objectForKey: keyAudioCodec] intValue] != [[[self track] objectForKey: keyAudioInputCodec] intValue]) { + goodToAdd = NO; + } + } + + if (YES == goodToAdd) { + [permittedCodecs addObject: dict]; + } + } + } + + // Now make sure the permitted list and the actual ones matches + [self setCodecs: permittedCodecs]; + + // Ensure our codec is on the list of permitted codecs + if (nil == [self codec] || NO == [permittedCodecs containsObject: [self codec]]) { + if (0 < [permittedCodecs count]) { + [self setCodec: [permittedCodecs objectAtIndex: 0]]; // This should be defaulting to Core Audio + } + else { + [self setCodec: nil]; + } + } + + return; +} + +// The rules here are provided as-is from the original -[Controller audioTrackPopUpChanged:mixdownToUse:] routine +// with the comments taken from there as well. +- (void) updateMixdowns + +{ + NSMutableArray *retval = [NSMutableArray array]; + int trackCodec = [[track objectForKey: keyAudioInputCodec] intValue]; + int codecCodec = [[codec objectForKey: keyAudioCodec] intValue]; + + if (HB_ACODEC_AC3 == trackCodec && HB_ACODEC_AC3 == codecCodec) { + [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedString(@"AC3 Passthru", @"AC3 Passthru"), keyAudioMixdownName, + [NSNumber numberWithInt: HB_ACODEC_AC3], keyAudioMixdown, + [NSNumber numberWithBool: YES], keyAudioMixdownLimitsToTrackBitRate, + [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault, + nil]]; + } + else if (HB_ACODEC_DCA == trackCodec && HB_ACODEC_DCA == codecCodec) { + [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys: + NSLocalizedString(@"DTS Passthru", @"DTS Passthru"), keyAudioMixdownName, + [NSNumber numberWithInt: HB_ACODEC_DCA], keyAudioMixdown, + [NSNumber numberWithBool: YES], keyAudioMixdownLimitsToTrackBitRate, + [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault, + nil]]; + } + else { + int audioCodecsSupport6Ch = (trackCodec && HB_ACODEC_LAME != codecCodec); + int channelLayout = [[track objectForKey: keyAudioInputChannelLayout] intValue]; + int layout = channelLayout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK; + + /* add a mono option? */ + [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithUTF8String: hb_audio_mixdowns[0].human_readable_name], keyAudioMixdownName, + [NSNumber numberWithInt: hb_audio_mixdowns[0].amixdown], keyAudioMixdown, + [NSNumber numberWithBool: NO], keyAudioMixdownLimitsToTrackBitRate, + [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault, + nil]]; + + /* offer stereo if we have a stereo-or-better source */ + if (layout >= HB_INPUT_CH_LAYOUT_STEREO) { + [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithUTF8String: hb_audio_mixdowns[1].human_readable_name], keyAudioMixdownName, + [NSNumber numberWithInt: hb_audio_mixdowns[1].amixdown], keyAudioMixdown, + [NSNumber numberWithBool: NO], keyAudioMixdownLimitsToTrackBitRate, + [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault, + nil]]; + } + + /* do we want to add a dolby surround (DPL1) option? */ + if (HB_INPUT_CH_LAYOUT_3F1R == layout || HB_INPUT_CH_LAYOUT_3F2R == layout || HB_INPUT_CH_LAYOUT_DOLBY == layout) { + [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithUTF8String: hb_audio_mixdowns[2].human_readable_name], keyAudioMixdownName, + [NSNumber numberWithInt: hb_audio_mixdowns[2].amixdown], keyAudioMixdown, + [NSNumber numberWithBool: NO], keyAudioMixdownLimitsToTrackBitRate, + [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault, + nil]]; + } + + /* do we want to add a dolby pro logic 2 (DPL2) option? */ + if (HB_INPUT_CH_LAYOUT_3F2R == layout) { + [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithUTF8String: hb_audio_mixdowns[3].human_readable_name], keyAudioMixdownName, + [NSNumber numberWithInt: hb_audio_mixdowns[3].amixdown], keyAudioMixdown, + [NSNumber numberWithBool: NO], keyAudioMixdownLimitsToTrackBitRate, + [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault, + nil]]; + } + + /* do we want to add a 6-channel discrete option? */ + if (1 == audioCodecsSupport6Ch && HB_INPUT_CH_LAYOUT_3F2R == layout && (channelLayout & HB_INPUT_CH_LAYOUT_HAS_LFE)) { + [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithUTF8String: hb_audio_mixdowns[4].human_readable_name], keyAudioMixdownName, + [NSNumber numberWithInt: hb_audio_mixdowns[4].amixdown], keyAudioMixdown, + [NSNumber numberWithBool: NO], keyAudioMixdownLimitsToTrackBitRate, + [NSNumber numberWithBool: NO], keyAudioMixdownCanBeDefault, + nil]]; + } + + // based on the fact that we are in an else section where the ifs before hand would have detected the following two + // situations, the following code will never add anything to the returned array. I am leaving this in place for + // historical reasons. + /* do we want to add an AC-3 passthrough option? */ + if (HB_ACODEC_AC3 == trackCodec && HB_ACODEC_AC3 == codecCodec) { + [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithUTF8String: hb_audio_mixdowns[5].human_readable_name], keyAudioMixdownName, + [NSNumber numberWithInt: HB_ACODEC_AC3], keyAudioMixdown, + [NSNumber numberWithBool: YES], keyAudioMixdownLimitsToTrackBitRate, + [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault, + nil]]; + } + + /* do we want to add a DTS Passthru option ? HB_ACODEC_DCA*/ + if (HB_ACODEC_DCA == trackCodec && HB_ACODEC_DCA == codecCodec) { + [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithUTF8String: hb_audio_mixdowns[5].human_readable_name], keyAudioMixdownName, + [NSNumber numberWithInt: HB_ACODEC_DCA], keyAudioMixdown, + [NSNumber numberWithBool: YES], keyAudioMixdownLimitsToTrackBitRate, + [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault, + nil]]; + } + } + + // Now make sure the permitted list and the actual ones matches + [self setMixdowns: retval]; + + // Ensure our mixdown is on the list of permitted ones + if (nil == [self mixdown] || NO == [retval containsObject: [self mixdown]]) { + [self setMixdown: [retval lastDictionaryWithObject: [NSNumber numberWithBool: YES] matchingKey: keyAudioMixdownCanBeDefault]]; + } + + return; +} + +- (void) updateBitRates + +{ + NSMutableArray *permittedBitRates = [NSMutableArray array]; + int count; + NSDictionary *dict; + BOOL has6chMixdown = (HB_AMIXDOWN_6CH == [[[self mixdown] objectForKey: keyAudioMixdown] intValue]); + + count = [masterBitRateArray count]; + NSString *minKey = (has6chMixdown) ? keyAudioMinimumBitrate6Channel : keyAudioMinimumBitrate; + NSString *maxKey = (has6chMixdown) ? keyAudioMaximumBitrate6Channel : keyAudioMaximumBitrate; + int minBitRate = [[codec objectForKey: minKey] intValue]; + int maxBitRate = [[codec objectForKey: maxKey] intValue]; + int currentBitRate; + int trackInputBitRate = [[[self track] objectForKey: keyAudioInputBitrate] intValue]; + BOOL limitsToTrackInputBitRate = [[[self mixdown] objectForKey: keyAudioMixdownLimitsToTrackBitRate] boolValue]; + BOOL shouldAdd; + + for (unsigned int i = 0; i < count; i++) { + dict = [masterBitRateArray objectAtIndex: i]; + currentBitRate = [[dict objectForKey: keyAudioBitrate] intValue]; + + // First ensure the bitrate falls within range of the codec + shouldAdd = (currentBitRate >= minBitRate && currentBitRate <= maxBitRate); + + // Now make sure the mixdown is not limiting us to the track input bitrate + if (YES == shouldAdd && YES == limitsToTrackInputBitRate) { + if (currentBitRate != trackInputBitRate) { + shouldAdd = NO; + } + } + + if (YES == shouldAdd) { + [permittedBitRates addObject: dict]; + } + } + + // There is a situation where we have a mixdown requirement to match the track input bit rate, + // but it does not fall into the range the codec supports. Therefore, we force it here. + if (YES == limitsToTrackInputBitRate && 0 == [permittedBitRates count]) { + NSDictionary *missingBitRate = [masterBitRateArray dictionaryWithObject: [NSNumber numberWithInt: trackInputBitRate] matchingKey: keyAudioBitrate]; + if (nil == missingBitRate) { + // We are in an even worse situation where the requested bit rate does not even exist in the underlying + // library of supported bitrates. Of course since this value is ignored we can freely make a bogus one + // for the UI just to make the user a little more aware. + missingBitRate = [NSDictionary dictionaryWithObjectsAndKeys: + [NSString stringWithFormat: @"%d", trackInputBitRate], keyAudioBitrateName, + [NSNumber numberWithInt: trackInputBitRate], keyAudioBitrate, + nil]; + } + [permittedBitRates addObject: missingBitRate]; + } + + // Make sure we are updated with the permitted list + [self setBitRates: permittedBitRates]; + + // Select the proper one + if (YES == has6chMixdown) { + [self setBitRate: bitRate384]; + } + else { + [self setBitRate: defaultBitRate]; + } + if (nil == [self bitRate] || NO == [permittedBitRates containsObject: [self bitRate]]) { + [self setBitRate: [permittedBitRates lastObject]]; + } + + return; +} + +#pragma mark - +#pragma mark Accessors + +@synthesize track; +@synthesize codec; +@synthesize mixdown; +@synthesize sampleRate; +@synthesize bitRate; +@synthesize drc; +@synthesize videoContainerTag; +@synthesize controller; + +@synthesize codecs; +@synthesize mixdowns; +@synthesize bitRates; + +- (void) setVideoContainerTag: (NSNumber *) aValue + +{ + if ((nil != aValue || nil != videoContainerTag) && NO == [aValue isEqual: videoContainerTag]) { + [aValue retain]; + [videoContainerTag release]; + videoContainerTag = aValue; + [self updateCodecs]; + } + return; +} + +// We do some detection of the None track to do special things. +- (void) setTrack: (NSDictionary *) aValue + +{ + if ((nil != aValue || nil != track) && NO == [aValue isEqual: track]) { + BOOL switchingFromNone = [track isEqual: [controller noneTrack]]; + BOOL switchingToNone = [aValue isEqual: [controller noneTrack]]; + + [aValue retain]; + [track release]; + track = aValue; + + if (nil != aValue) { + [self updateCodecs]; + if (YES == [self enabled]) { + [self setSampleRate: [[self sampleRates] objectAtIndex: 0]]; // default to Auto + } + if (YES == switchingFromNone) { + [controller switchingTrackFromNone: self]; + } + if (YES == switchingToNone) { + [controller settingTrackToNone: self]; + } + } + } + return; +} + +- (void) setCodec: (NSDictionary *) aValue + +{ + if ((nil != aValue || nil != codec) && NO == [aValue isEqual: codec]) { + [aValue retain]; + [codec release]; + codec = aValue; + [self updateMixdowns]; + [self updateBitRates]; + } + return; +} + +- (void) setMixdown: (NSDictionary *) aValue + +{ + if ((nil != aValue || nil != mixdown) && NO == [aValue isEqual: mixdown]) { + [aValue retain]; + [mixdown release]; + mixdown = aValue; + [self updateBitRates]; + [[NSNotificationCenter defaultCenter] postNotificationName: HBMixdownChangedNotification object: self]; + } + return; +} + +- (NSArray *) tracks { return [controller masterTrackArray]; } + +- (NSArray *) sampleRates { return masterSampleRateArray; } + +- (void) dealloc + +{ + [self setTrack: nil]; + [self setCodec: nil]; + [self setMixdown: nil]; + [self setSampleRate: nil]; + [self setBitRate: nil]; + [self setDrc: nil]; + [self setVideoContainerTag: nil]; + [self setCodecs: nil]; + [self setMixdowns: nil]; + [self setBitRates: nil]; + [super dealloc]; + return; +} + +#pragma mark - +#pragma mark Special Setters + +- (void) setTrackFromIndex: (int) aValue + +{ + [self setTrack: [[self tracks] dictionaryWithObject: [NSNumber numberWithInt: aValue] matchingKey: keyAudioTrackIndex]]; + return; +} + +// This returns whether it is able to set the actual codec desired. +- (BOOL) setCodecFromName: (NSString *) aValue + +{ + NSDictionary *dict = [[self codecs] dictionaryWithObject: aValue matchingKey: keyAudioCodecName]; + + if (nil != dict) { + [self setCodec: dict]; + } + return (nil != dict); +} + +- (void) setMixdownFromName: (NSString *) aValue + +{ + NSDictionary *dict = [[self mixdowns] dictionaryWithObject: aValue matchingKey: keyAudioMixdownName]; + + if (nil != dict) { + [self setMixdown: dict]; + } + return; +} + +- (void) setSampleRateFromName: (NSString *) aValue + +{ + NSDictionary *dict = [[self sampleRates] dictionaryWithObject: aValue matchingKey: keyAudioSampleRateName]; + + if (nil != dict) { + [self setSampleRate: dict]; + } + return; +} + +- (void) setBitRateFromName: (NSString *) aValue + +{ + NSDictionary *dict = [[self bitRates] dictionaryWithObject: aValue matchingKey: keyAudioBitrateName]; + + if (nil != dict) { + [self setBitRate: dict]; + } + return; +} + + +#pragma mark - +#pragma mark Validation + +// Because we have indicated that the binding for the drc validates immediately we can implement the +// key value binding method to ensure the drc stays in our accepted range. +- (BOOL) validateDrc: (id *) ioValue error: (NSError *) outError + +{ + BOOL retval = YES; + + if (nil != *ioValue) { + if (0.0 < [*ioValue floatValue] && 1.0 > [*ioValue floatValue]) { + *ioValue = [NSNumber numberWithFloat: 1.0]; + } + } + + return retval; +} + +#pragma mark - +#pragma mark Bindings Support + +- (BOOL) enabled + +{ + return (nil != track) ? (NO == [track isEqual: [controller noneTrack]]) : NO; +} + +- (BOOL) mixdownEnabled + +{ + BOOL retval = [self enabled]; + + if (YES == retval) { + int myMixdown = [[[self mixdown] objectForKey: keyAudioMixdown] intValue]; + if (HB_ACODEC_AC3 == myMixdown || HB_ACODEC_DCA == myMixdown) { + retval = NO; + } + } + return retval; +} + ++ (NSSet *) keyPathsForValuesAffectingEnabled + +{ + return [NSSet setWithObjects: @"track", nil]; +} + ++ (NSSet *) keyPathsForValuesAffectingMixdownEnabled + +{ + return [NSSet setWithObjects: @"track", @"mixdown", nil]; +} + +@end |