5 // Created on 2010-08-30.
9 #import "HBAudioController.h"
12 NSString *keyAudioCodecName = @"keyAudioCodecName";
13 NSString *keyAudioMP4 = @"keyAudioMP4";
14 NSString *keyAudioMKV = @"keyAudioMKV";
15 NSString *keyAudioSampleRateName = @"keyAudioSampleRateName";
16 NSString *keyAudioBitrateName = @"keyAudioBitrateName";
17 NSString *keyAudioMustMatchTrack = @"keyAudioMustMatchTrack";
18 NSString *keyAudioMixdownName = @"keyAudioMixdownName";
19 NSString *keyAudioMixdownLimitsToTrackBitRate = @"keyAudioMixdownLimitsToTrackBitRate";
20 NSString *keyAudioMixdownCanBeDefault = @"keyAudioMixdownCanBeDefault";
22 NSString *keyAudioCodec = @"codec";
23 NSString *keyAudioMixdown = @"mixdown";
24 NSString *keyAudioSamplerate = @"samplerate";
25 NSString *keyAudioBitrate = @"bitrate";
27 static NSMutableArray *masterCodecArray = nil;
28 static NSMutableArray *masterSampleRateArray = nil;
29 static NSMutableArray *masterBitRateArray = nil;
31 @interface NSArray (HBAudioSupport)
32 - (NSDictionary *) dictionaryWithObject: (id) anObject matchingKey: (NSString *) aKey;
33 - (NSDictionary *) lastDictionaryWithObject: (id) anObject matchingKey: (NSString *) aKey;
35 @implementation NSArray (HBAudioSupport)
36 - (NSDictionary *) dictionaryWithObject: (id) anObject matchingKey: (NSString *) aKey reverse: (BOOL) reverse
39 NSDictionary *retval = nil;
40 NSEnumerator *enumerator = reverse ? [self reverseObjectEnumerator] : [self objectEnumerator];
44 while (nil != (dict = [enumerator nextObject]) && nil == retval) {
45 if (nil != (aValue = [dict objectForKey: aKey]) && YES == [aValue isEqual: anObject]) {
51 - (NSDictionary *) dictionaryWithObject: (id) anObject matchingKey: (NSString *) aKey
52 { return [self dictionaryWithObject: anObject matchingKey: aKey reverse: NO]; }
53 - (NSDictionary *) lastDictionaryWithObject: (id) anObject matchingKey: (NSString *) aKey
54 { return [self dictionaryWithObject: anObject matchingKey: aKey reverse: YES]; }
58 @implementation HBAudio
61 #pragma mark Object Setup
66 if ([HBAudio class] == self) {
68 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
71 masterCodecArray = [[NSMutableArray alloc] init]; // knowingly leaked
72 [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
73 NSLocalizedString(@"AAC (CoreAudio)", @"AAC (CoreAudio)"), keyAudioCodecName,
74 [NSNumber numberWithInt: HB_ACODEC_CA_AAC], keyAudioCodec,
75 [NSNumber numberWithBool: YES], keyAudioMP4,
76 [NSNumber numberWithBool: YES], keyAudioMKV,
77 [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
79 [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
80 NSLocalizedString(@"AAC (faac)", @"AAC (faac)"), keyAudioCodecName,
81 [NSNumber numberWithInt: HB_ACODEC_FAAC], keyAudioCodec,
82 [NSNumber numberWithBool: YES], keyAudioMP4,
83 [NSNumber numberWithBool: YES], keyAudioMKV,
84 [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
86 [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
87 NSLocalizedString(@"MP3 (lame)", @"MP3 (lame)"), keyAudioCodecName,
88 [NSNumber numberWithInt: HB_ACODEC_LAME], keyAudioCodec,
89 [NSNumber numberWithBool: YES], keyAudioMP4,
90 [NSNumber numberWithBool: YES], keyAudioMKV,
91 [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
93 [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
94 NSLocalizedString(@"AC3 Passthru", @"AC3 Passthru"), keyAudioCodecName,
95 [NSNumber numberWithInt: HB_ACODEC_AC3_PASS], keyAudioCodec,
96 [NSNumber numberWithBool: YES], keyAudioMP4,
97 [NSNumber numberWithBool: YES], keyAudioMKV,
98 [NSNumber numberWithInt: HB_ACODEC_AC3], keyAudioMustMatchTrack,
100 [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
101 NSLocalizedString(@"AC3", @"AC3"), keyAudioCodecName,
102 [NSNumber numberWithInt: HB_ACODEC_AC3], keyAudioCodec,
103 [NSNumber numberWithBool: YES], keyAudioMP4,
104 [NSNumber numberWithBool: YES], keyAudioMKV,
105 [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
107 [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
108 NSLocalizedString(@"DTS Passthru", @"DTS Passthru"), keyAudioCodecName,
109 [NSNumber numberWithInt: HB_ACODEC_DCA_PASS], keyAudioCodec,
110 [NSNumber numberWithBool: NO], keyAudioMP4,
111 [NSNumber numberWithBool: YES], keyAudioMKV,
112 [NSNumber numberWithInt: HB_ACODEC_DCA], keyAudioMustMatchTrack,
114 [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
115 NSLocalizedString(@"Vorbis (vorbis)", @"Vorbis (vorbis)"), keyAudioCodecName,
116 [NSNumber numberWithInt: HB_ACODEC_VORBIS], keyAudioCodec,
117 [NSNumber numberWithBool: NO], keyAudioMP4,
118 [NSNumber numberWithBool: YES], keyAudioMKV,
119 [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
122 // Note that for the Auto value we use 0 for the sample rate because our controller will give back the track's
123 // input sample rate when it finds this 0 value as the selected sample rate. We do this because the input
124 // sample rate depends on the track, which means it depends on the title, so cannot be nicely set up here.
125 masterSampleRateArray = [[NSMutableArray alloc] init]; // knowingly leaked
126 [masterSampleRateArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
127 NSLocalizedString(@"Auto", @"Auto"), keyAudioSampleRateName,
128 [NSNumber numberWithInt: 0], keyAudioSamplerate,
130 for (i = 0; i < hb_audio_rates_count; i++) {
131 [masterSampleRateArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
132 [NSString stringWithUTF8String: hb_audio_rates[i].string], keyAudioSampleRateName,
133 [NSNumber numberWithInt: hb_audio_rates[i].rate], keyAudioSamplerate,
137 masterBitRateArray = [[NSMutableArray alloc] init]; // knowingly leaked
138 for (i = 0; i < hb_audio_bitrates_count; i++) {
139 int rate = hb_audio_bitrates[i].rate;
140 dict = [NSDictionary dictionaryWithObjectsAndKeys:
141 [NSString stringWithUTF8String: hb_audio_bitrates[i].string], keyAudioBitrateName,
142 [NSNumber numberWithInt: rate], keyAudioBitrate,
144 [masterBitRateArray addObject: dict];
152 // Ensure the list of codecs is accurate
153 // Update the current value of codec based on the revised list
154 - (void) updateCodecs
157 NSMutableArray *permittedCodecs = [NSMutableArray array];
158 unsigned int count = [masterCodecArray count];
160 NSString *keyThatAllows = nil;
162 // Determine which key we use to see which codecs are permitted
163 switch ([videoContainerTag intValue]) {
165 keyThatAllows = keyAudioMP4;
168 keyThatAllows = keyAudioMKV;
171 keyThatAllows = @"error condition";
175 // First get a list of the permitted codecs based on the internal rules
176 if (nil != track && YES == [self enabled]) {
179 for (unsigned int i = 0; i < count; i++) {
180 dict = [masterCodecArray objectAtIndex: i];
182 // First make sure only codecs permitted by the container are here
183 goodToAdd = [[dict objectForKey: keyThatAllows] boolValue];
185 // 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
186 if (YES == [[dict objectForKey: keyAudioMustMatchTrack] boolValue]) {
187 if ([[dict objectForKey: keyAudioMustMatchTrack] intValue] != [[[self track] objectForKey: keyAudioInputCodec] intValue]) {
192 if (YES == goodToAdd) {
193 [permittedCodecs addObject: dict];
198 // Now make sure the permitted list and the actual ones matches
199 [self setCodecs: permittedCodecs];
201 // Ensure our codec is on the list of permitted codecs
202 if (nil == [self codec] || NO == [permittedCodecs containsObject: [self codec]]) {
203 if (0 < [permittedCodecs count]) {
204 [self setCodec: [permittedCodecs objectAtIndex: 0]]; // This should be defaulting to Core Audio
207 [self setCodec: nil];
214 // The rules here are provided as-is from the original -[Controller audioTrackPopUpChanged:mixdownToUse:] routine
215 // with the comments taken from there as well.
216 - (void) updateMixdowns
219 NSMutableArray *retval = [NSMutableArray array];
220 int trackCodec = [[track objectForKey: keyAudioInputCodec] intValue];
221 int codecCodec = [[codec objectForKey: keyAudioCodec] intValue];
223 if (HB_ACODEC_AC3 == trackCodec && HB_ACODEC_AC3_PASS == codecCodec) {
224 [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys:
225 NSLocalizedString(@"AC3 Passthru", @"AC3 Passthru"), keyAudioMixdownName,
226 [NSNumber numberWithInt: HB_ACODEC_AC3_PASS], keyAudioMixdown,
227 [NSNumber numberWithBool: YES], keyAudioMixdownLimitsToTrackBitRate,
228 [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault,
231 else if (HB_ACODEC_DCA == trackCodec && HB_ACODEC_DCA_PASS == codecCodec) {
232 [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys:
233 NSLocalizedString(@"DTS Passthru", @"DTS Passthru"), keyAudioMixdownName,
234 [NSNumber numberWithInt: HB_ACODEC_DCA_PASS], keyAudioMixdown,
235 [NSNumber numberWithBool: YES], keyAudioMixdownLimitsToTrackBitRate,
236 [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault,
240 int audioCodecsSupport6Ch = (trackCodec && HB_ACODEC_LAME != codecCodec);
241 int channelLayout = [[track objectForKey: keyAudioInputChannelLayout] intValue];
242 int layout = channelLayout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
244 /* add a mono option? */
245 [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys:
246 [NSString stringWithUTF8String: hb_audio_mixdowns[0].human_readable_name], keyAudioMixdownName,
247 [NSNumber numberWithInt: hb_audio_mixdowns[0].amixdown], keyAudioMixdown,
248 [NSNumber numberWithBool: NO], keyAudioMixdownLimitsToTrackBitRate,
249 [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault,
252 /* offer stereo if we have a stereo-or-better source */
253 if (layout >= HB_INPUT_CH_LAYOUT_STEREO) {
254 [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys:
255 [NSString stringWithUTF8String: hb_audio_mixdowns[1].human_readable_name], keyAudioMixdownName,
256 [NSNumber numberWithInt: hb_audio_mixdowns[1].amixdown], keyAudioMixdown,
257 [NSNumber numberWithBool: NO], keyAudioMixdownLimitsToTrackBitRate,
258 [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault,
262 /* do we want to add a dolby surround (DPL1) option? */
263 if (HB_INPUT_CH_LAYOUT_3F1R == layout || HB_INPUT_CH_LAYOUT_3F2R == layout || HB_INPUT_CH_LAYOUT_DOLBY == layout) {
264 [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys:
265 [NSString stringWithUTF8String: hb_audio_mixdowns[2].human_readable_name], keyAudioMixdownName,
266 [NSNumber numberWithInt: hb_audio_mixdowns[2].amixdown], keyAudioMixdown,
267 [NSNumber numberWithBool: NO], keyAudioMixdownLimitsToTrackBitRate,
268 [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault,
272 /* do we want to add a dolby pro logic 2 (DPL2) option? */
273 if (HB_INPUT_CH_LAYOUT_3F2R == layout) {
274 [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys:
275 [NSString stringWithUTF8String: hb_audio_mixdowns[3].human_readable_name], keyAudioMixdownName,
276 [NSNumber numberWithInt: hb_audio_mixdowns[3].amixdown], keyAudioMixdown,
277 [NSNumber numberWithBool: NO], keyAudioMixdownLimitsToTrackBitRate,
278 [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault,
282 /* do we want to add a 6-channel discrete option? */
283 if (1 == audioCodecsSupport6Ch && HB_INPUT_CH_LAYOUT_3F2R == layout && (channelLayout & HB_INPUT_CH_LAYOUT_HAS_LFE)) {
284 [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys:
285 [NSString stringWithUTF8String: hb_audio_mixdowns[4].human_readable_name], keyAudioMixdownName,
286 [NSNumber numberWithInt: hb_audio_mixdowns[4].amixdown], keyAudioMixdown,
287 [NSNumber numberWithBool: NO], keyAudioMixdownLimitsToTrackBitRate,
288 [NSNumber numberWithBool: (HB_ACODEC_AC3 == codecCodec) ? YES : NO], keyAudioMixdownCanBeDefault,
292 // based on the fact that we are in an else section where the ifs before hand would have detected the following two
293 // situations, the following code will never add anything to the returned array. I am leaving this in place for
294 // historical reasons.
295 /* do we want to add an AC-3 passthrough option? */
296 if (HB_ACODEC_AC3 == trackCodec && HB_ACODEC_AC3_PASS == codecCodec) {
297 [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys:
298 [NSString stringWithUTF8String: hb_audio_mixdowns[5].human_readable_name], keyAudioMixdownName,
299 [NSNumber numberWithInt: HB_ACODEC_AC3_PASS], keyAudioMixdown,
300 [NSNumber numberWithBool: YES], keyAudioMixdownLimitsToTrackBitRate,
301 [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault,
305 /* do we want to add a DTS Passthru option ? HB_ACODEC_DCA*/
306 if (HB_ACODEC_DCA == trackCodec && HB_ACODEC_DCA_PASS == codecCodec) {
307 [retval addObject: [NSDictionary dictionaryWithObjectsAndKeys:
308 [NSString stringWithUTF8String: hb_audio_mixdowns[5].human_readable_name], keyAudioMixdownName,
309 [NSNumber numberWithInt: HB_ACODEC_DCA_PASS], keyAudioMixdown,
310 [NSNumber numberWithBool: YES], keyAudioMixdownLimitsToTrackBitRate,
311 [NSNumber numberWithBool: YES], keyAudioMixdownCanBeDefault,
316 if (NO == [self enabled]) {
320 // Now make sure the permitted list and the actual ones matches
321 [self setMixdowns: retval];
323 // Ensure our mixdown is on the list of permitted ones
324 if (YES == [[NSUserDefaults standardUserDefaults] boolForKey: @"CodecDefaultsMixdown"] ||
325 nil == [self mixdown] || NO == [retval containsObject: [self mixdown]]) {
326 [self setMixdown: [retval lastDictionaryWithObject: [NSNumber numberWithBool: YES] matchingKey: keyAudioMixdownCanBeDefault]];
332 - (void) updateBitRates: (BOOL) shouldSetDefault
335 NSMutableArray *permittedBitRates = [NSMutableArray array];
339 count = [masterBitRateArray count];
342 NSString *defaultBitRate;
344 int trackInputBitRate = [[[self track] objectForKey: keyAudioInputBitrate] intValue];
345 BOOL limitsToTrackInputBitRate = [[[self mixdown] objectForKey: keyAudioMixdownLimitsToTrackBitRate] boolValue];
347 int theSampleRate = [[[self sampleRate] objectForKey: keyAudioSamplerate] intValue];
349 if (0 == theSampleRate) { // this means Auto
350 theSampleRate = [[[self track] objectForKey: keyAudioInputSampleRate] intValue];
353 int ourCodec = [[codec objectForKey: keyAudioCodec] intValue];
354 int ourMixdown = [[[self mixdown] objectForKey: keyAudioMixdown] intValue];
355 hb_get_audio_bitrate_limits(ourCodec, theSampleRate, ourMixdown, &minBitRate, &maxBitRate);
356 int theDefaultBitRate = hb_get_default_audio_bitrate(ourCodec, theSampleRate, ourMixdown);
357 defaultBitRate = [NSString stringWithFormat: @"%d", theDefaultBitRate];
359 for (unsigned int i = 0; i < count; i++) {
360 dict = [masterBitRateArray objectAtIndex: i];
361 currentBitRate = [[dict objectForKey: keyAudioBitrate] intValue];
363 // First ensure the bitrate falls within range of the codec
364 shouldAdd = (currentBitRate >= minBitRate && currentBitRate <= maxBitRate);
366 // Now make sure the mixdown is not limiting us to the track input bitrate
367 if (YES == shouldAdd && YES == limitsToTrackInputBitRate) {
368 if (currentBitRate != trackInputBitRate) {
373 if (YES == shouldAdd) {
374 [permittedBitRates addObject: dict];
378 // There is a situation where we have a mixdown requirement to match the track input bit rate,
379 // but it does not fall into the range the codec supports. Therefore, we force it here.
380 if (YES == limitsToTrackInputBitRate && 0 == [permittedBitRates count]) {
381 NSDictionary *missingBitRate = [masterBitRateArray dictionaryWithObject: [NSNumber numberWithInt: trackInputBitRate] matchingKey: keyAudioBitrate];
382 if (nil == missingBitRate) {
383 // We are in an even worse situation where the requested bit rate does not even exist in the underlying
384 // library of supported bitrates. Of course since this value is ignored we can freely make a bogus one
385 // for the UI just to make the user a little more aware.
386 missingBitRate = [NSDictionary dictionaryWithObjectsAndKeys:
387 [NSString stringWithFormat: @"%d", trackInputBitRate], keyAudioBitrateName,
388 [NSNumber numberWithInt: trackInputBitRate], keyAudioBitrate,
391 [permittedBitRates addObject: missingBitRate];
394 if (NO == [self enabled]) {
395 permittedBitRates = nil;
398 // Make sure we are updated with the permitted list
399 [self setBitRates: permittedBitRates];
401 // Select the proper one
402 if (YES == shouldSetDefault) {
403 [self setBitRateFromName: defaultBitRate];
406 if (nil == [self bitRate] || NO == [permittedBitRates containsObject: [self bitRate]]) {
407 [self setBitRate: [permittedBitRates lastObject]];
416 if (self = [super init]) {
417 [self addObserver: self forKeyPath: @"videoContainerTag" options: 0 context: NULL];
418 [self addObserver: self forKeyPath: @"track" options: NSKeyValueObservingOptionOld context: NULL];
419 [self addObserver: self forKeyPath: @"codec" options: 0 context: NULL];
420 [self addObserver: self forKeyPath: @"mixdown" options: 0 context: NULL];
421 [self addObserver: self forKeyPath: @"sampleRate" options: 0 context: NULL];
427 #pragma mark Accessors
432 @synthesize sampleRate;
435 @synthesize videoContainerTag;
436 @synthesize controller;
439 @synthesize mixdowns;
440 @synthesize bitRates;
442 - (NSArray *) tracks { return [controller masterTrackArray]; }
444 - (NSArray *) sampleRates { return masterSampleRateArray; }
449 [self removeObserver: self forKeyPath: @"videoContainerTag"];
450 [self removeObserver: self forKeyPath: @"track"];
451 [self removeObserver: self forKeyPath: @"codec"];
452 [self removeObserver: self forKeyPath: @"mixdown"];
453 [self removeObserver: self forKeyPath: @"sampleRate"];
454 [self setTrack: nil];
455 [self setCodec: nil];
456 [self setMixdown: nil];
457 [self setSampleRate: nil];
458 [self setBitRate: nil];
460 [self setVideoContainerTag: nil];
461 [self setCodecs: nil];
462 [self setMixdowns: nil];
463 [self setBitRates: nil];
471 - (void) observeValueForKeyPath: (NSString *) keyPath ofObject: (id) object change: (NSDictionary *) change context: (void *) context
474 if (YES == [keyPath isEqualToString: @"videoContainerTag"]) {
477 else if (YES == [keyPath isEqualToString: @"track"]) {
478 if (nil != [self track]) {
480 if (YES == [self enabled]) {
481 [self setSampleRate: [[self sampleRates] objectAtIndex: 0]]; // default to Auto
483 if (YES == [[controller noneTrack] isEqual: [change objectForKey: NSKeyValueChangeOldKey]]) {
484 [controller switchingTrackFromNone: self];
486 if (YES == [[controller noneTrack] isEqual: [self track]]) {
487 [controller settingTrackToNone: self];
491 else if (YES == [keyPath isEqualToString: @"codec"]) {
492 [self updateMixdowns];
493 [self updateBitRates: YES];
495 else if (YES == [keyPath isEqualToString: @"mixdown"]) {
496 [self updateBitRates: YES];
497 [[NSNotificationCenter defaultCenter] postNotificationName: HBMixdownChangedNotification object: self];
499 else if (YES == [keyPath isEqualToString: @"sampleRate"]) {
500 [self updateBitRates: NO];
506 #pragma mark Special Setters
508 - (void) setTrackFromIndex: (int) aValue
511 [self setTrack: [[self tracks] dictionaryWithObject: [NSNumber numberWithInt: aValue] matchingKey: keyAudioTrackIndex]];
515 // This returns whether it is able to set the actual codec desired.
516 - (BOOL) setCodecFromName: (NSString *) aValue
519 NSDictionary *dict = [[self codecs] dictionaryWithObject: aValue matchingKey: keyAudioCodecName];
522 [self setCodec: dict];
524 return (nil != dict);
527 - (void) setMixdownFromName: (NSString *) aValue
530 NSDictionary *dict = [[self mixdowns] dictionaryWithObject: aValue matchingKey: keyAudioMixdownName];
533 [self setMixdown: dict];
538 - (void) setSampleRateFromName: (NSString *) aValue
541 NSDictionary *dict = [[self sampleRates] dictionaryWithObject: aValue matchingKey: keyAudioSampleRateName];
544 [self setSampleRate: dict];
549 - (void) setBitRateFromName: (NSString *) aValue
552 NSDictionary *dict = [[self bitRates] dictionaryWithObject: aValue matchingKey: keyAudioBitrateName];
555 [self setBitRate: dict];
562 #pragma mark Validation
564 // Because we have indicated that the binding for the drc validates immediately we can implement the
565 // key value binding method to ensure the drc stays in our accepted range.
566 - (BOOL) validateDrc: (id *) ioValue error: (NSError *) outError
571 if (nil != *ioValue) {
572 if (0.0 < [*ioValue floatValue] && 1.0 > [*ioValue floatValue]) {
573 *ioValue = [NSNumber numberWithFloat: 1.0];
581 #pragma mark Bindings Support
586 return (nil != track) ? (NO == [track isEqual: [controller noneTrack]]) : NO;
589 - (BOOL) mixdownEnabled
592 BOOL retval = [self enabled];
595 int myMixdown = [[[self mixdown] objectForKey: keyAudioMixdown] intValue];
596 if (HB_ACODEC_AC3_PASS == myMixdown || HB_ACODEC_DCA_PASS == myMixdown) {
606 BOOL retval = [self enabled];
609 int myTrackCodec = [[[self track] objectForKey: keyAudioInputCodec] intValue];
610 int myCodecCodec = [[[self codec] objectForKey: keyAudioCodec] intValue];
611 if (HB_ACODEC_AC3 != myTrackCodec || HB_ACODEC_AC3_PASS == myCodecCodec) {
618 + (NSSet *) keyPathsForValuesAffectingValueForKey: (NSString *) key
623 if (YES == [key isEqualToString: @"enabled"]) {
624 retval = [NSSet setWithObjects: @"track", nil];
626 else if (YES == [key isEqualToString: @"AC3Enabled"]) {
627 retval = [NSSet setWithObjects: @"track", @"codec", nil];
629 else if (YES == [key isEqualToString: @"mixdownEnabled"]) {
630 retval = [NSSet setWithObjects: @"track", @"mixdown", nil];