From 03240f16f0d076e0f9306c0bcb2118e549833058 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 9 Jun 2014 22:03:26 -0700 Subject: [PATCH] modernize code --- Source/CurrentsongAppDelegate.h | 25 +- Source/CurrentsongAppDelegate.m | 209 +++---- Source/CurrentsongStatusView.h | 33 +- Source/CurrentsongStatusView.m | 262 ++++----- Source/MSDurationFormatter.m | 31 +- Source/NSAttributedStringAdditions.h | 3 +- Source/NSAttributedStringAdditions.m | 7 +- Source/en.lproj/MainMenu.xib | 817 ++++++++++++++------------- Source/iTunes.h | 58 +- 9 files changed, 738 insertions(+), 707 deletions(-) diff --git a/Source/CurrentsongAppDelegate.h b/Source/CurrentsongAppDelegate.h index f1eae80..bf53a9c 100644 --- a/Source/CurrentsongAppDelegate.h +++ b/Source/CurrentsongAppDelegate.h @@ -12,22 +12,15 @@ @class LaunchAtLoginController; @interface CurrentsongAppDelegate : NSObject -{ - NSStatusItem *mStatusItem; - CurrentsongStatusView *mStatusView; - NSTimer *mMenuUpdateTimer; - BOOL mMenuIsOpen; - - IBOutlet NSMenu *mMenu; - IBOutlet NSMenuItem *mNameMenuItem; - IBOutlet NSMenuItem *mArtistMenuItem; - IBOutlet NSMenuItem *mAlbumMenuItem; - IBOutlet NSMenuItem *mStreamTitleMenuItem; - IBOutlet NSMenuItem *mTimeMenuItem; - IBOutlet NSMenuItem *mVersionMenuItem; - - IBOutlet LaunchAtLoginController *mLaunchAtLoginController; -} + +@property (weak) IBOutlet NSMenu *menu; +@property (weak) IBOutlet NSMenuItem *nameMenuItem; +@property (weak) IBOutlet NSMenuItem *artistMenuItem; +@property (weak) IBOutlet NSMenuItem *albumMenuItem; +@property (weak) IBOutlet NSMenuItem *streamTitleMenuItem; +@property (weak) IBOutlet NSMenuItem *timeMenuItem; +@property (weak) IBOutlet NSMenuItem *versionMenuItem; +@property (weak) IBOutlet LaunchAtLoginController *launchAtLoginController; - (IBAction)toggleShowArtist:(id)sender; - (IBAction)toggleShowAlbum:(id)sender; diff --git a/Source/CurrentsongAppDelegate.m b/Source/CurrentsongAppDelegate.m index 3b4cc41..77b7f65 100644 --- a/Source/CurrentsongAppDelegate.m +++ b/Source/CurrentsongAppDelegate.m @@ -25,7 +25,17 @@ - (void)updateMenuTrackTime; @end -@implementation CurrentsongAppDelegate +@implementation CurrentsongAppDelegate { + NSStatusItem *_statusItem; + CurrentsongStatusView *_statusView; + NSTimer *_menuUpdateTimer; + BOOL _menuIsOpen; +} + ++ (iTunesApplication *)iTunes +{ + return [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"]; +} - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { @@ -42,7 +52,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification NSInteger result = [alert runModal]; [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kCSPrefShownLaunchAtLoginPrompt]; - [mLaunchAtLoginController setLaunchAtLogin:(result == NSAlertDefaultReturn)]; + [_launchAtLoginController setLaunchAtLogin:(result == NSAlertDefaultReturn)]; } } @@ -50,37 +60,35 @@ - (void)awakeFromNib { // Initialize preferences [[NSUserDefaults standardUserDefaults] registerDefaults: - [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInteger:kCSStyleFormatted], kCSPrefViewStyle, - [NSNumber numberWithDouble:kCSViewWidthLarge], kCSPrefMaxWidth, - [NSNumber numberWithBool:YES], kCSPrefShowArtist, - [NSNumber numberWithBool:NO], kCSPrefShowAlbum, - [NSNumber numberWithBool:YES], kCSPrefScrollLongText, - nil]]; + @{kCSPrefViewStyle: @(kCSStyleFormatted), + kCSPrefMaxWidth: [NSNumber numberWithDouble:kCSViewWidthLarge], + kCSPrefShowArtist: @YES, + kCSPrefShowAlbum: @NO, + kCSPrefScrollLongText: @YES}]; // Inject version number into menu - [mVersionMenuItem setTitle:[NSString stringWithFormat:NSLocalizedString(@"Currentsong %@", @"application name with version number"), + [_versionMenuItem setTitle:[NSString stringWithFormat:NSLocalizedString(@"Currentsong %@", @"application name with version number"), [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]]]; // Install status item - mStatusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; - [mStatusItem setMenu:mMenu]; - [mMenu setDelegate:self]; + _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; + [_statusItem setMenu:_menu]; + [_menu setDelegate:self]; // Set up view - mStatusView = [[CurrentsongStatusView alloc] init]; - mStatusView.statusItem = mStatusItem; - mStatusView.viewStyle = (CurrentsongViewStyle)[[NSUserDefaults standardUserDefaults] integerForKey:kCSPrefViewStyle]; - mStatusView.maxWidth = [[NSUserDefaults standardUserDefaults] doubleForKey:kCSPrefMaxWidth]; - mStatusView.showArtist = [[NSUserDefaults standardUserDefaults] boolForKey:kCSPrefShowArtist]; - mStatusView.showAlbum = [[NSUserDefaults standardUserDefaults] boolForKey:kCSPrefShowAlbum]; - mStatusView.shouldScroll = [[NSUserDefaults standardUserDefaults] boolForKey:kCSPrefScrollLongText]; + _statusView = [[CurrentsongStatusView alloc] init]; + _statusView.statusItem = _statusItem; + _statusView.viewStyle = (CurrentsongViewStyle)[[NSUserDefaults standardUserDefaults] integerForKey:kCSPrefViewStyle]; + _statusView.maxWidth = [[NSUserDefaults standardUserDefaults] doubleForKey:kCSPrefMaxWidth]; + _statusView.showArtist = [[NSUserDefaults standardUserDefaults] boolForKey:kCSPrefShowArtist]; + _statusView.showAlbum = [[NSUserDefaults standardUserDefaults] boolForKey:kCSPrefShowAlbum]; + _statusView.shouldScroll = [[NSUserDefaults standardUserDefaults] boolForKey:kCSPrefScrollLongText]; // Get initial track info NSDictionary *initialTrackInfo = [self fetchTrackInfo]; [self updateMenuItemsWithTrackInfo:initialTrackInfo]; - [mStatusView updateTrackInfo:initialTrackInfo]; - [mStatusItem setView:mStatusView]; + [_statusView updateTrackInfo:initialTrackInfo]; + [_statusItem setView:_statusView]; // Start listening to iTunes notifications NSDistributedNotificationCenter *dnc = [NSDistributedNotificationCenter defaultCenter]; @@ -97,16 +105,16 @@ - (void)dealloc { [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self]; - [mMenuUpdateTimer invalidate]; + [_menuUpdateTimer invalidate]; } // Handle play state and track changes - (void)trackInfoDidChange:(NSNotification *)notification { [self updateMenuItemsWithTrackInfo:[notification userInfo]]; - [mStatusView updateTrackInfo:[notification userInfo]]; + [_statusView updateTrackInfo:[notification userInfo]]; - if (mMenuIsOpen) { + if (_menuIsOpen) { [self updateMenuTrackTime]; } } @@ -123,7 +131,7 @@ - (void)anotherAppDidTerminate:(NSNotification *)notification // Fetches play state, artist, name, album, and stream title. - (NSDictionary *)fetchTrackInfo { - iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"]; + iTunesApplication *iTunes = [[self class] iTunes]; // Application not found or not running if (!iTunes || ![iTunes isRunning]) { @@ -146,15 +154,25 @@ - (NSDictionary *)fetchTrackInfo NSString *streamTitle = iTunes.currentStreamTitle; NSMutableDictionary *info = [NSMutableDictionary dictionary]; - if (playerStateString) [info setObject:playerStateString forKey:@"Player State"]; - if (artist) [info setObject:artist forKey:@"Artist"]; - if (name) [info setObject:name forKey:@"Name"]; - if (album) [info setObject:album forKey:@"Album"]; - if (streamTitle) [info setObject:streamTitle forKey:@"Stream Title"]; + if (playerStateString) { + [info setObject:playerStateString forKey:@"Player State"]; + } + if (artist) { + [info setObject:artist forKey:@"Artist"]; + } + if (name) { + [info setObject:name forKey:@"Name"]; + } + if (album) { + [info setObject:album forKey:@"Album"]; + } + if (streamTitle) { + [info setObject:streamTitle forKey:@"Stream Title"]; + } // note: these keys aren't provided by the track change notification - [info setObject:[NSNumber numberWithInteger:iTunes.playerPosition] forKey:@"Player Position"]; - [info setObject:[NSNumber numberWithDouble:currentTrack.duration] forKey:@"Duration"]; + [info setObject:@(iTunes.playerPosition) forKey:@"Player Position"]; + [info setObject:@(currentTrack.duration) forKey:@"Duration"]; return info; } @@ -189,35 +207,34 @@ - (BOOL)validateMenuItem:(NSMenuItem *)menuItem [self updateMenuTrackTime]; return NO; } else if ([menuItem action] == @selector(toggleShowArtist:)) { - [menuItem setState:mStatusView.showArtist]; + [menuItem setState:_statusView.showArtist]; } else if ([menuItem action] == @selector(toggleShowAlbum:)) { - [menuItem setState:mStatusView.showAlbum]; + [menuItem setState:_statusView.showAlbum]; } else if ([menuItem action] == @selector(toggleTwoLineDisplay:)) { - [menuItem setState:(mStatusView.viewStyle == kCSStyleTwoLevel)]; + [menuItem setState:(_statusView.viewStyle == kCSStyleTwoLevel)]; } else if ([menuItem action] == @selector(toggleScrollLongText:)) { - [menuItem setState:mStatusView.shouldScroll]; + [menuItem setState:_statusView.shouldScroll]; } else if ([menuItem action] == @selector(setLargeViewWidth:)) { - [menuItem setState:(mStatusView.maxWidth == kCSViewWidthLarge)]; + [menuItem setState:(_statusView.maxWidth == kCSViewWidthLarge)]; } else if ([menuItem action] == @selector(setMediumViewWidth:)) { - [menuItem setState:(mStatusView.maxWidth == kCSViewWidthMedium)]; + [menuItem setState:(_statusView.maxWidth == kCSViewWidthMedium)]; } else if ([menuItem action] == @selector(setSmallViewWidth:)) { - [menuItem setState:(mStatusView.maxWidth == kCSViewWidthSmall)]; + [menuItem setState:(_statusView.maxWidth == kCSViewWidthSmall)]; } else if ([menuItem action] == @selector(setTitleOnly:)) { - [menuItem setState:(!mStatusView.showArtist && !mStatusView.showAlbum && !(mStatusView.viewStyle == kCSStyleTwoLevel))]; + [menuItem setState:(!_statusView.showArtist && !_statusView.showAlbum && !(_statusView.viewStyle == kCSStyleTwoLevel))]; } else if ([menuItem action] == @selector(setTitleAndArtist:)) { - [menuItem setState:(mStatusView.showArtist && !mStatusView.showAlbum && !(mStatusView.viewStyle == kCSStyleTwoLevel))]; + [menuItem setState:(_statusView.showArtist && !_statusView.showAlbum && !(_statusView.viewStyle == kCSStyleTwoLevel))]; } else if ([menuItem action] == @selector(setTitleArtistAlbum:)) { - [menuItem setState:(mStatusView.showArtist && mStatusView.showAlbum && !(mStatusView.viewStyle == kCSStyleTwoLevel))]; + [menuItem setState:(_statusView.showArtist && _statusView.showAlbum && !(_statusView.viewStyle == kCSStyleTwoLevel))]; } else if ([menuItem action] == @selector(setTitleAndArtistStacked:)) { - [menuItem setState:(mStatusView.showArtist && !mStatusView.showAlbum && (mStatusView.viewStyle == kCSStyleTwoLevel))]; + [menuItem setState:(_statusView.showArtist && !_statusView.showAlbum && (_statusView.viewStyle == kCSStyleTwoLevel))]; } else if ([menuItem action] == @selector(setTitleArtistAlbumStacked:)) { - [menuItem setState:(mStatusView.showArtist && mStatusView.showAlbum && (mStatusView.viewStyle == kCSStyleTwoLevel))]; + [menuItem setState:(_statusView.showArtist && _statusView.showAlbum && (_statusView.viewStyle == kCSStyleTwoLevel))]; } else if ([menuItem action] == @selector(toggleLaunchAtLogin:)) { - [menuItem setState:[mLaunchAtLoginController launchAtLogin]]; + [menuItem setState:[_launchAtLoginController launchAtLogin]]; } else if ([menuItem action] == @selector(launchITunes:)) { - iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"]; - [menuItem setTitle:([iTunes isRunning]) ? NSLocalizedString(@"iTunes", @"iTunes") - : NSLocalizedString(@"Launch iTunes", @"Launch iTunes")]; + [menuItem setTitle:([[[self class] iTunes] isRunning]) ? NSLocalizedString(@"iTunes", @"iTunes") + : NSLocalizedString(@"Launch iTunes", @"Launch iTunes")]; } return YES; } @@ -230,31 +247,31 @@ - (void)updateMenuItemsWithTrackInfo:(NSDictionary *)trackInfo NSString *streamTitle = [trackInfo objectForKey:@"Stream Title"]; if ([name length] > 0) { - [mNameMenuItem setHidden:NO]; - [mNameMenuItem setTitle:name]; + [_nameMenuItem setHidden:NO]; + [_nameMenuItem setTitle:name]; } else { - [mNameMenuItem setHidden:YES]; + [_nameMenuItem setHidden:YES]; } if ([artist length] > 0) { - [mArtistMenuItem setHidden:NO]; - [mArtistMenuItem setTitle:artist]; + [_artistMenuItem setHidden:NO]; + [_artistMenuItem setTitle:artist]; } else { - [mArtistMenuItem setHidden:YES]; + [_artistMenuItem setHidden:YES]; } if ([album length] > 0) { - [mAlbumMenuItem setHidden:NO]; - [mAlbumMenuItem setTitle:album]; + [_albumMenuItem setHidden:NO]; + [_albumMenuItem setTitle:album]; } else { - [mAlbumMenuItem setHidden:YES]; + [_albumMenuItem setHidden:YES]; } if ([streamTitle length] > 0) { - [mStreamTitleMenuItem setHidden:NO]; - [mStreamTitleMenuItem setTitle:streamTitle]; + [_streamTitleMenuItem setHidden:NO]; + [_streamTitleMenuItem setTitle:streamTitle]; } else { - [mStreamTitleMenuItem setHidden:YES]; + [_streamTitleMenuItem setHidden:YES]; } } @@ -263,7 +280,7 @@ - (void)updateMenuTrackTime NSDictionary *info = [self fetchTrackInfo]; NSString *elapsedTimeString = [[self class] timeStringFromTrackInfo:info]; if (elapsedTimeString) { - [mTimeMenuItem setTitle:elapsedTimeString]; + [_timeMenuItem setTitle:elapsedTimeString]; } } @@ -274,32 +291,29 @@ - (void)menuUpdateTimerFired:(NSTimer *)timer - (void)menuWillOpen:(NSMenu *)menu { - if (menu == mMenu) - { - if (!mMenuUpdateTimer) - { - mMenuUpdateTimer = [[NSTimer alloc] initWithFireDate:[NSDate date] + if (menu == _menu) { + if (!_menuUpdateTimer) { + _menuUpdateTimer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:1 target:self selector:@selector(menuUpdateTimerFired:) userInfo:nil repeats:YES]; - [[NSRunLoop currentRunLoop] addTimer:mMenuUpdateTimer forMode:NSRunLoopCommonModes]; + [[NSRunLoop currentRunLoop] addTimer:_menuUpdateTimer forMode:NSRunLoopCommonModes]; } - mStatusView.highlighted = YES; - mMenuIsOpen = YES; + _statusView.highlighted = YES; + _menuIsOpen = YES; } } - (void)menuDidClose:(NSMenu *)menu { - if (menu == mMenu) - { - [mMenuUpdateTimer invalidate]; - mMenuUpdateTimer = nil; - mStatusView.highlighted = NO; - mMenuIsOpen = NO; + if (menu == _menu) { + [_menuUpdateTimer invalidate]; + _menuUpdateTimer = nil; + _statusView.highlighted = NO; + _menuIsOpen = NO; } } @@ -311,74 +325,74 @@ - (IBAction)trackElapsedTime:(id)sender {} - (IBAction)toggleShowArtist:(id)sender { - mStatusView.showArtist = !mStatusView.showArtist; - [[NSUserDefaults standardUserDefaults] setBool:mStatusView.showArtist forKey:kCSPrefShowArtist]; + _statusView.showArtist = !_statusView.showArtist; + [[NSUserDefaults standardUserDefaults] setBool:_statusView.showArtist forKey:kCSPrefShowArtist]; } - (IBAction)toggleShowAlbum:(id)sender { - mStatusView.showAlbum = !mStatusView.showAlbum; - [[NSUserDefaults standardUserDefaults] setBool:mStatusView.showAlbum forKey:kCSPrefShowAlbum]; + _statusView.showAlbum = !_statusView.showAlbum; + [[NSUserDefaults standardUserDefaults] setBool:_statusView.showAlbum forKey:kCSPrefShowAlbum]; } - (IBAction)toggleTwoLineDisplay:(id)sender { - mStatusView.viewStyle = (mStatusView.viewStyle == kCSStyleTwoLevel) ? kCSStyleFormatted : kCSStyleTwoLevel; - [[NSUserDefaults standardUserDefaults] setInteger:mStatusView.viewStyle forKey:kCSPrefViewStyle]; + _statusView.viewStyle = (_statusView.viewStyle == kCSStyleTwoLevel) ? kCSStyleFormatted : kCSStyleTwoLevel; + [[NSUserDefaults standardUserDefaults] setInteger:_statusView.viewStyle forKey:kCSPrefViewStyle]; // make sure the second line is showing - if (!mStatusView.showArtist) { + if (!_statusView.showArtist) { [self toggleShowArtist:self]; } } - (void)writeDisplayPreference { - [[NSUserDefaults standardUserDefaults] setBool:mStatusView.showArtist forKey:kCSPrefShowArtist]; - [[NSUserDefaults standardUserDefaults] setBool:mStatusView.showAlbum forKey:kCSPrefShowAlbum]; - [[NSUserDefaults standardUserDefaults] setInteger:mStatusView.viewStyle forKey:kCSPrefViewStyle]; + [[NSUserDefaults standardUserDefaults] setBool:_statusView.showArtist forKey:kCSPrefShowArtist]; + [[NSUserDefaults standardUserDefaults] setBool:_statusView.showAlbum forKey:kCSPrefShowAlbum]; + [[NSUserDefaults standardUserDefaults] setInteger:_statusView.viewStyle forKey:kCSPrefViewStyle]; } - (IBAction)setTitleOnly:(id)sender { - [mStatusView setShowArtist:NO showAlbum:NO viewStyle:kCSStyleFormatted]; + [_statusView setShowArtist:NO showAlbum:NO viewStyle:kCSStyleFormatted]; [self writeDisplayPreference]; } - (IBAction)setTitleAndArtist:(id)sender { - [mStatusView setShowArtist:YES showAlbum:NO viewStyle:kCSStyleFormatted]; + [_statusView setShowArtist:YES showAlbum:NO viewStyle:kCSStyleFormatted]; [self writeDisplayPreference]; } - (IBAction)setTitleArtistAlbum:(id)sender { - [mStatusView setShowArtist:YES showAlbum:YES viewStyle:kCSStyleFormatted]; + [_statusView setShowArtist:YES showAlbum:YES viewStyle:kCSStyleFormatted]; [self writeDisplayPreference]; } - (IBAction)setTitleAndArtistStacked:(id)sender { - [mStatusView setShowArtist:YES showAlbum:NO viewStyle:kCSStyleTwoLevel]; + [_statusView setShowArtist:YES showAlbum:NO viewStyle:kCSStyleTwoLevel]; [self writeDisplayPreference]; } - (IBAction)setTitleArtistAlbumStacked:(id)sender; { - [mStatusView setShowArtist:YES showAlbum:YES viewStyle:kCSStyleTwoLevel]; + [_statusView setShowArtist:YES showAlbum:YES viewStyle:kCSStyleTwoLevel]; [self writeDisplayPreference]; } - (IBAction)toggleScrollLongText:(id)sender { - mStatusView.shouldScroll = !mStatusView.shouldScroll; - [[NSUserDefaults standardUserDefaults] setBool:mStatusView.shouldScroll forKey:kCSPrefScrollLongText]; + _statusView.shouldScroll = !_statusView.shouldScroll; + [[NSUserDefaults standardUserDefaults] setBool:_statusView.shouldScroll forKey:kCSPrefScrollLongText]; } - (void)setMaxWidth:(CGFloat)maxWidth { - mStatusView.maxWidth = maxWidth; - [[NSUserDefaults standardUserDefaults] setDouble:mStatusView.maxWidth forKey:kCSPrefMaxWidth]; + _statusView.maxWidth = maxWidth; + [[NSUserDefaults standardUserDefaults] setDouble:_statusView.maxWidth forKey:kCSPrefMaxWidth]; } - (IBAction)setLargeViewWidth:(id)sender @@ -398,14 +412,13 @@ - (IBAction)setSmallViewWidth:(id)sender - (IBAction)toggleLaunchAtLogin:(id)sender { - [mLaunchAtLoginController setLaunchAtLogin:![mLaunchAtLoginController launchAtLogin]]; + [_launchAtLoginController setLaunchAtLogin:![_launchAtLoginController launchAtLogin]]; } - (IBAction)launchITunes:(id)sender { // Reveal the current track (only if iTunes is already running) - iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"]; - [[iTunes currentTrack] reveal]; + [[[[self class] iTunes] currentTrack] reveal]; // Activate iTunes (or launch it) [[NSWorkspace sharedWorkspace] launchAppWithBundleIdentifier:@"com.apple.iTunes" diff --git a/Source/CurrentsongStatusView.h b/Source/CurrentsongStatusView.h index 0bcaec2..733cd55 100644 --- a/Source/CurrentsongStatusView.h +++ b/Source/CurrentsongStatusView.h @@ -8,44 +8,15 @@ #import -typedef enum +typedef NS_ENUM(NSInteger, CurrentsongViewStyle) { kCSStyleFormatted, kCSStylePlain, kCSStyleTwoLevel -} CurrentsongViewStyle; +}; @interface CurrentsongStatusView : NSView -{ - NSStatusItem *mStatusItem; - - // Properties - BOOL mHighlighted; - CurrentsongViewStyle mViewStyle; - CGFloat mMaxWidth; - BOOL mShowArtist; - BOOL mShowAlbum; - BOOL mShouldScroll; - - // Track data - BOOL mShowPauseIcon; - BOOL mIsStream; - NSString *mArtist; - NSString *mName; - NSString *mAlbum; - - NSAttributedString *mTopRow; - NSAttributedString *mBottomRow; - CGFloat mTopRowScrollOffset; - CGFloat mBottomRowScrollOffset; - BOOL mScrollTopRow; - BOOL mScrollBottomRow; - NSTimer *mScrollTimer; - - CGImageRef mAlphaMask; - BOOL mAlphaMaskAccountsForPauseIcon; -} @property (nonatomic,strong) NSStatusItem *statusItem; @property (nonatomic,assign) BOOL highlighted; diff --git a/Source/CurrentsongStatusView.m b/Source/CurrentsongStatusView.m index d0f6d37..a37354b 100644 --- a/Source/CurrentsongStatusView.m +++ b/Source/CurrentsongStatusView.m @@ -25,40 +25,42 @@ @interface CurrentsongStatusView () @property (nonatomic,strong) NSString *album; @property (nonatomic,strong) NSAttributedString *topRow; @property (nonatomic,strong) NSAttributedString *bottomRow; -- (BOOL)isScrolling; +@property (nonatomic, getter=isScrolling, readonly) BOOL scrolling; - (void)startScrolling; - (void)stopScrolling; @end #pragma mark - -@implementation CurrentsongStatusView - -@synthesize statusItem = mStatusItem; -@synthesize viewStyle = mViewStyle; -@synthesize maxWidth = mMaxWidth; -@synthesize showArtist = mShowArtist; -@synthesize showAlbum = mShowAlbum; -@synthesize shouldScroll = mShouldScroll; -@synthesize artist = mArtist; -@synthesize name = mName; -@synthesize album = mAlbum; -@synthesize topRow = mTopRow; -@synthesize bottomRow = mBottomRow; -@synthesize highlighted = mHighlighted; +@implementation CurrentsongStatusView { + BOOL _highlighted; + CGFloat _maxWidth; + BOOL _showPauseIcon; + BOOL _isStream; + + NSAttributedString *_topRow; + NSAttributedString *_bottomRow; + CGFloat _topRowScrollOffset; + CGFloat _bottomRowScrollOffset; + BOOL _scrollTopRow; + BOOL _scrollBottomRow; + NSTimer *_scrollTimer; + + CGImageRef _alphaMask; + BOOL _alphaMaskAccountsForPauseIcon; +} #pragma mark - - (void)dealloc { - CGImageRelease(mAlphaMask); - [mScrollTimer invalidate]; + CGImageRelease(_alphaMask); + [_scrollTimer invalidate]; } // Mimic the white shadow under menu item text in the menu bar + (NSShadow *)menuBarShadow { static NSShadow *shadow = nil; - if (!shadow) - { + if (!shadow) { shadow = [[NSShadow alloc] init]; [shadow setShadowColor:[NSColor colorWithDeviceWhite:1 alpha:0.25]]; [shadow setShadowOffset:NSMakeSize(0, -1)]; @@ -71,7 +73,7 @@ + (NSShadow *)menuBarShadow - (void)drawPauseIcon { NSPoint iconOrigin = NSMakePoint(5,7); - [((mHighlighted) ? [NSColor whiteColor] : [NSColor blackColor]) set]; + [((_highlighted) ? [NSColor whiteColor] : [NSColor blackColor]) set]; NSRect rect = NSMakeRect(iconOrigin.x,iconOrigin.y,3,9); [NSBezierPath fillRect:rect]; rect.origin.x += 5; @@ -81,7 +83,7 @@ - (void)drawPauseIcon - (void)generateEdgeMask { NSSize viewSize = [self frame].size; - CGFloat leftEdge = (mShowPauseIcon) ? kCSViewPauseIconOffset : 0; + CGFloat leftEdge = (_showPauseIcon) ? kCSViewPauseIconOffset : 0; CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray(); CGContextRef maskContext = CGBitmapContextCreate(NULL, viewSize.width, viewSize.height, 8, viewSize.width, cs, 0); @@ -91,7 +93,7 @@ - (void)generateEdgeMask CGContextFillRect(maskContext, NSRectToCGRect([self bounds])); #if kCSViewFadeEdges - if (mShowPauseIcon) { + if (_showPauseIcon) { CGContextSetGrayFillColor(maskContext, 0, 1); CGContextFillRect(maskContext, NSMakeRect(0, 0, leftEdge, viewSize.height)); } @@ -107,9 +109,9 @@ - (void)generateEdgeMask CGContextFillRect(maskContext, CGRectMake(0, 0, leftEdge+kCSViewSideMargin, viewSize.height)); // left edges #endif - CGImageRelease(mAlphaMask); - mAlphaMask = CGBitmapContextCreateImage(maskContext); - mAlphaMaskAccountsForPauseIcon = mShowPauseIcon; + CGImageRelease(_alphaMask); + _alphaMask = CGBitmapContextCreateImage(maskContext); + _alphaMaskAccountsForPauseIcon = _showPauseIcon; CGContextRelease(maskContext); } @@ -119,17 +121,17 @@ - (void)setEdgeMask NSSize viewSize = [self frame].size; // generate the mask if necessary - BOOL needToRegenerateMask = (!mAlphaMask || - CGImageGetWidth(mAlphaMask) != viewSize.width || - CGImageGetHeight(mAlphaMask) != viewSize.height || - mAlphaMaskAccountsForPauseIcon != mShowPauseIcon); + BOOL needToRegenerateMask = (!_alphaMask || + CGImageGetWidth(_alphaMask) != viewSize.width || + CGImageGetHeight(_alphaMask) != viewSize.height || + _alphaMaskAccountsForPauseIcon != _showPauseIcon); if (needToRegenerateMask) { [self generateEdgeMask]; } CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; - CGContextClipToMask(context, NSRectToCGRect([self bounds]), mAlphaMask); + CGContextClipToMask(context, NSRectToCGRect([self bounds]), _alphaMask); } // If yPosition is less than 0, draw the text centered in the view. @@ -162,7 +164,7 @@ - (void)drawTextRow:(NSAttributedString *)text leftEdge:(CGFloat)leftEdge yPosit - (void)drawRect:(NSRect)rect { - [mStatusItem drawStatusBarBackgroundInRect:[self bounds] withHighlight:mHighlighted]; + [_statusItem drawStatusBarBackgroundInRect:[self bounds] withHighlight:_highlighted]; [NSGraphicsContext saveGraphicsState]; CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; @@ -171,51 +173,51 @@ - (void)drawRect:(NSRect)rect CGContextSetShouldSmoothFonts(context, NO); // add subtle white shadow to match other menu bar text - if (!mHighlighted) { + if (!_highlighted) { [[CurrentsongStatusView menuBarShadow] set]; } // draw pause icon CGFloat leftEdge = kCSViewSideMargin; - if (mShowPauseIcon) { + if (_showPauseIcon) { leftEdge += kCSViewPauseIconOffset; [self drawPauseIcon]; } // set clipping mask and draw text - BOOL twoRows = ([mTopRow length] > 0 && [mBottomRow length] > 0); + BOOL twoRows = ([_topRow length] > 0 && [_bottomRow length] > 0); [self setEdgeMask]; - [self drawTextRow:mTopRow leftEdge:leftEdge yPosition:((twoRows) ? 11 : kCSDrawTextCentered) scrollOffset:mTopRowScrollOffset]; - [self drawTextRow:mBottomRow leftEdge:leftEdge yPosition:((twoRows) ? 1 : kCSDrawTextCentered) scrollOffset:mBottomRowScrollOffset]; + [self drawTextRow:_topRow leftEdge:leftEdge yPosition:((twoRows) ? 11 : kCSDrawTextCentered) scrollOffset:_topRowScrollOffset]; + [self drawTextRow:_bottomRow leftEdge:leftEdge yPosition:((twoRows) ? 1 : kCSDrawTextCentered) scrollOffset:_bottomRowScrollOffset]; [NSGraphicsContext restoreGraphicsState]; } - (void)updateBounds { - CGFloat height = mStatusItem.statusBar.thickness; - CGFloat topRowWidth = (mTopRow) ? [mTopRow size].width : 0; - CGFloat bottomRowWidth = (mBottomRow) ? [mBottomRow size].width : 0; + CGFloat height = _statusItem.statusBar.thickness; + CGFloat topRowWidth = (_topRow) ? [_topRow size].width : 0; + CGFloat bottomRowWidth = (_bottomRow) ? [_bottomRow size].width : 0; CGFloat width = MAX(topRowWidth, bottomRowWidth); CGFloat padding = kCSViewSideMargin*2; width += padding; - // If mMaxWidth is greater than 0, enforce maximum width - if (mMaxWidth > 0) { - width = MIN(mMaxWidth, width); + // If _maxWidth is greater than 0, enforce maximum width + if (_maxWidth > 0) { + width = MIN(_maxWidth, width); } - if (mShowPauseIcon) { + if (_showPauseIcon) { padding += kCSViewPauseIconOffset; width += kCSViewPauseIconOffset; } - mScrollTopRow = (topRowWidth > width-padding); - mScrollBottomRow = (bottomRowWidth > width-padding); + _scrollTopRow = (topRowWidth > width-padding); + _scrollBottomRow = (bottomRowWidth > width-padding); - if (mShouldScroll && (mScrollTopRow || mScrollBottomRow) && ![self isScrolling]) { + if (_shouldScroll && (_scrollTopRow || _scrollBottomRow) && ![self isScrolling]) { [self startScrolling]; - } else if (!(mScrollTopRow || mScrollBottomRow) && [self isScrolling]) { + } else if (!(_scrollTopRow || _scrollBottomRow) && [self isScrolling]) { [self stopScrolling]; } @@ -225,55 +227,65 @@ - (void)updateBounds - (void)updateAppearance { - BOOL haveArtist = mShowArtist && ([mArtist length] > 0); - BOOL haveName = ([mName length] > 0); - BOOL haveAlbum = mShowAlbum && ([mAlbum length] > 0); + BOOL haveArtist = _showArtist && ([_artist length] > 0); + BOOL haveName = ([_name length] > 0); + BOOL haveAlbum = _showAlbum && ([_album length] > 0); self.bottomRow = nil; // No track name, not plaing if (!haveName) { - mShowPauseIcon = NO; - self.topRow = [NSAttributedString menuBarAttributedString:@"\u266B" attributes:mHighlighted]; + _showPauseIcon = NO; + self.topRow = [NSAttributedString menuBarAttributedString:@"\u266B" attributes:_highlighted]; } else { - if (mViewStyle == kCSStyleFormatted) - { + if (_viewStyle == kCSStyleFormatted) { NSMutableAttributedString *topRowFormatted = [[NSMutableAttributedString alloc] init]; NSMutableArray *fields = [NSMutableArray arrayWithCapacity:3]; - if (haveName) [fields addObject:[NSAttributedString menuBarAttributedString:mName attributes:mHighlighted|kCSBold]]; - if (haveArtist) [fields addObject:[NSAttributedString menuBarAttributedString:mArtist attributes:mHighlighted]]; - if (haveAlbum) [fields addObject:[NSAttributedString menuBarAttributedString:mAlbum attributes:mHighlighted|kCSLight]]; - + if (haveName) { + [fields addObject:[NSAttributedString menuBarAttributedString:_name attributes:_highlighted|kCSBold]]; + } + if (haveArtist) { + [fields addObject:[NSAttributedString menuBarAttributedString:_artist attributes:_highlighted]]; + } + if (haveAlbum) { + [fields addObject:[NSAttributedString menuBarAttributedString:_album attributes:_highlighted|kCSLight]]; + } + BOOL first = YES; - for (NSAttributedString *astr in fields) - { - if (!first) [topRowFormatted appendAttributedString: - [NSAttributedString menuBarAttributedString:@" " attributes:mHighlighted]]; + for (NSAttributedString *astr in fields) { + if (!first) { + [topRowFormatted appendAttributedString:[NSAttributedString menuBarAttributedString:@" " attributes:_highlighted]]; + } [topRowFormatted appendAttributedString:astr]; first = NO; } self.topRow = topRowFormatted; - } - else if (mViewStyle == kCSStyleTwoLevel) - { - self.topRow = [NSAttributedString menuBarAttributedString:mName attributes:mHighlighted|kCSBold|kCSSmall]; + } else if (_viewStyle == kCSStyleTwoLevel) { + self.topRow = [NSAttributedString menuBarAttributedString:_name attributes:_highlighted|kCSBold|kCSSmall]; NSMutableArray *fields = [NSMutableArray arrayWithCapacity:2]; - if (haveArtist) [fields addObject:mArtist]; - if (haveAlbum) [fields addObject:mAlbum]; + if (haveArtist) { + [fields addObject:_artist]; + } + if (haveAlbum) { + [fields addObject:_album]; + } self.bottomRow = [NSAttributedString menuBarAttributedString:[fields componentsJoinedByString:@" \u2014 "] - attributes:mHighlighted|kCSSmall]; - } - else - { + attributes:_highlighted|kCSSmall]; + } else { NSMutableArray *fields = [NSMutableArray arrayWithCapacity:3]; - if (haveName) [fields addObject:mName]; - if (haveArtist) [fields addObject:mArtist]; - if (haveAlbum) [fields addObject:mAlbum]; - + if (haveName) { + [fields addObject:_name]; + } + if (haveArtist) { + [fields addObject:_artist]; + } + if (haveAlbum) { + [fields addObject:_album]; + } self.topRow = [NSAttributedString menuBarAttributedString:[fields componentsJoinedByString:@" \u2014 "] - attributes:mHighlighted]; + attributes:_highlighted]; } } @@ -287,24 +299,23 @@ - (void)updateTrackInfo:(NSDictionary *)trackInfo NSString *album = [trackInfo objectForKey:@"Album"]; NSString *streamTitle = [trackInfo objectForKey:@"Stream Title"]; NSString *playerState = [trackInfo objectForKey:@"Player State"]; - mShowPauseIcon = ([playerState isEqualToString:@"Stopped"] || [playerState isEqualToString:@"Paused"]); + _showPauseIcon = ([playerState isEqualToString:@"Stopped"] || [playerState isEqualToString:@"Paused"]); // Streaming? if (streamTitle) { - mIsStream = YES; + _isStream = YES; album = name; name = streamTitle; } else { - mIsStream = NO; + _isStream = NO; } // Reset scroll offset if the track changed if ([self isScrolling] && (![artist isEqualToString:self.artist] || ![name isEqualToString:self.name] || - ![album isEqualToString:self.album])) - { - mTopRowScrollOffset = kCSViewScrollStartOffset; - mBottomRowScrollOffset = kCSViewScrollStartOffset; + ![album isEqualToString:self.album])) { + _topRowScrollOffset = kCSViewScrollStartOffset; + _bottomRowScrollOffset = kCSViewScrollStartOffset; } self.artist = artist; @@ -319,45 +330,45 @@ - (void)updateTrackInfo:(NSDictionary *)trackInfo - (BOOL)isScrolling { - return (mScrollTimer != nil); + return (_scrollTimer != nil); } - (void)startScrolling { - if (mScrollTimer) { + if (_scrollTimer) { return; } - mScrollTimer = [NSTimer scheduledTimerWithTimeInterval:kCSViewScrollTimerFrequency - target:self - selector:@selector(scrollTimerFired:) - userInfo:nil - repeats:YES]; + _scrollTimer = [NSTimer scheduledTimerWithTimeInterval:kCSViewScrollTimerFrequency + target:self + selector:@selector(scrollTimerFired:) + userInfo:nil + repeats:YES]; } - (void)stopScrolling { - if (!mScrollTimer) { + if (!_scrollTimer) { return; } - [mScrollTimer invalidate]; - mScrollTimer = nil; + [_scrollTimer invalidate]; + _scrollTimer = nil; } - (void)scrollTimerFired:(NSTimer *)timer { - if (mScrollTopRow && mTopRow) { - mTopRowScrollOffset += 1; - if (mTopRowScrollOffset >= [mTopRow size].width+kCSViewScrollPadding) { - mTopRowScrollOffset = kCSViewScrollStartOffset; + if (_scrollTopRow && _topRow) { + _topRowScrollOffset += 1; + if (_topRowScrollOffset >= [_topRow size].width+kCSViewScrollPadding) { + _topRowScrollOffset = kCSViewScrollStartOffset; } } - if (mScrollBottomRow && mBottomRow) { - mBottomRowScrollOffset += 1; - if (mBottomRowScrollOffset >= [mBottomRow size].width+kCSViewScrollPadding) { - mBottomRowScrollOffset = kCSViewScrollStartOffset; + if (_scrollBottomRow && _bottomRow) { + _bottomRowScrollOffset += 1; + if (_bottomRowScrollOffset >= [_bottomRow size].width+kCSViewScrollPadding) { + _bottomRowScrollOffset = kCSViewScrollStartOffset; } } @@ -369,61 +380,60 @@ - (void)scrollTimerFired:(NSTimer *)timer - (void)setHighlighted:(BOOL)highlighted { - mHighlighted = highlighted; [self updateAppearance]; + _highlighted = highlighted; [self updateAppearance]; } - (void)setViewStyle:(CurrentsongViewStyle)viewStyle { - mViewStyle = viewStyle; - mTopRowScrollOffset = kCSViewScrollStartOffset; - mBottomRowScrollOffset = kCSViewScrollStartOffset; + _viewStyle = viewStyle; + _topRowScrollOffset = kCSViewScrollStartOffset; + _bottomRowScrollOffset = kCSViewScrollStartOffset; [self updateAppearance]; } - (void)setMaxWidth:(CGFloat)maxWidth { - mMaxWidth = maxWidth; - mTopRowScrollOffset = kCSViewScrollStartOffset; - mBottomRowScrollOffset = kCSViewScrollStartOffset; + _maxWidth = maxWidth; + _topRowScrollOffset = kCSViewScrollStartOffset; + _bottomRowScrollOffset = kCSViewScrollStartOffset; [self updateAppearance]; } - (void)setShowArtist:(BOOL)showArtist { - mShowArtist = showArtist; - mTopRowScrollOffset = kCSViewScrollStartOffset; - mBottomRowScrollOffset = kCSViewScrollStartOffset; + _showArtist = showArtist; + _topRowScrollOffset = kCSViewScrollStartOffset; + _bottomRowScrollOffset = kCSViewScrollStartOffset; [self updateAppearance]; } - (void)setShowAlbum:(BOOL)showAlbum { - mShowAlbum = showAlbum; - mTopRowScrollOffset = kCSViewScrollStartOffset; - mBottomRowScrollOffset = kCSViewScrollStartOffset; + _showAlbum = showAlbum; + _topRowScrollOffset = kCSViewScrollStartOffset; + _bottomRowScrollOffset = kCSViewScrollStartOffset; [self updateAppearance]; } - (void)setShowArtist:(BOOL)showArtist showAlbum:(BOOL)showAlbum viewStyle:(CurrentsongViewStyle)viewStyle { - mShowArtist = showArtist; - mShowAlbum = showAlbum; - mViewStyle = viewStyle; - mTopRowScrollOffset = kCSViewScrollStartOffset; - mBottomRowScrollOffset = kCSViewScrollStartOffset; + _showArtist = showArtist; + _showAlbum = showAlbum; + _viewStyle = viewStyle; + _topRowScrollOffset = kCSViewScrollStartOffset; + _bottomRowScrollOffset = kCSViewScrollStartOffset; [self updateAppearance]; } - (void)setShouldScroll:(BOOL)shouldScroll { - if (mShouldScroll != shouldScroll) - { + if (_shouldScroll != shouldScroll) { if (!shouldScroll) { [self stopScrolling]; } - mShouldScroll = shouldScroll; - mTopRowScrollOffset = kCSViewScrollStartOffset; - mBottomRowScrollOffset = kCSViewScrollStartOffset; + _shouldScroll = shouldScroll; + _topRowScrollOffset = kCSViewScrollStartOffset; + _bottomRowScrollOffset = kCSViewScrollStartOffset; [self updateAppearance]; } } @@ -431,7 +441,7 @@ - (void)setShouldScroll:(BOOL)shouldScroll #pragma mark Events - (void)mouseDown:(NSEvent *)event { - [mStatusItem popUpStatusItemMenu:[mStatusItem menu]]; + [_statusItem popUpStatusItemMenu:[_statusItem menu]]; [self setNeedsDisplay:YES]; } diff --git a/Source/MSDurationFormatter.m b/Source/MSDurationFormatter.m index e7a6279..be72bdf 100644 --- a/Source/MSDurationFormatter.m +++ b/Source/MSDurationFormatter.m @@ -15,20 +15,23 @@ @implementation MSDurationFormatter + (void)initialize { - // Cocoa provides no way to access the localized time separator, - // so extract them manually from the current locale - // This doesn't support weirdos with custom date/time formats, but whatever - NSString *dateFormat = [NSDateFormatter dateFormatFromTemplate:@"hhmmss" options:0 locale:[NSLocale currentLocale]]; - NSMutableCharacterSet *separatorChars = [NSMutableCharacterSet letterCharacterSet]; - [separatorChars formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]]; - [separatorChars invert]; - NSRange separatorRange = [dateFormat rangeOfCharacterFromSet:separatorChars]; - - if (separatorRange.location != NSNotFound) { - sSeparator = [dateFormat substringWithRange:separatorRange]; - } else { - sSeparator = @":"; - } + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // Cocoa provides no way to access the localized time separator, + // so extract them manually from the current locale + // This doesn't support weirdos with custom date/time formats, but whatever + NSString *dateFormat = [NSDateFormatter dateFormatFromTemplate:@"hhmmss" options:0 locale:[NSLocale currentLocale]]; + NSMutableCharacterSet *separatorChars = [NSMutableCharacterSet letterCharacterSet]; + [separatorChars formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]]; + [separatorChars invert]; + NSRange separatorRange = [dateFormat rangeOfCharacterFromSet:separatorChars]; + + if (separatorRange.location != NSNotFound) { + sSeparator = [dateFormat substringWithRange:separatorRange]; + } else { + sSeparator = @":"; + } + }); } + (NSString *)hoursMinutesSecondsFromSeconds:(NSInteger)seconds diff --git a/Source/NSAttributedStringAdditions.h b/Source/NSAttributedStringAdditions.h index 45ec03a..b40f22f 100644 --- a/Source/NSAttributedStringAdditions.h +++ b/Source/NSAttributedStringAdditions.h @@ -9,7 +9,7 @@ #import -enum +typedef NS_OPTIONS(NSUInteger, CurrentsongTextAttributeMask) { kCSPlain = 0, kCSHighlighted = 1, @@ -17,7 +17,6 @@ enum kCSLight = 4, kCSSmall = 8 }; -typedef NSInteger CurrentsongTextAttributeMask; @interface NSAttributedString (NSAttributedStringAdditions) diff --git a/Source/NSAttributedStringAdditions.m b/Source/NSAttributedStringAdditions.m index 53c4570..268a636 100644 --- a/Source/NSAttributedStringAdditions.m +++ b/Source/NSAttributedStringAdditions.m @@ -10,7 +10,6 @@ @implementation NSAttributedString (NSAttributedStringAdditions) - + (NSAttributedString *)attributedStringWithString:(NSString *)str attributes:(NSDictionary *)attrs { return [[NSAttributedString alloc] initWithString:str attributes:attrs]; @@ -31,10 +30,8 @@ + (NSAttributedString *)menuBarAttributedString:(NSString *)str attributes:(Curr NSColor *color = [NSColor colorWithDeviceWhite:(highlight) ? 1.0 : 0.0 alpha:alpha]; - NSDictionary *attrsDict = [NSDictionary dictionaryWithObjectsAndKeys: - font, NSFontAttributeName, - color, NSForegroundColorAttributeName, - nil]; + NSDictionary *attrsDict = @{NSFontAttributeName: font, + NSForegroundColorAttributeName: color}; return [NSAttributedString attributedStringWithString:str attributes:attrsDict]; } diff --git a/Source/en.lproj/MainMenu.xib b/Source/en.lproj/MainMenu.xib index 6cb80a9..9d9661a 100644 --- a/Source/en.lproj/MainMenu.xib +++ b/Source/en.lproj/MainMenu.xib @@ -1,31 +1,28 @@ - + - 1080 - 12E55 - 3084 - 1187.39 - 626.00 + 1070 + 13D65 + 6154.17 + 1265.20 + 698.00 com.apple.InterfaceBuilder.CocoaPlugin - 3084 + 6154.17 - - YES + NSCustomObject NSMenu NSMenuItem - - - YES + + com.apple.InterfaceBuilder.CocoaPlugin - + PluginDependencyRecalculationVersion - - YES + NSApplication @@ -40,8 +37,7 @@ - - YES + YES @@ -119,10 +115,10 @@ submenuAction: + - - YES + YES @@ -269,7 +265,7 @@ - + @@ -280,15 +276,14 @@ - + LaunchAtLoginController - + - - YES + delegate @@ -305,46 +300,6 @@ 560 - - - mMenu - - - - 554 - - - - mArtistMenuItem - - - - 556 - - - - mAlbumMenuItem - - - - 557 - - - - mTimeMenuItem - - - - 558 - - - - mNameMenuItem - - - - 561 - trackElapsedTime: @@ -353,14 +308,6 @@ 562 - - - mStreamTitleMenuItem - - - - 564 - setLargeViewWidth: @@ -433,14 +380,6 @@ 595 - - - mLaunchAtLoginController - - - - 597 - toggleLaunchAtLogin: @@ -465,15 +404,76 @@ 601 - + + + menu + + + + 602 + + + + albumMenuItem + + + + 603 + + + + artistMenuItem + + + + 604 + + + + launchAtLoginController + + + + 605 + + + + nameMenuItem + + + + 606 + + + + streamTitleMenuItem + + + + 607 + + + + timeMenuItem + + + + 608 + + + + versionMenuItem + + + + 609 + + - - YES + 0 - - YES - + @@ -503,8 +503,7 @@ 533 - - YES + @@ -514,7 +513,7 @@ - + @@ -545,10 +544,9 @@ 539 - - YES + - + @@ -559,8 +557,7 @@ 541 - - YES + @@ -578,7 +575,7 @@ - + @@ -681,305 +678,341 @@ - - - - YES - - YES - -1.IBPluginDependency - -2.IBPluginDependency - -3.IBPluginDependency - 494.IBPluginDependency - 533.IBPluginDependency - 534.IBPluginDependency - 535.IBPluginDependency - 536.IBPluginDependency - 537.IBPluginDependency - 538.IBPluginDependency - 539.IBPluginDependency - 540.IBPluginDependency - 541.IBPluginDependency - 548.IBPluginDependency - 549.IBPluginDependency - 550.IBPluginDependency - 551.IBPluginDependency - 552.IBPluginDependency - 553.IBPluginDependency - 559.IBPluginDependency - 563.IBPluginDependency - 568.IBPluginDependency - 577.IBPluginDependency - 578.IBPluginDependency - 579.IBPluginDependency - 584.IBPluginDependency - 585.IBPluginDependency - 586.IBPluginDependency - 587.IBPluginDependency - 589.IBPluginDependency - 590.IBPluginDependency - 596.IBPluginDependency - 599.IBPluginDependency - - - 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 - 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 - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - - - YES - - + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {570, 269.5} + 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 + 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 + + - - YES - - - + - 601 + 609 - - YES + CurrentsongAppDelegate NSObject - - YES - - YES - launchITunes: - setLargeViewWidth: - setMediumViewWidth: - setSmallViewWidth: - setTitleAndArtist: - setTitleAndArtistStacked: - setTitleArtistAlbum: - setTitleArtistAlbumStacked: - setTitleOnly: - toggleLaunchAtLogin: - toggleScrollLongText: - toggleShowAlbum: - toggleShowArtist: - toggleTwoLineDisplay: - trackElapsedTime: - - - YES - id - id - id - id - id - id - id - id - id - id - id - id - id - id - id - - - - YES - - YES - launchITunes: - setLargeViewWidth: - setMediumViewWidth: - setSmallViewWidth: - setTitleAndArtist: - setTitleAndArtistStacked: - setTitleArtistAlbum: - setTitleArtistAlbumStacked: - setTitleOnly: - toggleLaunchAtLogin: - toggleScrollLongText: - toggleShowAlbum: - toggleShowArtist: - toggleTwoLineDisplay: - trackElapsedTime: - - - YES - - launchITunes: - id - - - setLargeViewWidth: - id - - - setMediumViewWidth: - id - - - setSmallViewWidth: - id - - - setTitleAndArtist: - id - - - setTitleAndArtistStacked: - id - - - setTitleArtistAlbum: - id - - - setTitleArtistAlbumStacked: - id - - - setTitleOnly: - id - - - toggleLaunchAtLogin: - id - - - toggleScrollLongText: - id - - - toggleShowAlbum: - id - - - toggleShowArtist: - id - - - toggleTwoLineDisplay: - id - - - trackElapsedTime: - id - - - - - YES - - YES - mAlbumMenuItem - mArtistMenuItem - mLaunchAtLoginController - mMenu - mNameMenuItem - mStreamTitleMenuItem - mTimeMenuItem - mVersionMenuItem - - - YES - NSMenuItem - NSMenuItem - LaunchAtLoginController - NSMenu - NSMenuItem - NSMenuItem - NSMenuItem - NSMenuItem - - - - YES - - YES - mAlbumMenuItem - mArtistMenuItem - mLaunchAtLoginController - mMenu - mNameMenuItem - mStreamTitleMenuItem - mTimeMenuItem - mVersionMenuItem - - - YES - - mAlbumMenuItem - NSMenuItem - - - mArtistMenuItem - NSMenuItem - - - mLaunchAtLoginController - LaunchAtLoginController - - - mMenu - NSMenu - - - mNameMenuItem - NSMenuItem - - - mStreamTitleMenuItem - NSMenuItem - - - mTimeMenuItem - NSMenuItem - - - mVersionMenuItem - NSMenuItem - + + id + id + id + id + id + id + id + id + id + id + id + id + id + id + + + + launchITunes: + id + + + setLargeViewWidth: + id + + + setMediumViewWidth: + id + + + setSmallViewWidth: + id + + + setTitleAndArtist: + id + + + setTitleAndArtistStacked: + id + + + setTitleArtistAlbum: + id + + + setTitleArtistAlbumStacked: + id + + + setTitleOnly: + id + + + toggleLaunchAtLogin: + id + + + toggleScrollLongText: + id + + + toggleShowAlbum: + id + + + toggleShowArtist: + id + + + toggleTwoLineDisplay: + id + + + + NSMenuItem + NSMenuItem + LaunchAtLoginController + NSMenu + NSMenuItem + NSMenuItem + NSMenuItem + NSMenuItem + + + + albumMenuItem + NSMenuItem + + + artistMenuItem + NSMenuItem + + + launchAtLoginController + LaunchAtLoginController + + + menu + NSMenu + + + nameMenuItem + NSMenuItem + + + streamTitleMenuItem + NSMenuItem + + + timeMenuItem + NSMenuItem + + + versionMenuItem + NSMenuItem + + + + IBProjectSource + ../Source/CurrentsongAppDelegate.h + + + + CurrentsongAppDelegate + + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + + + + launchITunes: + id + + + setLargeViewWidth: + id + + + setMediumViewWidth: + id + + + setSmallViewWidth: + id + + + setTitleAndArtist: + id + + + setTitleAndArtistStacked: + id + + setTitleArtistAlbum: + id + + + setTitleArtistAlbumStacked: + id + + + setTitleOnly: + id + + + toggleLaunchAtLogin: + id + + + toggleScrollLongText: + id + + + toggleShowAlbum: + id + + + toggleShowArtist: + id + + + toggleTwoLineDisplay: + id + + + trackElapsedTime: + id + + + + IBProjectSource + ../Source/CurrentsongAppDelegate.m + + + CurrentsongAppDelegate + NSObject + + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + + + + + + + + + + + + + + + + + + + + NSMenuItem + NSMenuItem + LaunchAtLoginController + NSMenu + NSMenuItem + NSMenuItem + NSMenuItem + NSMenuItem + + + + + + + + + + + IBProjectSource ./Classes/CurrentsongAppDelegate.h + + FirstResponder + + IBUserSource + + + + + LaunchAtLoginController + NSObject + + IBProjectSource + ../Source/LaunchAtLoginController.h + + LaunchAtLoginController NSObject @@ -988,28 +1021,24 @@ ./Classes/LaunchAtLoginController.h - + 0 IBCocoaFramework + NO + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 - + YES 3 - - YES - - YES - NSMenuCheckmark - NSMenuMixedState - - - YES - {11, 11} - {10, 3} - - + + {11, 11} + {10, 3} + diff --git a/Source/iTunes.h b/Source/iTunes.h index 5da6f8d..7be2928 100644 --- a/Source/iTunes.h +++ b/Source/iTunes.h @@ -6,7 +6,7 @@ #import -@class iTunesPrintSettings, iTunesApplication, iTunesItem, iTunesArtwork, iTunesEncoder, iTunesEQPreset, iTunesPlaylist, iTunesAudioCDPlaylist, iTunesDevicePlaylist, iTunesLibraryPlaylist, iTunesRadioTunerPlaylist, iTunesSource, iTunesTrack, iTunesAudioCDTrack, iTunesDeviceTrack, iTunesFileTrack, iTunesSharedTrack, iTunesURLTrack, iTunesUserPlaylist, iTunesFolderPlaylist, iTunesVisual, iTunesWindow, iTunesBrowserWindow, iTunesEQWindow, iTunesPlaylistWindow; +@class iTunesPrintSettings, iTunesApplication, iTunesItem, iTunesAirPlayDevice, iTunesArtwork, iTunesEncoder, iTunesEQPreset, iTunesPlaylist, iTunesAudioCDPlaylist, iTunesLibraryPlaylist, iTunesRadioTunerPlaylist, iTunesSource, iTunesTrack, iTunesAudioCDTrack, iTunesFileTrack, iTunesSharedTrack, iTunesURLTrack, iTunesUserPlaylist, iTunesFolderPlaylist, iTunesVisual, iTunesWindow, iTunesBrowserWindow, iTunesEQWindow, iTunesPlaylistWindow; enum iTunesEKnd { iTunesEKndTrackListing = 'kTrk' /* a basic listing of tracks within a playlist */, @@ -49,7 +49,6 @@ enum iTunesESrc { iTunesESrcIPod = 'kPod', iTunesESrcAudioCD = 'kACD', iTunesESrcMP3CD = 'kMCD', - iTunesESrcDevice = 'kDev', iTunesESrcRadioTuner = 'kTun', iTunesESrcSharedLibrary = 'kShd', iTunesESrcUnknown = 'kUnk' @@ -75,7 +74,6 @@ enum iTunesESpK { iTunesESpKLibrary = 'kSpL', iTunesESpKMovies = 'kSpI', iTunesESpKMusic = 'kSpZ', - iTunesESpKPartyShuffle = 'kSpS', iTunesESpKPodcasts = 'kSpP', iTunesESpKPurchasedMusic = 'kSpM', iTunesESpKTVShows = 'kSpT' @@ -84,6 +82,7 @@ typedef enum iTunesESpK iTunesESpK; enum iTunesEVdK { iTunesEVdKNone = 'kNon' /* not a video or unknown video kind */, + iTunesEVdKHomeVideo = 'kVdH' /* home video track */, iTunesEVdKMovie = 'kVdM' /* movie track */, iTunesEVdKMusicVideo = 'kVdV' /* music video track */, iTunesEVdKTVShow = 'kVdT' /* TV show track */ @@ -96,6 +95,15 @@ enum iTunesERtK { }; typedef enum iTunesERtK iTunesERtK; +enum iTunesEAPD { + iTunesEAPDComputer = 'kAPC', + iTunesEAPDAirPortExpress = 'kAPX', + iTunesEAPDAppleTV = 'kAPT', + iTunesEAPDAirPlayDevice = 'kAPO', + iTunesEAPDUnknown = 'kAPU' +}; +typedef enum iTunesEAPD iTunesEAPD; + /* @@ -135,6 +143,7 @@ typedef enum iTunesERtK iTunesERtK; // The application program @interface iTunesApplication : SBApplication +- (SBElementArray *) AirPlayDevices; - (SBElementArray *) browserWindows; - (SBElementArray *) encoders; - (SBElementArray *) EQPresets; @@ -144,6 +153,9 @@ typedef enum iTunesERtK iTunesERtK; - (SBElementArray *) visuals; - (SBElementArray *) windows; +@property (readonly) BOOL AirPlayEnabled; // is AirPlay currently enabled? +@property (readonly) BOOL converting; // is a track currently being converted? +@property (copy) NSArray *currentAirPlayDevices; // the currently selected AirPlay device(s) @property (copy) iTunesEncoder *currentEncoder; // the currently selected encoder (MP3, AIFF, WAV, etc.) @property (copy) iTunesEQPreset *currentEQPreset; // the currently selected equalizer preset @property (copy, readonly) iTunesPlaylist *currentPlaylist; // the playlist containing the currently targeted track @@ -157,13 +169,14 @@ typedef enum iTunesERtK iTunesERtK; @property BOOL fullScreen; // are visuals displayed using the entire screen? @property (copy, readonly) NSString *name; // the name of the application @property BOOL mute; // has the sound output been muted? -@property NSInteger playerPosition; // the player’s position within the currently playing track in seconds. +@property double playerPosition; // the player’s position within the currently playing track in seconds @property (readonly) iTunesEPlS playerState; // is iTunes stopped, paused, or playing? @property (copy, readonly) SBObject *selection; // the selection visible to the user @property NSInteger soundVolume; // the sound output volume (0 = minimum, 100 = maximum) @property (copy, readonly) NSString *version; // the version of iTunes @property BOOL visualsEnabled; // are visuals currently being displayed? @property iTunesEVSz visualSize; // the size of the displayed visual +@property (copy, readonly) NSString *iAdIdentifier; // the iAd identifier - (void) printPrintDialog:(BOOL)printDialog withProperties:(iTunesPrintSettings *)withProperties kind:(iTunesEKnd)kind theme:(NSString *)theme; // Print the specified object(s) - (void) run; // run iTunes @@ -196,7 +209,8 @@ typedef enum iTunesERtK iTunesERtK; - (NSInteger) id; // the id of the item @property (readonly) NSInteger index; // The index of the item in internal application order. @property (copy) NSString *name; // the name of the item -@property (copy, readonly) NSString *persistentID; // the id of the item as a hexidecimal string. This id does not change over time. +@property (copy, readonly) NSString *persistentID; // the id of the item as a hexadecimal string. This id does not change over time. +@property (copy) NSDictionary *properties; // every property of the item - (void) printPrintDialog:(BOOL)printDialog withProperties:(iTunesPrintSettings *)withProperties kind:(iTunesEKnd)kind theme:(NSString *)theme; // Print the specified object(s) - (void) close; // Close an object @@ -207,6 +221,22 @@ typedef enum iTunesERtK iTunesERtK; - (void) playOnce:(BOOL)once; // play the current track or the specified track or file. - (void) reveal; // reveal and select a track or playlist +@end + +// an AirPlay device +@interface iTunesAirPlayDevice : iTunesItem + +@property (readonly) BOOL active; // is the device currently being played to? +@property (readonly) BOOL available; // is the device currently available? +@property (readonly) iTunesEAPD kind; // the kind of the device +@property (copy, readonly) NSString *networkAddress; // the network (MAC) address of the device +- (BOOL) protected; // is the device password- or passcode-protected? +@property BOOL selected; // is the device currently selected? +@property (readonly) BOOL supportsAudio; // does the device support audio playback? +@property (readonly) BOOL supportsVideo; // does the device support video playback? +@property NSInteger soundVolume; // the output volume for the device (0 = minimum, 100 = maximum) + + @end // a piece of art within a track @@ -284,14 +314,6 @@ typedef enum iTunesERtK iTunesERtK; @property NSInteger year; // the year the album was recorded/released -@end - -// a playlist representing the contents of a portable device -@interface iTunesDevicePlaylist : iTunesPlaylist - -- (SBElementArray *) deviceTracks; - - @end // the master music library playlist @@ -316,7 +338,6 @@ typedef enum iTunesERtK iTunesERtK; @interface iTunesSource : iTunesItem - (SBElementArray *) audioCDPlaylists; -- (SBElementArray *) devicePlaylists; - (SBElementArray *) libraryPlaylists; - (SBElementArray *) playlists; - (SBElementArray *) radioTunerPlaylists; @@ -363,6 +384,7 @@ typedef enum iTunesERtK iTunesERtK; @property BOOL gapless; // is this track from a gapless album? @property (copy) NSString *genre; // the music/audio genre (category) of the track @property (copy) NSString *grouping; // the grouping (piece) of the track. Generally used to denote movements within a classical work. +@property (readonly) BOOL iTunesU; // is this track an iTunes U episode? @property (copy, readonly) NSString *kind; // a text description of the track @property (copy) NSString *longDescription; @property (copy) NSString *lyrics; // the lyrics of the track @@ -385,7 +407,7 @@ typedef enum iTunesERtK iTunesERtK; @property (copy) NSString *sortName; // override string to use for the track when sorting by name @property (copy) NSString *sortComposer; // override string to use for the track when sorting by composer @property (copy) NSString *sortShow; // override string to use for the track when sorting by show name -@property (readonly) NSInteger size; // the size of the track (in bytes) +@property (readonly) long long size; // the size of the track (in bytes) @property double start; // the start time of the track in seconds @property (copy, readonly) NSString *time; // the length of the track in MM:SS format @property NSInteger trackCount; // the total number of tracks on the source album @@ -404,12 +426,6 @@ typedef enum iTunesERtK iTunesERtK; @property (copy, readonly) NSURL *location; // the location of the file represented by this track -@end - -// a track residing on a portable music player -@interface iTunesDeviceTrack : iTunesTrack - - @end // a track representing an audio file (MP3, AIFF, etc.)