if (!_handshakeCompleted && user) {
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://post.audioscrobbler.com/?hs=true&p=1.1&c=%@&v=%@&u=%@", AUDIOSCROBBLER_ID, AUDIOSCROBBLER_VERSION, user]];
+ [_lastStatus release];
+ _lastStatus = [NSLocalizedString(@"audioscrobbler_handshaking", @"Attempting to handshake with server") retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"AudioscrobblerStatusChanged" object:nil userInfo:[NSDictionary dictionaryWithObject:_lastStatus forKey:@"StatusString"]];
+
_currentStatus = AudioscrobblerRequestingHandshakeStatus;
_responseData = [[NSMutableData alloc] init];
[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15] delegate:self];
}
ITDebugLog(@"Audioscrobbler: Sending track submission request");
+ [_lastStatus release];
+ _lastStatus = [NSLocalizedString(@"audioscrobbler_submitting", @"Submitting tracks to server") retain];
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"AudioscrobblerStatusChanged" object:nil userInfo:[NSDictionary dictionaryWithObject:_lastStatus forKey:@"StatusString"]];
//Create and send the request
NSMutableURLRequest *request = [[NSURLRequest requestWithURL:_postURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15] mutableCopy];
[_responseData release];
}
+-(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
+{
+ //Don't cache any Audioscrobbler communication
+ return nil;
+}
+
@end
repeatPlaylist = "Repeat Playlist";
repeatOneTrack = "Repeat One Track";
noSongPlaying = "No song is playing.";
+noAlbumArt = "No art for current song.";
iTunesNotResponding = "iTunes is not responding.";
noUpcomingSongs = "No upcoming songs.";
autolaunch = "Auto-launch MenuTunes";
cd = "CD";
sharedLibrary = "Shared Library";
debugmodeenabled = "Debug Mode Enabled\nAll actions MenuTunes performs will be logged\nto the console. To disable debug mode, quit\nand relaunch MenuTunes.\n\n(debug mode is enabled by holding down\nthe control key while MenuTunes opens)";
+audioscrobbler_handshaking = "Attempting to handshake with server";
audioscrobbler_handshake_complete = "Handshake complete";
audioscrobbler_handshake_failed = "Handshake failed";
audioscrobbler_bad_user = "Handshake failed - invalid user name";
audioscrobbler_protocol_error = "Internal protocol error";
+audioscrobbler_submitting = "Sending data to server";
audioscrobbler_submission_ok = "Last track submission successful";
audioscrobbler_bad_password = "Last track submission failed - invalid password";
audioscrobbler_submission_failed = "Last track submission failed - see console for error";
- (void)closePreferences;
- (MenuController *)menuController;
+- (void)showCurrentAlbumArt;
- (void)showCurrentTrackInfo;
@end
{
ITDebugLog(@"Audioscrobbler: Attempting to submit current track");
[timer invalidate];
- if ([df boolForKey:@"audioscrobblerEnabled"]) {
+ if ([df boolForKey:@"audioscrobblerEnabled"] && [[AudioscrobblerController sharedController] handshakeCompleted]) {
NS_DURING
int elapsed = [[self currentRemote] currentSongPlayed], length = [[self currentRemote] currentSongDuration], requiredInterval = ((length / 2 < 240) ? length / 2 : 240);
if ((abs(elapsed - requiredInterval) < 5) && ([[self currentRemote] playerPlayingState] == ITMTRemotePlayerPlaying)) {
[[ITHotKeyCenter sharedCenter] registerHotKey:[hotKey autorelease]];
}
+ if ([df objectForKey:@"AlbumArt"] != nil) {
+ ITDebugLog(@"Setting up album art hot key.");
+ hotKey = [[ITHotKey alloc] init];
+ [hotKey setName:@"AlbumArt"];
+ [hotKey setKeyCombo:[ITKeyCombo keyComboWithPlistRepresentation:[df objectForKey:@"AlbumArt"]]];
+ [hotKey setTarget:self];
+ [hotKey setAction:@selector(showCurrentAlbumArtHotKey)];
+ [[ITHotKeyCenter sharedCenter] registerHotKey:[hotKey autorelease]];
+ }
+
if ([df objectForKey:@"UpcomingSongs"] != nil) {
ITDebugLog(@"Setting up upcoming songs hot key.");
hotKey = [[ITHotKey alloc] init];
[self showCurrentTrackInfo];
}
+- (void)showCurrentAlbumArtHotKey
+{
+ //If we're already visible and the setting says so, vanish instead of displaying again.
+ if ([df boolForKey:@"ToggleTrackInfoWithHotKey"] && [statusWindowController currentStatusWindowType] == StatusWindowAlbumArtType && [[StatusWindow sharedWindow] visibilityState] == ITWindowVisibleState) {
+ ITDebugLog(@"Art window is already visible, hiding track window.");
+ [[StatusWindow sharedWindow] vanish:nil];
+ return;
+ }
+ [self showCurrentAlbumArt];
+}
+
+- (void)showCurrentAlbumArt
+{
+ NSImage *art = nil;
+ NS_DURING
+ art = [[self currentRemote] currentSongAlbumArt];
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
+
+ if (art) {
+ NSSize oldSize = [art size], newSize;
+ if (oldSize.width > 300 && oldSize.height > 300) {
+ if (oldSize.width > oldSize.height) {
+ newSize = NSMakeSize(300, oldSize.height * (300.0f / oldSize.width));
+ } else {
+ newSize = NSMakeSize(oldSize.width * (300.0f / oldSize.height), 300);
+ }
+ } else {
+ newSize = oldSize;
+ }
+
+ art = [[[[NSImage alloc] initWithData:[art TIFFRepresentation]] autorelease] imageScaledSmoothlyToSize:newSize];
+
+ [statusWindowController showAlbumArtWindowWithImage:art];
+ } else {
+ NSString *string = nil;
+ NS_DURING
+ if ([[self currentRemote] currentSongTitle]) {
+ string = NSLocalizedString(@"noAlbumArt", @"No art for current song.");
+ } else {
+ string = NSLocalizedString(@"noSongPlaying", @"No song is playing.");
+ }
+ NS_HANDLER
+ [self networkError:localException];
+ NS_ENDHANDLER
+ //Show the no song playing window if there is no album art or no track is playing
+ [statusWindowController showAlbumArtWindowWithErrorText:string];
+ }
+}
+
- (void)showCurrentTrackInfo
{
ITMTRemotePlayerSource source = 0;
{
StatusWindow *sw = (StatusWindow *)[StatusWindow sharedWindow];
_timeUpdateCount++;
- if ([sw visibilityState] != ITWindowHiddenState) {
+ if ([statusWindowController currentStatusWindowType] == StatusWindowTrackInfoType && [sw visibilityState] != ITWindowHiddenState) {
NSString *time = nil, *length;
NS_DURING
length = [[self currentRemote] currentSongLength];
@"Rewind",
@"ShowPlayer",
@"TrackInfo",
+ @"AlbumArt",
@"UpcomingSongs",
@"IncrementVolume",
@"DecrementVolume",
@"Rewind",
@"Show Player",
@"Track Info",
+ @"Album Art",
@"Upcoming Songs",
@"Increment Volume",
@"Decrement Volume",
- (void)setImage:(NSImage *)newImage;
- (void)setLocked:(BOOL)flag;
+- (void)buildImageWindowWithImage:(NSImage *)image;
- (void)buildTextWindowWithString:(id)text;
- (void)buildMeterWindowWithCharacter:(NSString *)character
size:(float)size
float maxHeight = ( screenHeight - (SW_BORDER * 2) );
float excessWidth = 0.0;
float excessHeight = 0.0;
- NSPoint windowOrigin;
+ NSPoint windowOrigin = NSZeroPoint;
ITImageView *imageView;
BOOL shouldAnimate = ( ! (([self visibilityState] == ITWindowAppearingState) ||
([self visibilityState] == ITWindowVanishingState)) );
contentHeight = ( ( imageHeight > dataHeight ) ? imageHeight : dataHeight );
// Setup the Window, and remove all its contentview's subviews.
- windowWidth = ( (SW_PAD / divisor) + imageWidth + (SW_SPACE / divisor) + dataWidth + (SW_PAD / divisor) );
+ windowWidth = ( (SW_PAD / divisor) + imageWidth + ((dataWidth > 0) ? (SW_SPACE / divisor) + dataWidth : 0) + (SW_PAD / divisor) );
windowHeight = ( (SW_PAD / divisor) + contentHeight + (SW_PAD / divisor) );
// Constrain size to max limits. Adjust data sizes accordingly.
[[[self contentView] subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
// Setup, position, fill, and add the image view to the content view.
- imageRect = NSMakeRect( (SW_PAD / divisor) + 4,
+ imageRect = NSMakeRect( (SW_PAD / divisor) + ((dataWidth > 0) ? 4 : 0),
((SW_PAD / divisor) + ((contentHeight - imageHeight) / 2)),
imageWidth,
imageHeight );
dataHeight);
}
+- (void)buildImageWindowWithImage:(NSImage *)image
+{
+ if (!_locked) {
+ float divisor = 1.0;
+ NSRect dataRect;
+
+ if (_sizing == ITTransientStatusWindowSmall) {
+ divisor = SMALL_DIVISOR;
+ } else if (_sizing == ITTransientStatusWindowMini) {
+ divisor = MINI_DIVISOR;
+ }
+
+ [self setImage:image];
+ dataRect = [self setupWindowWithDataSize:NSMakeSize(0, 0)]; //We have no text, so there is no data
+ [[self contentView] setNeedsDisplay:YES];
+ }
+}
+
- (void)buildTextWindowWithString:(id)text
{
if ( ! _locked ) {
typedef enum {
StatusWindowNoType = -1,
StatusWindowTrackInfoType,
+ StatusWindowAlbumArtType,
StatusWindowUpcomingSongsType,
StatusWindowVolumeType,
StatusWindowRatingType,
- (void)showPreferencesUpdateWindow;
- (void)showDebugModeEnabledWindow;
+- (void)showAlbumArtWindowWithImage:(NSImage *)image;
+- (void)showAlbumArtWindowWithErrorText:(NSString *)string;
- (void)showSongInfoWindowWithSource:(ITMTRemotePlayerSource)source
title: (NSString *)title
album: (NSString *)album
[text release];
}
+- (void)showAlbumArtWindowWithImage:(NSImage *)image
+{
+ if (image) {
+ _currentType = StatusWindowAlbumArtType;
+ [_window setImage:[NSImage imageNamed:@"Library"]];
+ [_window buildImageWindowWithImage:image];
+ [_window appear:self];
+ }
+}
+
+- (void)showAlbumArtWindowWithErrorText:(NSString *)string
+{
+ if (string && [string length] > 0) {
+ _currentType = StatusWindowAlbumArtType;
+ [_window buildTextWindowWithString:string];
+ [_window appear:self];
+ }
+}
+
- (void)showUpcomingSongsWindowWithTitles:(NSArray *)titleStrings
{
// NSString *bull = [NSString stringWithUTF8String:"‣ "];