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)showAlbumArtWindowWithImage:(NSImage *)image
205 _currentType = StatusWindowAlbumArtType;
206 [_window setImage:[NSImage imageNamed:@"Library"]];
207 [_window buildImageWindowWithImage:image];
208 [_window appear:self];
212 - (void)showAlbumArtWindowWithErrorText:(NSString *)string
214 if (string && [string length] > 0) {
215 _currentType = StatusWindowAlbumArtType;
216 [_window buildTextWindowWithString:string];
217 [_window appear:self];
221 - (void)showUpcomingSongsWindowWithTitles:(NSArray *)titleStrings
223 // NSString *bull = [NSString stringWithUTF8String:"‣ "];
224 NSString *bull = [NSString stringWithUTF8String:"♪ "];
225 NSString *end = [@"\n" stringByAppendingString:bull];
226 [_window setImage:[NSImage imageNamed:@"Upcoming"]];
227 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
228 [_window buildTextWindowWithString:[bull stringByAppendingString:[titleStrings componentsJoinedByString:end]]];
229 _currentType = StatusWindowUpcomingSongsType;
230 [_window appear:self];
233 - (void)showVolumeWindowWithLevel:(float)level
235 [_window setImage:[NSImage imageNamed:@"Volume"]];
236 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
237 [_window buildMeterWindowWithCharacter:[NSString stringWithUTF8String:"▊"]
240 active:( ceil(level * 100) / 10 )];
241 _currentType = StatusWindowVolumeType;
242 [_window appear:self];
245 - (void)showRatingWindowWithRating:(float)rating
247 [_window setImage:[NSImage imageNamed:@"Rating"]];
248 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
249 [_window buildMeterWindowWithCharacter:[NSString stringWithUTF8String:"★"]
252 active:( ceil(rating * 100) / 20 )];
253 _currentType = StatusWindowRatingType;
254 [_window appear:self];
257 - (void)showShuffleWindow:(BOOL)shuffle
259 [_window setImage:[NSImage imageNamed:@"Shuffle"]];
260 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
261 [_window buildTextWindowWithString:( shuffle ? NSLocalizedString(@"shuffleOn", @"Shuffle On") : NSLocalizedString(@"shuffleOff", @"Shuffle Off"))];
262 _currentType = StatusWindowRatingType;
263 [_window appear:self];
266 - (void)showRepeatWindowWithMode:(StatusWindowRepeatMode)mode
268 NSString *string = nil;
270 if ( mode == StatusWindowRepeatNone ) {
271 string = NSLocalizedString(@"repeatOff", @"Repeat Off");
272 } else if ( mode == StatusWindowRepeatGroup ) {
273 string = NSLocalizedString(@"repeatPlaylist", @"Repeat Playlist");
274 } else if ( mode == StatusWindowRepeatTrack ) {
275 string = NSLocalizedString(@"repeatOneTrack", @"Repeat One Track");;
278 [_window setImage:[NSImage imageNamed:@"Repeat"]];
279 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
280 [_window buildTextWindowWithString:string];
281 _currentType = StatusWindowRepeatType;
282 [_window appear:self];
285 - (void)showSongShufflabilityWindow:(BOOL)shufflable
287 [_window setImage:[NSImage imageNamed:@"Shuffle"]];
288 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
289 [_window buildTextWindowWithString:( !shufflable ? NSLocalizedString(@"shufflableOn", @"Current Song Skipped When Shuffling") : NSLocalizedString(@"shufflableOff", @"Current Song Not Skipped When Shuffling"))];
290 _currentType = StatusWindowShufflabilityType;
291 [_window appear:self];
294 - (void)showSetupQueryWindow
296 NSString *message = NSLocalizedString(@"autolaunch_msg", @"Would you like MenuTunes to launch\nautomatically at startup?");
298 [_window setImage:[NSImage imageNamed:@"Setup"]];
299 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
300 [_window buildDialogWindowWithMessage:message
301 defaultButton:NSLocalizedString(@"launch_at_startup", @"Launch at Startup")
302 alternateButton:NSLocalizedString(@"launch_manually", @"Launch Manually")
303 target:[PreferencesController sharedPrefs]
304 defaultAction:@selector(autoLaunchOK)
305 alternateAction:@selector(autoLaunchCancel)];
307 _currentType = StatusWindowSetupType;
308 [_window appear:self];
309 [_window setLocked:YES];
313 - (void)showRegistrationQueryWindow
315 NSString *message = NSLocalizedString(@"trialexpired_msg", @"Your 7-day unlimited trial period has elapsed.\nYou must register to continue using MenuTunes.");
317 [_window setImage:[NSImage imageNamed:@"Register"]];
318 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
319 [_window buildDialogWindowWithMessage:message
320 defaultButton:NSLocalizedString(@"registernow", @"Register Now")
321 alternateButton:NSLocalizedString(@"quitmenutunes", @"Quit MenuTunes")
322 target:[MainController sharedController]
323 defaultAction:@selector(registerNowOK)
324 alternateAction:@selector(registerNowCancel)];
326 _currentType = StatusWindowRegistrationType;
327 [_window appear:self];
328 [_window setLocked:YES];
331 - (void)showReconnectQueryWindow
333 NSString *message = NSLocalizedString(@"sharedplayeravailable_msg", @"The selected shared player is available again.\nWould you like to reconnect to it?");
334 [_window setLocked:NO];
335 [_window setImage:[NSImage imageNamed:@"Setup"]];
336 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
337 [_window buildDialogWindowWithMessage:message
338 defaultButton:NSLocalizedString(@"reconnect", @"Reconnect")
339 alternateButton:NSLocalizedString(@"ignore", @"Ignore")
340 target:[MainController sharedController]
341 defaultAction:@selector(reconnect)
342 alternateAction:@selector(cancelReconnect)];
344 _currentType = StatusWindowNetworkType;
345 [_window appear:self];
346 [_window setLocked:YES];
349 - (void)showNetworkErrorQueryWindow
351 NSString *message = NSLocalizedString(@"sharedplayerunreachable_msg", @"The remote MenuTunes server is unreachable.\nMenuTunes will revert back to the local player.");
353 [_window setImage:[NSImage imageNamed:@"Setup"]];
354 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
355 [_window buildDialogWindowWithMessage:message
356 defaultButton:@" OK "
358 target:[MainController sharedController]
359 defaultAction:@selector(cancelReconnect)
360 alternateAction:nil];
362 _currentType = StatusWindowNetworkType;
363 [_window appear:self];
364 [_window setLocked:YES];
367 - (void)showPreferencesUpdateWindow
369 NSString *message = NSLocalizedString(@"reconfigureprefs_msg", @"The new features in this version of MenuTunes\nrequire you to reconfigure your preferences.");
371 [_window setImage:[NSImage imageNamed:@"Setup"]];
372 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
373 [_window buildDialogWindowWithMessage:message
374 defaultButton:NSLocalizedString(@"showpreferences", @"Show Preferences")
375 alternateButton:@"OK"
376 target:[MainController sharedController]
377 defaultAction:@selector(showPreferencesAndClose)
378 alternateAction:@selector(cancelReconnect)];
380 _currentType = StatusWindowPreferencesType;
381 [_window appear:self];
382 [_window setLocked:YES];
385 - (void)showDebugModeEnabledWindow
387 [_window setImage:[NSImage imageNamed:@"Setup"]];
388 [_window setSizing:(ITTransientStatusWindowSizing)[df integerForKey:@"statusWindowSizing"]];
389 [_window buildDialogWindowWithMessage:NSLocalizedString(@"debugmodeenabled", @"Debug Mode Enabled")
392 target:[MainController sharedController]
393 defaultAction:@selector(cancelReconnect)
394 alternateAction:nil];
396 _currentType = StatusWindowDebugType;
397 [_window appear:self];
398 [_window setLocked:YES];
401 - (StatusWindowType)currentStatusWindowType
406 - (void)updateTime:(NSString *)time
408 if (time && [time length]) {
409 [_window updateTime:time range:_timeRange];