1/* 2 Project: MPDCon 3 4 Copyright (C) 2004 5 6 Author: Daniel Luederwald 7 8 Created: 2004-05-12 17:59:14 +0200 by flip 9 10 Application Controller 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 "AppController.h" 28 29/* --------------------- 30 - Private Interface - 31 ---------------------*/ 32 33@interface AppController(Private) 34 35- (void) _updateView: (id)sender; 36 37@end 38 39@implementation AppController 40 41/* -------------------------- 42 - Initialization Methods - 43 --------------------------*/ 44 45- (void) dealloc 46{ 47 [mpdController release]; 48 [anTimer release]; 49 [randomPlaylistFeed release]; 50 51 [super dealloc]; 52 53} 54 55/* --------------- 56 - Gui Methods - 57 ---------------*/ 58 59- (void) awakeFromNib 60{ 61 NSNotificationCenter *defCenter; 62 BOOL reversedTime; 63 64 defCenter = [NSNotificationCenter defaultCenter]; 65 66 [[NSApp mainMenu] setTitle:@"MPDCon"]; 67 68 [window setFrameAutosaveName: @"PlayerWindow"]; 69 70 mpdController = [MPDController sharedMPDController]; 71 randomPlaylistFeed = [[RandomPlaylistFeed alloc] init]; 72 73 prevState = state_NOCONN; 74 75 [defCenter addObserver: self 76 selector: @selector(didDisconnect:) 77 name: DidNotConnectNotification 78 object: nil]; 79 80 [defCenter addObserver: self 81 selector: @selector(didConnect:) 82 name: DidConnectNotification 83 object: nil]; 84 85 [defCenter addObserver: self 86 selector: @selector(prefsChanged:) 87 name: PreferencesChangedNotification 88 object: nil]; 89 90 didDisconnect = NO; 91 92 [self connect: self]; 93 94 reversedTime = [[NSUserDefaults standardUserDefaults] 95 boolForKey: @"reversedTime"]; 96 97 [playView setReversedTime: reversedTime]; 98} 99 100- (void) showPrefPanel: (id)sender 101{ 102 [[PreferencesController sharedPreferencesController] showWindow: sender]; 103} 104 105- (void) showLyricsInspector: (id)sender 106{ 107 if (! connected) 108 { 109 return; 110 } 111 112 [[LyricsInspector sharedLyricsInspector] showWindow: sender]; 113} 114 115- (void) showSongInspector: (id)sender 116{ 117 if (! connected) 118 { 119 return; 120 } 121 122 [[SongInspector sharedSongInspector] showWindow: sender]; 123} 124 125- (void) showPlaylistInspector: (id)sender 126{ 127 if (! connected) 128 { 129 return; 130 } 131 [[PlaylistInspector sharedPlaylistInspector] showWindow: sender]; 132} 133 134 135- (void) showPlaylist: (id)sender 136{ 137 if (! connected) 138 { 139 return; 140 } 141 142 [[PlaylistController sharedPlaylistController] showWindow: sender]; 143} 144 145- (void) managePlaylists: (id)sender 146{ 147 if (! connected) 148 { 149 return; 150 } 151 152 [[PlaylistsManagerController sharedPLManagerController] showWindow: sender]; 153} 154 155- (void) browseCollection: (id)sender 156{ 157 if (! connected) 158 { 159 return; 160 } 161 162 [[CollectionController sharedCollectionController] showWindow: self]; 163} 164 165- (void) browseCollectionByDirectory: (id)sender 166{ 167 if (! connected) 168 { 169 return; 170 } 171 172 [[CollectionBrowser sharedCollectionBrowser] showWindow: self]; 173} 174 175- (void) serverStatistics: (id)sender 176{ 177 if (! connected) 178 { 179 return; 180 } 181 182 [[StatisticsController sharedStatisticsController] showWindow: sender]; 183} 184 185- (void) showCrossfade: (id)sender 186{ 187 if (! connected) 188 { 189 return; 190 } 191 192 [[CrossfadeController sharedCrossfadeController] showWindow: sender]; 193} 194 195- (void) connect: (id)sender 196{ 197 NSString *host; 198 NSString *port; 199 NSString *pword; 200 NSString *tout; 201 202 host = [[NSUserDefaults standardUserDefaults] 203 objectForKey: @"mpdHost"]; 204 port = [[NSUserDefaults standardUserDefaults] 205 objectForKey: @"mpdPort"]; 206 tout = [[NSUserDefaults standardUserDefaults] 207 objectForKey: @"mpdTimeout"]; 208 pword = nil; 209 210 if ([[NSUserDefaults standardUserDefaults] 211 integerForKey: @"usePassword"] != 0) 212 { 213 pword = [[NSUserDefaults standardUserDefaults] 214 objectForKey: @"mpdPassword"]; 215 } 216 217 if ((host == nil) || (port == nil) || (tout == nil)) 218 { 219 [self showPrefPanel: self]; 220 } 221 else 222 { 223 didDisconnect = NO; 224 [mpdController connectToServer: host port: port password: pword timeout: tout]; 225 } 226} 227 228- (void) updateCollection: (id) sender 229{ 230 [mpdController updateCollection]; 231} 232 233- (void) play: (id)sender 234{ 235 if (! connected) 236 { 237 return; 238 } 239 240 [mpdController play]; 241} 242 243- (void) stop: (id)sender 244{ 245 if (! connected) 246 { 247 return; 248 } 249 250 [mpdController stop]; 251} 252 253- (void) prev: (id)sender 254{ 255 if (! connected) 256 { 257 return; 258 } 259 260 [mpdController prev]; 261} 262 263- (void) next: (id)sender 264{ 265 if (! connected) 266 { 267 return; 268 } 269 270 [mpdController next]; 271} 272 273- (void) shuffle: (id)sender 274{ 275 if (! connected) 276 return; 277 [mpdController toggleShuffle]; 278} 279 280- (void) repeat: (id)sender 281{ 282 if (! connected) 283 { 284 return; 285 } 286 287 [mpdController toggleRepeat]; 288} 289 290- (void) percentChanged: (id)sender 291{ 292 int seekTime; 293 294 if (! connected) 295 { 296 [percentSlider setFloatValue: 0.0]; 297 return; 298 } 299 300 if ([mpdController getState] == state_NOCONN) 301 { 302 [percentSlider setFloatValue: 0.0]; 303 return; 304 } 305 306 seekTime = (int) [percentSlider floatValue]; 307 308 [mpdController seekToTime: seekTime]; 309 310 [playView setElapsedTime: seekTime]; 311} 312 313- (void) volumeChanged: (id)sender 314{ 315 if ((! connected) || ([mpdController getState] == state_NOCONN)) 316 { 317 [volumeSlider setFloatValue: 0.0]; 318 return; 319 } 320 321 [mpdController setVolume: [volumeSlider floatValue]]; 322} 323 324/* ------------------------ 325 - Notification Methods - 326 ------------------------*/ 327 328- (void) didDisconnect: (NSNotification *)notif 329{ 330 if (!didDisconnect) 331 { 332 didDisconnect = YES; 333 if (connected) 334 { 335 if (anTimer) 336 { 337 [anTimer invalidate]; 338 } 339 } 340 341 connected = NO; 342 343 [playView enableDisplay: NO]; 344 345 [playButton setImage: [NSImage imageNamed: @"Play.tiff"]]; 346 347 [percentSlider setFloatValue: 0.0]; 348 349 NSRunAlertPanel(_(@"Server Problems"), [notif object], nil, nil, nil); 350 } 351} 352 353- (void) didConnect: (NSNotification *)aNotif 354{ 355 if (! connected) 356 { 357 connected = YES; 358 anTimer = [NSTimer scheduledTimerWithTimeInterval: 1 359 target: self 360 selector: 361 @selector(_updateView:) 362 userInfo: nil 363 repeats: YES]; 364 } 365 366 didDisconnect = NO; 367} 368 369 370- (void) prefsChanged: (NSNotification *)notif 371{ 372 [self connect: self]; 373} 374 375/* ------------------- 376 - Service Methods - 377 -------------------*/ 378 379- (void) getPlaylist: (NSPasteboard*)pboard 380 userData: (NSString*)userData 381 error: (NSString**)error 382{ 383 NSMutableString *allSongsString; 384 NSString *formString; 385 NSArray *playlist; 386 int length; 387 int totaltime, tMin, tSecs, tHour; 388 389 int i, j; 390 391 allSongsString = [[NSMutableString alloc] init]; 392 393 playlist = [mpdController getPlaylist]; 394 395 length = [[NSString stringWithFormat: @"%"PRIuPTR, [playlist count]] length]; 396 397 formString = [NSString stringWithFormat: @"Track %s%d%s - ", 398 "%", length, "d/%d"]; 399 400 j = [playlist count]; 401 402 totaltime = 0; 403 for (i = 0; i < j; i++) 404 { 405 int time; 406 407 [allSongsString appendString: 408 [NSString stringWithFormat: formString, i+1, j]]; 409 [allSongsString appendString: [[playlist objectAtIndex: i] getArtist]]; 410 [allSongsString appendString: @" - "]; 411 [allSongsString appendString: [[playlist objectAtIndex: i] getTitle]]; 412 [allSongsString appendString: @" - "]; 413 414 time = [[playlist objectAtIndex: i] getTotalTime]; 415 416 totaltime += time; 417 418 tSecs = (time % 60); 419 tMin = (int) time/60; 420 421 [allSongsString appendString: 422 [NSString stringWithFormat: @"%d:%02d\n", 423 tMin, tSecs]]; 424 } 425 426 tSecs = (totaltime % 60); 427 tMin = (int) (totaltime/60) % 60; 428 tHour = (int) totaltime/3600; 429 430 [allSongsString appendString: 431 [NSString stringWithFormat: 432 @"\nTotal Playtime: %d:%02d:%02d\n", 433 tHour, tMin, tSecs]]; 434 435 [pboard declareTypes: [NSArray arrayWithObject: NSStringPboardType] 436 owner: nil]; 437 438 [pboard setString: allSongsString forType: NSStringPboardType]; 439 RELEASE(allSongsString); 440 return; 441} 442 443- (void) getAlbums: (NSPasteboard*)pboard 444 userData: (NSString*)userData 445 error: (NSString**)error 446{ 447 NSMutableString *allAlbumsString; 448 NSArray *artists; 449 450 int i; 451 452 allAlbumsString = [[NSMutableString alloc] init]; 453 454 artists = [mpdController getAllArtists]; 455 456 for (i = 0; i < [artists count]; i++) 457 { 458 NSString *artist; 459 NSArray *albums; 460 461 int j; 462 463 artist = [artists objectAtIndex: i]; 464 465 albums = [mpdController getAlbumsForArtist: artist]; 466 467 for (j = 0; j < [albums count]; j++) 468 { 469 NSString *album; 470 471 album = [albums objectAtIndex: j]; 472 473 [allAlbumsString appendString: 474 [NSString stringWithFormat: @"%@ - %@\n", 475 artist, album]]; 476 } 477 } 478 479 [pboard declareTypes: [NSArray arrayWithObject: NSStringPboardType] 480 owner: nil]; 481 482 [pboard setString: allAlbumsString forType: NSStringPboardType]; 483 RELEASE(allAlbumsString); 484 return; 485} 486 487/* -------------------------------- 488 - Application Delegate Methods - 489 --------------------------------*/ 490 491- (void) applicationDidFinishLaunching: (NSNotification *)not 492{ 493 [NSApp setServicesProvider: self]; 494} 495 496 497 498 - (BOOL) validateMenuItem: (id<NSMenuItem>)menuItem 499{ 500 501 switch ([menuItem tag]) 502 { 503 case 10: 504 case 14: 505 case 15: 506 case 16: 507 case 17: 508 case 18: 509 return connected; 510 break; 511 case 13: 512 return didDisconnect; 513 break; 514 default: 515 return YES; 516 break; 517 } 518 519} 520 521@end 522 523 524/* ------------------- 525 - Private Methods - 526 -------------------*/ 527 @implementation AppController(Private) 528 529- (void) _updateView: (id)sender 530{ 531 int state; 532 533 if (! connected) { 534 return; 535 } 536 537 if ([mpdController getState] == state_NOCONN) { 538 return; 539 } 540 if ([mpdController getState] == state_UNKNOWN) { 541 return; 542 } 543 544 if ([mpdController playlistChanged]) { 545 NSNotification *aNotif; 546 547 aNotif = [NSNotification notificationWithName: 548 PlaylistChangedNotification 549 object: nil]; 550 551 [[NSNotificationCenter defaultCenter] 552 postNotification: aNotif]; 553 } 554 555 if ([mpdController isRandom]) { 556 [shuffleButton setState: YES]; 557 } else { 558 [shuffleButton setState: NO]; 559 } 560 561 if ([mpdController isRepeat]) { 562 [repeatButton setState: YES]; 563 } else { 564 [repeatButton setState: NO]; 565 } 566 567 [volumeSlider setIntValue: [mpdController getVolume]]; 568 569 state = [mpdController getState]; 570 571 if((state == state_PLAY) || (state == state_PAUSE)) { 572 PlaylistItem *currSong; 573 574 int currentSongNr; 575 int playlistLength; 576 577 578 currentSongNr = [mpdController getCurrentSongNr]; 579 580 playlistLength = [mpdController getPlaylistLength]; 581 582 currSong = [[mpdController getCurrentSong] retain]; 583 584 if (currentSongNr != playedSong) { 585 playedSong = currentSongNr; 586 if ([currSong getTotalTime] != 0) { 587 [percentSlider setMaxValue: (double) [currSong getTotalTime]]; 588 } 589 590 [[NSNotificationCenter defaultCenter] 591 postNotification: [NSNotification 592 notificationWithName: SongChangedNotification 593 object: nil]]; 594 } 595 596 [playView enableDisplay: YES]; 597 598 [playView setCurrentSong: currentSongNr]; 599 [playView setTotalSongs: playlistLength]; 600 601 if((state == state_PAUSE) && (prevState != state_PAUSE)) { 602 NSImage *pImage; 603 604 prevState = state_PAUSE; 605 606 pImage = [NSImage imageNamed: @"Play.tiff"]; 607 608 [playButton setImage: pImage]; 609 610 } 611 else if ((state == state_PLAY) &&(prevState != state_PLAY)) { 612 NSImage *pImage; 613 614 prevState = state_PLAY; 615 616 pImage = [NSImage imageNamed: @"Pause.tiff"]; 617 618 [playButton setImage: pImage]; 619 620 [[NSNotificationCenter defaultCenter] 621 postNotification: [NSNotification 622 notificationWithName: SongChangedNotification 623 object: nil]]; 624 } 625 626 [playView setDisplaySong: currSong]; 627 628 if ([currSong getTotalTime] != 0) { 629 [percentSlider setDoubleValue: (double)[currSong getElapsedTime]]; 630 } 631 632 [currSong release]; 633 } else if (prevState != state_STOP) { 634 NSImage *pImage; 635 636 prevState = state_STOP; 637 638 pImage = [NSImage imageNamed: @"Play.tiff"]; 639 [playButton setImage: pImage]; 640 641 [playButton setTitle: @"Play"]; 642 643 [percentSlider setFloatValue: 0.0]; 644 645 [playView enableDisplay: NO]; 646 647 [[NSNotificationCenter defaultCenter] 648 postNotification: [NSNotification 649 notificationWithName: SongChangedNotification 650 object: nil]]; 651 } 652 653} 654 655@end 656