1/* 2 Project: MPDCon 3 4 Copyright (C) 2012 5 6 Author: Sebastian Reitenbach 7 8 Created: 2012-10-31 9 10 Playlist Inspector 11 12 This application is free software; you can redistribute it and/or 13 modify it under the terms of the GNU General Public 14 License as published by the Free Software Foundation; either 15 version 2 of the License, or (at your option) any later version. 16 17 This application is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 Library General Public License for more details. 21 22 You should have received a copy of the GNU General Public 23 License along with this library; if not, write to the Free 24 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. 25*/ 26 27#include <AppKit/AppKit.h> 28#include "PlaylistInspector.h" 29#include "SongRatingCell.h" 30#include "Strings.h" 31#include "CollectionController.h" 32 33@implementation PlaylistInspector 34 35+ (id) sharedPlaylistInspector 36{ 37 static PlaylistInspector *_sharedPlaylistInspector = nil; 38 39 if (! _sharedPlaylistInspector) { 40 _sharedPlaylistInspector = 41 [[PlaylistInspector allocWithZone: [self zone]] init]; 42 } 43 44 return _sharedPlaylistInspector; 45} 46 47- (id) init 48{ 49 if ((self = [self initWithWindowNibName: @"PlaylistInspector"]) != nil) 50 { 51 [self setWindowFrameAutosaveName: @"PlaylistInspector"]; 52 defaults = [NSUserDefaults standardUserDefaults]; 53 mpdController = [MPDController sharedMPDController]; 54 playlistController = [PlaylistController sharedPlaylistController]; 55 threadlock = [NSLock new]; 56 } 57 return self; 58} 59 60- (void) dealloc 61{ 62 [minRatingCol release]; 63 [maxRatingCol release]; 64 [defaults release]; 65 [threadlock release]; 66 67 [super dealloc]; 68} 69 70/* GUI methods */ 71- (void) awakeFromNib 72{ 73 NSNotificationCenter *defCenter; 74 75 SongRatingCell *minRatingCell; 76 SongRatingCell *maxRatingCell; 77 78 ASSIGN(minRatingCol, [minRatingStars tableColumnWithIdentifier: @"minrating"]); 79 ASSIGN(maxRatingCol, [maxRatingStars tableColumnWithIdentifier: @"maxrating"]); 80 [minRatingStars setAutosaveName: @"MinRatingStarsTable"]; 81 [minRatingStars setAutosaveTableColumns: YES]; 82 [minRatingStars setHeaderView: nil]; 83 [minRatingStars setTarget:self]; 84 [maxRatingStars setAutosaveName: @"MaxRatingStarsTable"]; 85 [maxRatingStars setAutosaveTableColumns: YES]; 86 [maxRatingStars setHeaderView: nil]; 87 [maxRatingStars setTarget:self]; 88 89 defCenter = [NSNotificationCenter defaultCenter]; 90 [defCenter addObserver: self 91 selector: @selector(songChanged:) 92 name: SongChangedNotification 93 object: nil]; 94 [defCenter addObserver: self 95 selector: @selector(playlistChanged:) 96 name: PlaylistChangedNotification 97 object: nil]; 98 99 minRatingCell = [[SongRatingCell alloc] init]; 100 maxRatingCell = [[SongRatingCell alloc] init]; 101 [minRatingCol setDataCell:minRatingCell]; 102 [maxRatingCol setDataCell:maxRatingCell]; 103 104 [randomPlaylistFeed setState: [defaults integerForKey: @"RandomPlaylistFeed"]]; 105 [ratingBasedFeed setState: [defaults integerForKey: @"RatingBasedFeed"]]; 106 [includeUnratedSongs setState: [defaults integerForKey: @"IncludeUnratedSongs"]]; 107 [nrNewSongs setStringValue: [NSString stringWithFormat:@"%"PRIiPTR, [defaults integerForKey: @"NrOfFutureSongs"]? 108 [defaults integerForKey: @"NrOfFutureSongs"]:20]]; 109 [nrPlayedSongs setStringValue: [NSString stringWithFormat:@"%"PRIiPTR, [defaults integerForKey: @"NrOfOldSongsToKeep"]? 110 [defaults integerForKey: @"NrOfOldSongsToKeep"]:20]]; 111 112 if (![randomPlaylistFeed state]) 113 { 114 [nrNewSongs setEditable: NO]; 115 [nrPlayedSongs setEditable: NO]; 116 [nrOfNewSongsText setEnabled: NO]; 117 [nrOfPlayedSongsText setEnabled: NO]; 118 [ratingBasedFeed setEnabled:NO]; 119 [minRatingText setEnabled: NO]; 120 [maxRatingText setEnabled: NO]; 121 [includeUnratedSongs setEnabled:NO]; 122 // the stuff below doesn't work like expected, also setEnabled: NO doesn't seem to work either 123 [minRatingCell setEditable: NO]; 124 [maxRatingCell setEditable: NO]; 125 } 126 else 127 { 128 if (![ratingBasedFeed state]) 129 { 130 // the stuff below doesn't work like expected 131 // also setEnabled: NO doesn't seem to work either 132 [minRatingText setEnabled: NO]; 133 [maxRatingText setEnabled: NO]; 134 [minRatingCell setEditable: NO]; 135 [maxRatingCell setEditable: NO]; 136 [includeUnratedSongs setEnabled:NO]; 137 } 138 } 139 [self updatePlaylistInspector]; 140 RELEASE(minRatingCell); 141 RELEASE(maxRatingCell); 142} 143 144- (void) nrOfFutureSongsChanged: (id) sender 145{ 146 [defaults setInteger: [nrNewSongs integerValue] forKey:@"NrOfFutureSongs"]; 147 [defaults synchronize]; 148 [self sendRandomPlaylistFeedDefaultsChangedNotification]; 149} 150- (void) nrOfOldSongsToKeepChanged: (id) sender 151{ 152 [defaults setInteger: [nrPlayedSongs integerValue] forKey:@"NrOfOldSongsToKeep"]; 153 [defaults synchronize]; 154 [self sendRandomPlaylistFeedDefaultsChangedNotification]; 155} 156- (void) randomPlaylistFeedStateChanged: (id) sender 157{ 158 [defaults setInteger: [randomPlaylistFeed state] forKey:@"RandomPlaylistFeed"]; 159 [defaults synchronize]; 160 [self sendRandomPlaylistFeedDefaultsChangedNotification]; 161 if ([randomPlaylistFeed state]) 162 { 163 [nrNewSongs setEditable: YES]; 164 [nrPlayedSongs setEditable: YES]; 165 [nrOfNewSongsText setEnabled: YES]; 166 [nrOfPlayedSongsText setEnabled: YES]; 167 [ratingBasedFeed setEnabled:YES]; 168 if ([ratingBasedFeed state]) 169 { 170 [minRatingStars setEnabled: YES]; 171 [maxRatingStars setEnabled: YES]; 172 [minRatingText setEnabled: YES]; 173 [maxRatingText setEnabled: YES]; 174 [includeUnratedSongs setEnabled:YES]; 175 } 176 } 177 else 178 { 179 [nrNewSongs setEditable: NO]; 180 [nrPlayedSongs setEditable: NO]; 181 [nrOfNewSongsText setEnabled: NO]; 182 [nrOfPlayedSongsText setEnabled: NO]; 183 [ratingBasedFeed setEnabled:NO]; 184 // the stuff below doesn't work like expected, also setEnabled: NO doesn't seem to work either 185 [maxRatingStars setEnabled: NO]; 186 [minRatingStars setEnabled: NO]; 187 [minRatingText setEnabled: NO]; 188 [maxRatingText setEnabled: NO]; 189 [includeUnratedSongs setEnabled:NO]; 190 } 191} 192- (void) ratingBasedFeedStateChanged: (id) sender 193{ 194 [defaults setInteger: [ratingBasedFeed state] forKey:@"RatingBasedFeed"]; 195 [defaults synchronize]; 196 [self sendRandomPlaylistFeedDefaultsChangedNotification]; 197 // the disabling is not working, they seem to be always enabled 198 if ([ratingBasedFeed state]) 199 { 200 [maxRatingStars setEnabled: YES]; 201 [minRatingStars setEnabled: YES]; 202 [minRatingText setEnabled: YES]; 203 [maxRatingText setEnabled: YES]; 204 [includeUnratedSongs setEnabled:YES]; 205 } 206 else 207 { 208 [maxRatingStars setEnabled: NO]; 209 [minRatingStars setEnabled: NO]; 210 [minRatingText setEnabled: NO]; 211 [maxRatingText setEnabled: NO]; 212 [includeUnratedSongs setEnabled:NO]; 213 } 214} 215 216- (void) includeUnratedSongsChanged: (id) sender 217{ 218 [defaults setInteger: [includeUnratedSongs state] forKey:@"IncludeUnratedSongs"]; 219 [defaults synchronize]; 220 [self sendRandomPlaylistFeedDefaultsChangedNotification]; 221} 222 223/* the delegate methods */ 224- (void) songChanged:(NSNotification *)aNotif 225{ 226 [self updateCurrentSongNr]; 227} 228 229- (void) playlistChanged:(NSNotification *)aNotif 230{ 231 [self updatePlaylistInfo]; 232} 233 234- (void) updateCurrentSongNr 235{ 236 [currentSongNr setStringValue:[NSString stringWithFormat:@"%i", [mpdController getCurrentSongNr]]]; 237} 238 239- (void) updatePlaylistInfo 240{ 241 [playlistPlayingTime setStringValue: [playlistController playlistLength]]; 242 [nrOfSongsInPlaylist setStringValue: [NSString stringWithFormat:@"%i", [mpdController getPlaylistLength]]]; 243 [self updateCurrentSongNr]; 244} 245 246 247 248- (void) updatePlaylistInspector 249{ 250 [minRatingStars reloadData]; 251 [maxRatingStars reloadData]; 252 [playlistPlayingTime setStringValue: [playlistController playlistLength]]; 253 [currentSongNr setStringValue:[NSString stringWithFormat:@"%i", [mpdController getCurrentSongNr]]]; 254 [nrOfSongsInPlaylist setStringValue: [NSString stringWithFormat:@"%i", [mpdController getPlaylistLength]]]; 255 return; 256} 257 258- (NSInteger) numberOfRowsInTableView: (NSTableView *)tableView 259{ 260 return 1; 261} 262 263- (id) tableView: (NSTableView *) tableView 264objectValueForTableColumn: (NSTableColumn *) tableColumn 265 row: (NSInteger) row 266{ 267 NSString *identifier; 268 269 identifier = [tableColumn identifier]; 270 271 if ([identifier isEqual:@"minrating"]) 272 { 273 return [NSNumber numberWithInteger: 274 [defaults integerForKey: @"RandomPlaylistMinRating"]]; 275 } 276 else 277 { 278 return [NSNumber numberWithInteger: 279 [defaults integerForKey: @"RandomPlaylistMaxRating"]?[defaults integerForKey: @"RandomPlaylistMaxRating"]:5]; 280 } 281} 282 283// method below doesn't get called, its actually intended 284// to disable the editing of the rating stars... 285- (BOOL) tableView: (NSTableView *) tableView 286shouldEditTableColumn: (NSTableColumn *)aTableColumn 287 row:(NSInteger)rowIndex 288{ 289 if ([randomPlaylistFeed state] && [ratingBasedFeed state]) 290 { 291 return YES; 292 } 293 else 294 { 295 return NO; 296 } 297} 298 299 300-(void) tableView: (NSTableView *) aTableView 301 setObjectValue: (id) anObj 302 forTableColumn: (NSTableColumn *) aTableColumn 303 row: (NSInteger) rowIndex 304{ 305 if (aTableColumn == minRatingCol) { 306 /* We can't keep that as an assertion now, as it can easily fail when 307 * the broken GNUstep NSTableView lets you edit the string value for the cell. 308 */ 309 if ([anObj isKindOfClass: [NSNumber class]] == NO) { 310 NSLog(@"Warning: %@ is not a number value.", anObj); 311 } 312 [defaults setInteger: [anObj intValue] forKey:@"RandomPlaylistMinRating"]; 313 } else if (aTableColumn == maxRatingCol) { 314 /* We can't keep that as an assertion now, as it can easily fail when 315 * the broken GNUstep NSTableView lets you edit the string value for the cell. 316 */ 317 if ([anObj isKindOfClass: [NSNumber class]] == NO) { 318 NSLog(@"Warning: %@ is not a number value.", anObj); 319 } 320 [defaults setInteger: [anObj intValue] forKey:@"RandomPlaylistMaxRating"]; 321 } 322 [defaults synchronize]; 323 [self sendRandomPlaylistFeedDefaultsChangedNotification]; 324} 325 326- (void) sendRandomPlaylistFeedDefaultsChangedNotification 327{ 328 NSNotification *aNotif; 329 aNotif = [NSNotification notificationWithName: 330 RandomPlaylistFeedDefaultsChangedNotification 331 object: nil]; 332 [[NSNotificationCenter defaultCenter] 333 postNotification: aNotif]; 334} 335@end 336