1 /* 2 * Controller.cpp - Media Player for the Haiku Operating System 3 * 4 * Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de> 5 * Copyright (C) 2007-2008 Stephan Aßmus <superstippi@gmx.de> (MIT Ok) 6 * Copyright (C) 2007-2009 Fredrik Modéen <[FirstName]@[LastName].se> (MIT ok) 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 24 #include "Controller.h" 25 26 #include <new> 27 #include <stdio.h> 28 #include <string.h> 29 30 #include <Autolock.h> 31 #include <Bitmap.h> 32 #include <Debug.h> 33 #include <MediaFile.h> 34 #include <MediaTrack.h> 35 #include <Path.h> 36 #include <Window.h> // for debugging only 37 38 #include "AutoDeleter.h" 39 #include "ControllerView.h" 40 #include "MainApp.h" 41 #include "PlaybackState.h" 42 #include "Settings.h" 43 #include "VideoView.h" 44 45 // suppliers 46 #include "AudioTrackSupplier.h" 47 #include "MediaTrackAudioSupplier.h" 48 #include "MediaTrackVideoSupplier.h" 49 #include "ProxyAudioSupplier.h" 50 #include "ProxyVideoSupplier.h" 51 #include "VideoTrackSupplier.h" 52 53 using std::nothrow; 54 55 56 void 57 HandleError(const char *text, status_t err) 58 { 59 if (err != B_OK) { 60 printf("%s. error 0x%08x (%s)\n",text, (int)err, strerror(err)); 61 fflush(NULL); 62 exit(1); 63 } 64 } 65 66 67 // #pragma mark - Controller::Listener 68 69 70 Controller::Listener::Listener() {} 71 Controller::Listener::~Listener() {} 72 void Controller::Listener::FileFinished() {} 73 void Controller::Listener::FileChanged(PlaylistItem* item, status_t result) {} 74 void Controller::Listener::VideoTrackChanged(int32) {} 75 void Controller::Listener::AudioTrackChanged(int32) {} 76 void Controller::Listener::VideoStatsChanged() {} 77 void Controller::Listener::AudioStatsChanged() {} 78 void Controller::Listener::PlaybackStateChanged(uint32) {} 79 void Controller::Listener::PositionChanged(float) {} 80 void Controller::Listener::VolumeChanged(float) {} 81 void Controller::Listener::MutedChanged(bool) {} 82 83 84 // #pragma mark - Controller 85 86 87 enum { 88 MSG_SET_TO = 'stto' 89 }; 90 91 92 Controller::Controller() 93 : 94 NodeManager(), 95 fVideoView(NULL), 96 fVolume(1.0), 97 fActiveVolume(1.0), 98 fMuted(false), 99 100 fItem(NULL), 101 fMediaFile(NULL), 102 103 fVideoSupplier(new ProxyVideoSupplier()), 104 fAudioSupplier(new ProxyAudioSupplier(this)), 105 fVideoTrackSupplier(NULL), 106 fAudioTrackSupplier(NULL), 107 108 fAudioTrackList(4), 109 fVideoTrackList(2), 110 111 fPosition(0), 112 fDuration(0), 113 fVideoFrameRate(25.0), 114 fSeekRequested(false), 115 116 fGlobalSettingsListener(this), 117 118 fListeners(4) 119 { 120 Settings::Default()->AddListener(&fGlobalSettingsListener); 121 _AdoptGlobalSettings(); 122 123 fAutoplay = fAutoplaySetting; 124 } 125 126 127 Controller::~Controller() 128 { 129 Settings::Default()->RemoveListener(&fGlobalSettingsListener); 130 SetTo(NULL); 131 } 132 133 134 // #pragma mark - NodeManager interface 135 136 137 void 138 Controller::MessageReceived(BMessage* message) 139 { 140 switch (message->what) { 141 case MSG_OBJECT_CHANGED: 142 // received from fGlobalSettingsListener 143 // TODO: find out which object, if we ever watch more than 144 // the global settings instance... 145 _AdoptGlobalSettings(); 146 break; 147 148 case MSG_SET_TO: 149 { 150 PlaylistItem* item; 151 if (message->FindPointer("item", (void**)&item) == B_OK) { 152 PlaylistItemRef itemRef(item, true); 153 // The reference was passed with the message. 154 SetTo(itemRef); 155 } else 156 _NotifyFileChanged(NULL, B_BAD_VALUE); 157 158 break; 159 } 160 161 default: 162 NodeManager::MessageReceived(message); 163 } 164 } 165 166 167 int64 168 Controller::Duration() 169 { 170 // This should really be total frames (video frames at that) 171 // TODO: It is not so nice that the MediaPlayer still measures 172 // in video frames if only playing audio. Here for example, it will 173 // return a duration of 0 if the audio clip happens to be shorter than 174 // one video frame at 25 fps. 175 return (int64)((double)fDuration * fVideoFrameRate / 1000000.0); 176 } 177 178 179 VideoTarget* 180 Controller::CreateVideoTarget() 181 { 182 return fVideoView; 183 } 184 185 186 VideoSupplier* 187 Controller::CreateVideoSupplier() 188 { 189 return fVideoSupplier; 190 } 191 192 193 AudioSupplier* 194 Controller::CreateAudioSupplier() 195 { 196 return fAudioSupplier; 197 } 198 199 200 // #pragma mark - 201 202 203 status_t 204 Controller::SetToAsync(const PlaylistItemRef& item) 205 { 206 PlaylistItemRef additionalReference(item); 207 208 BMessage message(MSG_SET_TO); 209 status_t ret = message.AddPointer("item", item.Get()); 210 if (ret != B_OK) 211 return ret; 212 213 ret = PostMessage(&message); 214 if (ret != B_OK) 215 return ret; 216 217 // The additional reference is now passed along with the message... 218 additionalReference.Detach(); 219 220 return B_OK; 221 } 222 223 224 status_t 225 Controller::SetTo(const PlaylistItemRef& item) 226 { 227 BAutolock _(this); 228 229 if (fItem == item) { 230 if (InitCheck() == B_OK) { 231 if (fAutoplay) { 232 SetPosition(0.0); 233 StartPlaying(true); 234 } 235 } 236 return B_OK; 237 } 238 239 fItem = item; 240 241 fAudioSupplier->SetSupplier(NULL, fVideoFrameRate); 242 fVideoSupplier->SetSupplier(NULL); 243 244 fAudioTrackList.MakeEmpty(); 245 fVideoTrackList.MakeEmpty(); 246 247 ObjectDeleter<BMediaFile> oldMediaFileDeleter(fMediaFile); 248 // BMediaFile destructor will call ReleaseAllTracks() 249 fMediaFile = NULL; 250 251 // Do not delete the supplier chain until after we called 252 // NodeManager::Init() to setup a new media node chain 253 ObjectDeleter<VideoTrackSupplier> videoSupplierDeleter( 254 fVideoTrackSupplier); 255 ObjectDeleter<AudioTrackSupplier> audioSupplierDeleter( 256 fAudioTrackSupplier); 257 258 fVideoTrackSupplier = NULL; 259 fAudioTrackSupplier = NULL; 260 261 fDuration = 0; 262 fVideoFrameRate = 25.0; 263 264 if (fItem.Get() == NULL) 265 return B_BAD_VALUE; 266 267 BMediaFile* mf = fItem->CreateMediaFile(); 268 ObjectDeleter<BMediaFile> mediaFileDeleter(mf); 269 270 status_t err = mf->InitCheck(); 271 if (err != B_OK) { 272 printf("Controller::SetTo: initcheck failed\n"); 273 _NotifyFileChanged(item.Get(), err); 274 return err; 275 } 276 277 int trackcount = mf->CountTracks(); 278 if (trackcount <= 0) { 279 printf("Controller::SetTo: trackcount %d\n", trackcount); 280 _NotifyFileChanged(item.Get(), B_MEDIA_NO_HANDLER); 281 return B_MEDIA_NO_HANDLER; 282 } 283 284 for (int i = 0; i < trackcount; i++) { 285 BMediaTrack* t = mf->TrackAt(i); 286 media_format f; 287 err = t->EncodedFormat(&f); 288 if (err != B_OK) { 289 printf("Controller::SetTo: EncodedFormat failed for track index %d, error 0x%08lx (%s)\n", 290 i, err, strerror(err)); 291 mf->ReleaseTrack(t); 292 continue; 293 } 294 295 if (t->Duration() <= 0) { 296 printf("Controller::SetTo: warning! track index %d has no duration\n", i); 297 } 298 299 if (f.IsAudio()) { 300 if (!fAudioTrackList.AddItem(t)) 301 return B_NO_MEMORY; 302 } else if (f.IsVideo()) { 303 if (!fVideoTrackList.AddItem(t)) 304 return B_NO_MEMORY; 305 } else { 306 printf("Controller::SetTo: track index %d has unknown type\n", i); 307 mf->ReleaseTrack(t); 308 } 309 } 310 311 //printf("Controller::SetTo: %d audio track, %d video track\n", 312 // AudioTrackCount(), VideoTrackCount()); 313 314 fMediaFile = mf; 315 mediaFileDeleter.Detach(); 316 317 SelectAudioTrack(0); 318 SelectVideoTrack(0); 319 320 if (fAudioTrackSupplier == NULL && fVideoTrackSupplier == NULL) { 321 printf("Controller::SetTo: no audio or video tracks found or " 322 "no decoders\n"); 323 _NotifyFileChanged(item.Get(), B_MEDIA_NO_HANDLER); 324 delete fMediaFile; 325 fMediaFile = NULL; 326 return B_MEDIA_NO_HANDLER; 327 } 328 329 // prevent blocking the creation of new overlay buffers 330 fVideoView->DisableOverlay(); 331 332 // get video properties (if there is video at all) 333 bool useOverlays = fVideoView ? fVideoView->UseOverlays() : true; 334 335 int width; 336 int height; 337 GetSize(&width, &height); 338 color_space preferredVideoFormat = B_NO_COLOR_SPACE; 339 if (fVideoTrackSupplier != NULL) { 340 const media_format& format = fVideoTrackSupplier->Format(); 341 preferredVideoFormat = format.u.raw_video.display.format; 342 } 343 344 uint32 enabledNodes; 345 if (!fVideoTrackSupplier) 346 enabledNodes = AUDIO_ONLY; 347 else if (!fAudioTrackSupplier) 348 enabledNodes = VIDEO_ONLY; 349 else 350 enabledNodes = AUDIO_AND_VIDEO; 351 352 float audioFrameRate = 44100.0f; 353 uint32 audioChannels = 2; 354 if (fAudioTrackSupplier != NULL) { 355 const media_format& audioTrackFormat = fAudioTrackSupplier->Format(); 356 audioFrameRate = audioTrackFormat.u.raw_audio.frame_rate; 357 audioChannels = audioTrackFormat.u.raw_audio.channel_count; 358 // if (fVideoTrackSupplier == NULL) 359 // fVideoFrameRate = audioFrameRate; 360 } 361 362 if (InitCheck() != B_OK) { 363 Init(BRect(0, 0, width - 1, height - 1), fVideoFrameRate, 364 preferredVideoFormat, audioFrameRate, audioChannels, LOOPING_ALL, 365 false, 1.0, enabledNodes, useOverlays); 366 } else { 367 FormatChanged(BRect(0, 0, width - 1, height - 1), fVideoFrameRate, 368 preferredVideoFormat, audioFrameRate, audioChannels, enabledNodes, 369 useOverlays); 370 } 371 372 _NotifyFileChanged(item.Get(), B_OK); 373 374 SetPosition(0.0); 375 if (fAutoplay) 376 StartPlaying(true); 377 378 return B_OK; 379 } 380 381 382 void 383 Controller::PlayerActivated(bool active) 384 { 385 if (LockWithTimeout(5000) != B_OK) 386 return; 387 388 if (active && gMainApp->PlayerCount() > 1) { 389 if (fActiveVolume != fVolume) 390 SetVolume(fActiveVolume); 391 } else { 392 fActiveVolume = fVolume; 393 if (gMainApp->PlayerCount() > 1) 394 switch (fBackgroundMovieVolumeMode) { 395 case mpSettings::BG_MOVIES_MUTED: 396 SetVolume(0.0); 397 break; 398 case mpSettings::BG_MOVIES_HALF_VLUME: 399 SetVolume(fVolume * 0.25); 400 break; 401 case mpSettings::BG_MOVIES_FULL_VOLUME: 402 default: 403 break; 404 } 405 } 406 407 Unlock(); 408 } 409 410 411 void 412 Controller::GetSize(int *width, int *height, int* _widthAspect, 413 int* _heightAspect) 414 { 415 BAutolock _(this); 416 417 if (fVideoTrackSupplier) { 418 media_format format = fVideoTrackSupplier->Format(); 419 *height = format.u.raw_video.display.line_count; 420 *width = format.u.raw_video.display.line_width; 421 int widthAspect = 0; 422 int heightAspect = 0; 423 // Ignore format aspect when both values are 1. If they have been 424 // intentionally at 1:1 then no harm is done for quadratic videos, 425 // only if the video is indeed encoded anamorphotic, but supposed 426 // to be displayed quadratic... extremely unlikely. 427 if (format.u.raw_video.pixel_width_aspect 428 != format.u.raw_video.pixel_height_aspect 429 && format.u.raw_video.pixel_width_aspect != 1) { 430 widthAspect = format.u.raw_video.pixel_width_aspect; 431 heightAspect = format.u.raw_video.pixel_height_aspect; 432 } 433 if (_widthAspect != NULL) 434 *_widthAspect = widthAspect; 435 if (_heightAspect != NULL) 436 *_heightAspect = heightAspect; 437 } else { 438 *height = 0; 439 *width = 0; 440 if (_widthAspect != NULL) 441 *_widthAspect = 1; 442 if (_heightAspect != NULL) 443 *_heightAspect = 1; 444 } 445 } 446 447 448 int 449 Controller::AudioTrackCount() 450 { 451 BAutolock _(this); 452 453 return fAudioTrackList.CountItems(); 454 } 455 456 457 int 458 Controller::VideoTrackCount() 459 { 460 BAutolock _(this); 461 462 return fVideoTrackList.CountItems(); 463 } 464 465 466 status_t 467 Controller::SelectAudioTrack(int n) 468 { 469 BAutolock _(this); 470 471 BMediaTrack* track = (BMediaTrack *)fAudioTrackList.ItemAt(n); 472 if (!track) 473 return B_ERROR; 474 475 ObjectDeleter<AudioTrackSupplier> deleter(fAudioTrackSupplier); 476 fAudioTrackSupplier = new MediaTrackAudioSupplier(track, n); 477 478 bigtime_t a = fAudioTrackSupplier->Duration(); 479 bigtime_t v = fVideoTrackSupplier ? fVideoTrackSupplier->Duration() : 0;; 480 fDuration = max_c(a, v); 481 DurationChanged(); 482 // TODO: notify duration changed! 483 484 fAudioSupplier->SetSupplier(fAudioTrackSupplier, fVideoFrameRate); 485 486 _NotifyAudioTrackChanged(n); 487 return B_OK; 488 } 489 490 491 int 492 Controller::CurrentAudioTrack() 493 { 494 BAutolock _(this); 495 496 if (fAudioTrackSupplier == NULL) 497 return -1; 498 499 return fAudioTrackSupplier->TrackIndex(); 500 } 501 502 503 status_t 504 Controller::SelectVideoTrack(int n) 505 { 506 BAutolock _(this); 507 508 BMediaTrack* track = (BMediaTrack *)fVideoTrackList.ItemAt(n); 509 if (!track) 510 return B_ERROR; 511 512 status_t initStatus; 513 ObjectDeleter<VideoTrackSupplier> deleter(fVideoTrackSupplier); 514 fVideoTrackSupplier = new MediaTrackVideoSupplier(track, n, initStatus); 515 if (initStatus < B_OK) { 516 delete fVideoTrackSupplier; 517 fVideoTrackSupplier = NULL; 518 return initStatus; 519 } 520 521 bigtime_t a = fAudioTrackSupplier ? fAudioTrackSupplier->Duration() : 0; 522 bigtime_t v = fVideoTrackSupplier->Duration(); 523 fDuration = max_c(a, v); 524 fVideoFrameRate = fVideoTrackSupplier->Format().u.raw_video.field_rate; 525 if (fVideoFrameRate <= 0.0) { 526 printf("Controller::SelectVideoTrack(%d) - invalid video frame rate: %.1f\n", 527 n, fVideoFrameRate); 528 fVideoFrameRate = 25.0; 529 } 530 531 DurationChanged(); 532 // TODO: notify duration changed! 533 534 fVideoSupplier->SetSupplier(fVideoTrackSupplier); 535 536 _NotifyVideoTrackChanged(n); 537 return B_OK; 538 } 539 540 541 int 542 Controller::CurrentVideoTrack() 543 { 544 BAutolock _(this); 545 546 if (fVideoTrackSupplier == NULL) 547 return -1; 548 549 return fVideoTrackSupplier->TrackIndex(); 550 } 551 552 553 // #pragma mark - 554 555 556 void 557 Controller::Stop() 558 { 559 //printf("Controller::Stop\n"); 560 561 BAutolock _(this); 562 563 StopPlaying(); 564 SetPosition(0.0); 565 566 fAutoplay = fAutoplaySetting; 567 } 568 569 570 void 571 Controller::Play() 572 { 573 //printf("Controller::Play\n"); 574 575 BAutolock _(this); 576 577 StartPlaying(); 578 fAutoplay = true; 579 } 580 581 582 void 583 Controller::Pause() 584 { 585 // printf("Controller::Pause\n"); 586 587 BAutolock _(this); 588 589 PausePlaying(); 590 591 fAutoplay = fAutoplaySetting; 592 } 593 594 595 void 596 Controller::TogglePlaying() 597 { 598 // printf("Controller::TogglePlaying\n"); 599 600 BAutolock _(this); 601 602 if (InitCheck() == B_OK) { 603 NodeManager::TogglePlaying(); 604 605 fAutoplay = IsPlaying() || fAutoplaySetting; 606 } 607 } 608 609 610 uint32 611 Controller::PlaybackState() 612 { 613 BAutolock _(this); 614 615 return _PlaybackState(PlaybackManager::PlayMode()); 616 } 617 618 619 bigtime_t 620 Controller::TimeDuration() 621 { 622 BAutolock _(this); 623 624 return fDuration; 625 } 626 627 628 bigtime_t 629 Controller::TimePosition() 630 { 631 BAutolock _(this); 632 633 return fPosition; 634 } 635 636 637 void 638 Controller::SetVolume(float value) 639 { 640 // printf("Controller::SetVolume %.4f\n", value); 641 if (!Lock()) 642 return; 643 644 value = max_c(0.0, min_c(2.0, value)); 645 646 if (fVolume != value) { 647 if (fMuted) 648 ToggleMute(); 649 650 fVolume = value; 651 fAudioSupplier->SetVolume(fVolume); 652 653 _NotifyVolumeChanged(fVolume); 654 } 655 656 Unlock(); 657 } 658 659 void 660 Controller::VolumeUp() 661 { 662 // TODO: linear <-> exponential 663 SetVolume(Volume() + 0.05); 664 } 665 666 void 667 Controller::VolumeDown() 668 { 669 // TODO: linear <-> exponential 670 SetVolume(Volume() - 0.05); 671 } 672 673 void 674 Controller::ToggleMute() 675 { 676 if (!Lock()) 677 return; 678 679 fMuted = !fMuted; 680 681 if (fMuted) 682 fAudioSupplier->SetVolume(0.0); 683 else 684 fAudioSupplier->SetVolume(fVolume); 685 686 _NotifyMutedChanged(fMuted); 687 688 Unlock(); 689 } 690 691 692 float 693 Controller::Volume() 694 { 695 BAutolock _(this); 696 697 return fVolume; 698 } 699 700 701 void 702 Controller::SetPosition(float value) 703 { 704 BAutolock _(this); 705 706 SetFramePosition(Duration() * value); 707 } 708 709 710 void 711 Controller::SetFramePosition(int32 value) 712 { 713 BAutolock _(this); 714 715 int32 seekFrame = max_c(0, min_c(Duration(), value)); 716 int32 currentFrame = CurrentFrame(); 717 if (seekFrame != currentFrame) { 718 fSeekFrame = seekFrame; 719 fSeekRequested = true; 720 SetCurrentFrame(seekFrame); 721 } 722 } 723 724 725 void 726 Controller::SetTimePosition(bigtime_t value) 727 { 728 BAutolock _(this); 729 730 SetPosition((float)value / TimeDuration()); 731 } 732 733 734 // #pragma mark - 735 736 737 bool 738 Controller::HasFile() 739 { 740 // you need to hold the data lock 741 return fMediaFile != NULL; 742 } 743 744 745 status_t 746 Controller::GetFileFormatInfo(media_file_format* fileFormat) 747 { 748 // you need to hold the data lock 749 if (!fMediaFile) 750 return B_NO_INIT; 751 return fMediaFile->GetFileFormatInfo(fileFormat); 752 } 753 754 755 status_t 756 Controller::GetCopyright(BString* copyright) 757 { 758 // you need to hold the data lock 759 if (!fMediaFile) 760 return B_NO_INIT; 761 *copyright = fMediaFile->Copyright(); 762 return B_OK; 763 } 764 765 766 status_t 767 Controller::GetLocation(BString* location) 768 { 769 // you need to hold the data lock 770 if (fItem.Get() == NULL) 771 return B_NO_INIT; 772 *location = fItem->LocationURI(); 773 return B_OK; 774 } 775 776 777 status_t 778 Controller::GetName(BString* name) 779 { 780 // you need to hold the data lock 781 if (fItem.Get() == NULL) 782 return B_NO_INIT; 783 *name = fItem->Name(); 784 return B_OK; 785 } 786 787 788 status_t 789 Controller::GetEncodedVideoFormat(media_format* format) 790 { 791 // you need to hold the data lock 792 if (fVideoTrackSupplier) 793 return fVideoTrackSupplier->GetEncodedFormat(format); 794 return B_NO_INIT; 795 } 796 797 798 status_t 799 Controller::GetVideoCodecInfo(media_codec_info* info) 800 { 801 // you need to hold the data lock 802 if (fVideoTrackSupplier) 803 return fVideoTrackSupplier->GetCodecInfo(info); 804 return B_NO_INIT; 805 } 806 807 808 status_t 809 Controller::GetEncodedAudioFormat(media_format* format) 810 { 811 // you need to hold the data lock 812 if (fAudioTrackSupplier) 813 return fAudioTrackSupplier->GetEncodedFormat(format); 814 return B_NO_INIT; 815 } 816 817 818 status_t 819 Controller::GetAudioCodecInfo(media_codec_info* info) 820 { 821 // you need to hold the data lock 822 if (fAudioTrackSupplier) 823 return fAudioTrackSupplier->GetCodecInfo(info); 824 return B_NO_INIT; 825 } 826 827 828 // #pragma mark - 829 830 831 void 832 Controller::SetVideoView(VideoView *view) 833 { 834 BAutolock _(this); 835 836 fVideoView = view; 837 } 838 839 840 bool 841 Controller::IsOverlayActive() 842 { 843 if (fVideoView) 844 return fVideoView->IsOverlayActive(); 845 846 return false; 847 } 848 849 850 // #pragma mark - 851 852 853 bool 854 Controller::AddListener(Listener* listener) 855 { 856 BAutolock _(this); 857 858 if (listener && !fListeners.HasItem(listener)) 859 return fListeners.AddItem(listener); 860 return false; 861 } 862 863 864 void 865 Controller::RemoveListener(Listener* listener) 866 { 867 BAutolock _(this); 868 869 fListeners.RemoveItem(listener); 870 } 871 872 873 // #pragma mark - Private 874 875 876 void 877 Controller::_AdoptGlobalSettings() 878 { 879 mpSettings settings = Settings::CurrentSettings(); 880 // thread safe 881 882 fAutoplaySetting = settings.autostart; 883 // not yet used: 884 fLoopMovies = settings.loopMovie; 885 fLoopSounds = settings.loopSound; 886 fBackgroundMovieVolumeMode = settings.backgroundMovieVolumeMode; 887 } 888 889 890 uint32 891 Controller::_PlaybackState(int32 playingMode) const 892 { 893 uint32 state = 0; 894 switch (playingMode) { 895 case MODE_PLAYING_PAUSED_FORWARD: 896 case MODE_PLAYING_PAUSED_BACKWARD: 897 state = PLAYBACK_STATE_PAUSED; 898 break; 899 case MODE_PLAYING_FORWARD: 900 case MODE_PLAYING_BACKWARD: 901 state = PLAYBACK_STATE_PLAYING; 902 break; 903 904 default: 905 state = PLAYBACK_STATE_STOPPED; 906 break; 907 } 908 return state; 909 } 910 911 912 // #pragma mark - Notifications 913 914 915 void 916 Controller::_NotifyFileChanged(PlaylistItem* item, status_t result) const 917 { 918 BList listeners(fListeners); 919 int32 count = listeners.CountItems(); 920 for (int32 i = 0; i < count; i++) { 921 Listener* listener = (Listener*)listeners.ItemAtFast(i); 922 listener->FileChanged(item, result); 923 } 924 } 925 926 927 void 928 Controller::_NotifyFileFinished() const 929 { 930 BList listeners(fListeners); 931 int32 count = listeners.CountItems(); 932 for (int32 i = 0; i < count; i++) { 933 Listener* listener = (Listener*)listeners.ItemAtFast(i); 934 listener->FileFinished(); 935 } 936 } 937 938 939 void 940 Controller::_NotifyVideoTrackChanged(int32 index) const 941 { 942 BList listeners(fListeners); 943 int32 count = listeners.CountItems(); 944 for (int32 i = 0; i < count; i++) { 945 Listener* listener = (Listener*)listeners.ItemAtFast(i); 946 listener->VideoTrackChanged(index); 947 } 948 } 949 950 951 void 952 Controller::_NotifyAudioTrackChanged(int32 index) const 953 { 954 BList listeners(fListeners); 955 int32 count = listeners.CountItems(); 956 for (int32 i = 0; i < count; i++) { 957 Listener* listener = (Listener*)listeners.ItemAtFast(i); 958 listener->AudioTrackChanged(index); 959 } 960 } 961 962 963 void 964 Controller::_NotifyVideoStatsChanged() const 965 { 966 BList listeners(fListeners); 967 int32 count = listeners.CountItems(); 968 for (int32 i = 0; i < count; i++) { 969 Listener* listener = (Listener*)listeners.ItemAtFast(i); 970 listener->VideoStatsChanged(); 971 } 972 } 973 974 975 void 976 Controller::_NotifyAudioStatsChanged() const 977 { 978 BList listeners(fListeners); 979 int32 count = listeners.CountItems(); 980 for (int32 i = 0; i < count; i++) { 981 Listener* listener = (Listener*)listeners.ItemAtFast(i); 982 listener->AudioStatsChanged(); 983 } 984 } 985 986 987 void 988 Controller::_NotifyPlaybackStateChanged(uint32 state) const 989 { 990 BList listeners(fListeners); 991 int32 count = listeners.CountItems(); 992 for (int32 i = 0; i < count; i++) { 993 Listener* listener = (Listener*)listeners.ItemAtFast(i); 994 listener->PlaybackStateChanged(state); 995 } 996 } 997 998 999 void 1000 Controller::_NotifyPositionChanged(float position) const 1001 { 1002 BList listeners(fListeners); 1003 int32 count = listeners.CountItems(); 1004 for (int32 i = 0; i < count; i++) { 1005 Listener* listener = (Listener*)listeners.ItemAtFast(i); 1006 listener->PositionChanged(position); 1007 } 1008 } 1009 1010 1011 void 1012 Controller::_NotifyVolumeChanged(float volume) const 1013 { 1014 BList listeners(fListeners); 1015 int32 count = listeners.CountItems(); 1016 for (int32 i = 0; i < count; i++) { 1017 Listener* listener = (Listener*)listeners.ItemAtFast(i); 1018 listener->VolumeChanged(volume); 1019 } 1020 } 1021 1022 1023 void 1024 Controller::_NotifyMutedChanged(bool muted) const 1025 { 1026 BList listeners(fListeners); 1027 int32 count = listeners.CountItems(); 1028 for (int32 i = 0; i < count; i++) { 1029 Listener* listener = (Listener*)listeners.ItemAtFast(i); 1030 listener->MutedChanged(muted); 1031 } 1032 } 1033 1034 1035 void 1036 Controller::NotifyPlayModeChanged(int32 mode) const 1037 { 1038 uint32 state = _PlaybackState(mode); 1039 if (fVideoView) 1040 fVideoView->SetPlaying(state == PLAYBACK_STATE_PLAYING); 1041 _NotifyPlaybackStateChanged(state); 1042 } 1043 1044 1045 void 1046 Controller::NotifyLoopModeChanged(int32 mode) const 1047 { 1048 } 1049 1050 1051 void 1052 Controller::NotifyLoopingEnabledChanged(bool enabled) const 1053 { 1054 } 1055 1056 1057 void 1058 Controller::NotifyVideoBoundsChanged(BRect bounds) const 1059 { 1060 } 1061 1062 1063 void 1064 Controller::NotifyFPSChanged(float fps) const 1065 { 1066 } 1067 1068 1069 void 1070 Controller::NotifyCurrentFrameChanged(int32 frame) const 1071 { 1072 // check if we are still waiting to reach the seekframe, 1073 // don't pass the event on to the listeners in that case 1074 if (fSeekRequested && fSeekFrame != frame) 1075 return; 1076 1077 fSeekFrame = -1; 1078 fSeekRequested = false; 1079 1080 float position = 0.0; 1081 double duration = (double)fDuration * fVideoFrameRate / 1000000.0; 1082 if (duration > 0) 1083 position = (float)frame / duration; 1084 fPosition = (bigtime_t)(position * fDuration + 0.5); 1085 _NotifyPositionChanged(position); 1086 } 1087 1088 1089 void 1090 Controller::NotifySpeedChanged(float speed) const 1091 { 1092 } 1093 1094 1095 void 1096 Controller::NotifyFrameDropped() const 1097 { 1098 // printf("Controller::NotifyFrameDropped()\n"); 1099 } 1100 1101 1102 void 1103 Controller::NotifyStopFrameReached() const 1104 { 1105 // Currently, this means we reached the end of the current 1106 // file and should play the next file 1107 _NotifyFileFinished(); 1108 } 1109 1110 1111 void 1112 Controller::NotifySeekHandled() const 1113 { 1114 fSeekRequested = false; 1115 fSeekFrame = -1; 1116 } 1117 1118