aboutsummaryrefslogtreecommitdiff
path: root/VKPC/PlaylistTableController.m
diff options
context:
space:
mode:
Diffstat (limited to 'VKPC/PlaylistTableController.m')
-rw-r--r--VKPC/PlaylistTableController.m351
1 files changed, 351 insertions, 0 deletions
diff --git a/VKPC/PlaylistTableController.m b/VKPC/PlaylistTableController.m
new file mode 100644
index 0000000..71a2cff
--- /dev/null
+++ b/VKPC/PlaylistTableController.m
@@ -0,0 +1,351 @@
+//
+// PlaylistTableController.m
+// VKPC
+//
+// Created by Eugene on 12/1/13.
+// Copyright (c) 2013-2014 Eugene Z. All rights reserved.
+//
+
+#import "PopoverController.h"
+#import "PlaylistTableController.h"
+#import "PlaylistTableCellView.h"
+#import "PlaylistTableView.h"
+#import "Queue.h"
+#import "QueueControllerProtocol.h"
+#import "Playlist.h"
+#import "Controller.h"
+#import "Playlist.h"
+
+static NSString * const kTitleKey = @"title";
+static NSString * const kArtistKey = @"artist";
+static NSString * const kPlayImageKey = @"playImage";
+static NSString * const kDurationKey = @"duration";
+static NSString * const kIdKey = @"id";
+
+static Playlist *prePlaylist = nil;
+//static const int kRowHeight = 51;
+
+@implementation PlaylistTableController {
+ BOOL haveTrackForNextPlaylist;
+ PlaylistTableView *playlistTableView;
+ NSArrayController *playlistArrayController;
+ NSView *placeholderView;
+ Queue *setTracksQueue;
+ NSMutableDictionary *trackForNextPlaylist;
+}
+
+- (id)init {
+ if (self = [super init]) {
+ _inited = NO;
+ haveTrackForNextPlaylist = NO;
+
+ trackForNextPlaylist = [[NSMutableDictionary alloc] init];
+
+ setTracksQueue = [[Queue alloc] init];
+ [setTracksQueue setHandler:self];
+
+ _playlist = [[Playlist alloc] init];
+
+ playlistTableView = [PopoverController shared].playlistTableView;
+ playlistArrayController = [PopoverController shared].playlistArrayController;
+ placeholderView = [PopoverController shared].customView;
+ // popoverController = [PopoverController shared];
+
+ // set some variables
+ // playlistTableView = _playlistTableView;
+ // playlistArrayController = controller;
+ // placeholderView = view;
+ // popoverController = _popoverController;
+
+ // init some objects ..
+ NSScrollView *scrollView = [[PopoverController shared] scrollView];
+ [[scrollView contentView] setPostsBoundsChangedNotifications: YES];
+ [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(viewDidScroll:) name:NSViewBoundsDidChangeNotification object:nil];
+
+ playlistTableView.controller = self;
+ // [playlistTableView setController:self];
+ [playlistTableView setDataSource:self];
+ [playlistTableView setDelegate:self];
+ [playlistTableView numberOfRows];
+
+ [playlistArrayController addObject:[_playlist tracks]];
+
+ if (prePlaylist != nil) {
+ [setTracksQueue addTask:prePlaylist];
+ } else {
+ [self playlistUpdated];
+ }
+ _inited = YES;
+
+ }
+ return self;
+}
+
+
+//- (void)initController:(PlaylistTableView *)_playlistTableView withArrayController:(NSArrayController *)controller placeholderView:(NSView *)view withPopoverController:(PopoverController *)_popoverController {
+// }
+
+//- (BOOL)inited {
+// return inited;
+//}
+
+//- (void)dealloc {
+// [super dealloc];
+//}
+
+/** Playlist related methods **/
+
+//- (Playlist *)playlist {
+// return playlist;
+//}
+
+- (void)setPlaylistDataWithTracks:(NSArray *)tracks title:(NSString *)title id:(NSInteger)_id activeId:(NSString *)activeId activePlaying:(BOOL)activePlaying browser:(NSString *)browser {
+ for (int i = 0; i < [tracks count]; i++) {
+ [[tracks objectAtIndex:i] setObject:VKPCGetImagesDictionary()[VKPCImageEmpty] forKey:kPlayImageKey];
+ }
+ Playlist *pl = [[Playlist alloc] init];
+ pl.title = title;
+ pl.tracks = [NSMutableArray arrayWithArray:tracks];
+ pl.playlistID = _id;
+ pl.browser = browser;
+
+ if (![activeId isEqualToString:@""]) {
+ [pl setPlayingIndex:[pl trackIndexById:activeId]];
+ [pl setPlayingStatus:(activePlaying ? PlayingStatusPlaying : PlayingStatusPaused)];
+ } else {
+ [pl setPlayingIndex:-1];
+ [pl setPlayingStatus:PlayingStatusNotPlaying];
+ }
+
+ [setTracksQueue addTask:pl];
+}
+
++ (void)preSetPlaylistDataWithTracks:(NSArray *)tracks title:(NSString *)title id:(NSInteger)_id activeId:(NSString *)activeId activePlaying:(BOOL)activePlaying browser:(NSString *)browser {
+ if (prePlaylist == nil) {
+ prePlaylist = [[Playlist alloc] init];
+ }
+ prePlaylist.tracks = [NSMutableArray arrayWithArray:tracks];
+ prePlaylist.title = title;
+ prePlaylist.browser = browser;
+ prePlaylist.playlistID = _id;
+
+ if (![activeId isEqualToString:@""]) {
+ int index = [prePlaylist trackIndexById:activeId];
+ if (index != [prePlaylist playing].index) [self showNotification:index];
+ [prePlaylist setPlayingIndex:index];
+ [prePlaylist setPlayingStatus:(activePlaying ? PlayingStatusPlaying : PlayingStatusPaused)];
+ } else {
+ [prePlaylist setPlayingIndex:-1];
+ [prePlaylist setPlayingStatus:PlayingStatusNotPlaying];
+ }
+}
+
+- (void)clearPlaylist {
+ if (![_playlist empty]) {
+ NSLog(@"clearPlaylist(): is not empty");
+ if (_inited) {
+ Playlist *pl = [[Playlist alloc] init];
+ [pl clear];
+
+ [setTracksQueue addTask:pl];
+ } else {
+ [_playlist clear];
+ }
+ }
+}
+
+- (void)onQueueTask:(id)task forQueue:(Queue *)queue {
+ if (setTracksQueue == queue) {
+ [_playlist replaceWithDataFromPlaylist:task];
+
+ if (haveTrackForNextPlaylist) {
+ NSInteger toPlaylistId = [(NSNumber *)[trackForNextPlaylist objectForKey:@"playlistId"] intValue];
+ if (toPlaylistId == _playlist.playlistID) {
+ [_playlist setPlayingIndex:[_playlist trackIndexById:[trackForNextPlaylist objectForKey:@"id"]]];
+ [_playlist setPlayingStatus:( [(NSString *)[trackForNextPlaylist objectForKey:@"status"] isEqualToString:@"play"] ? PlayingStatusPlaying : PlayingStatusPaused )];
+ }
+ [trackForNextPlaylist removeAllObjects];
+ haveTrackForNextPlaylist = false;
+ }
+
+ [self playlistUpdated];
+ }
+}
+
+- (void)playlistUpdated {
+ if ([_playlist lastPlaying].index != -1 && [_playlist lastPlaying].index < [self numberOfRowsInTable]) {
+ [[self getCellViewForIndex:_playlist.lastPlaying.index] setPlayingStatus:PlayingStatusNotPlaying];
+ }
+
+ // Update title
+ [[PopoverController shared] updateTitle:_playlist.title];
+
+ // Update tracks
+ [playlistTableView beginUpdates];
+ [playlistTableView performSelectorOnMainThread:@selector(reloadData)
+ withObject:nil
+ waitUntilDone:YES];
+
+ NSLog(@"in playlistUpdated: dispatch_async() now");
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSLog(@"<reloadData done>");
+ [playlistTableView endUpdates];
+ [placeholderView setHidden:(_playlist.tracks.count > 0)]; // TODO maybe just send message to popoverController?
+
+ if ([_playlist playing].index != -1) {
+ [self setPlayingRow:_playlist.playing.index withStatus:[_playlist playing].status];
+ } else if ([_playlist lastPlaying].index != -1) {
+ [self unselectRow:_playlist.lastPlaying.index];
+ }
+
+ [[PopoverController shared] resizeWithContentHeight:[playlistTableView getContentSize]];
+ [setTracksQueue taskDone];
+ });
+}
+
+- (void)setPlayingTrackById:(NSString *)_id withStatus:(PlayingStatus)status forPlaylist:(NSInteger)playlistId {
+ if (playlistId != _playlist.playlistID) {
+ [trackForNextPlaylist setValue:_id forKey:@"id"];
+ [trackForNextPlaylist setValue:(status == PlayingStatusPlaying ? @"play" : @"pause") forKey:@"status"];
+ [trackForNextPlaylist setValue:[NSNumber numberWithLong:playlistId] forKey:@"playlistId"];
+ haveTrackForNextPlaylist = YES;
+ return;
+ }
+
+ int index = [_playlist trackIndexById:_id];
+ if (index != -1) {
+ if ([_playlist playing].index != index) [self showNotification:index];
+
+ if (_inited) {
+ if (index <= [playlistTableView numberOfRows]) {
+ //if ([playlist playing].index != index) [self showNotification:index];
+ [self setPlayingRow:index withStatus:status];
+ }
+ } else {
+ [_playlist setPlayingIndex:index];
+ [_playlist setPlayingStatus:status];
+ }
+ }
+}
+
++ (void)showNotification:(NSInteger)trackIndex {
+ if (trackIndex < prePlaylist.tracks.count && [[NSUserDefaults standardUserDefaults] boolForKey:VKPCPreferencesShowNotifications] == YES) {
+ NSDictionary *track = [[prePlaylist tracks] objectAtIndex:trackIndex];
+ ShowNotification([track objectForKey:@"artist"], [track objectForKey:@"title"]);
+ }
+}
+
+- (void)showNotification:(NSInteger)trackIndex {
+ if (trackIndex < _playlist.tracks.count && [[NSUserDefaults standardUserDefaults] boolForKey:VKPCPreferencesShowNotifications] == YES) {
+ NSDictionary *track = [[_playlist tracks] objectAtIndex:trackIndex];
+ ShowNotification([track objectForKey:@"artist"], [track objectForKey:@"title"]);
+ }
+}
+
+/** UI **/
+
+- (void)viewDidScroll:(NSNotification *)notification {
+ NSScrollView *view = [[PopoverController shared] scrollView];
+
+ // Fix for retina
+ if ([view contentView].bounds.origin.y != (int)[view contentView].bounds.origin.y) {
+ NSPoint point = NSMakePoint([view contentView].bounds.origin.x, (int)([view contentView].bounds.origin.y + 0.5));
+ [[view documentView] scrollPoint:point];
+ }
+}
+
+- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
+ return _playlist.tracks.count;
+}
+
+- (id)tableView:(NSTableView *)tableView
+objectValueForTableColumn:(NSTableColumn *)tableColumn
+ row:(NSInteger)row {
+ if (row < [[_playlist tracks] count])
+ return [[_playlist tracks] objectAtIndex:row];
+ return nil;
+}
+
+- (NSView *)tableView:(NSTableView *)tableView
+ viewForTableColumn:(NSTableColumn *)tableColumn
+ row:(NSInteger)row {
+ PlaylistTableCellView *view = [playlistTableView makeViewWithIdentifier:@"VKPCCell" owner:self];
+ if (view == nil) {
+ NSLog(@"VIEW IS NIL");
+ }
+ PlayingStatus newPlayingStatus = _playlist.playing.index == row ? _playlist.playing.status : PlayingStatusNotPlaying;
+ [view setPlayingStatus:newPlayingStatus];
+ return view;
+}
+
+// User clicked on row
+- (void)selectedRowAtIndex:(NSInteger)index {
+ NSDictionary *track = _playlist.tracks[index];
+
+ if (_playlist.playing.index != index) {
+ [self setPlayingRow:index withStatus:PlayingStatusPlaying];
+
+ [_playlist setPlayingIndex:index];
+ [_playlist setPlayingStatus:PlayingStatusPlaying];
+ } else if (_playlist.playing.index == index) {
+ if (_playlist.playing.status == PlayingStatusPlaying) {
+ [self setPlayingRow:index withStatus:PlayingStatusPaused];
+ [_playlist setPlayingStatus:PlayingStatusPaused];
+ } else {
+ [self setPlayingRow:index withStatus:PlayingStatusPlaying];
+ [_playlist setPlayingStatus:PlayingStatusPlaying];
+ }
+ }
+
+ // TODO call script
+// [Script executeForAll:@"common" withCommand:@"operateTrack" withData:[track objectForKey:kIdKey]];
+ [Controller operateTrack:track[kIdKey]];
+}
+
+- (void)setPlayingRow:(NSInteger)index withStatus:(PlayingStatus)status {
+ if (index >= [self numberOfRowsInTable]) {
+ return;
+ }
+
+ PlaylistTableCellView *cellView = [self getCellViewForIndex:index];
+
+ if (_playlist.lastPlaying.index != index) {
+ if (_playlist.lastPlaying.index >= 0 && _playlist.lastPlaying.index < [self numberOfRowsInTable]) {
+ [[self getCellViewForIndex:_playlist.lastPlaying.index] setPlayingStatus:PlayingStatusNotPlaying];
+ }
+ }
+
+ if (_playlist.playing.index != index) {
+ if (_playlist.playing.index != -1 && _playlist.playing.index < [self numberOfRowsInTable]) {
+ [[self getCellViewForIndex:_playlist.playing.index] setPlayingStatus:PlayingStatusNotPlaying];
+ }
+ [_playlist setPlayingIndex:index];
+ [_playlist setPlayingStatus:status];
+
+ [cellView setPlayingStatus:status];
+ } else if (_playlist.playing.index == index) {
+ [_playlist setPlayingStatus:status];
+ [cellView setPlayingStatus:status];
+ }
+
+ [playlistTableView scrollRowToVisible:index];
+}
+
+- (void)unselectRow:(NSInteger)index {
+ if (index >= [self numberOfRowsInTable]) {
+ return;
+ }
+
+ PlaylistTableCellView *cellView = [self getCellViewForIndex:index];
+ [cellView setPlayingStatus:PlayingStatusNotPlaying];
+}
+
+- (PlaylistTableCellView *)getCellViewForIndex:(NSInteger)index {
+ return [playlistTableView viewAtColumn:0 row:index makeIfNecessary:YES];
+}
+
+- (int)numberOfRowsInTable {
+ return (int)[playlistTableView numberOfRows];
+}
+
+@end