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