1/* 2 Project: MPDCon 3 4 Copyright (C) 2004 5 6 Author: Daniel Luederwald 7 8 Created: 2004-05-14 11:37:03 +0200 by flip 9 10 This application is free software; you can redistribute it and/or 11 modify it under the terms of the GNU General Public 12 License as published by the Free Software Foundation; either 13 version 2 of the License, or (at your option) any later version. 14 15 This application is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 Library General Public License for more details. 19 20 You should have received a copy of the GNU General Public 21 License along with this library; if not, write to the Free 22 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. 23*/ 24 25#include <unistd.h> 26#include "MPDController.h" 27 28/* --------------------- 29 - Private Interface - 30 ---------------------*/ 31@interface MPDController(Private) 32 33- (BOOL) _doConnect; 34- (BOOL) _checkConnection; 35 36- (PlaylistItem *) _getPlaylistItemForSong: (const struct mpd_song *)anSong; 37- (unsigned int) _getAllAlbumsCount; 38- (unsigned int) _getAllArtistsCount; 39 40int _stringSort(id string1, id string2, void *context); 41@end 42 43@implementation MPDController 44 45/* -------------------------- 46 - Initialization Methods - 47 --------------------------*/ 48 49+ (id) sharedMPDController 50{ 51 static MPDController *_sharedMPDController = nil; 52 53 if (! _sharedMPDController) 54 { 55 _sharedMPDController = [[MPDController allocWithZone: [self zone]] init]; 56 } 57 58 return _sharedMPDController; 59} 60 61- (id) init 62{ 63 numArtists = 0; 64 numAlbums = 0; 65 66 return self; 67} 68 69- (void) dealloc 70{ 71 mpd_connection_free(mpdConnection); 72 73 [host release]; 74 [port release]; 75 [password release]; 76 [timeout release]; 77 78 [super dealloc]; 79} 80 81/* ---------------------- 82 - Connection Methods - 83 ----------------------*/ 84 85- (BOOL) connectToServer: (NSString *)hostName 86 port: (NSString *)portNr 87 password: (NSString *)pword 88 timeout: (NSString *)tout 89{ 90 if ((hostName) && (portNr) && (tout)) { 91 BOOL didConnect; 92 93 if (host) { 94 [host release]; 95 } 96 if (port) { 97 [port release]; 98 } 99 if (password) { 100 [password release]; 101 } 102 if (port) { 103 [timeout release]; 104 } 105 host = [hostName copy]; 106 port = [portNr copy]; 107 password = [pword copy]; 108 timeout = [tout copy]; 109 110 didConnect = [self _doConnect]; 111 return didConnect; 112 } else { 113 return NO; 114 } 115} 116 117/* ---------------- 118 - Play Methods - 119 ----------------*/ 120 121- (void) play 122{ 123 [self playSong: -1]; 124} 125 126- (void) playSong: (int)theSong 127{ 128 struct mpd_status *mpdStatus; 129 130 if (![self _checkConnection]) { 131 return; 132 } 133 if (theSong != -1) { 134 mpd_send_play_pos(mpdConnection, theSong); 135 } else { 136 137 mpdStatus = mpd_run_status(mpdConnection); 138 if (mpdStatus != NULL) { 139 if(mpd_status_get_state(mpdStatus) == MPD_STATE_STOP) { 140 mpd_send_play(mpdConnection); 141 } else { 142 mpd_send_toggle_pause(mpdConnection); 143 } 144 mpd_response_finish(mpdConnection); 145 mpd_status_free(mpdStatus); 146 } 147 } 148} 149 150- (void) stop 151{ 152 struct mpd_status *mpdStatus; 153 154 if (! [self _checkConnection]) 155 { 156 return; 157 } 158 159 mpdStatus = mpd_run_status(mpdConnection); 160 if (mpdStatus != NULL) { 161 if((mpd_status_get_state(mpdStatus) == MPD_STATE_PLAY) || 162 (mpd_status_get_state(mpdStatus) == MPD_STATE_PAUSE)) { 163 mpd_send_stop(mpdConnection); 164 mpd_response_finish(mpdConnection); 165 } 166 mpd_status_free(mpdStatus); 167 } 168} 169 170- (void) prev 171{ 172 struct mpd_status *mpdStatus; 173 174 if (! [self _checkConnection]) 175 { 176 return; 177 } 178 179 mpdStatus = mpd_run_status(mpdConnection); 180 if (mpdStatus != NULL) { 181 if((mpd_status_get_state(mpdStatus) == MPD_STATE_PLAY) || 182 (mpd_status_get_state(mpdStatus) == MPD_STATE_PAUSE)) { 183 mpd_send_previous(mpdConnection); 184 mpd_response_finish(mpdConnection); 185 } 186 mpd_status_free(mpdStatus); 187 } 188} 189 190- (void) next 191{ 192 struct mpd_status *mpdStatus; 193 194 if (! [self _checkConnection]) 195 { 196 return; 197 } 198 199 mpdStatus = mpd_run_status(mpdConnection); 200 if (mpdStatus != NULL) { 201 if((mpd_status_get_state(mpdStatus) == MPD_STATE_PLAY) || 202 (mpd_status_get_state(mpdStatus) == MPD_STATE_PAUSE)) { 203 mpd_send_next(mpdConnection); 204 mpd_response_finish(mpdConnection); 205 } 206 mpd_status_free(mpdStatus); 207 } 208} 209 210- (void) toggleShuffle 211{ 212 struct mpd_status *mpdStatus; 213 214 if (! [self _checkConnection]) 215 { 216 return; 217 } 218 219 mpdStatus = mpd_run_status(mpdConnection); 220 if (mpdStatus != NULL) { 221 mpd_send_random(mpdConnection, (mpd_status_get_random(mpdStatus) == 0) ? 1 : 0); 222 mpd_response_finish(mpdConnection); 223 mpd_status_free(mpdStatus); 224 } 225} 226 227- (void) toggleRepeat 228{ 229 struct mpd_status *mpdStatus; 230 231 if (! [self _checkConnection]) 232 { 233 return; 234 } 235 236 mpdStatus = mpd_run_status(mpdConnection); 237 if (mpdStatus != NULL) { 238 mpd_send_repeat(mpdConnection, (mpd_status_get_repeat(mpdStatus) == 0) ? 1 : 0); 239 mpd_response_finish(mpdConnection); 240 mpd_status_free(mpdStatus); 241 } 242} 243 244- (void) seekToTime: (int)time 245{ 246 struct mpd_status *mpdStatus; 247 248 if (! [self _checkConnection]) 249 { 250 return; 251 } 252 253 mpdStatus = mpd_run_status(mpdConnection); 254 if (mpdStatus != NULL) { 255 if ((mpd_status_get_state(mpdStatus) == MPD_STATE_PLAY) 256 || (mpd_status_get_state(mpdStatus) == MPD_STATE_PAUSE)) { 257 mpd_send_seek_pos(mpdConnection, mpd_status_get_song_pos(mpdStatus), time); 258 mpd_response_finish(mpdConnection); 259 } 260 mpd_status_free(mpdStatus); 261 } 262} 263 264- (void) setVolume: (int)volume 265{ 266 if (! [self _checkConnection]) 267 { 268 return; 269 } 270 271 mpd_send_set_volume(mpdConnection, volume); 272 273 mpd_response_finish(mpdConnection); 274} 275 276- (void) setCrossfade: (int)cfTime 277{ 278 if (! [self _checkConnection]) 279 { 280 return; 281 } 282 283 mpd_send_crossfade(mpdConnection, cfTime); 284 mpd_response_finish(mpdConnection); 285} 286 287/* ----------------------- 288 - Information Methods - 289 -----------------------*/ 290 291- (int) getState 292{ 293 int state = state_NOCONN; 294 struct mpd_status *mpdStatus; 295 296 if (! [self _checkConnection]) { 297 return state; 298 } 299 mpdStatus = mpd_run_status(mpdConnection); 300 301 if (mpdStatus != NULL) { 302 switch (mpd_status_get_state(mpdStatus)) { 303 case MPD_STATE_UNKNOWN: 304 state = state_UNKNOWN; 305 break; 306 case MPD_STATE_STOP: 307 state = state_STOP; 308 break; 309 case MPD_STATE_PLAY: 310 state = state_PLAY; 311 break; 312 case MPD_STATE_PAUSE: 313 state = state_PAUSE; 314 break; 315 } 316 mpd_status_free(mpdStatus); 317 } else { 318 state = state_UNKNOWN; 319 } 320 321 mpd_response_finish(mpdConnection); 322 323 return state; 324} 325 326- (BOOL) isRandom 327{ 328 BOOL random = NO; 329 struct mpd_status *mpdStatus; 330 331 if (! [self _checkConnection]) { 332 return random; 333 } 334 mpdStatus = mpd_run_status(mpdConnection); 335 if (mpdStatus != NULL) { 336 if ((mpd_status_get_random(mpdStatus)) == 1) { 337 random = YES; 338 } else { 339 random = NO; 340 } 341 mpd_response_finish(mpdConnection); 342 mpd_status_free(mpdStatus); 343 } 344 345 return random; 346} 347 348- (BOOL) isRepeat 349{ 350 BOOL repeat = NO; 351 struct mpd_status *mpdStatus; 352 353 if (! [self _checkConnection]) { 354 return repeat; 355 } 356 mpdStatus = mpd_run_status(mpdConnection); 357 if (mpdStatus != NULL) { 358 if (mpdStatus && (mpd_status_get_repeat(mpdStatus)) == 1) { 359 repeat = YES; 360 } else { 361 repeat = NO; 362 } 363 mpd_response_finish(mpdConnection); 364 mpd_status_free(mpdStatus); 365 } 366 367 return repeat; 368} 369 370- (int) getVolume 371{ 372 int volume = 0; 373 struct mpd_status *mpdStatus; 374 375 if (! [self _checkConnection]) { 376 return 0; 377 } 378 379 mpdStatus = mpd_run_status(mpdConnection); 380 if (mpdStatus != NULL) { 381 volume = mpd_status_get_volume(mpdStatus); 382 mpd_response_finish(mpdConnection); 383 mpd_status_free(mpdStatus); 384 } 385 386 return volume; 387} 388 389- (int) getCrossfade 390{ 391 int cfTime = 0; 392 struct mpd_status *mpdStatus; 393 394 if (! [self _checkConnection]) { 395 return 0; 396 } 397 398 mpdStatus = mpd_run_status(mpdConnection); 399 400 if (mpdStatus != NULL) { 401 cfTime = mpd_status_get_crossfade(mpdStatus); 402 mpd_status_free(mpdStatus); 403 } 404 405 return cfTime; 406} 407 408- (StatisticsItem *) getStatistics 409{ 410 struct mpd_stats *mpdStats; 411 StatisticsItem *statItem; 412 413 if (! [self _checkConnection]) { 414 return nil; 415 } 416 417 mpdStats = mpd_run_stats(mpdConnection); 418 if (mpdStats != NULL) { 419 statItem = [[StatisticsItem alloc] init]; 420 421 [statItem setNumberOfArtists: mpd_stats_get_number_of_artists(mpdStats)]; 422 [statItem setNumberOfAlbums: mpd_stats_get_number_of_albums(mpdStats)]; 423 [statItem setNumberOfSongs: mpd_stats_get_number_of_songs(mpdStats)]; 424 [statItem setUptime: mpd_stats_get_uptime(mpdStats)]; 425 [statItem setDbUpdatetime: mpd_stats_get_db_update_time(mpdStats)]; 426 [statItem setPlaytime: mpd_stats_get_play_time(mpdStats)]; 427 [statItem setDbPlaytime: mpd_stats_get_db_play_time(mpdStats)]; 428 429 mpd_stats_free(mpdStats); 430 mpd_response_finish(mpdConnection); 431 return [statItem autorelease]; 432 } else { 433 return nil; 434 } 435} 436 437/* --------------------- 438 - Playlist Commands - 439 ---------------------*/ 440 441- (PlaylistItem *) getCurrentSong 442{ 443 struct mpd_status *mpdStatus; 444 PlaylistItem *currSong = nil; 445 446 if (! [self _checkConnection]) { 447 return currSong; 448 } 449 450 if (!mpd_command_list_begin(mpdConnection, true) || 451 !mpd_send_status(mpdConnection) || 452 !mpd_send_current_song(mpdConnection) || 453 !mpd_command_list_end(mpdConnection)) { 454 return currSong; 455 } 456 457 mpdStatus = mpd_recv_status(mpdConnection); 458 if (mpdStatus == NULL) { 459 return currSong; 460 } 461 462 if(mpd_status_get_state(mpdStatus) == MPD_STATE_PLAY || 463 mpd_status_get_state(mpdStatus) == MPD_STATE_PAUSE) 464 { 465 struct mpd_song *mpdSong; 466 467 if (!mpd_response_next(mpdConnection)) { 468 return nil; 469 } 470 mpdSong = mpd_recv_song(mpdConnection); 471 472 currSong = [[self _getPlaylistItemForSong: mpdSong] retain]; 473 474 [currSong setElapsedTime: mpd_status_get_elapsed_time(mpdStatus)]; 475 [currSong setTotalTime: mpd_status_get_total_time(mpdStatus)]; 476 mpd_song_free(mpdSong); 477 478 mpd_response_finish(mpdConnection); 479 } 480 481 mpd_status_free(mpdStatus); 482 483 if (currSong) 484 { 485 return [currSong autorelease]; 486 } 487 else 488 { 489 return currSong; 490 } 491} 492 493- (int) getCurrentSongNr 494{ 495 int songNr = -1; 496 struct mpd_status *mpdStatus; 497 498 if (! [self _checkConnection]) 499 { 500 return songNr; 501 } 502 503 mpdStatus = mpd_run_status(mpdConnection); 504 if (mpdStatus != NULL) { 505 songNr = mpd_status_get_song_pos(mpdStatus)+1; 506 507 mpd_response_finish(mpdConnection); 508 mpd_status_free(mpdStatus); 509 } 510 511 return songNr; 512} 513 514- (int) getPlaylistLength 515{ 516 int length = 0; 517 struct mpd_status *mpdStatus; 518 519 if (! [self _checkConnection]) { 520 return 0; 521 } 522 523 mpdStatus = mpd_run_status(mpdConnection); 524 if (mpdStatus != NULL) { 525 length = mpd_status_get_queue_length(mpdStatus); 526 mpd_response_finish(mpdConnection); 527 mpd_status_free(mpdStatus); 528 } 529 530 return length; 531} 532 533- (NSArray *) getPlaylist 534{ 535 NSMutableArray *playlist; 536 struct mpd_status *mpdStatus; 537 538 if (! [self _checkConnection]) { 539 return nil; 540 } 541 if(!mpd_send_list_queue_meta(mpdConnection)) { 542 return nil; 543 } 544 struct mpd_song *mpdSong; 545 playlist = [[NSMutableArray alloc] init]; 546 547 while((mpdSong = mpd_recv_song(mpdConnection)) != NULL) { 548 PlaylistItem *tmpSong; 549 550 tmpSong = [[self _getPlaylistItemForSong: mpdSong] retain]; 551 [playlist addObject: tmpSong]; 552 [tmpSong release]; 553 mpd_song_free(mpdSong); 554 } 555 556 mpd_response_finish(mpdConnection); 557 mpdStatus = mpd_run_status(mpdConnection); 558 if (mpdStatus != NULL) { 559 currPlaylistVersion = mpd_status_get_queue_version(mpdStatus); 560 mpd_response_finish(mpdConnection); 561 mpd_status_free(mpdStatus); 562 } else { 563 currPlaylistVersion = 0; 564 } 565 return [playlist autorelease]; 566} 567 568- (BOOL) collectionChanged 569{ 570 BOOL retVal = NO; 571 unsigned int tmpArtistsNum = [self _getAllArtistsCount]; 572 unsigned int tmpAlbumsNum = [self _getAllAlbumsCount]; 573 if (tmpArtistsNum != numArtists) { 574 numArtists = tmpArtistsNum; 575 retVal = YES; 576 } 577 if (tmpAlbumsNum != numAlbums) { 578 numAlbums = tmpAlbumsNum; 579 retVal = YES; 580 } 581 return retVal; 582} 583 584- (BOOL) playlistChanged 585{ 586 587 BOOL changed = NO; 588 struct mpd_status *mpdStatus; 589 590 if (! [self _checkConnection]) { 591 return NO; 592 } 593 594 mpdStatus = mpd_run_status(mpdConnection); 595 if (mpdStatus != NULL) { 596 unsigned int version = 0; 597 version = mpd_status_get_queue_version(mpdStatus); 598 mpd_response_finish(mpdConnection); 599 mpd_status_free(mpdStatus); 600 if (version != currPlaylistVersion) { 601 changed = YES; 602 } else { 603 changed = NO; 604 } 605 } 606 return changed; 607} 608 609- (void) shuffleList 610{ 611 if (! [self _checkConnection]) { 612 return; 613 } 614 mpd_run_shuffle(mpdConnection); 615} 616 617- (void) clearPlaylist 618{ 619 if (! [self _checkConnection]) { 620 return; 621 } 622 mpd_run_clear(mpdConnection); 623} 624 625- (void) removeSong: (int)song 626{ 627 if (! [self _checkConnection]) { 628 return; 629 } 630 mpd_run_delete(mpdConnection, song); 631} 632 633- (void) removeSongRange: (NSRange)songRange 634{ 635 if (! [self _checkConnection]) { 636 return; 637 } 638 if (songRange.location != NSNotFound) 639 { 640 mpd_run_delete_range(mpdConnection, songRange.location, songRange.length); 641 } 642} 643 644 645- (void) addTrack: (NSString *)file 646{ 647 if (! [self _checkConnection]) { 648 return; 649 } 650 mpd_run_add(mpdConnection, [file UTF8String]); 651} 652 653- (void) moveSongNr: (int)song1 to: (int)song2 654{ 655 if (! [self _checkConnection]) { 656 return; 657 } 658 mpd_run_move(mpdConnection, song1, song2); 659} 660 661- (void) moveSongWithID: (int)song1 to: (int)song2 662{ 663 if (! [self _checkConnection]) { 664 return; 665 } 666 mpd_run_move_id(mpdConnection, song1, song2); 667} 668 669- (NSArray *) getAllPlaylists 670{ 671 NSMutableArray *tmpArray; 672 struct mpd_entity *mpdInfoEntity; 673 674 if (! [self _checkConnection]) { 675 return nil; 676 } 677 mpd_send_list_playlists(mpdConnection); 678 679 tmpArray = [[NSMutableArray alloc] init]; 680 681 while((mpdInfoEntity = mpd_recv_entity(mpdConnection))) { 682 if(mpd_entity_get_type(mpdInfoEntity) == MPD_ENTITY_TYPE_PLAYLIST) { 683 const struct mpd_playlist *mpdPlaylist = mpd_entity_get_playlist(mpdInfoEntity); 684 [tmpArray addObject: [NSString stringWithUTF8String: mpd_playlist_get_path(mpdPlaylist)]]; 685 } 686 mpd_entity_free(mpdInfoEntity); 687 } 688 mpd_response_finish(mpdConnection); 689 690 return [tmpArray autorelease]; 691 692} 693 694- (void) loadPlaylist: (NSString *)title 695{ 696 if (! [self _checkConnection]) { 697 return; 698 } 699 mpd_run_load(mpdConnection, [title cString]); 700} 701 702- (void) savePlaylist: (NSString *)title 703{ 704 if (! [self _checkConnection]) { 705 return; 706 } 707 mpd_run_save(mpdConnection, [title cString]); 708} 709 710- (void) removePlaylist: (NSString *)title 711{ 712 if (! [self _checkConnection]) { 713 return; 714 } 715 mpd_run_rm(mpdConnection, [title cString]); 716} 717 718 719/* ----------------------- 720 - Collection Commands - 721 -----------------------*/ 722 723- (NSArray *) getAllArtists 724{ 725 NSMutableArray *allArtists; 726 struct mpd_pair *pair; 727 728 if (! [self _checkConnection]) { 729 return nil; 730 } 731 mpd_search_db_tags(mpdConnection, MPD_TAG_ARTIST); 732 mpd_search_commit(mpdConnection); 733 734 allArtists = [[NSMutableArray alloc] init]; 735 736 while ((pair = mpd_recv_pair_tag(mpdConnection, MPD_TAG_ARTIST)) != NULL) 737 { 738 [allArtists addObject: pair->value ?[NSString stringWithUTF8String: pair->value]:@""]; 739 mpd_return_pair(mpdConnection, pair); 740 } 741 742 mpd_response_finish(mpdConnection); 743 return [[allArtists autorelease] sortedArrayUsingFunction: _stringSort 744 context: NULL]; 745} 746 747- (NSArray *) getAllAlbums 748{ 749 NSMutableArray *allAlbums; 750 struct mpd_pair *pair; 751 752 if (! [self _checkConnection]) { 753 return nil; 754 } 755 mpd_search_db_tags(mpdConnection, MPD_TAG_ALBUM); 756 mpd_search_commit(mpdConnection); 757 758 allAlbums = [[NSMutableArray alloc] init]; 759 760 while ((pair = mpd_recv_pair_tag(mpdConnection, MPD_TAG_ALBUM)) != NULL) { 761 [allAlbums addObject: [NSString stringWithUTF8String: pair->value]]; 762 free(pair); 763 } 764 765 mpd_response_finish(mpdConnection); 766 return [[allAlbums autorelease] sortedArrayUsingFunction: _stringSort 767 context: NULL]; 768} 769 770- (NSArray *) getAllTracksWithMetadata: (BOOL) withMetadata 771{ 772 NSMutableArray *allTracks; 773 struct mpd_entity *mpdEntity; 774 775 if (! [self _checkConnection]) 776 { 777 return nil; 778 } 779 780 allTracks = [[NSMutableArray alloc] init]; 781 if (withMetadata) 782 { 783 mpd_send_list_all_meta(mpdConnection, NULL); 784 } 785 else 786 { 787 mpd_send_list_all(mpdConnection, NULL); 788 } 789 while ((mpdEntity = mpd_recv_entity(mpdConnection)) != NULL) { 790 if (mpd_entity_get_type(mpdEntity) == MPD_ENTITY_TYPE_SONG) { 791 const struct mpd_song *mpdSong; 792 PlaylistItem *tmpSong; 793 794 mpdSong = mpd_entity_get_song(mpdEntity); 795 tmpSong = [[self _getPlaylistItemForSong: mpdSong] retain]; 796 [allTracks addObject: tmpSong]; 797 [tmpSong release]; 798 } 799 mpd_entity_free(mpdEntity); 800 } 801 mpd_response_finish(mpdConnection); 802 return [allTracks autorelease]; 803} 804 805-(NSArray *) getAllFilesInDirectory: (NSString *) directory 806{ 807 NSMutableArray *allFiles; 808 NSArray *allTracks; 809 NSEnumerator *trackEnum; 810 PlaylistItem *song; 811 812 allFiles = [[NSMutableArray alloc] init]; 813 allTracks = [self getAllTracksWithMetadata: NO]; 814 trackEnum = [allTracks objectEnumerator]; 815 816 while((song = [trackEnum nextObject]) != nil) 817 { 818 NSString *songDir = [NSString stringWithFormat:@"%@", [[song getPath] stringByDeletingLastPathComponent]]; 819 if ([directory isEqual:songDir]) 820 { 821 [allFiles addObject:[[song getPath] lastPathComponent]]; 822 } 823 } 824 return [allFiles autorelease]; 825} 826 827- (NSArray *) getAlbumsForArtist: (NSString *)artist 828{ 829#warning FIXME getAllAlbumsForArtist 830return nil; 831/* 832 NSMutableArray *allAlbums; 833 char *albumName; 834 835 if (! [self _doConnect]) 836 { 837 return nil; 838 } 839 840 841 mpd_sendListCommand(mpdConnection, MPD_TAG_ALBUM, [artist UTF8String]); 842 843 if (! [self _checkConnection]) 844 { 845 return nil; 846 } 847 848 allAlbums = [[NSMutableArray alloc] init]; 849 850 while ((albumName = mpd_getNextAlbum(mpdConnection)) != NULL) 851 { 852 [allAlbums addObject: [NSString stringWithUTF8String: albumName]]; 853 free(albumName); 854 } 855 856 mpd_response_finish(mpdConnection); 857 858 return [[allAlbums autorelease] sortedArrayUsingFunction: _stringSort 859 context:NULL]; 860*/ 861 862} 863 864- (NSArray *) getAllTracksForArtist: (NSString *)artist 865{ 866#warning FIXME getAllTracksForArtist 867 868return nil; 869 870/* 871 NSMutableArray *allTracks; 872 struct mpd_entity *mpdInfoEntity; 873 874 if (! [self _doConnect]) 875 { 876 return nil; 877 } 878 879 mpd_sendFindCommand(mpdConnection, MPD_TAG_ARTIST, [artist UTF8String]); 880 881 if (! [self _checkConnection]) 882 { 883 return nil; 884 } 885 886 allTracks = [[NSMutableArray alloc] init]; 887 888 while((mpdInfoEntity = mpd_recv_entity(mpdConnection))) 889 { 890 if(mpd_entity_get_type(mpdInfoEntity) == MPD_ENTITY_TYPE_SONG) 891 { 892 const struct mpd_song *mpdSong; 893 PlaylistItem *tmpSong; 894 895 mpdSong = mpd_entity_get_song(mpdInfoEntity); 896 897 tmpSong = [[self _getPlaylistItemForSong: mpdSong] retain]; 898 899 [allTracks addObject: tmpSong]; 900 901 [tmpSong release]; 902 } 903 mpd_entity_free(mpdInfoEntity); 904 } 905 906 mpd_response_finish(mpdConnection); 907 908 return [allTracks autorelease]; 909 910*/ 911} 912 913- (NSArray *) getAllTracksForArtist: (NSString *)artist 914 album: (NSString *)album 915{ 916 NSArray *tmpArray; 917 NSMutableArray *allTracks; 918 int i; 919 920 tmpArray = [[self getAllTracksForArtist: artist] retain]; 921 922 if (! tmpArray) { 923 return nil; 924 } 925 926 allTracks = [[NSMutableArray alloc] init]; 927 928 for (i = 0; i < [tmpArray count]; i++) { 929 if ([[[tmpArray objectAtIndex: i] getAlbum] isEqual: album]) { 930 [allTracks addObject: [tmpArray objectAtIndex: i]]; 931 } 932 } 933 934 [tmpArray release]; 935 return [allTracks autorelease]; 936} 937 938- (NSArray *) getAllTracksForAlbum: (NSString *)album 939{ 940 941#warning FIXME getAllTracksForAlbum 942 943return nil; 944/* 945 NSMutableArray *allTracks; 946 struct mpd_entity *mpdInfoEntity; 947 948 if (! [self _doConnect]) 949 { 950 return nil; 951 } 952 953 mpd_sendFindCommand(mpdConnection, MPD_TAG_ALBUM, [album UTF8String]); 954 955 if (! [self _checkConnection]) 956 { 957 return nil; 958 } 959 960 allTracks = [[NSMutableArray alloc] init]; 961 962 while((mpdInfoEntity = mpd_recv_entity(mpdConnection))) 963 { 964 if(mpd_entity_get_type(mpdInfoEntity) == MPD_ENTITY_TYPE_SONG) 965 { 966 const struct mpd_song *mpdSong; 967 PlaylistItem *tmpSong; 968 969 mpdSong = mpd_entity_get_song(mpdInfoEntity); 970 971 tmpSong = [[self _getPlaylistItemForSong: mpdSong] retain]; 972 973 [allTracks addObject: tmpSong]; 974 975 [tmpSong release]; 976 } 977 mpd_entity_free(mpdInfoEntity); 978 } 979 980 mpd_response_finish(mpdConnection); 981 982 return [allTracks autorelease]; 983*/ 984} 985 986- (void) updateCollection 987{ 988 if (! [self _checkConnection]) { 989 return; 990 } 991 992 mpd_send_update(mpdConnection, ""); 993 mpd_response_finish(mpdConnection); 994 if ([self collectionChanged]) 995 { 996 NSNotification *aNotif; 997 aNotif = [NSNotification notificationWithName: 998 ShownCollectionChangedNotification 999 object: nil]; 1000 [[NSNotificationCenter defaultCenter] 1001 postNotification: aNotif]; 1002 } 1003} 1004 1005- (NSArray *) getAllDirectories 1006{ 1007 NSMutableArray *allDirs; 1008 struct mpd_directory *dir; 1009 1010 if (! [self _checkConnection]) 1011 { 1012 return nil; 1013 } 1014 1015 allDirs = [[NSMutableArray alloc] init]; 1016 mpd_send_list_all(mpdConnection, NULL); 1017 while ((dir = mpd_recv_directory(mpdConnection)) != NULL) 1018 { 1019 const char *tmpdir; 1020 tmpdir = mpd_directory_get_path(dir); 1021 1022 [allDirs addObject:[NSString stringWithUTF8String:tmpdir]]; 1023 mpd_directory_free(dir); 1024 } 1025 mpd_response_finish(mpdConnection); 1026 1027 return [allDirs autorelease]; 1028} 1029 1030@end 1031 1032/* ------------------- 1033 - Private Methods - 1034 -------------------*/ 1035 1036@implementation MPDController(Private) 1037- (BOOL) _doConnect 1038{ 1039 char *mpdHost; 1040 int mpdPort; 1041 unsigned int mpdTimeout; 1042 1043 mpdHost = (char *)[host cString]; 1044 mpdPort = (int) [port floatValue]; 1045 mpdTimeout = (unsigned int) [timeout intValue]; 1046 mpdConnection = mpd_connection_new(mpdHost, mpdPort, mpdTimeout); 1047 if (mpdConnection == NULL) { 1048 NSLog(@"Cannot connect to server: Out of memory"); 1049 return NO; 1050 } 1051 1052 if (password) { 1053 mpd_send_password(mpdConnection, (char *)[password cString]); 1054 mpd_response_finish(mpdConnection); 1055 } 1056 1057 if (mpd_connection_get_error(mpdConnection) != MPD_ERROR_SUCCESS) { 1058 [[NSNotificationCenter defaultCenter] postNotification: 1059 [NSNotification notificationWithName: DidNotConnectNotification 1060 object: [NSString stringWithUTF8String: 1061 mpd_connection_get_error_message(mpdConnection)]]]; 1062 mpd_connection_clear_error(mpdConnection); 1063 return NO; 1064 } else { 1065 [[NSNotificationCenter defaultCenter] postNotification: 1066 [NSNotification notificationWithName: DidConnectNotification object: nil]]; 1067 return YES; 1068 } 1069} 1070 1071- (BOOL) _checkConnection 1072{ 1073 if (mpd_connection_get_error(mpdConnection) != MPD_ERROR_SUCCESS) { 1074 if (mpd_connection_get_error(mpdConnection) == MPD_ERROR_TIMEOUT) { 1075 // we are trying to reconnect here 1076 // _doConnect will send the notification if it also fails 1077 mpd_response_finish(mpdConnection); 1078 mpd_connection_clear_error(mpdConnection); 1079 mpd_connection_free(mpdConnection); 1080 if ([self _doConnect]) { 1081 return YES; 1082 } 1083 } else { 1084 mpd_response_finish(mpdConnection); 1085 [[NSNotificationCenter defaultCenter] postNotification: 1086 [NSNotification notificationWithName: DidNotConnectNotification 1087 object: [NSString stringWithUTF8String: 1088 mpd_connection_get_error_message(mpdConnection)]]]; 1089 mpd_connection_clear_error(mpdConnection); 1090 mpd_response_finish(mpdConnection); 1091 } 1092 return NO; 1093 } else { 1094 mpd_response_finish(mpdConnection); 1095 return YES; 1096 } 1097} 1098 1099- (PlaylistItem *) _getPlaylistItemForSong: (const struct mpd_song *)anSong 1100{ 1101 PlaylistItem *plItem; 1102 const char *songArtist = mpd_song_get_tag(anSong,MPD_TAG_ARTIST,0); 1103 const char *songTitle = mpd_song_get_tag(anSong,MPD_TAG_TITLE,0); 1104 const char *songAlbum = mpd_song_get_tag(anSong,MPD_TAG_ALBUM,0); 1105 const char *songTrackNr = mpd_song_get_tag(anSong,MPD_TAG_TRACK,0); 1106 const char *songGenre = mpd_song_get_tag(anSong,MPD_TAG_GENRE,0); 1107 const char *songDate = mpd_song_get_tag(anSong,MPD_TAG_DATE,0); 1108 const char *songComposer = mpd_song_get_tag(anSong,MPD_TAG_COMPOSER,0); 1109 const char *songPerformer = mpd_song_get_tag(anSong,MPD_TAG_PERFORMER,0); 1110 const char *songDisc = mpd_song_get_tag(anSong,MPD_TAG_DISC,0); 1111 const char *songComment = mpd_song_get_tag(anSong,MPD_TAG_COMMENT,0); 1112 1113 plItem = [[PlaylistItem alloc] init]; 1114 1115 if (songArtist == NULL) { 1116 [plItem setArtist: _(@"Unknown Artist")]; 1117 } else { 1118 [plItem setArtist: [NSString stringWithUTF8String: songArtist]]; 1119 } 1120 1121 if (songTitle == NULL) { 1122 [plItem setTitle: _(@"Unknown Title")]; 1123 } else { 1124 [plItem setTitle: [NSString stringWithUTF8String: songTitle]]; 1125 } 1126 1127 if (songAlbum == NULL) { 1128 [plItem setAlbum: _(@"Unknown Album")]; 1129 } else { 1130 [plItem setAlbum: [NSString stringWithUTF8String: songAlbum]]; 1131 } 1132 1133 if (songGenre == NULL) { 1134 [plItem setGenre: _(@"Unknown Genre")]; 1135 } else { 1136 [plItem setGenre: [NSString stringWithUTF8String: songGenre]]; 1137 } 1138 1139 if (songDate == NULL) { 1140 [plItem setDate: _(@"Unknown")]; 1141 } else { 1142 [plItem setDate: [NSString stringWithUTF8String: songDate]]; 1143 } 1144 1145 if (songComposer == NULL) { 1146 [plItem setComposer: _(@"No composer info available")]; 1147 } else { 1148 [plItem setComposer: [NSString stringWithUTF8String: songComposer]]; 1149 } 1150 1151 if (songPerformer == NULL) { 1152 [plItem setPerformer: _(@"No performer info available")]; 1153 } else { 1154 [plItem setPerformer: [NSString stringWithUTF8String: songPerformer]]; 1155 } 1156 1157 if (songDisc == NULL) { 1158 // if we don't know, we just assume its the first disc 1159 [plItem setDisc: _(@"1")]; 1160 } else { 1161 [plItem setDisc: [NSString stringWithUTF8String: songDisc]]; 1162 } 1163 1164 if (songComment == NULL) { 1165 [plItem setComment: _(@"No Comment")]; 1166 } else { 1167 [plItem setComment: [NSString stringWithUTF8String: songComment]]; 1168 } 1169 1170 [plItem setPath: [NSString stringWithUTF8String: mpd_song_get_uri(anSong)]]; 1171 1172 if (songTrackNr == NULL) { 1173 [plItem setTrackNr: @""]; 1174 } else { 1175 [plItem setTrackNr: [NSString stringWithUTF8String: songTrackNr]]; 1176 } 1177 1178 [plItem setTotalTime: mpd_song_get_duration(anSong)]; 1179 1180 [plItem setID: mpd_song_get_id(anSong)]; 1181 [plItem setPos: mpd_song_get_pos(anSong)]; 1182 return [plItem autorelease]; 1183} 1184 1185int _stringSort(id string1, id string2, void *context) 1186{ 1187 NSString *str1, *str2; 1188 1189 str1 = (NSString *) string1; 1190 str2 = (NSString *) string2; 1191 1192 return [str1 caseInsensitiveCompare: str2]; 1193} 1194 1195- (unsigned int) _getAllArtistsCount 1196{ 1197 struct mpd_stats *mpdStats; 1198 unsigned int artists = 0; 1199 if (! [self _checkConnection]) { 1200 return artists; 1201 } 1202 mpdStats = mpd_run_stats(mpdConnection); 1203 if (mpdStats != NULL) { 1204 artists = mpd_stats_get_number_of_artists(mpdStats); 1205 mpd_stats_free(mpdStats); 1206 mpd_response_finish(mpdConnection); 1207 return artists; 1208 } else { 1209 return artists; 1210 } 1211} 1212 1213- (unsigned int) _getAllAlbumsCount 1214{ 1215 struct mpd_stats *mpdStats; 1216 unsigned int albums = 0; 1217 if (! [self _checkConnection]) { 1218 return albums; 1219 } 1220 mpdStats = mpd_run_stats(mpdConnection); 1221 if (mpdStats != NULL) { 1222 albums = mpd_stats_get_number_of_albums(mpdStats); 1223 mpd_stats_free(mpdStats); 1224 mpd_response_finish(mpdConnection); 1225 return albums; 1226 } 1227 return albums; 1228} 1229 1230@end 1231