// // MainController.m // iLyrics // // Created by Kim Wittenburg on 10.06.12. // Copyright (c) 2012 __MyCompanyName__. All rights reserved. // #import "MainController.h" @implementation MainController { NSMutableArray *loadedResults; id currentHoster; BOOL lyricsSelected; NSInteger selectedSavePanelButton; NSURL *saveFile; iTunesApplication *iTunes; Lyrics *currentLyrics; int selectedRow; } @synthesize iLyricsMenuItem; @synthesize window; @synthesize searchField; @synthesize resultsOutline; @synthesize loadMoreResultsButton; @synthesize showPreviewCheckBox; @synthesize previewPopover; @synthesize previewTextArea; @synthesize songLabel; @synthesize artistLabel; @synthesize sendToiTunesButton; @synthesize downloadLyricsButton; @synthesize lyricsArea; -(id)init { iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"]; loadedResults = [[NSMutableArray alloc] init]; currentHoster = [[Magistrix alloc] init]; return [super init]; } #pragma mark - #pragma mark Outline view Data Source and Delegate -(NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item { return item == nil ? [loadedResults count] : 0; } -(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item { return [loadedResults objectAtIndex:index]; } -(BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item { return NO; } -(id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { if ([[tableColumn identifier] isEqualToString:@"song"]) { return [item name]; } else { return [item artist]; } return nil; } -(NSString *)outlineView:(NSOutlineView *)outlineView toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)tableColumn item:(id)item mouseLocation:(NSPoint)mouseLocation { //item is an instance of SearchResult [self shouldShowPreviewForCellRect:*rect searchResult:item]; return nil; } #pragma mark - #pragma mark Responding to Lyrics Search - (IBAction)getCurrentiTunesSong:(id)sender { iTunesTrack *track = [iTunes currentTrack]; if (track == nil) { NSBeginAlertSheet(NSLocalizedString(@"iTunes.messages.iTunesIdle.title", @""), NSLocalizedString(@"OK", @""), nil, nil, window, nil, nil, nil, nil, NSLocalizedString(@"iTunes.messages.iTunesIdle.detail", @"")); return; } NSString *name = [track name]; NSString *artist = [track artist]; if (name == nil) { NSBeginAlertSheet(NSLocalizedString(@"iTunes.messages.noTrackPlaying.title", @""), NSLocalizedString(@"OK", @""), nil, nil, window, nil, nil, nil, nil, NSLocalizedString(@"iTunes.messages.noTrackPlaying.detail", @"")); return; } NSString *searchText = [NSString stringWithFormat:@"%@ - %@", name, artist]; [searchField setStringValue:searchText]; [searchField performClick:sender]; } - (IBAction)startNewSearch:(id)sender { [self resetLoadedResults:sender]; if ([[searchField stringValue] length] > 0) { [currentHoster startNewSearchForQuery:[searchField stringValue]]; [self loadNextResults:sender]; } } - (IBAction)loadNextResults:(id)sender { NSArray *nextResults = [currentHoster nextResults]; if (nextResults == nil) { NSRunCriticalAlertPanel(NSLocalizedString(@"Hoster.messages.networkError.title", @""), NSLocalizedString(@"Hoster.messages.networkError.detail", @""), NSLocalizedString(@"OK", @""), nil, nil); return; } if ([nextResults count] == 0) { NSRunAlertPanel(NSLocalizedString(@"Hoster.messages.noResults.title", @""), NSLocalizedString(@"Hoster.messages.noResults.detail", @""), NSLocalizedString(@"OK", @""), nil, nil); return; } [loadedResults addObjectsFromArray:nextResults]; [resultsOutline reloadData]; [loadMoreResultsButton setEnabled:[currentHoster hasMoreResults]]; } -(IBAction)resetLoadedResults:(id)sender { [currentHoster resetLoadedResults]; [loadedResults removeAllObjects]; [resultsOutline reloadData]; [loadMoreResultsButton setEnabled:[currentHoster hasMoreResults]]; [self lyricsSelectionChanged:resultsOutline]; } - (IBAction)lyricsSelectionChanged:(NSOutlineView *)sender { int index = [sender selectedRow]; if (index < 0) { lyricsSelected = NO; currentLyrics = nil; NSString *noSelectionText = NSLocalizedString(@"iLyrics.text.noSelection", @""); [songLabel setStringValue:noSelectionText]; [artistLabel setStringValue:noSelectionText]; [lyricsArea setString:noSelectionText]; [lyricsArea setEditable:NO]; } else { if (selectedRow != index) { lyricsSelected = YES; SearchResult *result = [loadedResults objectAtIndex:index]; Lyrics *lyrics = [currentHoster lyricsBySearchResult:result]; currentLyrics = lyrics; if (lyrics == nil) { NSRunCriticalAlertPanel(NSLocalizedString(@"Hoster.messages.networkError.title", @""), NSLocalizedString(@"Hoster.messages.networkError.detail", @""), NSLocalizedString(@"OK", @""), nil, nil); NSString *noNetwork = NSLocalizedString(@"Hoster.text.noNetwork", @""); [songLabel setStringValue:noNetwork]; [artistLabel setStringValue:noNetwork]; [lyricsArea setString:noNetwork]; [lyricsArea setEditable:NO]; } [songLabel setStringValue:[lyrics name]]; [artistLabel setStringValue:[lyrics artist]]; [lyricsArea setString:[lyrics lyrics]]; [lyricsArea setEditable:YES]; } } selectedRow = index; [window update]; } -(void) shouldShowPreviewForCellRect: (NSRect) rect searchResult: (SearchResult *) result { if ([showPreviewCheckBox state] == NSOnState) { NSString *lyrics = [result preview]; if (lyrics) { rect.size.width = [resultsOutline frame].size.width; [previewTextArea setString:lyrics]; [previewPopover showRelativeToRect:rect ofView:resultsOutline preferredEdge:NSMaxXEdge]; } } } - (IBAction)sendLyricsToiTunes:(id)sender { iTunesTrack *track = [iTunes currentTrack]; NSString *name = [track name]; if (name == nil) { NSBeginAlertSheet(NSLocalizedString(@"iTunes.messages.noTrackPlaying.title", @""), NSLocalizedString(@"OK", @""), nil, nil, window, nil, nil, nil, nil, NSLocalizedString(@"iTunes.messages.noTrackPlaying.detail", @"")); return; } NSString *oldLyrics = [track lyrics]; if (oldLyrics != nil && [oldLyrics length] > 0) { NSBeginAlertSheet(NSLocalizedString(@"iTunes.messages.replaceLyrics.title", @""), NSLocalizedString(@"Yes", @""), NSLocalizedString(@"No", @""), nil, window, self, @selector(replaceLyricsSheetDidEnd:returnCode:contextInfo:), nil, nil, NSLocalizedString(@"iTunes.messages.replaceLyrics.detail", @"")); } else { [self replaceLyricsSheetDidEnd:nil returnCode:NSAlertDefaultReturn contextInfo:nil]; } } - (void)replaceLyricsSheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { if (returnCode == NSAlertDefaultReturn) { iTunesTrack *track = [iTunes currentTrack]; [track setLyrics:[lyricsArea string]]; [GrowlApplicationBridge notifyWithTitle:NSLocalizedString(@"Growl.messages.lyricsSent.title", @"") description:[NSString stringWithFormat:NSLocalizedString(@"Growl.messages.lyricsSent.detail", @""), [track name]] notificationName:@"Lyrics sent to iTunes" iconData:nil priority:0 isSticky:NO clickContext:nil]; } } - (IBAction)downloadLyrics:(id)sender { NSSavePanel *savePanel = [NSSavePanel savePanel]; [savePanel setAllowedFileTypes:[NSArray arrayWithObject:@"txt"]]; [savePanel setAllowsOtherFileTypes:YES]; [savePanel setCanSelectHiddenExtension:YES]; [savePanel setExtensionHidden:YES]; [savePanel setNameFieldStringValue:[currentLyrics name]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(savePanelDidClose:) name:NSWindowDidEndSheetNotification object:window]; void (^handler) (NSInteger) = ^(NSInteger result) { selectedSavePanelButton = result; saveFile = [savePanel URL]; }; [savePanel beginSheetModalForWindow:window completionHandler:handler]; } - (IBAction)showLyricsInBrowser:(id)sender { int row = [resultsOutline clickedRow]; if (row < 0) { row = [resultsOutline selectedRow]; } NSURL *link = [[loadedResults objectAtIndex:row] link]; [[NSWorkspace sharedWorkspace] openURL:link]; } -(void) savePanelDidClose: (NSNotification *) notification{ [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidEndSheetNotification object:window]; if (selectedSavePanelButton == NSOKButton) { BOOL success = [[[lyricsArea string] dataUsingEncoding:NSUTF8StringEncoding] writeToURL:saveFile atomically:NO]; if (!success) { NSBeginAlertSheet(NSLocalizedString(@"messages.error.saveLyrics.title", @""), NSLocalizedString(@"OK", @""), nil, nil, window, nil, nil, nil, nil, NSLocalizedString(@"messages.error.saveLyrics.detail", @"")); } else { [GrowlApplicationBridge notifyWithTitle:NSLocalizedString(@"Growl.messages.lyricsSaved.title", @"") description:[NSString stringWithFormat:NSLocalizedString(@"Growl.messages.lyricsSaved.detail", @""), [saveFile path]] notificationName:@"Lyrics saved to File" iconData:nil priority:0 isSticky:NO clickContext:nil]; } } } -(Lyrics *)currentLyrics { return currentLyrics; } #pragma mark - #pragma mark Show the window - (IBAction)showiLyricsWindow:(id)sender { [window makeKeyAndOrderFront:sender]; } #pragma mark window delegate -(BOOL)validateMenuItem:(NSMenuItem *)menuItem { return [self validateUserInterfaceItem:menuItem]; } -(BOOL)validateToolbarItem:(NSToolbarItem *)theItem { return [self validateUserInterfaceItem:theItem]; } -(BOOL)validateUserInterfaceItem:(id)item { SEL action = [item action]; if (action == @selector(downloadLyrics:)) { [downloadLyricsButton setEnabled:lyricsSelected]; return lyricsSelected; } if (action == @selector(sendLyricsToiTunes:)) { BOOL enabled = lyricsSelected && [iTunes isRunning]; [sendToiTunesButton setEnabled:enabled]; return enabled; } if (action == @selector(getCurrentiTunesSong:)) { return [iTunes isRunning]; } if (action == @selector(showPreview:)) { return [resultsOutline clickedRow] >= 0; } if (action == @selector(showLyricsInBrowser:)) { if ([resultsOutline clickedRow] >= 0) { return YES; } else if ([resultsOutline selectedRow] >= 0) { return YES; } else { return NO; } } return [self respondsToSelector:[item action]]; } -(void)windowDidBecomeMain:(NSNotification *)notification { [iLyricsMenuItem setOffStateImage:nil]; [iLyricsMenuItem setState:NSOnState]; } -(void)windowDidResignMain:(NSNotification *)notification { [iLyricsMenuItem setOffStateImage:nil]; [iLyricsMenuItem setState:NSOffState]; } -(void)windowDidMiniaturize:(NSNotification *)notification { NSString *imgPath = [[NSBundle mainBundle] pathForImageResource:@"Diamond"]; NSImage *miniaturizedImage = [[NSImage alloc] initWithContentsOfFile:imgPath]; [iLyricsMenuItem setOffStateImage:miniaturizedImage]; [iLyricsMenuItem setState:NSOffState]; } -(void)saveToDefalts:(NSUserDefaults *)defaults { [defaults setBool:[showPreviewCheckBox state] == NSOnState forKey:@"Show preview"]; } -(void)loadFromDefaults:(NSUserDefaults *)defaults { [showPreviewCheckBox setState:[defaults boolForKey:@"Show preview"]?NSOnState:NSOffState]; } @end