2 * Controller.cpp - Media Player for the Haiku Operating System
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)
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.
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.
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.
24 #include "Controller.h"
34 #include <Window.h> // for debugging only
36 #include "AutoDeleter.h"
37 #include "ControllerView.h"
39 #include "PlaybackState.h"
41 #include "VideoView.h"
44 #include "AudioTrackSupplier.h"
45 #include "MediaTrackAudioSupplier.h"
46 #include "MediaTrackVideoSupplier.h"
47 #include "ProxyAudioSupplier.h"
48 #include "ProxyVideoSupplier.h"
49 #include "SubTitles.h"
50 #include "TrackSupplier.h"
51 #include "VideoTrackSupplier.h"
56 class TrackSupplierReleaser
{
58 TrackSupplierReleaser(PlaylistItemRef
& owner
)
64 virtual ~TrackSupplierReleaser()
67 fOwner
.Get()->ReleaseTrackSupplier();
76 PlaylistItemRef
& fOwner
;
82 HandleError(const char *text
, status_t err
)
85 printf("%s. error 0x%08x (%s)\n",text
, (int)err
, strerror(err
));
92 // #pragma mark - Controller::Listener
95 Controller::Listener::Listener() {}
96 Controller::Listener::~Listener() {}
97 void Controller::Listener::FileFinished() {}
98 void Controller::Listener::FileChanged(PlaylistItem
* item
, status_t result
) {}
99 void Controller::Listener::VideoTrackChanged(int32
) {}
100 void Controller::Listener::AudioTrackChanged(int32
) {}
101 void Controller::Listener::SubTitleTrackChanged(int32
) {}
102 void Controller::Listener::VideoStatsChanged() {}
103 void Controller::Listener::AudioStatsChanged() {}
104 void Controller::Listener::PlaybackStateChanged(uint32
) {}
105 void Controller::Listener::PositionChanged(float) {}
106 void Controller::Listener::SeekHandled(int64 seekFrame
) {}
107 void Controller::Listener::VolumeChanged(float) {}
108 void Controller::Listener::MutedChanged(bool) {}
111 // #pragma mark - Controller
119 Controller::Controller()
129 fVideoSupplier(new ProxyVideoSupplier()),
130 fAudioSupplier(new ProxyAudioSupplier(this)),
131 fVideoTrackSupplier(NULL
),
132 fAudioTrackSupplier(NULL
),
138 fVideoFrameRate(25.0),
140 fPendingSeekRequests(0),
142 fRequestedSeekFrame(-1),
144 fGlobalSettingsListener(this),
148 Settings::Default()->AddListener(&fGlobalSettingsListener
);
149 _AdoptGlobalSettings();
151 fAutoplay
= fAutoplaySetting
;
155 Controller::~Controller()
157 Settings::Default()->RemoveListener(&fGlobalSettingsListener
);
162 // #pragma mark - NodeManager interface
166 Controller::MessageReceived(BMessage
* message
)
168 switch (message
->what
) {
169 case MSG_OBJECT_CHANGED
:
170 // received from fGlobalSettingsListener
171 // TODO: find out which object, if we ever watch more than
172 // the global settings instance...
173 _AdoptGlobalSettings();
179 if (message
->FindPointer("item", (void**)&item
) == B_OK
) {
180 PlaylistItemRef
itemRef(item
, true);
181 // The reference was passed with the message.
184 _NotifyFileChanged(NULL
, B_BAD_VALUE
);
190 NodeManager::MessageReceived(message
);
196 Controller::Duration()
198 return _FrameDuration();
203 Controller::CreateVideoTarget()
210 Controller::CreateVideoSupplier()
212 return fVideoSupplier
;
217 Controller::CreateAudioSupplier()
219 return fAudioSupplier
;
227 Controller::SetToAsync(const PlaylistItemRef
& item
)
229 PlaylistItemRef
additionalReference(item
);
231 BMessage
message(MSG_SET_TO
);
232 status_t ret
= message
.AddPointer("item", item
.Get());
236 ret
= PostMessage(&message
);
240 // The additional reference is now passed along with the message...
241 additionalReference
.Detach();
248 Controller::SetTo(const PlaylistItemRef
& item
)
253 if (InitCheck() == B_OK
) {
262 fAudioSupplier
->SetSupplier(NULL
, fVideoFrameRate
);
263 fVideoSupplier
->SetSupplier(NULL
);
266 TrackSupplierReleaser
oldSupplierReleaser(fItem
);
270 // Do not delete the supplier chain until after we called
271 // NodeManager::Init() to setup a new media node chain
272 ObjectDeleter
<VideoTrackSupplier
> videoSupplierDeleter(
273 fVideoTrackSupplier
);
274 ObjectDeleter
<AudioTrackSupplier
> audioSupplierDeleter(
275 fAudioTrackSupplier
);
277 fVideoTrackSupplier
= NULL
;
278 fAudioTrackSupplier
= NULL
;
280 fSubTitlesIndex
= -1;
284 fVideoFrameRate
= 25.0;
286 fPendingSeekRequests
= 0;
288 fRequestedSeekFrame
= -1;
290 if (fItem
.Get() == NULL
)
293 TrackSupplier
* trackSupplier
= fItem
->GetTrackSupplier();
294 if (trackSupplier
== NULL
) {
295 _NotifyFileChanged(item
.Get(), B_NO_MEMORY
);
298 TrackSupplierReleaser
trackSupplierReleaser(fItem
);
300 status_t err
= trackSupplier
->InitCheck();
302 printf("Controller::SetTo: InitCheck failed\n");
303 _NotifyFileChanged(item
.Get(), err
);
307 if (trackSupplier
->CountAudioTracks() == 0
308 && trackSupplier
->CountVideoTracks() == 0) {
309 _NotifyFileChanged(item
.Get(), B_MEDIA_NO_HANDLER
);
310 return B_MEDIA_NO_HANDLER
;
316 if (fAudioTrackSupplier
== NULL
&& fVideoTrackSupplier
== NULL
) {
317 printf("Controller::SetTo: no audio or video tracks found or "
319 _NotifyFileChanged(item
.Get(), B_MEDIA_NO_HANDLER
);
320 return B_MEDIA_NO_HANDLER
;
323 trackSupplierReleaser
.Detach();
325 // prevent blocking the creation of new overlay buffers
327 fVideoView
->DisableOverlay();
329 // get video properties (if there is video at all)
330 bool useOverlays
= fVideoView
? fVideoView
->UseOverlays() : true;
334 GetSize(&width
, &height
);
335 color_space preferredVideoFormat
= B_NO_COLOR_SPACE
;
336 if (fVideoTrackSupplier
!= NULL
) {
337 const media_format
& format
= fVideoTrackSupplier
->Format();
338 preferredVideoFormat
= format
.u
.raw_video
.display
.format
;
342 if (!fVideoTrackSupplier
)
343 enabledNodes
= AUDIO_ONLY
;
344 else if (!fAudioTrackSupplier
)
345 enabledNodes
= VIDEO_ONLY
;
347 enabledNodes
= AUDIO_AND_VIDEO
;
349 float audioFrameRate
= 44100.0f
;
350 uint32 audioChannels
= 2;
351 if (fAudioTrackSupplier
!= NULL
) {
352 const media_format
& audioTrackFormat
= fAudioTrackSupplier
->Format();
353 audioFrameRate
= audioTrackFormat
.u
.raw_audio
.frame_rate
;
354 audioChannels
= audioTrackFormat
.u
.raw_audio
.channel_count
;
357 if (InitCheck() != B_OK
) {
358 Init(BRect(0, 0, width
- 1, height
- 1), fVideoFrameRate
,
359 preferredVideoFormat
, audioFrameRate
, audioChannels
, LOOPING_ALL
,
360 false, 1.0, enabledNodes
, useOverlays
);
362 FormatChanged(BRect(0, 0, width
- 1, height
- 1), fVideoFrameRate
,
363 preferredVideoFormat
, audioFrameRate
, audioChannels
, enabledNodes
,
367 _NotifyFileChanged(item
.Get(), B_OK
);
377 Controller::PlayerActivated(bool active
)
379 if (LockWithTimeout(5000) != B_OK
)
382 if (active
&& gMainApp
->PlayerCount() > 1) {
383 if (fActiveVolume
!= fVolume
)
384 SetVolume(fActiveVolume
);
386 fActiveVolume
= fVolume
;
387 if (gMainApp
->PlayerCount() > 1)
388 switch (fBackgroundMovieVolumeMode
) {
389 case mpSettings::BG_MOVIES_MUTED
:
392 case mpSettings::BG_MOVIES_HALF_VLUME
:
393 SetVolume(fVolume
* 0.25);
395 case mpSettings::BG_MOVIES_FULL_VOLUME
:
406 Controller::GetSize(int *width
, int *height
, int* _widthAspect
,
411 if (fVideoTrackSupplier
) {
412 media_format format
= fVideoTrackSupplier
->Format();
413 *height
= format
.u
.raw_video
.display
.line_count
;
414 *width
= format
.u
.raw_video
.display
.line_width
;
416 int heightAspect
= 0;
417 // Ignore format aspect when both values are 1. If they have been
418 // intentionally at 1:1 then no harm is done for quadratic videos,
419 // only if the video is indeed encoded anamorphotic, but supposed
420 // to be displayed quadratic... extremely unlikely.
421 if (format
.u
.raw_video
.pixel_width_aspect
422 != format
.u
.raw_video
.pixel_height_aspect
423 && format
.u
.raw_video
.pixel_width_aspect
!= 1) {
424 widthAspect
= format
.u
.raw_video
.pixel_width_aspect
;
425 heightAspect
= format
.u
.raw_video
.pixel_height_aspect
;
427 if (_widthAspect
!= NULL
)
428 *_widthAspect
= widthAspect
;
429 if (_heightAspect
!= NULL
)
430 *_heightAspect
= heightAspect
;
434 if (_widthAspect
!= NULL
)
436 if (_heightAspect
!= NULL
)
443 Controller::AudioTrackCount()
447 if (fItem
!= NULL
&& fItem
->HasTrackSupplier())
448 return fItem
->GetTrackSupplier()->CountAudioTracks();
454 Controller::VideoTrackCount()
458 if (fItem
!= NULL
&& fItem
->HasTrackSupplier())
459 return fItem
->GetTrackSupplier()->CountVideoTracks();
465 Controller::SubTitleTrackCount()
469 if (fItem
!= NULL
&& fItem
->HasTrackSupplier())
470 return fItem
->GetTrackSupplier()->CountSubTitleTracks();
476 Controller::SelectAudioTrack(int n
)
479 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
482 ObjectDeleter
<AudioTrackSupplier
> deleter(fAudioTrackSupplier
);
484 = fItem
->GetTrackSupplier()->CreateAudioTrackForIndex(n
);
485 if (fAudioTrackSupplier
== NULL
)
488 bigtime_t a
= fAudioTrackSupplier
->Duration();
489 bigtime_t v
= fVideoTrackSupplier
!= NULL
490 ? fVideoTrackSupplier
->Duration() : 0;
491 fDuration
= max_c(a
, v
);
493 // TODO: notify duration changed!
495 fAudioSupplier
->SetSupplier(fAudioTrackSupplier
, fVideoFrameRate
);
497 _NotifyAudioTrackChanged(n
);
503 Controller::CurrentAudioTrack()
507 if (fAudioTrackSupplier
== NULL
)
510 return fAudioTrackSupplier
->TrackIndex();
515 Controller::AudioTrackChannelCount()
518 if (GetEncodedAudioFormat(&format
) == B_OK
)
519 return format
.u
.encoded_audio
.output
.channel_count
;
526 Controller::SelectVideoTrack(int n
)
530 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
533 ObjectDeleter
<VideoTrackSupplier
> deleter(fVideoTrackSupplier
);
535 = fItem
->GetTrackSupplier()->CreateVideoTrackForIndex(n
);
536 if (fVideoTrackSupplier
== NULL
)
539 bigtime_t a
= fAudioTrackSupplier
? fAudioTrackSupplier
->Duration() : 0;
540 bigtime_t v
= fVideoTrackSupplier
->Duration();
541 fDuration
= max_c(a
, v
);
542 fVideoFrameRate
= fVideoTrackSupplier
->Format().u
.raw_video
.field_rate
;
543 if (fVideoFrameRate
<= 0.0) {
544 printf("Controller::SelectVideoTrack(%d) - invalid video frame rate: %.1f\n",
546 fVideoFrameRate
= 25.0;
550 // TODO: notify duration changed!
552 fVideoSupplier
->SetSupplier(fVideoTrackSupplier
);
554 _NotifyVideoTrackChanged(n
);
560 Controller::CurrentVideoTrack()
564 if (fVideoTrackSupplier
== NULL
)
567 return fVideoTrackSupplier
->TrackIndex();
572 Controller::SelectSubTitleTrack(int n
)
576 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
581 fItem
->GetTrackSupplier()->SubTitleTrackForIndex(n
);
583 const SubTitle
* subTitle
= NULL
;
584 if (fSubTitles
!= NULL
)
585 subTitle
= fSubTitles
->SubTitleAt(_TimePosition());
586 if (subTitle
!= NULL
)
587 fVideoView
->SetSubTitle(subTitle
->text
.String());
589 fVideoView
->SetSubTitle(NULL
);
591 _NotifySubTitleTrackChanged(n
);
597 Controller::CurrentSubTitleTrack()
601 if (fSubTitles
== NULL
)
604 return fSubTitlesIndex
;
609 Controller::SubTitleTrackName(int n
)
613 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
616 const SubTitles
* subTitles
617 = fItem
->GetTrackSupplier()->SubTitleTrackForIndex(n
);
618 if (subTitles
== NULL
)
621 return subTitles
->Name();
631 //printf("Controller::Stop\n");
638 fAutoplay
= fAutoplaySetting
;
645 //printf("Controller::Play\n");
657 // printf("Controller::Pause\n");
663 fAutoplay
= fAutoplaySetting
;
668 Controller::TogglePlaying()
670 // printf("Controller::TogglePlaying\n");
674 if (InitCheck() == B_OK
) {
675 NodeManager::TogglePlaying();
677 fAutoplay
= IsPlaying() || fAutoplaySetting
;
683 Controller::PlaybackState()
687 return _PlaybackState(PlaybackManager::PlayMode());
692 Controller::TimeDuration()
701 Controller::TimePosition()
705 return _TimePosition();
710 Controller::SetVolume(float value
)
712 // printf("Controller::SetVolume %.4f\n", value);
715 value
= max_c(0.0, min_c(2.0, value
));
717 if (fVolume
!= value
) {
722 fAudioSupplier
->SetVolume(fVolume
);
724 _NotifyVolumeChanged(fVolume
);
729 Controller::VolumeUp()
731 // TODO: linear <-> exponential
732 SetVolume(Volume() + 0.05);
736 Controller::VolumeDown()
738 // TODO: linear <-> exponential
739 SetVolume(Volume() - 0.05);
743 Controller::ToggleMute()
750 fAudioSupplier
->SetVolume(0.0);
752 fAudioSupplier
->SetVolume(fVolume
);
754 _NotifyMutedChanged(fMuted
);
768 Controller::SetPosition(float value
)
772 return SetFramePosition(_FrameDuration() * value
);
777 Controller::SetFramePosition(int64 value
)
781 fPendingSeekRequests
++;
782 fRequestedSeekFrame
= max_c(0, min_c(_FrameDuration(), value
));
783 fSeekFrame
= fRequestedSeekFrame
;
785 int64 currentFrame
= CurrentFrame();
787 // Snap to a video keyframe, since that will be the fastest
788 // to display and seeking will feel more snappy. Note that we
789 // don't store this change in fSeekFrame, since we still want
790 // to report the originally requested seek frame in TimePosition()
791 // until we could reach that frame.
792 if (Duration() > 240 && fVideoTrackSupplier
!= NULL
793 && abs(value
- currentFrame
) > 5) {
794 fVideoTrackSupplier
->FindKeyFrameForFrame(&fSeekFrame
);
797 //printf("SetFramePosition(%lld) -> %lld (current: %lld, duration: %lld) "
798 //"(video: %p)\n", value, fSeekFrame, currentFrame, _FrameDuration(),
799 //fVideoTrackSupplier);
800 if (fSeekFrame
!= currentFrame
) {
801 int64 seekFrame
= fSeekFrame
;
802 SetCurrentFrame(fSeekFrame
);
803 // May trigger the notification and reset fSeekFrame,
804 // if next current frame == seek frame.
807 NotifySeekHandled(fRequestedSeekFrame
);
813 Controller::SetTimePosition(bigtime_t value
)
817 return SetPosition((float)value
/ TimeDuration());
825 Controller::HasFile()
827 // you need to hold the data lock
828 return fItem
!= NULL
&& fItem
->HasTrackSupplier();
833 Controller::GetFileFormatInfo(media_file_format
* fileFormat
)
835 // you need to hold the data lock
836 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
838 return fItem
->GetTrackSupplier()->GetFileFormatInfo(fileFormat
);
843 Controller::GetCopyright(BString
* copyright
)
845 // you need to hold the data lock
846 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
848 return fItem
->GetTrackSupplier()->GetCopyright(copyright
);
853 Controller::GetLocation(BString
* location
)
855 // you need to hold the data lock
856 if (fItem
.Get() == NULL
)
858 *location
= fItem
->LocationURI();
864 Controller::GetName(BString
* name
)
866 // you need to hold the data lock
867 if (fItem
.Get() == NULL
)
869 *name
= fItem
->Name();
875 Controller::GetEncodedVideoFormat(media_format
* format
)
877 // you need to hold the data lock
878 if (fVideoTrackSupplier
)
879 return fVideoTrackSupplier
->GetEncodedFormat(format
);
885 Controller::GetVideoCodecInfo(media_codec_info
* info
)
887 // you need to hold the data lock
888 if (fVideoTrackSupplier
)
889 return fVideoTrackSupplier
->GetCodecInfo(info
);
895 Controller::GetEncodedAudioFormat(media_format
* format
)
897 // you need to hold the data lock
898 if (fAudioTrackSupplier
)
899 return fAudioTrackSupplier
->GetEncodedFormat(format
);
905 Controller::GetAudioCodecInfo(media_codec_info
* info
)
907 // you need to hold the data lock
908 if (fAudioTrackSupplier
)
909 return fAudioTrackSupplier
->GetCodecInfo(info
);
915 Controller::GetMetaData(BMessage
* metaData
)
917 // you need to hold the data lock
918 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
920 return fItem
->GetTrackSupplier()->GetMetaData(metaData
);
925 Controller::GetVideoMetaData(int32 index
, BMessage
* metaData
)
927 // you need to hold the data lock
928 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
930 return fItem
->GetTrackSupplier()->GetVideoMetaData(index
, metaData
);
935 Controller::GetAudioMetaData(int32 index
, BMessage
* metaData
)
937 // you need to hold the data lock
938 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
940 return fItem
->GetTrackSupplier()->GetAudioMetaData(index
, metaData
);
948 Controller::SetVideoView(VideoView
*view
)
957 Controller::IsOverlayActive()
960 return fVideoView
->IsOverlayActive();
970 Controller::AddListener(Listener
* listener
)
974 if (listener
&& !fListeners
.HasItem(listener
))
975 return fListeners
.AddItem(listener
);
981 Controller::RemoveListener(Listener
* listener
)
985 fListeners
.RemoveItem(listener
);
989 // #pragma mark - Private
993 Controller::_AdoptGlobalSettings()
996 Settings::Default()->Get(settings
);
998 fAutoplaySetting
= settings
.autostart
;
1000 fLoopMovies
= settings
.loopMovie
;
1001 fLoopSounds
= settings
.loopSound
;
1002 fBackgroundMovieVolumeMode
= settings
.backgroundMovieVolumeMode
;
1007 Controller::_PlaybackState(int32 playingMode
) const
1010 switch (playingMode
) {
1011 case MODE_PLAYING_PAUSED_FORWARD
:
1012 case MODE_PLAYING_PAUSED_BACKWARD
:
1013 state
= PLAYBACK_STATE_PAUSED
;
1015 case MODE_PLAYING_FORWARD
:
1016 case MODE_PLAYING_BACKWARD
:
1017 state
= PLAYBACK_STATE_PLAYING
;
1021 state
= PLAYBACK_STATE_STOPPED
;
1029 Controller::_TimePosition() const
1034 // Check if we are still waiting to reach the seekframe,
1035 // pass the last pending seek frame back to the caller, so
1036 // that the view of the current frame/time from the outside
1037 // does not depend on the internal latency to reach requested
1038 // frames asynchronously.
1040 if (fPendingSeekRequests
> 0)
1041 frame
= fRequestedSeekFrame
;
1043 frame
= fCurrentFrame
;
1045 return frame
* fDuration
/ _FrameDuration();
1050 Controller::_FrameDuration() const
1052 // This should really be total frames (video frames at that)
1053 // TODO: It is not so nice that the MediaPlayer still measures
1054 // in video frames if only playing audio. Here for example, it will
1055 // return a duration of 0 if the audio clip happens to be shorter than
1056 // one video frame at 25 fps.
1057 return (int64
)((double)fDuration
* fVideoFrameRate
/ 1000000.0);
1061 // #pragma mark - Notifications
1065 Controller::_NotifyFileChanged(PlaylistItem
* item
, status_t result
) const
1067 BList
listeners(fListeners
);
1068 int32 count
= listeners
.CountItems();
1069 for (int32 i
= 0; i
< count
; i
++) {
1070 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1071 listener
->FileChanged(item
, result
);
1077 Controller::_NotifyFileFinished() const
1079 BList
listeners(fListeners
);
1080 int32 count
= listeners
.CountItems();
1081 for (int32 i
= 0; i
< count
; i
++) {
1082 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1083 listener
->FileFinished();
1089 Controller::_NotifyVideoTrackChanged(int32 index
) const
1091 BList
listeners(fListeners
);
1092 int32 count
= listeners
.CountItems();
1093 for (int32 i
= 0; i
< count
; i
++) {
1094 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1095 listener
->VideoTrackChanged(index
);
1101 Controller::_NotifyAudioTrackChanged(int32 index
) const
1103 BList
listeners(fListeners
);
1104 int32 count
= listeners
.CountItems();
1105 for (int32 i
= 0; i
< count
; i
++) {
1106 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1107 listener
->AudioTrackChanged(index
);
1113 Controller::_NotifySubTitleTrackChanged(int32 index
) const
1115 BList
listeners(fListeners
);
1116 int32 count
= listeners
.CountItems();
1117 for (int32 i
= 0; i
< count
; i
++) {
1118 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1119 listener
->SubTitleTrackChanged(index
);
1125 Controller::_NotifyVideoStatsChanged() const
1127 BList
listeners(fListeners
);
1128 int32 count
= listeners
.CountItems();
1129 for (int32 i
= 0; i
< count
; i
++) {
1130 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1131 listener
->VideoStatsChanged();
1137 Controller::_NotifyAudioStatsChanged() const
1139 BList
listeners(fListeners
);
1140 int32 count
= listeners
.CountItems();
1141 for (int32 i
= 0; i
< count
; i
++) {
1142 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1143 listener
->AudioStatsChanged();
1149 Controller::_NotifyPlaybackStateChanged(uint32 state
) const
1151 BList
listeners(fListeners
);
1152 int32 count
= listeners
.CountItems();
1153 for (int32 i
= 0; i
< count
; i
++) {
1154 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1155 listener
->PlaybackStateChanged(state
);
1161 Controller::_NotifyPositionChanged(float position
) const
1163 BList
listeners(fListeners
);
1164 int32 count
= listeners
.CountItems();
1165 for (int32 i
= 0; i
< count
; i
++) {
1166 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1167 listener
->PositionChanged(position
);
1173 Controller::_NotifySeekHandled(int64 seekFrame
) const
1175 BList
listeners(fListeners
);
1176 int32 count
= listeners
.CountItems();
1177 for (int32 i
= 0; i
< count
; i
++) {
1178 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1179 listener
->SeekHandled(seekFrame
);
1185 Controller::_NotifyVolumeChanged(float volume
) const
1187 BList
listeners(fListeners
);
1188 int32 count
= listeners
.CountItems();
1189 for (int32 i
= 0; i
< count
; i
++) {
1190 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1191 listener
->VolumeChanged(volume
);
1197 Controller::_NotifyMutedChanged(bool muted
) const
1199 BList
listeners(fListeners
);
1200 int32 count
= listeners
.CountItems();
1201 for (int32 i
= 0; i
< count
; i
++) {
1202 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1203 listener
->MutedChanged(muted
);
1209 Controller::NotifyPlayModeChanged(int32 mode
) const
1211 uint32 state
= _PlaybackState(mode
);
1213 fVideoView
->SetPlaying(state
== PLAYBACK_STATE_PLAYING
);
1214 _NotifyPlaybackStateChanged(state
);
1219 Controller::NotifyLoopModeChanged(int32 mode
) const
1225 Controller::NotifyLoopingEnabledChanged(bool enabled
) const
1231 Controller::NotifyVideoBoundsChanged(BRect bounds
) const
1237 Controller::NotifyFPSChanged(float fps
) const
1243 Controller::NotifyCurrentFrameChanged(int64 frame
) const
1245 fCurrentFrame
= frame
;
1246 bigtime_t timePosition
= _TimePosition();
1247 _NotifyPositionChanged((float)timePosition
/ fDuration
);
1249 if (fSubTitles
!= NULL
) {
1250 const SubTitle
* subTitle
= fSubTitles
->SubTitleAt(timePosition
);
1251 if (subTitle
!= NULL
)
1252 fVideoView
->SetSubTitle(subTitle
->text
.String());
1254 fVideoView
->SetSubTitle(NULL
);
1260 Controller::NotifySpeedChanged(float speed
) const
1266 Controller::NotifyFrameDropped() const
1268 // printf("Controller::NotifyFrameDropped()\n");
1273 Controller::NotifyStopFrameReached() const
1275 // Currently, this means we reached the end of the current
1276 // file and should play the next file
1277 _NotifyFileFinished();
1282 Controller::NotifySeekHandled(int64 seekedFrame
) const
1284 if (fPendingSeekRequests
== 0)
1287 fPendingSeekRequests
--;
1288 if (fPendingSeekRequests
== 0) {
1290 fRequestedSeekFrame
= -1;
1293 _NotifySeekHandled(seekedFrame
);