-/*
- * MenuTunes
- * AudioscrobblerController
- * Audioscrobbler Support Class
- *
- * Original Author : Kent Sutherland <kent.sutherland@ithinksw.com>
- * Responsibility : Kent Sutherland <kent.sutherland@ithinksw.com>
- *
- * Copyright (c) 2005 iThink Software.
- * All Rights Reserved
- *
- */
-
#import "AudioscrobblerController.h"
#import "PreferencesController.h"
#import <openssl/evp.h>
_postURL = [NSURL URLWithString:@"http://audioscrobbler.com/"];*/
_delayDate = [[NSDate date] retain];
- _responseData = nil;
+ _responseData = [[NSMutableData alloc] init];
_tracks = [[NSMutableArray alloc] init];
_submitTracks = [[NSMutableArray alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAudioscrobblerNotification:) name:@"AudioscrobblerHandshakeComplete" object:self];
return;
}
+ //If we've already tried to handshake three times in a row unsuccessfully, set the attempt count to -3
+ if (_handshakeAttempts > 3) {
+ ITDebugLog(@"Audioscrobbler: Maximum handshake limit reached (3). Retrying when handshake attempts reach zero.");
+ _handshakeAttempts = -3;
+
+ //Remove any tracks we were trying to submit, just to be safe
+ [_submitTracks removeAllObjects];
+
+ return;
+ }
+
+ //Increment the number of times we've tried to handshake
+ _handshakeAttempts++;
+
+ //We're still on our self-imposed cooldown time.
+ if (_handshakeAttempts < 0) {
+ ITDebugLog(@"Audioscrobbler: Handshake timeout. Retrying when handshake attempts reach zero.");
+ return;
+ }
+
//Delay if we haven't met the interval time limit
NSTimeInterval interval = [_delayDate timeIntervalSinceNow];
if (interval > 0) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"AudioscrobblerStatusChanged" object:nil userInfo:[NSDictionary dictionaryWithObject:_lastStatus forKey:@"StatusString"]];
_currentStatus = AudioscrobblerRequestingHandshakeStatus;
- _responseData = [[NSMutableData alloc] init];
+ //_responseData = [[NSMutableData alloc] init];
[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15] delegate:self];
}
}
return;
}
+ ITDebugLog(@"Audioscrobbler: Submitting queued tracks");
+
+ if ([_tracks count] == 0) {
+ ITDebugLog(@"Audioscrobbler: No queued tracks to submit.");
+ return;
+ }
+
NSString *user = [[NSUserDefaults standardUserDefaults] stringForKey:@"audioscrobblerUser"], *passString = [PreferencesController getKeychainItemPasswordForUser:user];
char *pass = (char *)[passString UTF8String];
unsigned char *buffer;
EVP_MD_CTX ctx;
- ITDebugLog(@"Audioscrobbler: Submitting queued tracks");
-
- if ([_tracks count] == 0) {
- ITDebugLog(@"Audioscrobbler: No queued tracks to submit.");
- return;
- }
-
//Build the MD5 response string we send along with the request
buffer = malloc(EVP_MD_size(EVP_md5()));
EVP_DigestInit(&ctx, EVP_md5());
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[requestString dataUsingEncoding:NSUTF8StringEncoding]];
_currentStatus = AudioscrobblerSubmittingTracksStatus;
- _responseData = [[NSMutableData alloc] init];
+ //_responseData = [[NSMutableData alloc] init];
+ [_responseData setData:nil];
[NSURLConnection connectionWithRequest:request delegate:self];
[requestString release];
[request release];
//For now we're not going to cache results, as it is less of a headache
//[_tracks removeObjectsInArray:_submitTracks];
[_tracks removeAllObjects];
- [_submitTracks removeAllObjects];
+ //[_submitTracks removeAllObjects];
//If we have tracks left, submit again after the interval seconds
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
- [_responseData release];
+ [_responseData setData:nil];
[_lastStatus release];
_lastStatus = [[NSString stringWithFormat:NSLocalizedString(@"audioscrobbler_error", @"Error - %@"), [error localizedDescription]] retain];
[[NSNotificationCenter defaultCenter] postNotificationName:@"AudioscrobblerStatusChanged" object:self userInfo:[NSDictionary dictionaryWithObject:_lastStatus forKey:@"StatusString"]];
[[NSNotificationCenter defaultCenter] postNotificationName:@"AudioscrobblerHandshakeComplete" object:self];
key = @"audioscrobbler_handshake_complete";
comment = @"Handshake complete";
+ _handshakeAttempts = 0;
} else {
//We have a protocol error
}
key = @"audioscrobbler_bad_user";
comment = @"Handshake failed - invalid user name";
//We have a bad user
+
+ //Don't count this as a bad handshake attempt
+ _handshakeAttempts = 0;
} else {
ITDebugLog(@"Audioscrobbler: Handshake failed, protocol error");
key = @"audioscrobbler_protocol_error";
ITDebugLog(@"Audioscrobbler: Submission successful, clearing queue.");
/*[_tracks removeObjectsInArray:_submitTracks];
[_submitTracks removeAllObjects];*/
+ [_submitTracks removeAllObjects];
if ([_tracks count] > 0) {
ITDebugLog(@"Audioscrobbler: Tracks remaining in queue, submitting remaining tracks");
[self performSelector:@selector(submitTracks) withObject:nil afterDelay:2];
key = @"audioscrobbler_bad_password";
comment = @"Last track submission failed - invalid password";
//Bad auth
+
+ //Add the tracks we were trying to submit back into the submission queue
+ [_tracks addObjectsFromArray:_submitTracks];
+
+ _handshakeCompleted = NO;
+
+ //If we were previously valid with the same login name, try reauthenticating and sending again
+ [self attemptHandshake:YES];
} else if (([responseAction length] > 5) && [[responseAction substringToIndex:5] isEqualToString:@"FAILED"]) {
ITDebugLog(@"Audioscrobbler: Submission failed (%@)", [responseAction substringFromIndex:6]);
key = @"audioscrobbler_submission_failed";
comment = @"Last track submission failed - see console for error";
//Failed
+
+ //We got an unknown error. To be safe we're going to remove the tracks we tried to submit
+ [_submitTracks removeAllObjects];
+
+ _handshakeCompleted = NO;
}
}
_lastStatus = [NSLocalizedString(key, comment) retain];
[[NSNotificationCenter defaultCenter] postNotificationName:@"AudioscrobblerStatusChanged" object:nil userInfo:[NSDictionary dictionaryWithObject:_lastStatus forKey:@"StatusString"]];
[string release];
- [_responseData release];
+ [_responseData setData:nil];
}
-(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse