Playlist Generator  1.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Properties Defines
Playlist2/SpotifyPlayer.m
Go to the documentation of this file.
00001 //
00002 //  SpotifyPlayer.m
00003 //  Playlist2
00004 //
00005 //  Created by Max Woolf on 20/01/2012.
00006 //  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
00007 //
00008 
00009 #import "SpotifyPlayer.h"
00010 #import "CocoaLibSpotify.h"
00011 #import "appkey.h"
00012 #import "AddToPlaylistViewController.h"
00013 
00014 @implementation SpotifyPlayer
00015 
00016 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
00017 {
00018     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
00019     if (self) {
00020         // Custom initialization
00021     }
00022     return self;
00023 }
00024 
00025 - (void)didReceiveMemoryWarning
00026 {
00027     // Releases the view if it doesn't have a superview.
00028     [super didReceiveMemoryWarning];
00029     
00030     // Release any cached data, images, etc that aren't in use.
00031 }
00032 
00033 -(void)setArray:(NSArray *)theArray
00034 {
00035     if(trackURIs != theArray)
00036     {
00037         trackURIs = theArray;
00038     }
00039 }
00040 
00041 -(void)loginToSpotifyWithUsername:(NSString *)username andPassword:(NSString *)password
00042 {
00043     [hud setMode:MBProgressHUDModeIndeterminate];
00044     [hud setLabelText:@"Logging in to Spotify..."];
00045     [hud show:YES];
00046     [SPSession initializeSharedSessionWithApplicationKey:[NSData dataWithBytes:&g_appkey length:g_appkey_size] userAgent:@"max.playlist2" error:nil];
00047     [[SPSession sharedSession]attemptLoginWithUserName:username password:password rememberCredentials:NO];
00048     [[SPSession sharedSession] setDelegate:self];
00049     [[SPSession sharedSession] setPlaybackDelegate:self];
00050 }
00051 
00052 #pragma mark - Spotify Delegate
00053 - (void)session:(SPSession *)aSession didFailToLoginWithError:(NSError *)error
00054 {
00055     UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:@"Failed to Login" message:[error localizedDescription] delegate:self cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
00056     [hud hide:YES];
00057     [errorAlert show];
00058 }
00059 
00060 - (void)sessionDidLoginSuccessfully:(SPSession *)aSession
00061 {
00062     NSLog(@"Login Successful");
00063     
00064     [hud setLabelText:@"Loading track"];
00065     //Create a playback manager
00066     manager = [[SPPlaybackManager alloc] initWithPlaybackSession:[SPSession sharedSession]];
00067     [self playTrackAtIndex:0];
00068 }
00069 
00070 - (void)sessionDidLosePlayToken:(SPSession *)aSession
00071 {
00072     [SPSession sharedSession].playing = NO;
00073     //[playPauseButton setImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal];
00074     UIAlertView *loseTokenAlert = [[UIAlertView alloc] initWithTitle:@"Sorry" message:@"Playback was paused because this account was logged in elsewhere" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
00075     [loseTokenAlert show];
00076 }
00077 
00078 - (void)sessionDidEndPlayback:(SPSession *)aSession
00079 {
00080     [self nextTrack:nil];
00081 }
00082 
00083 - (void)session:(SPSession *)aSession didEncounterStreamingError:(NSError *)error
00084 {
00085     UIAlertView *streamingErrorAlert = [[UIAlertView alloc] initWithTitle:@"Awww... crap." message:@"Streaming error, this isn't going to work..." delegate:self cancelButtonTitle:@"Alright" otherButtonTitles:nil];
00086     [streamingErrorAlert show];
00087 }
00088 
00089 #pragma mark - Controls
00090 //Called to play the track at index in the preloaded array of Spotify URIs.
00091 //index should already be validated before this is called or it will throw an out of bounds exception.
00092 -(void)playTrackAtIndex:(NSNumber *)index
00093 {
00094     NSURL *trackURL = [NSURL URLWithString:[trackURIs objectAtIndex:[index intValue]]];
00095     SPTrack *track = [[SPSession sharedSession] trackForURL:trackURL];
00096     if (track != nil) {
00097         
00098         if (!track.isLoaded) {
00099             NSLog(@"Still waiting for metadata to load... trying again.");
00100             [self performSelector:@selector(playTrackAtIndex:) withObject:index afterDelay:0.1];
00101             return;
00102         }
00103         
00104         //Set metadata
00105         SPArtist *currentArtist = [[track artists]objectAtIndex:0]; //Just get the first artist, there might be a few
00106         
00107         NSString *artistName = [[NSString alloc] initWithString:currentArtist.name];
00108         [artistLabel setText:artistName];
00109         [trackLabel setText:[track name]];
00110         
00111         nowPlayingInfo = [[NSMutableDictionary alloc] init];
00112         [nowPlayingInfo setValue:artistName forKey:MPMediaItemPropertyAlbumArtist];
00113         [nowPlayingInfo setValue:[track name] forKey:MPMediaItemPropertyTitle];
00114         
00115         [self getCoverImageForTrack:track];
00116         
00117         NSError *error = nil;
00118         if (![manager playTrack:track error:&error]) {
00119             UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Cannot Play Track"
00120                                                             message:[error localizedDescription]
00121                                                            delegate:nil
00122                                                   cancelButtonTitle:@"OK"
00123                                                   otherButtonTitles:nil];
00124             [alert show];
00125         }
00126         
00127         
00128         [hud hide:YES afterDelay:1];
00129         currentTrackPlayingIndex = [index intValue];
00130         currentTrackDuration = [track duration];
00131         [progressMeter setMaximumValue:currentTrackDuration];
00132 
00133         timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timerFireMethod:) userInfo:nil repeats:YES];
00134         [[NSRunLoop currentRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];
00135         return;
00136     }
00137 }
00138 
00139 - (void)timerFireMethod:(NSTimer*)theTimer
00140 {
00141     [progressMeter setValue:[progressMeter value]+1];
00142 }
00143 
00144 -(IBAction)togglePlayPause:(id)sender
00145 {
00146     if(manager.isPlaying)
00147     {
00148         [SPSession sharedSession].playing = NO;
00149         [playPauseButton setImage:[UIImage imageNamed:@"play.png"]];
00150          }else{
00151         [SPSession sharedSession].playing = YES;
00152         [playPauseButton setImage:[UIImage imageNamed:@"pause.png"]];
00153     }
00154 }
00155 
00156 -(IBAction)movedSlider:(id)sender;
00157 {
00158     NSLog(@"%f", [progressMeter value]);
00159     [manager seekToTrackPosition:[progressMeter value]];
00160 }
00161 
00162 -(IBAction)nextTrack:(id)sender
00163 {
00164     if(currentTrackPlayingIndex < [trackURIs count]-1)
00165     {
00166         [hud setLabelText:@"Loading"];
00167         [hud show:YES];
00168         [progressMeter setValue:0];
00169         [timer invalidate];
00170         [self playTrackAtIndex: [NSNumber numberWithInt:currentTrackPlayingIndex+1]];
00171     }
00172 }
00173 
00174 -(IBAction)previousTrack:(id)sender
00175 {
00176     //Make sure you don't overshoot the array
00177     if(!currentTrackPlayingIndex == 0)
00178     {
00179         [hud setLabelText:@"Loading"];
00180         [hud show:YES];
00181         [progressMeter setValue:0];
00182         [timer invalidate];
00183         [self playTrackAtIndex:[NSNumber numberWithInt:currentTrackPlayingIndex-1]];
00184     }
00185 }
00186 
00187 -(void)getCoverImageForTrack:(SPTrack *)track
00188 {
00189     SPAlbum *currentAlbum = [track album]; 
00190     SPImage *coverSPImage = [currentAlbum cover];
00191     [coverSPImage beginLoading];
00192     
00193     if (!coverSPImage.loaded) {
00194         NSLog(@"Still waiting for image to load... trying again.");
00195         [self performSelector:@selector(getCoverImageForTrack:) withObject:track afterDelay:0.1];
00196         return;
00197     }
00198     
00199     UIImage *coverImage = [coverSPImage image];
00200     [nowPlayingInfo setValue:[[MPMediaItemArtwork alloc]initWithImage:coverImage] forKey:MPMediaItemPropertyArtwork];
00201     [nowPlaying setNowPlayingInfo:nowPlayingInfo];
00202     [coverImageView setImage:coverImage];
00203 }
00204 
00205 #pragma mark - Action Sheet
00206 -(void)showActionSheet:(id)sender
00207 {
00208     UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Options" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Add Track to Spotify Playlist", nil];
00209     [actionSheet showFromToolbar:bottomToolbar];
00210 }
00211 
00212 - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
00213 {
00214     if(buttonIndex == 0)
00215     {
00216         AddToPlaylistViewController *playlistController = [[AddToPlaylistViewController alloc] initWithURI:[trackURIs objectAtIndex:currentTrackPlayingIndex]];
00217         [self presentModalViewController:playlistController animated:YES];
00218     }
00219 }
00220 
00221 -(void) initAudioSession 
00222 {
00223     // Registers this class as the delegate of the audio session to listen for audio interruptions
00224     [[AVAudioSession sharedInstance] setDelegate: self];
00225     //Set the audio category of this app to playback.
00226     NSError *setCategoryError = nil; [[AVAudioSession sharedInstance]
00227                                       setCategory: AVAudioSessionCategoryPlayback error: &setCategoryError];
00228 
00229     
00230     //Activate the audio session
00231     NSError *activationError = nil;
00232     [[AVAudioSession sharedInstance] setActive: YES error: &activationError];
00233 
00234 }
00235 
00236 - (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent {
00237     if (receivedEvent.type == UIEventTypeRemoteControl) {
00238         switch (receivedEvent.subtype) {
00239             case UIEventSubtypeRemoteControlTogglePlayPause: {
00240                 [self togglePlayPause:self];
00241                 break;
00242             }
00243                 
00244             case UIEventSubtypeRemoteControlNextTrack: {
00245                 [self nextTrack:self];
00246                 break;
00247             }
00248                 
00249             case UIEventSubtypeRemoteControlPreviousTrack: {
00250                 [self previousTrack:self];
00251                 break;
00252             }
00253             default:
00254                 break;
00255         }
00256     }
00257 }
00258 
00259 #pragma mark - View lifecycle
00260 -(void)viewDidAppear:(BOOL)animated
00261 {
00262     [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
00263     [self becomeFirstResponder];
00264     hud = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
00265     [self.navigationController.view addSubview:hud];
00266     [self loginToSpotifyWithUsername:@"maxehmookau" andPassword:@"edithdora6"];
00267 }
00268 
00269 - (void)viewDidLoad
00270 {
00271     [self.navigationController setNavigationBarHidden:YES];
00272     [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:YES];
00273     nowPlaying = [MPNowPlayingInfoCenter defaultCenter];
00274               
00275     [self initAudioSession];
00276     currentTrackPlayingIndex = 0;
00277     [super viewDidLoad];
00278     // Do any additional setup after loading the view from its nib.
00279 }
00280 - (BOOL) canBecomeFirstResponder {
00281     return YES;
00282 }
00283 
00284 - (void)viewDidUnload
00285 {
00286     [[UIApplication sharedApplication] endReceivingRemoteControlEvents];
00287     [self resignFirstResponder];
00288     [super viewDidUnload];
00289     // Release any retained subviews of the main view.
00290     // e.g. self.myOutlet = nil;
00291 }
00292 
00293 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
00294 {
00295     // Return YES for supported orientations
00296     return (interfaceOrientation == UIInterfaceOrientationPortrait);
00297 }
00298 
00299 @end