1 #import "StatusWindowController.h"
2 #import "StatusWindow.h"
3 #import "PreferencesController.h"
4 #import "MainController.h"
6 #import <ITKit/ITTSWBackgroundView.h>
7 #import <ITKit/ITWindowEffect.h>
8 #import <ITKit/ITCutWindowEffect.h>
9 #import <ITKit/ITDissolveWindowEffect.h>
10 #import <ITKit/ITSlideHorizontallyWindowEffect.h>
11 #import <ITKit/ITSlideVerticallyWindowEffect.h>
12 #import <ITKit/ITPivotWindowEffect.h>
14 static StatusWindowController *sharedController;
16 @implementation StatusWindowController
19 + (StatusWindowController *)sharedController
21 if ( ! sharedController ) {
22 sharedController = [[StatusWindowController alloc] init];
25 return sharedController;
31 if ( ( self = [super init] ) ) {
36 NSArray *classList = [ITWindowEffect effectClasses];
39 NSArray *screens = [NSScreen screens];
44 ITWindowEffect *entryEffect;
45 ITWindowEffect *exitEffect;
47 _currentType = StatusWindowNoType;
49 _window = [[StatusWindow sharedWindow] retain];
50 df = [[NSUserDefaults standardUserDefaults] retain];
52 exitDelay = [df floatForKey:@"statusWindowVanishDelay"];
53 entryClass = [df stringForKey:@"statusWindowAppearanceEffect"];
54 exitClass = [df stringForKey:@"statusWindowVanishEffect"];
55 entrySpeed = [df floatForKey:@"statusWindowAppearanceSpeed"];
56 exitSpeed = [df floatForKey:@"statusWindowVanishSpeed"];
58 screenIndex = [df integerForKey:@"statusWindowScreenIndex"];
59 if (screenIndex >= [screens count]) {
62 [_window setScreen:[screens objectAtIndex:screenIndex]];
64 [_window setExitMode:ITTransientStatusWindowExitAfterDelay];
65 [_window setExitDelay:(exitDelay ? exitDelay : 4.0)];
67 [_window setHorizontalPosition:[df integerForKey:@"statusWindowHorizontalPosition"]];
68 [_window setVerticalPosition:[df integerForKey:@"statusWindowVerticalPosition"]];
70 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
72 if ( [classList containsObject:NSClassFromString(entryClass)] ) {
73 entryEffect = [[[NSClassFromString(entryClass) alloc] initWithWindow:_window] autorelease];
75 entryEffect = [[[ITCutWindowEffect alloc] initWithWindow:_window] autorelease];
78 if ( [classList containsObject:NSClassFromString(exitClass)] ) {
79 exitEffect = [[[NSClassFromString(exitClass) alloc] initWithWindow:_window] autorelease];
81 exitEffect = [[[ITDissolveWindowEffect alloc] initWithWindow:_window] autorelease];
84 [_window setEntryEffect:entryEffect];
85 [_window setExitEffect:exitEffect];
87 [[_window entryEffect] setEffectTime:(entrySpeed ? entrySpeed : 0.8)];
88 [[_window exitEffect] setEffectTime:(exitSpeed ? exitSpeed : 0.8)];
90 [(ITTSWBackgroundView *)[_window contentView]setBackgroundMode:
91 (ITTSWBackgroundMode)[df integerForKey:@"statusWindowBackgroundMode"]];
93 colorData = [df dataForKey:@"statusWindowBackgroundColor"];
96 [(ITTSWBackgroundView *)[_window contentView] setBackgroundColor:
97 (NSColor *)[NSUnarchiver unarchiveObjectWithData:colorData]];
99 [(ITTSWBackgroundView *)[_window contentView] setBackgroundColor:[NSColor blueColor]];
112 - (void)showSongInfoWindowWithSource:(ITMTRemotePlayerSource)source
113 title: (NSString *)title
114 album: (NSString *)album
115 artist: (NSString *)artist
116 composer: (NSString *)composer
117 time: (NSString *)time // FLOW: Should probably be NSDate or something.
118 track: (NSString *)track
120 playCount: (int)playCount
121 image: (NSImage *)art
123 NSImage *image = nil;
124 NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:title];
128 } else if ( source == ITMTRemoteLibrarySource ) {
129 image = [NSImage imageNamed:@"Library"];
130 } else if ( source == ITMTRemoteCDSource ) {
131 image = [NSImage imageNamed:@"CD"];
132 } else if ( source == ITMTRemoteRadioSource ) {
133 image = [NSImage imageNamed:@"Radio"];
134 } else if ( source == ITMTRemoteiPodSource ) {
135 image = [NSImage imageNamed:@"iPod"];
136 } else if ( source == ITMTRemoteGenericDeviceSource ) {
137 image = [NSImage imageNamed:@"MP3Player"];
138 } else if ( source == ITMTRemoteSharedLibrarySource ) {
139 image = [NSImage imageNamed:@"Library"];
142 [_window setImage:image];
143 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
146 [[text mutableString] appendFormat:@"\n%@", album];
147 //text = [text stringByAppendingString:[@"\n" stringByAppendingString:album]];
150 [[text mutableString] appendFormat:@"\n%@", artist];
151 //text = [text stringByAppendingString:[@"\n" stringByAppendingString:artist]];
154 [[text mutableString] appendFormat:@"\n%@", composer];
155 //text = [text stringByAppendingString:[@"\n" stringByAppendingString:composer]];
158 _timeRange = NSMakeRange([[text mutableString] length] + 1, [time length]);
159 [[text mutableString] appendFormat:@"\n%@", time];
160 //text = [text stringByAppendingString:[@"\n" stringByAppendingString:time]];
163 [[text mutableString] appendFormat:@"\n%@", track];
164 //text = [text stringByAppendingString:[@"\n" stringByAppendingString:track]];
166 if (playCount > -1) {
167 [[text mutableString] appendFormat:@"\n%@: %i", NSLocalizedString(@"playCount", @"Play Count"), playCount];
168 //text = [text stringByAppendingString:[NSString stringWithFormat:@"\n%@: %i", NSLocalizedString(@"playCount", @"Play Count"), playCount]];
172 NSString *ratingString = [NSString string];
173 NSString *emptyChar = [NSString stringWithUTF8String:"☆"];
174 NSString *fullChar = [NSString stringWithUTF8String:"★"];
175 int i, start = [[text mutableString] length], size = 18;
177 for ( i = 1; i < 6; i++ ) {
180 ratingString = [ratingString stringByAppendingString:fullChar];
182 ratingString = [ratingString stringByAppendingString:emptyChar];
186 [[text mutableString] appendFormat:@"\n%@", ratingString];
187 if ([_window sizing] == ITTransientStatusWindowSmall) {
188 size /= SMALL_DIVISOR;
189 } else if ([_window sizing] == ITTransientStatusWindowMini) {
190 size /= MINI_DIVISOR;
192 [text setAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSFont fontWithName:@"AppleGothic" size:size], NSFontAttributeName, nil, nil] range:NSMakeRange(start + 1, 5)];
193 //text = [text stringByAppendingString:[@"\n" stringByAppendingString:ratingString]];
196 _currentType = StatusWindowTrackInfoType;
197 [_window buildTextWindowWithString:text];
198 [_window appear:self];
202 - (void)showUpcomingSongsWindowWithTitles:(NSArray *)titleStrings
204 // NSString *bull = [NSString stringWithUTF8String:"‣ "];
205 NSString *bull = [NSString stringWithUTF8String:"♪ "];
206 NSString *end = [@"\n" stringByAppendingString:bull];
207 [_window setImage:[NSImage imageNamed:@"Upcoming"]];
208 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
209 [_window buildTextWindowWithString:[bull stringByAppendingString:[titleStrings componentsJoinedByString:end]]];
210 _currentType = StatusWindowUpcomingSongsType;
211 [_window appear:self];
214 - (void)showVolumeWindowWithLevel:(float)level
216 [_window setImage:[NSImage imageNamed:@"Volume"]];
217 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
218 [_window buildMeterWindowWithCharacter:[NSString stringWithUTF8String:"▊"]
221 active:( ceil(level * 100) / 10 )];
222 _currentType = StatusWindowVolumeType;
223 [_window appear:self];
226 - (void)showRatingWindowWithRating:(float)rating
228 [_window setImage:[NSImage imageNamed:@"Rating"]];
229 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
230 [_window buildMeterWindowWithCharacter:[NSString stringWithUTF8String:"★"]
233 active:( ceil(rating * 100) / 20 )];
234 _currentType = StatusWindowRatingType;
235 [_window appear:self];
238 - (void)showShuffleWindow:(BOOL)shuffle
240 [_window setImage:[NSImage imageNamed:@"Shuffle"]];
241 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
242 [_window buildTextWindowWithString:( shuffle ? NSLocalizedString(@"shuffleOn", @"Shuffle On") : NSLocalizedString(@"shuffleOff", @"Shuffle Off"))];
243 _currentType = StatusWindowRatingType;
244 [_window appear:self];
247 - (void)showRepeatWindowWithMode:(StatusWindowRepeatMode)mode
249 NSString *string = nil;
251 if ( mode == StatusWindowRepeatNone ) {
252 string = NSLocalizedString(@"repeatOff", @"Repeat Off");
253 } else if ( mode == StatusWindowRepeatGroup ) {
254 string = NSLocalizedString(@"repeatPlaylist", @"Repeat Playlist");
255 } else if ( mode == StatusWindowRepeatTrack ) {
256 string = NSLocalizedString(@"repeatOneTrack", @"Repeat One Track");;
259 [_window setImage:[NSImage imageNamed:@"Repeat"]];
260 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
261 [_window buildTextWindowWithString:string];
262 _currentType = StatusWindowRepeatType;
263 [_window appear:self];
266 - (void)showSongShufflabilityWindow:(BOOL)shufflable
268 [_window setImage:[NSImage imageNamed:@"Shuffle"]];
269 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
270 [_window buildTextWindowWithString:( !shufflable ? NSLocalizedString(@"shufflableOn", @"Current Song Skipped When Shuffling") : NSLocalizedString(@"shufflableOff", @"Current Song Not Skipped When Shuffling"))];
271 _currentType = StatusWindowShufflabilityType;
272 [_window appear:self];
275 - (void)showSetupQueryWindow
277 NSString *message = NSLocalizedString(@"autolaunch_msg", @"Would you like MenuTunes to launch\nautomatically at startup?");
279 [_window setImage:[NSImage imageNamed:@"Setup"]];
280 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
281 [_window buildDialogWindowWithMessage:message
282 defaultButton:NSLocalizedString(@"launch_at_startup", @"Launch at Startup")
283 alternateButton:NSLocalizedString(@"launch_manually", @"Launch Manually")
284 target:[PreferencesController sharedPrefs]
285 defaultAction:@selector(autoLaunchOK)
286 alternateAction:@selector(autoLaunchCancel)];
288 _currentType = StatusWindowSetupType;
289 [_window appear:self];
290 [_window setLocked:YES];
294 - (void)showRegistrationQueryWindow
296 NSString *message = NSLocalizedString(@"trialexpired_msg", @"Your 7-day unlimited trial period has elapsed.\nYou must register to continue using MenuTunes.");
298 [_window setImage:[NSImage imageNamed:@"Register"]];
299 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
300 [_window buildDialogWindowWithMessage:message
301 defaultButton:NSLocalizedString(@"registernow", @"Register Now")
302 alternateButton:NSLocalizedString(@"quitmenutunes", @"Quit MenuTunes")
303 target:[MainController sharedController]
304 defaultAction:@selector(registerNowOK)
305 alternateAction:@selector(registerNowCancel)];
307 _currentType = StatusWindowRegistrationType;
308 [_window appear:self];
309 [_window setLocked:YES];
312 - (void)showReconnectQueryWindow
314 NSString *message = NSLocalizedString(@"sharedplayeravailable_msg", @"The selected shared player is available again.\nWould you like to reconnect to it?");
315 [_window setLocked:NO];
316 [_window setImage:[NSImage imageNamed:@"Setup"]];
317 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
318 [_window buildDialogWindowWithMessage:message
319 defaultButton:NSLocalizedString(@"reconnect", @"Reconnect")
320 alternateButton:NSLocalizedString(@"ignore", @"Ignore")
321 target:[MainController sharedController]
322 defaultAction:@selector(reconnect)
323 alternateAction:@selector(cancelReconnect)];
325 _currentType = StatusWindowNetworkType;
326 [_window appear:self];
327 [_window setLocked:YES];
330 - (void)showNetworkErrorQueryWindow
332 NSString *message = NSLocalizedString(@"sharedplayerunreachable_msg", @"The remote MenuTunes server is unreachable.\nMenuTunes will revert back to the local player.");
334 [_window setImage:[NSImage imageNamed:@"Setup"]];
335 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
336 [_window buildDialogWindowWithMessage:message
337 defaultButton:@" OK "
339 target:[MainController sharedController]
340 defaultAction:@selector(cancelReconnect)
341 alternateAction:nil];
343 _currentType = StatusWindowNetworkType;
344 [_window appear:self];
345 [_window setLocked:YES];
348 - (void)showPreferencesUpdateWindow
350 NSString *message = NSLocalizedString(@"reconfigureprefs_msg", @"The new features in this version of MenuTunes\nrequire you to reconfigure your preferences.");
352 [_window setImage:[NSImage imageNamed:@"Setup"]];
353 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
354 [_window buildDialogWindowWithMessage:message
355 defaultButton:NSLocalizedString(@"showpreferences", @"Show Preferences")
356 alternateButton:@"OK"
357 target:[MainController sharedController]
358 defaultAction:@selector(showPreferencesAndClose)
359 alternateAction:@selector(cancelReconnect)];
361 _currentType = StatusWindowPreferencesType;
362 [_window appear:self];
363 [_window setLocked:YES];
366 - (void)showDebugModeEnabledWindow
368 [_window setImage:[NSImage imageNamed:@"Setup"]];
369 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
370 [_window buildDialogWindowWithMessage:NSLocalizedString(@"debugmodeenabled", @"Debug Mode Enabled")
373 target:[MainController sharedController]
374 defaultAction:@selector(cancelReconnect)
375 alternateAction:nil];
377 _currentType = StatusWindowDebugType;
378 [_window appear:self];
379 [_window setLocked:YES];
382 - (StatusWindowType)currentStatusWindowType
387 - (void)updateTime:(NSString *)time
389 if (time && [time length]) {
390 [_window updateTime:time range:_timeRange];