diff --git a/Application/AppController.m b/Application/AppController.m index 352140f14..c693a11c2 100644 --- a/Application/AppController.m +++ b/Application/AppController.m @@ -359,6 +359,8 @@ increase/decrease as long as the user holds the left/right, plus/minus button */ [userDefaultsValuesDict setObject:@"clearAndPlay" forKey:@"openingFilesBehavior"]; [userDefaultsValuesDict setObject:@"enqueue" forKey:@"openingFilesAlteredBehavior"]; + + [userDefaultsValuesDict setObject:@"albumGainWithPeak" forKey:@"volumeScaling"]; //Register and sync defaults [[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsValuesDict]; diff --git a/Audio/Chain/InputNode.h b/Audio/Chain/InputNode.h index 7b5aee25a..e77987f73 100644 --- a/Audio/Chain/InputNode.h +++ b/Audio/Chain/InputNode.h @@ -19,7 +19,10 @@ @interface InputNode : Node { id decoder; + int bytesPerSample; int bytesPerFrame; + int volumeScale; + BOOL swapEndian; BOOL shouldSeek; long seekFrame; @@ -38,4 +41,6 @@ - (id) decoder; +- (void)refreshVolumeScaling; + @end diff --git a/Audio/Chain/InputNode.m b/Audio/Chain/InputNode.m index 8262e732a..352a5df2c 100644 --- a/Audio/Chain/InputNode.m +++ b/Audio/Chain/InputNode.m @@ -11,6 +11,16 @@ #import "Plugin.h" #import "CoreAudioUtils.h" + +static BOOL hostIsBigEndian() +{ +#ifdef __BIG_ENDIAN__ + return YES; +#else + return NO; +#endif +} + @implementation InputNode - (BOOL)openWithSource:(id)source @@ -33,7 +43,18 @@ int bitsPerSample = [[properties objectForKey:@"bitsPerSample"] intValue]; int channels = [[properties objectForKey:@"channels"] intValue]; - bytesPerFrame = (bitsPerSample/8) * channels; + bytesPerSample = bitsPerSample / 8; + bytesPerFrame = bytesPerSample * channels; + + if (([[properties objectForKey:@"endian"] isEqualToString:@"big"] && !hostIsBigEndian()) || + ([[properties objectForKey:@"endian"] isEqualToString:@"little"] && hostIsBigEndian())) { + swapEndian = YES; + } + else { + swapEndian = NO; + } + + [self refreshVolumeScaling]; shouldContinue = YES; shouldSeek = NO; @@ -51,7 +72,10 @@ int bitsPerSample = [[properties objectForKey:@"bitsPerSample"] intValue]; int channels = [[properties objectForKey:@"channels"] intValue]; - bytesPerFrame = (bitsPerSample/8) * channels; + bytesPerSample = bitsPerSample / 8; + bytesPerFrame = bytesPerSample * channels; + + [self refreshVolumeScaling]; [self registerObservers]; @@ -75,6 +99,8 @@ forKeyPath:@"metadata" options:(NSKeyValueObservingOptionNew) context:NULL]; + + [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" options:0 context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath @@ -88,10 +114,74 @@ //Inform something of properties change //Disable support until it is properly implimented. //[controller inputFormatDidChange: propertiesToASBD([decoder properties])]; + [self refreshVolumeScaling]; } else if ([keyPath isEqual:@"metadata"]) { //Inform something of metadata change } + else if ([keyPath isEqual:@"values.volumeScaling"]) { + //User reset the volume scaling option + [self refreshVolumeScaling]; + } +} + +static float db_to_scale(float db) +{ + return pow(10.0, db / 20); +} + +- (void)refreshVolumeScaling +{ + NSDictionary *properties = [decoder properties]; + NSString * scaling = [[NSUserDefaults standardUserDefaults] stringForKey:@"volumeScaling"]; + BOOL useAlbum = [scaling hasPrefix:@"albumGain"]; + BOOL useTrack = useAlbum || [scaling hasPrefix:@"trackGain"]; + BOOL useVolume = useAlbum || useTrack || [scaling isEqualToString:@"volumeScale"]; + bool usePeak = [scaling hasSuffix:@"WithPeak"]; + float scale = 1.0; + float peak = 0.0; + if (useVolume) { + id pVolumeScale = [properties objectForKey:@"volume"]; + if (pVolumeScale != nil) + scale = [pVolumeScale floatValue]; + } + if (useTrack) { + id trackGain = [properties objectForKey:@"replayGainTrackGain"]; + id trackPeak = [properties objectForKey:@"replayGainTrackPeak"]; + if (trackGain != nil) + scale = db_to_scale([trackGain floatValue]); + if (trackPeak != nil) + peak = [trackPeak floatValue]; + } + if (useAlbum) { + id albumGain = [properties objectForKey:@"replayGainAlbumGain"]; + id albumPeak = [properties objectForKey:@"replayGainAlbumPeak"]; + if (albumGain != nil) + scale = db_to_scale([albumGain floatValue]); + if (albumPeak != nil) + peak = [albumPeak floatValue]; + } + if (usePeak) { + if (scale * peak > 1.0) + scale = 1.0 / peak; + } + volumeScale = scale * 4096; +} + +static int16_t swap_16(uint16_t input) +{ + return (input >> 8) | (input << 8); +} + +static int32_t swap_24(uint32_t input) +{ + int32_t temp = (input << 24) >> 8; + return temp | ((input >> 16) & 0xff) | (input & 0xff00); +} + +static int32_t swap_32(uint32_t input) +{ + return (input >> 24) | ((input >> 8) & 0xff00) | ((input << 8) & 0xff0000) | (input << 24); } - (void)process @@ -133,6 +223,72 @@ NSLog(@"closing? is %i", shouldClose); break; } + + if (volumeScale != 4096) { + int totalFrames = amountInBuffer / bytesPerSample; + switch (bytesPerSample) { + case 1: + { + uint8_t * samples = (uint8_t *)inputBuffer; + for (int i = 0; i < totalFrames; i++) + { + int32_t sample = (int8_t)samples[i] - 128; + sample = (sample * volumeScale) >> 12; + if ((unsigned)(sample + 0x80) & 0xffffff00) sample = (sample >> 31) ^ 0x7f; + samples[i] = sample + 128; + } + } + break; + + case 2: + { + int16_t * samples = (int16_t *)inputBuffer; + for (int i = 0; i < totalFrames; i++) + { + int32_t sample = samples[i]; + if (swapEndian) sample = swap_16(sample); + sample = (sample * volumeScale) >> 12; + if ((unsigned)(sample + 0x8000) & 0xffff0000) sample = (sample >> 31) ^ 0x7fff; + if (swapEndian) sample = swap_16(sample); + samples[i] = sample; + } + } + break; + + case 3: + { + uint8_t * samples = (uint8_t *)inputBuffer; + for (int i = 0; i < totalFrames; i++) + { + int32_t sample = (samples[i * 3] << 8) | (samples[i * 3 + 1] << 16) | (samples[i * 3 + 2] << 24); + sample >>= 8; + if (swapEndian) sample = swap_24(sample); + sample = (sample * volumeScale) >> 12; + if ((unsigned)(sample + 0x800000) & 0xff000000) sample = (sample >> 31) ^ 0x7fffff; + if (swapEndian) sample = swap_24(sample); + samples[i * 3] = sample; + samples[i * 3 + 1] = sample >> 8; + samples[i * 3 + 2] = sample >> 16; + } + } + break; + + case 4: + { + int32_t * samples = (int32_t *)inputBuffer; + for (int i = 0; i < totalFrames; i++) + { + int64_t sample = samples[i]; + if (swapEndian) sample = swap_32(sample); + sample = (sample * volumeScale) >> 12; + if ((unsigned)(sample + 0x80000000) & 0xffffffff00000000) sample = (sample >> 63) ^ 0x7fffffff; + if (swapEndian) sample = swap_32(sample); + samples[i] = sample; + } + } + break; + } + } [self writeData:inputBuffer amount:amountInBuffer]; amountInBuffer = 0; diff --git a/Playlist/PlaylistEntry.h b/Playlist/PlaylistEntry.h index e3f7f7180..7e3f7a6c3 100644 --- a/Playlist/PlaylistEntry.h +++ b/Playlist/PlaylistEntry.h @@ -32,6 +32,12 @@ NSNumber *year; NSNumber *track; NSImage *albumArt; + + float replayGainAlbumGain; + float replayGainAlbumPeak; + float replayGainTrackGain; + float replayGainTrackPeak; + float volume; long long totalFrames; int bitrate; @@ -91,6 +97,12 @@ @property int bitsPerSample; @property float sampleRate; +@property float replayGainAlbumGain; +@property float replayGainAlbumPeak; +@property float replayGainTrackGain; +@property float replayGainTrackPeak; +@property float volume; + @property(retain) NSString *endian; @property BOOL seekable; diff --git a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.h b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.h index 16f88dc34..e42256ea1 100644 --- a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.h +++ b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.h @@ -20,7 +20,11 @@ int tagLengthMs; int tagFadeMs; - int volumeScale; + float replayGainAlbumGain; + float replayGainAlbumPeak; + float replayGainTrackGain; + float replayGainTrackPeak; + float volume; int type; diff --git a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm index c2b14063c..61cdfd128 100644 --- a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm +++ b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm @@ -182,7 +182,11 @@ struct psf_info_meta_state int tag_length_ms; int tag_fade_ms; - int volume_scale; + float albumGain; + float albumPeak; + float trackGain; + float trackPeak; + float volume; }; static int parse_time_crap(NSString * value) @@ -205,16 +209,6 @@ static int parse_time_crap(NSString * value) return totalSeconds; } -static int db_to_int(NSString * value) -{ - return pow(10.0, [value floatValue] / 20) * 4096; -} - -static int scale_to_int(NSString * value) -{ - return [value floatValue] * 4096; -} - static int psf_info_meta(void * context, const char * name, const char * value) { struct psf_info_meta_state * state = ( struct psf_info_meta_state * ) context; @@ -237,19 +231,24 @@ static int psf_info_meta(void * context, const char * name, const char * value) if ([taglc hasPrefix:@"replaygain_"]) { - if ([taglc isEqualToString:@"replaygain_album_gain"]) + if ([taglc hasPrefix:@"replaygain_album_"]) { - state->volume_scale = db_to_int(svalue); + if ([taglc hasSuffix:@"gain"]) + state->albumGain = [svalue floatValue]; + else if ([taglc hasSuffix:@"peak"]) + state->albumPeak = [svalue floatValue]; } - else if (!state->volume_scale && [taglc isEqualToString:@"replaygain_track_gain"]) + else if ([taglc hasPrefix:@"replaygain_track_"]) { - state->volume_scale = db_to_int(svalue); + if ([taglc hasSuffix:@"gain"]) + state->trackGain = [svalue floatValue]; + else if ([taglc hasSuffix:@"peak"]) + state->trackPeak = [svalue floatValue]; } } else if ([taglc isEqualToString:@"volume"]) { - if (!state->volume_scale) - state->volume_scale = scale_to_int(svalue); + state->volume = [svalue floatValue]; } else if ([taglc isEqualToString:@"length"]) { @@ -763,8 +762,13 @@ struct gsf_sound_out : public GBASoundOut info.utf8 = false; info.tag_length_ms = 0; info.tag_fade_ms = 0; - info.volume_scale = 0; + info.albumGain = 0; + info.albumPeak = 0; + info.trackGain = 0; + info.trackPeak = 0; + info.volume = 1; + currentUrl = [[[[source url] absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] retain]; [[psf_file_container instance] add_hint:currentUrl source:currentSource]; @@ -784,7 +788,12 @@ struct gsf_sound_out : public GBASoundOut tagLengthMs = info.tag_length_ms; tagFadeMs = info.tag_fade_ms; - volumeScale = info.volume_scale; + + replayGainAlbumGain = info.albumGain; + replayGainAlbumPeak = info.albumPeak; + replayGainTrackGain = info.trackGain; + replayGainTrackPeak = info.trackPeak; + volume = info.volume; metadataList = info.info; @@ -848,18 +857,6 @@ struct gsf_sound_out : public GBASoundOut qsound_execute( emulatorCore, 0x7fffffff, ( int16_t * ) buf, &howmany); frames = howmany; } - - if ( volumeScale ) - { - int16_t * samples = ( int16_t * ) buf; - - for ( UInt32 i = 0, j = frames * 2; i < j; ++i ) - { - int sample = ( samples[ i ] * volumeScale ) >> 12; - if ( (uint32_t)(sample + 0x8000) & 0xffff0000 ) sample = ( sample >> 31 ) ^ 0x7fff; - samples[ i ] = ( int16_t ) sample; - } - } framesRead += frames; @@ -968,6 +965,11 @@ struct gsf_sound_out : public GBASoundOut [NSNumber numberWithInteger:totalFrames], @"totalFrames", [NSNumber numberWithInt:0], @"bitrate", [NSNumber numberWithBool:YES], @"seekable", + [NSNumber numberWithFloat:replayGainAlbumGain], @"replayGainAlbumGain", + [NSNumber numberWithFloat:replayGainAlbumPeak], @"replayGainAlbumPeak", + [NSNumber numberWithFloat:replayGainTrackGain], @"replayGainTrackGain", + [NSNumber numberWithFloat:replayGainTrackPeak], @"replayGainTrackPeak", + [NSNumber numberWithFloat:volume], @"volume", @"host", @"endian", nil]; } @@ -980,7 +982,6 @@ struct gsf_sound_out : public GBASoundOut info.utf8 = false; info.tag_length_ms = 0; info.tag_fade_ms = 0; - info.volume_scale = 0; NSString * decodedUrl = [[url absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; diff --git a/Preferences/General/English.lproj/Preferences.xib b/Preferences/General/English.lproj/Preferences.xib index e792fd979..6e08fb61e 100644 --- a/Preferences/General/English.lproj/Preferences.xib +++ b/Preferences/General/English.lproj/Preferences.xib @@ -1,2532 +1,413 @@ - - - - 1050 - 9L30 - 677 - 949.54 - 353.00 - - YES - - - - - - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - - - YES - - YES - - - YES - - - - YES - - PrefPaneController - - - FirstResponder - - - NSApplication - - - HotKeyPane - - - - 256 - - YES - - - 256 - {{91, 70}, {82, 19}} - - - YES - - -2075001280 - 4326400 - - - LucidaGrande - 1.100000e+01 - 3100 - - - YES - - 6 - System - textBackgroundColor - - 3 - MQA - - - - 6 - System - textColor - - 3 - MAA - - - - - - - 256 - {{175, 62}, {64, 32}} - - - YES - - 67239424 - 134217728 - Edit - - LucidaGrande - 1.300000e+01 - 1044 - - - -2038284033 - 1 - - - - - - 200 - 25 - - - - - 256 - {{45, 72}, {39, 17}} - - - YES - - 67239424 - 272629760 - Play: - - - - 6 - System - controlColor - - 3 - MC42NjY2NjY2OQA - - - - 6 - System - controlTextColor - - - - - - - 256 - {{17, 47}, {69, 17}} - - - YES - - 67239424 - 272629760 - Previous: - - - - - - - - - 256 - {{40, 22}, {44, 17}} - - - YES - - 67239424 - 272629760 - Next: - - - - - - - - - 256 - {{91, 45}, {82, 19}} - - - YES - - -2075001280 - 4326400 - - - - YES - - - - - - - 256 - {{91, 20}, {82, 19}} - - - YES - - -2075001280 - 4326400 - - - - YES - - - - - - - 256 - {{175, 37}, {64, 32}} - - - YES - - 67239424 - 134217728 - Edit - - - -2038284033 - 1 - - - - - - 200 - 25 - - - - - 256 - {{175, 12}, {64, 32}} - - - YES - - 67239424 - 134217728 - Edit - - - -2038284033 - 1 - - - - - - 200 - 25 - - - - {432, 109} - - - - NSView - - NSResponder - - - - 256 - - YES - - - 256 - {{18, 18}, {281, 18}} - - YES - - 67239424 - 0 - Only listen to remote when Cog is active. - - - 1211912703 - 2 - - NSImage - NSSwitch - - - NSSwitch - - - - 200 - 25 - - - - - 256 - {{18, 38}, {281, 18}} - - YES - - 67239424 - 0 - Enable remote control. - - - 1211912703 - 2 - - - - - 200 - 25 - - - - {432, 74} - - - NSView - - NSResponder - - - - 256 - - YES - - - 256 - {{18, 46}, {299, 18}} - - YES - - 67239424 - 0 - Automatically check for updates on startup. - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{111, 16}, {207, 26}} - - YES - - -2076049856 - 2048 - - - 109199615 - 1 - - LucidaGrande - 1.300000e+01 - 16 - - - - - - 400 - 75 - - - Stable - - 1048576 - 2147483647 - 1 - - NSImage - NSMenuCheckmark - - - NSImage - NSMenuMixedState - - _popUpItemAction: - - - YES - - - OtherViews - - - YES - - - - Unstable - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - Nightly - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 3 - YES - YES - 1 - - - - - 256 - {{17, 23}, {92, 17}} - - YES - - 67239424 - 272629760 - Update Feed: - - - - - - - - {432, 82} - - NSView - NSResponder - - - - YES - parseCueOnAdd - readCueInDir - readCueSheetsInFolders - - YES - - - OutputPane - - - - 256 - - YES - - - 256 - {{122, 16}, {252, 26}} - - YES - - -2076049856 - 2048 - - - 109199615 - 1 - - - - - - 400 - 75 - - - Item1 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - - OtherViews - - - YES - - - - Item2 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - Item3 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 3 - YES - YES - 1 - - - - - 256 - {{17, 22}, {103, 17}} - - YES - - 67239424 - 272629760 - Output Device: - - - - - - - - {432, 59} - - - NSView - - NSResponder - - - - YES - name - - YES - - YES - YES - YES - YES - YES - - - - 256 - - YES - - - 256 - {{18, 38}, {396, 18}} - - YES - - 67239424 - 0 - Enable Last.fm support. (Must have Last.fm client installed) - - - 1211912703 - 2 - - - - - 200 - 25 - - - - - 256 - {{18, 18}, {396, 18}} - - YES - - 67239424 - 0 - Automatically launch Last.fm client. - - - 1211912703 - 2 - - - - - 200 - 25 - - - - {432, 74} - - - NSView - - NSResponder - - - - YES - name - url - - NSDictionary - - YES - YES - YES - YES - - - - 268 - - YES - - - 268 - {{157, 78}, {257, 26}} - - YES - - -2076049856 - 2048 - - - 109199615 - 1 - - - 400 - 75 - - - Item 1 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - OtherViews - - YES - - - - Item 2 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - Item 3 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 1 - YES - YES - 2 - - - - - 268 - {{157, 45}, {257, 26}} - - YES - - -2076049856 - 2048 - - - 109199615 - 1 - - - 400 - 75 - - - Item 1 - - 1048576 - 2147483647 - 1 - - - _popUpItemAction: - - - YES - - OtherViews - - YES - - - - Item 2 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - Item 3 - - 1048576 - 2147483647 - - - _popUpItemAction: - - - - - 1 - YES - YES - 2 - - - - - 268 - {{17, 85}, {129, 17}} - - YES - - 67239488 - 272630784 - When opening files: - - - - - - - - - 268 - {{17, 42}, {138, 35}} - - YES - - 67239424 - 4194304 - V2hlbiBvcGVuaW5nIGZpbGUgd2l0aCDih6cgb3Ig4oyYK14gaGVsZDo - - - - - - - - - 268 - {{18, 18}, {395, 18}} - - YES - - -2080244224 - 0 - Read cue sheets when adding folders to playlist. - - - 1211912703 - 130 - - - - - 200 - 25 - - - - {432, 122} - - NSView - - - - YES - name - slug - preference - - NSDictionary - - YES - YES - YES - YES - - - - - YES - - - view - - - - 12 - - - - hotKeyPane - - - - 14 - - - - hotKeyChanged: - - - - 20 - - - - nextKeyView - - - - 22 - - - - nextKeyView - - - - 23 - - - - grabPlayHotKey: - - - - 31 - - - - grabPrevHotKey: - - - - 32 - - - - grabNextHotKey: - - - - 33 - - - - playHotKeyControl - - - - 34 - - - - prevHotKeyControl - - - - 35 - - - - nextHotKeyControl - - - - 36 - - - - hotKeyChanged: - - - - 37 - - - - hotKeyChanged: - - - - 38 - - - - value: values.SUCheckAtStartup - - - - - - value: values.SUCheckAtStartup - value - values.SUCheckAtStartup - 2 - - - 53 - - - - content: arrangedObjects - - - - - - content: arrangedObjects - content - arrangedObjects - 2 - - - 69 - - - - contentValues: arrangedObjects.name - - - - - - contentValues: arrangedObjects.name - contentValues - arrangedObjects.name - - 2 - - - 71 - - - - selectedIndex: selectionIndex - - - - - - selectedIndex: selectionIndex - selectedIndex - selectionIndex - - 2 - - - 72 - - - - view - - - - 73 - - - - takeDeviceID: - - - - 74 - - - - outputPane - - - - 75 - - - - outputDevices - - - - 76 - - - - value: values.remoteOnlyOnActive - - - - - - value: values.remoteOnlyOnActive - value - values.remoteOnlyOnActive - 2 - - - 79 - - - - value: values.enableAudioScrobbler - - - - - - value: values.enableAudioScrobbler - value - values.enableAudioScrobbler - 2 - - - 90 - - - - enabled: values.enableAudioScrobbler - - - - - - enabled: values.enableAudioScrobbler - enabled - values.enableAudioScrobbler - 2 - - - 93 - - - - value: values.automaticallyLaunchLastFM - - - - - - value: values.automaticallyLaunchLastFM - value - values.automaticallyLaunchLastFM - 2 - - - 95 - - - - value: values.remoteEnabled - - - - - - value: values.remoteEnabled - value - values.remoteEnabled - 2 - - - 97 - - - - enabled: values.remoteEnabled - - - - - - enabled: values.remoteEnabled - enabled - values.remoteEnabled - 2 - - - 98 - - - - updatesView - - - - 99 - - - - remoteView - - - - 100 - - - - scrobblerView - - - - 101 - - - - content: arrangedObjects - - - - - - content: arrangedObjects - content - arrangedObjects - 2 - - - 135 - - - - contentObjects: arrangedObjects.url - - - - - - contentObjects: arrangedObjects.url - contentObjects - arrangedObjects.url - - 2 - - - 144 - - - - contentValues: arrangedObjects.name - - - - - - contentValues: arrangedObjects.name - contentValues - arrangedObjects.name - - 2 - - - 145 - - - - selectedObject: values.SUFeedURL - - - - - - selectedObject: values.SUFeedURL - selectedObject - values.SUFeedURL - - 2 - - - 147 - - - - playlistView - - - - 244 - - - - content: arrangedObjects - - - - - - content: arrangedObjects - content - arrangedObjects - 2 - - - 263 - - - - content: arrangedObjects - - - - - - content: arrangedObjects - content - arrangedObjects - 2 - - - 264 - - - - contentObjects: arrangedObjects.preference - - - - - - contentObjects: arrangedObjects.preference - contentObjects - arrangedObjects.preference - - 2 - - - 304 - - - - contentValues: arrangedObjects.name - - - - - - contentValues: arrangedObjects.name - contentValues - arrangedObjects.name - - 2 - - - 305 - - - - selectedObject: values.openingFilesBehavior - - - - - - selectedObject: values.openingFilesBehavior - selectedObject - values.openingFilesBehavior - - 2 - - - 306 - - - - contentObjects: arrangedObjects.preference - - - - - - contentObjects: arrangedObjects.preference - contentObjects - arrangedObjects.preference - - 2 - - - 307 - - - - contentValues: arrangedObjects.name - - - - - - contentValues: arrangedObjects.name - contentValues - arrangedObjects.name - - 2 - - - 308 - - - - selectedObject: values.openingFilesAlteredBehavior - - - - - - selectedObject: values.openingFilesAlteredBehavior - selectedObject - values.openingFilesAlteredBehavior - - 2 - - - 309 - - - - value: values.readCueSheetsInFolders - - - - - - value: values.readCueSheetsInFolders - value - values.readCueSheetsInFolders - 2 - - - 328 - - - - - YES - - 0 - - YES - - - - - - -2 - - - RmlsZSdzIE93bmVyA - - - -1 - - - First Responder - - - -3 - - - Application - - - 6 - - - HotKeyPane - - - 11 - - - YES - - - - - - - - - - - - HotKeyView - - - 16 - - - YES - - - - - - 17 - - - YES - - - - - - 24 - - - YES - - - - - - 25 - - - YES - - - - - - 26 - - - YES - - - - - - 27 - - - YES - - - - - - 28 - - - YES - - - - - - 29 - - - YES - - - - - - 30 - - - YES - - - - - - 43 - - - YES - - - - - RemoteView - - - 44 - - - YES - - - - - - 77 - - - YES - - - - - - 50 - - - YES - - - - - - UpdatesView - - - 51 - - - YES - - - - - - 106 - - - YES - - - - - - 111 - - - YES - - - - - - 52 - - - Shared Defaults - - - 57 - - - OutputPane - - - 58 - - - YES - - - - - OutputView - - - 60 - - - YES - - - - - - 65 - - - YES - - - - - - 59 - - - OutputDevices - - - 85 - - - YES - - - - - ScrobblerView - - - 87 - - - YES - - - - - - 88 - - - YES - - - - - - 115 - - - Appcasts - - - 196 - - - - - 197 - - - - - 198 - - - - - 199 - - - - - 200 - - - - - 201 - - - - - 202 - - - - - 203 - - - - - 204 - - - - - 205 - - - - - 206 - - - - - 207 - - - - - 208 - - - YES - - - - - - 209 - - - - - 210 - - - YES - - - - - - 211 - - - - - 212 - - - - - 213 - - - - - 107 - - - YES - - - - - - - - 110 - - - - - 109 - - - - - 108 - - - - - 61 - - - YES - - - - - - - - 64 - - - - - 63 - - - - - 62 - - - - - 231 - - - YES - - - - - - - - PlaylistView - - - 246 - - - PlaylistBehavior - - - 247 - - - YES - - - - - - 248 - - - YES - - - - - - 249 - - - YES - - - - - - - - 250 - - - - - 251 - - - - - 252 - - - - - 253 - - - YES - - - - - - 254 - - - YES - - - - - - 255 - - - YES - - - - - - - - 256 - - - - - 257 - - - - - 258 - - - - - 259 - - - YES - - - - - - 260 - - - - - 261 - - - YES - - - - - - 262 - - - - - 310 - - - YES - - - - - - 311 - - - - - - - YES - - YES - -1.IBPluginDependency - -2.IBPluginDependency - -3.IBPluginDependency - -3.ImportedFromIB2 - 106.IBPluginDependency - 106.ImportedFromIB2 - 107.IBPluginDependency - 107.ImportedFromIB2 - 108.IBPluginDependency - 108.ImportedFromIB2 - 109.IBPluginDependency - 109.ImportedFromIB2 - 11.IBEditorWindowLastContentRect - 11.IBPluginDependency - 11.ImportedFromIB2 - 11.editorWindowContentRectSynchronizationRect - 110.IBPluginDependency - 110.ImportedFromIB2 - 111.IBPluginDependency - 111.ImportedFromIB2 - 115.CustomClassName - 115.IBPluginDependency - 115.ImportedFromIB2 - 16.CustomClassName - 16.IBPluginDependency - 16.ImportedFromIB2 - 17.IBPluginDependency - 17.ImportedFromIB2 - 196.IBPluginDependency - 197.IBPluginDependency - 198.IBPluginDependency - 199.IBPluginDependency - 200.IBPluginDependency - 201.IBPluginDependency - 202.IBPluginDependency - 203.IBPluginDependency - 204.IBPluginDependency - 205.IBPluginDependency - 206.IBPluginDependency - 207.IBPluginDependency - 208.IBPluginDependency - 209.IBPluginDependency - 210.IBPluginDependency - 211.IBPluginDependency - 212.IBPluginDependency - 213.IBPluginDependency - 231.IBEditorWindowLastContentRect - 231.IBPluginDependency - 231.editorWindowContentRectSynchronizationRect - 24.IBPluginDependency - 24.ImportedFromIB2 - 246.CustomClassName - 246.IBPluginDependency - 247.IBPluginDependency - 248.IBPluginDependency - 249.IBEditorWindowLastContentRect - 249.IBPluginDependency - 249.editorWindowContentRectSynchronizationRect - 25.IBPluginDependency - 25.ImportedFromIB2 - 250.IBPluginDependency - 251.IBPluginDependency - 252.IBPluginDependency - 253.IBPluginDependency - 254.IBPluginDependency - 255.IBEditorWindowLastContentRect - 255.IBPluginDependency - 256.IBPluginDependency - 257.IBPluginDependency - 258.IBPluginDependency - 259.IBPluginDependency - 26.IBPluginDependency - 26.ImportedFromIB2 - 260.IBPluginDependency - 261.IBPluginDependency - 262.IBPluginDependency - 27.CustomClassName - 27.IBPluginDependency - 27.ImportedFromIB2 - 28.CustomClassName - 28.IBPluginDependency - 28.ImportedFromIB2 - 29.IBPluginDependency - 29.ImportedFromIB2 - 30.IBPluginDependency - 30.ImportedFromIB2 - 310.IBPluginDependency - 311.IBPluginDependency - 43.IBEditorWindowLastContentRect - 43.IBPluginDependency - 43.ImportedFromIB2 - 44.IBPluginDependency - 44.ImportedFromIB2 - 50.IBEditorWindowLastContentRect - 50.IBPluginDependency - 50.ImportedFromIB2 - 50.editorWindowContentRectSynchronizationRect - 51.IBPluginDependency - 51.ImportedFromIB2 - 52.IBPluginDependency - 52.ImportedFromIB2 - 57.IBPluginDependency - 57.ImportedFromIB2 - 58.IBEditorWindowLastContentRect - 58.IBPluginDependency - 58.ImportedFromIB2 - 58.editorWindowContentRectSynchronizationRect - 59.CustomClassName - 59.IBPluginDependency - 59.ImportedFromIB2 - 6.IBPluginDependency - 6.ImportedFromIB2 - 60.IBPluginDependency - 60.ImportedFromIB2 - 61.IBPluginDependency - 61.ImportedFromIB2 - 62.IBPluginDependency - 62.ImportedFromIB2 - 63.IBPluginDependency - 63.ImportedFromIB2 - 64.IBPluginDependency - 64.ImportedFromIB2 - 65.IBPluginDependency - 65.ImportedFromIB2 - 77.IBPluginDependency - 77.ImportedFromIB2 - 85.IBEditorWindowLastContentRect - 85.IBPluginDependency - 85.ImportedFromIB2 - 85.editorWindowContentRectSynchronizationRect - 87.IBPluginDependency - 87.ImportedFromIB2 - 88.IBPluginDependency - 88.ImportedFromIB2 - - - YES - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - {{178, 505}, {432, 109}} - com.apple.InterfaceBuilder.CocoaPlugin - - {{42, 829}, {432, 109}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - AppcastArrayController - com.apple.InterfaceBuilder.CocoaPlugin - - HotKeyControl - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{488, 692}, {432, 122}} - com.apple.InterfaceBuilder.CocoaPlugin - {{376, 821}, {431, 100}} - com.apple.InterfaceBuilder.CocoaPlugin - - PlaylistBehaviorArrayController - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{595, 606}, {257, 63}} - com.apple.InterfaceBuilder.CocoaPlugin - {{522, 827}, {257, 63}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{595, 573}, {257, 63}} - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - HotKeyControl - com.apple.InterfaceBuilder.CocoaPlugin - - HotKeyControl - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - {{468, 859}, {432, 74}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - {{0, 913}, {432, 82}} - com.apple.InterfaceBuilder.CocoaPlugin - - {{21, 1040}, {432, 82}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - {{193, 624}, {432, 59}} - com.apple.InterfaceBuilder.CocoaPlugin - - {{21, 902}, {432, 59}} - OutputsArrayController - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - {{451, 691}, {432, 74}} - com.apple.InterfaceBuilder.CocoaPlugin - - {{63, 841}, {432, 74}} - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - - - - - YES - - YES - - - YES - - - - - YES - - YES - - - YES - - - - 328 - - - - YES - - AppcastArrayController - NSArrayController - - IBProjectSource - AppcastArrayController.h - - - - AppcastArrayController - NSArrayController - - IBUserSource - - - - - FileDrawerPane - PreferencePane - - openSheet: - id - - - rootPathTextView - NSTextField - - - IBUserSource - - - - - FirstResponder - NSObject - - IBUserSource - - - - - GeneralPreferencePane - NSObject - - view - NSView - - - IBProjectSource - GeneralPreferencePane.h - - - - HotKeyControl - NDHotKeyControl - - IBProjectSource - HotKeyControl.h - - - - HotKeyControl - NDHotKeyControl - - IBUserSource - - - - - HotKeyPane - GeneralPreferencePane - - YES - - YES - grabNextHotKey: - grabPlayHotKey: - grabPrevHotKey: - hotKeyChanged: - - - YES - id - id - id - id - - - - YES - - YES - nextHotKeyControl - playHotKeyControl - prevHotKeyControl - - - YES - HotKeyControl - HotKeyControl - HotKeyControl - - - - IBProjectSource - HotKeyPane.h - - - - HotKeyPane - GeneralPreferencePane - - IBUserSource - - - - - NDHotKeyControl - NSTextField - - IBProjectSource - NDHotKeyControl.h - - - - NDHotKeyControl - NSTextField - - IBUserSource - - - - - NSButton - - IBUserSource - - - - - NSObject - - IBProjectSource - NDHotKeyEvent.h - - - - NSObject - - IBUserSource - - - - - OutputPane - GeneralPreferencePane - - takeDeviceID: - id - - - outputDevices - OutputsArrayController - - - IBProjectSource - OutputPane.h - - - - OutputPane - GeneralPreferencePane - - IBUserSource - - - - - OutputsArrayController - NSArrayController - - IBProjectSource - OutputsArrayController.h - - - - OutputsArrayController - NSArrayController - - IBUserSource - - - - - PlaylistBehaviorArrayController - NSArrayController - - IBProjectSource - PlaylistBehaviorArrayController.h - - - - PrefPaneController - NSObject - - fileDrawerPane - FileDrawerPane - - - IBUserSource - - - - - PreferencePane - NSObject - - IBUserSource - - - - - - 0 - ../General.xcodeproj - 3 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + name + + + + + + + + + + + + + name + url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + name + slug + preference + + + + + name + slug + preference + + + + \ No newline at end of file diff --git a/Preferences/General/General.xcodeproj/project.pbxproj b/Preferences/General/General.xcodeproj/project.pbxproj index aeb6486cc..ac236596d 100644 --- a/Preferences/General/General.xcodeproj/project.pbxproj +++ b/Preferences/General/General.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 17E41DB80C130AA500AC744D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 17E41DB70C130AA500AC744D /* Localizable.strings */; }; 17E78A7E0D68BE3C005C5A59 /* file_tree.png in Resources */ = {isa = PBXBuildFile; fileRef = 17E78A7D0D68BE3C005C5A59 /* file_tree.png */; }; 17E78B6A0D68C1E3005C5A59 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = 17E78B680D68C1E3005C5A59 /* Preferences.xib */; }; + 83EF495F17FBC96A00642E3C /* VolumeBehaviorArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83EF495E17FBC96A00642E3C /* VolumeBehaviorArrayController.m */; }; 8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; }; 8E07AA880AAC8EA200A4B32F /* HotKeyPane.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E07AA810AAC8EA200A4B32F /* HotKeyPane.m */; }; 8E07AA890AAC8EA200A4B32F /* GeneralPreferencePane.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E07AA830AAC8EA200A4B32F /* GeneralPreferencePane.m */; }; @@ -53,6 +54,8 @@ 17E78A7D0D68BE3C005C5A59 /* file_tree.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = file_tree.png; path = Icons/file_tree.png; sourceTree = ""; }; 17E78B690D68C1E3005C5A59 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/Preferences.xib; sourceTree = ""; }; 32DBCF630370AF2F00C91783 /* General_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = General_Prefix.pch; sourceTree = ""; }; + 83EF495D17FBC96A00642E3C /* VolumeBehaviorArrayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VolumeBehaviorArrayController.h; sourceTree = ""; }; + 83EF495E17FBC96A00642E3C /* VolumeBehaviorArrayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VolumeBehaviorArrayController.m; sourceTree = ""; }; 8D5B49B6048680CD000E48DA /* General.preferencePane */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = General.preferencePane; sourceTree = BUILT_PRODUCTS_DIR; }; 8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 8E07AA800AAC8EA200A4B32F /* HotKeyPane.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HotKeyPane.h; sourceTree = ""; }; @@ -180,6 +183,8 @@ 17C643360B8A77CC00C53518 /* OutputsArrayController.m */, 99F1813D0DE01D7A00FD5FFB /* PlaylistBehaviorArrayController.h */, 99F1813E0DE01D7A00FD5FFB /* PlaylistBehaviorArrayController.m */, + 83EF495D17FBC96A00642E3C /* VolumeBehaviorArrayController.h */, + 83EF495E17FBC96A00642E3C /* VolumeBehaviorArrayController.m */, ); name = Custom; sourceTree = ""; @@ -296,6 +301,7 @@ 8E6C12160AACAE4100819171 /* NDHotKeyControl.m in Sources */, 8E6C12170AACAE4100819171 /* NDHotKeyEvent.m in Sources */, 8E6C13A00AACBAB500819171 /* HotKeyControl.m in Sources */, + 83EF495F17FBC96A00642E3C /* VolumeBehaviorArrayController.m in Sources */, 17C643380B8A77CC00C53518 /* OutputsArrayController.m in Sources */, 17C6433F0B8A783F00C53518 /* OutputPane.m in Sources */, 170744AD0BFF3938002475C9 /* AppcastArrayController.m in Sources */,