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>
6 * Copyright (C) 2007-2009 Fredrik Modéen <[FirstName]@[LastName].se>
8 * Released under the terms of the MIT license.
12 #include "Controller.h"
22 #include <Window.h> // for debugging only
24 #include "AutoDeleter.h"
25 #include "ControllerView.h"
27 #include "PlaybackState.h"
29 #include "VideoView.h"
32 #include "AudioTrackSupplier.h"
33 #include "MediaTrackAudioSupplier.h"
34 #include "MediaTrackVideoSupplier.h"
35 #include "ProxyAudioSupplier.h"
36 #include "ProxyVideoSupplier.h"
37 #include "SubTitles.h"
38 #include "TrackSupplier.h"
39 #include "VideoTrackSupplier.h"
44 class TrackSupplierReleaser
{
46 TrackSupplierReleaser(PlaylistItemRef
& owner
)
52 virtual ~TrackSupplierReleaser()
55 fOwner
.Get()->ReleaseTrackSupplier();
64 PlaylistItemRef
& fOwner
;
70 HandleError(const char *text
, status_t err
)
73 printf("%s. error 0x%08x (%s)\n",text
, (int)err
, strerror(err
));
80 // #pragma mark - Controller::Listener
83 Controller::Listener::Listener() {}
84 Controller::Listener::~Listener() {}
85 void Controller::Listener::FileFinished() {}
86 void Controller::Listener::FileChanged(PlaylistItem
* item
, status_t result
) {}
87 void Controller::Listener::VideoTrackChanged(int32
) {}
88 void Controller::Listener::AudioTrackChanged(int32
) {}
89 void Controller::Listener::SubTitleTrackChanged(int32
) {}
90 void Controller::Listener::VideoStatsChanged() {}
91 void Controller::Listener::AudioStatsChanged() {}
92 void Controller::Listener::PlaybackStateChanged(uint32
) {}
93 void Controller::Listener::PositionChanged(float) {}
94 void Controller::Listener::SeekHandled(int64 seekFrame
) {}
95 void Controller::Listener::VolumeChanged(float) {}
96 void Controller::Listener::MutedChanged(bool) {}
99 // #pragma mark - Controller
107 Controller::Controller()
117 fVideoSupplier(new ProxyVideoSupplier()),
118 fAudioSupplier(new ProxyAudioSupplier(this)),
119 fVideoTrackSupplier(NULL
),
120 fAudioTrackSupplier(NULL
),
126 fVideoFrameRate(25.0),
128 fPendingSeekRequests(0),
130 fRequestedSeekFrame(-1),
132 fGlobalSettingsListener(this),
136 Settings::Default()->AddListener(&fGlobalSettingsListener
);
137 _AdoptGlobalSettings();
139 fAutoplay
= fAutoplaySetting
;
143 Controller::~Controller()
145 Settings::Default()->RemoveListener(&fGlobalSettingsListener
);
150 // #pragma mark - NodeManager interface
154 Controller::MessageReceived(BMessage
* message
)
156 switch (message
->what
) {
157 case MSG_OBJECT_CHANGED
:
158 // received from fGlobalSettingsListener
159 // TODO: find out which object, if we ever watch more than
160 // the global settings instance...
161 _AdoptGlobalSettings();
167 if (message
->FindPointer("item", (void**)&item
) == B_OK
) {
168 PlaylistItemRef
itemRef(item
, true);
169 // The reference was passed with the message.
172 _NotifyFileChanged(NULL
, B_BAD_VALUE
);
178 NodeManager::MessageReceived(message
);
184 Controller::Duration()
186 return _FrameDuration();
191 Controller::CreateVideoTarget()
198 Controller::CreateVideoSupplier()
200 return fVideoSupplier
;
205 Controller::CreateAudioSupplier()
207 return fAudioSupplier
;
215 Controller::SetToAsync(const PlaylistItemRef
& item
)
217 PlaylistItemRef
additionalReference(item
);
219 BMessage
message(MSG_SET_TO
);
220 status_t ret
= message
.AddPointer("item", item
.Get());
224 ret
= PostMessage(&message
);
228 // The additional reference is now passed along with the message...
229 additionalReference
.Detach();
236 Controller::SetTo(const PlaylistItemRef
& item
)
241 if (InitCheck() == B_OK
) {
250 fAudioSupplier
->SetSupplier(NULL
, fVideoFrameRate
);
251 fVideoSupplier
->SetSupplier(NULL
);
254 TrackSupplierReleaser
oldSupplierReleaser(fItem
);
258 // Do not delete the supplier chain until after we called
259 // NodeManager::Init() to setup a new media node chain
260 ObjectDeleter
<VideoTrackSupplier
> videoSupplierDeleter(
261 fVideoTrackSupplier
);
262 ObjectDeleter
<AudioTrackSupplier
> audioSupplierDeleter(
263 fAudioTrackSupplier
);
265 fVideoTrackSupplier
= NULL
;
266 fAudioTrackSupplier
= NULL
;
268 fSubTitlesIndex
= -1;
272 fVideoFrameRate
= 25.0;
274 fPendingSeekRequests
= 0;
276 fRequestedSeekFrame
= -1;
278 if (fItem
.Get() == NULL
)
281 TrackSupplier
* trackSupplier
= fItem
->GetTrackSupplier();
282 if (trackSupplier
== NULL
) {
283 _NotifyFileChanged(item
.Get(), B_NO_MEMORY
);
286 TrackSupplierReleaser
trackSupplierReleaser(fItem
);
288 status_t err
= trackSupplier
->InitCheck();
290 printf("Controller::SetTo: InitCheck failed\n");
291 _NotifyFileChanged(item
.Get(), err
);
295 if (trackSupplier
->CountAudioTracks() == 0
296 && trackSupplier
->CountVideoTracks() == 0) {
297 _NotifyFileChanged(item
.Get(), B_MEDIA_NO_HANDLER
);
298 return B_MEDIA_NO_HANDLER
;
304 if (fAudioTrackSupplier
== NULL
&& fVideoTrackSupplier
== NULL
) {
305 printf("Controller::SetTo: no audio or video tracks found or "
307 _NotifyFileChanged(item
.Get(), B_MEDIA_NO_HANDLER
);
308 return B_MEDIA_NO_HANDLER
;
311 trackSupplierReleaser
.Detach();
313 // prevent blocking the creation of new overlay buffers
315 fVideoView
->DisableOverlay();
317 // get video properties (if there is video at all)
318 bool useOverlays
= fVideoView
? fVideoView
->UseOverlays() : true;
322 GetSize(&width
, &height
);
323 color_space preferredVideoFormat
= B_NO_COLOR_SPACE
;
324 if (fVideoTrackSupplier
!= NULL
) {
325 const media_format
& format
= fVideoTrackSupplier
->Format();
326 preferredVideoFormat
= format
.u
.raw_video
.display
.format
;
330 if (!fVideoTrackSupplier
)
331 enabledNodes
= AUDIO_ONLY
;
332 else if (!fAudioTrackSupplier
)
333 enabledNodes
= VIDEO_ONLY
;
335 enabledNodes
= AUDIO_AND_VIDEO
;
337 float audioFrameRate
= 44100.0f
;
338 uint32 audioChannels
= 2;
339 if (fAudioTrackSupplier
!= NULL
) {
340 const media_format
& audioTrackFormat
= fAudioTrackSupplier
->Format();
341 audioFrameRate
= audioTrackFormat
.u
.raw_audio
.frame_rate
;
342 audioChannels
= audioTrackFormat
.u
.raw_audio
.channel_count
;
345 if (InitCheck() != B_OK
) {
346 Init(BRect(0, 0, width
- 1, height
- 1), fVideoFrameRate
,
347 preferredVideoFormat
, audioFrameRate
, audioChannels
, LOOPING_ALL
,
348 false, 1.0, enabledNodes
, useOverlays
);
350 FormatChanged(BRect(0, 0, width
- 1, height
- 1), fVideoFrameRate
,
351 preferredVideoFormat
, audioFrameRate
, audioChannels
, enabledNodes
,
355 _NotifyFileChanged(item
.Get(), B_OK
);
365 Controller::PlayerActivated(bool active
)
367 if (LockWithTimeout(5000) != B_OK
)
370 if (active
&& gMainApp
->PlayerCount() > 1) {
371 if (fActiveVolume
!= fVolume
)
372 SetVolume(fActiveVolume
);
374 fActiveVolume
= fVolume
;
375 if (gMainApp
->PlayerCount() > 1)
376 switch (fBackgroundMovieVolumeMode
) {
377 case mpSettings::BG_MOVIES_MUTED
:
380 case mpSettings::BG_MOVIES_HALF_VLUME
:
381 SetVolume(fVolume
* 0.25);
383 case mpSettings::BG_MOVIES_FULL_VOLUME
:
394 Controller::GetSize(int *width
, int *height
, int* _widthAspect
,
399 if (fVideoTrackSupplier
) {
400 media_format format
= fVideoTrackSupplier
->Format();
401 *height
= format
.u
.raw_video
.display
.line_count
;
402 *width
= format
.u
.raw_video
.display
.line_width
;
404 int heightAspect
= 0;
405 // Ignore format aspect when both values are 1. If they have been
406 // intentionally at 1:1 then no harm is done for quadratic videos,
407 // only if the video is indeed encoded anamorphotic, but supposed
408 // to be displayed quadratic... extremely unlikely.
409 if (format
.u
.raw_video
.pixel_width_aspect
410 != format
.u
.raw_video
.pixel_height_aspect
411 && format
.u
.raw_video
.pixel_width_aspect
!= 1) {
412 widthAspect
= format
.u
.raw_video
.pixel_width_aspect
;
413 heightAspect
= format
.u
.raw_video
.pixel_height_aspect
;
415 if (_widthAspect
!= NULL
)
416 *_widthAspect
= widthAspect
;
417 if (_heightAspect
!= NULL
)
418 *_heightAspect
= heightAspect
;
422 if (_widthAspect
!= NULL
)
424 if (_heightAspect
!= NULL
)
431 Controller::AudioTrackCount()
435 if (fItem
!= NULL
&& fItem
->HasTrackSupplier())
436 return fItem
->GetTrackSupplier()->CountAudioTracks();
442 Controller::VideoTrackCount()
446 if (fItem
!= NULL
&& fItem
->HasTrackSupplier())
447 return fItem
->GetTrackSupplier()->CountVideoTracks();
453 Controller::SubTitleTrackCount()
457 if (fItem
!= NULL
&& fItem
->HasTrackSupplier())
458 return fItem
->GetTrackSupplier()->CountSubTitleTracks();
464 Controller::SelectAudioTrack(int n
)
467 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
470 ObjectDeleter
<AudioTrackSupplier
> deleter(fAudioTrackSupplier
);
472 = fItem
->GetTrackSupplier()->CreateAudioTrackForIndex(n
);
473 if (fAudioTrackSupplier
== NULL
)
476 bigtime_t a
= fAudioTrackSupplier
->Duration();
477 bigtime_t v
= fVideoTrackSupplier
!= NULL
478 ? fVideoTrackSupplier
->Duration() : 0;
479 fDuration
= max_c(a
, v
);
481 // TODO: notify duration changed!
483 fAudioSupplier
->SetSupplier(fAudioTrackSupplier
, fVideoFrameRate
);
485 _NotifyAudioTrackChanged(n
);
491 Controller::CurrentAudioTrack()
495 if (fAudioTrackSupplier
== NULL
)
498 return fAudioTrackSupplier
->TrackIndex();
503 Controller::AudioTrackChannelCount()
506 if (GetEncodedAudioFormat(&format
) == B_OK
)
507 return format
.u
.encoded_audio
.output
.channel_count
;
514 Controller::SelectVideoTrack(int n
)
518 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
521 ObjectDeleter
<VideoTrackSupplier
> deleter(fVideoTrackSupplier
);
523 = fItem
->GetTrackSupplier()->CreateVideoTrackForIndex(n
);
524 if (fVideoTrackSupplier
== NULL
)
527 bigtime_t a
= fAudioTrackSupplier
? fAudioTrackSupplier
->Duration() : 0;
528 bigtime_t v
= fVideoTrackSupplier
->Duration();
529 fDuration
= max_c(a
, v
);
530 fVideoFrameRate
= fVideoTrackSupplier
->Format().u
.raw_video
.field_rate
;
531 if (fVideoFrameRate
<= 0.0) {
532 printf("Controller::SelectVideoTrack(%d) - invalid video frame rate: %.1f\n",
534 fVideoFrameRate
= 25.0;
538 // TODO: notify duration changed!
540 fVideoSupplier
->SetSupplier(fVideoTrackSupplier
);
542 _NotifyVideoTrackChanged(n
);
548 Controller::CurrentVideoTrack()
552 if (fVideoTrackSupplier
== NULL
)
555 return fVideoTrackSupplier
->TrackIndex();
560 Controller::SelectSubTitleTrack(int n
)
564 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
569 fItem
->GetTrackSupplier()->SubTitleTrackForIndex(n
);
571 const SubTitle
* subTitle
= NULL
;
572 if (fSubTitles
!= NULL
)
573 subTitle
= fSubTitles
->SubTitleAt(_TimePosition());
574 if (subTitle
!= NULL
)
575 fVideoView
->SetSubTitle(subTitle
->text
.String());
577 fVideoView
->SetSubTitle(NULL
);
579 _NotifySubTitleTrackChanged(n
);
585 Controller::CurrentSubTitleTrack()
589 if (fSubTitles
== NULL
)
592 return fSubTitlesIndex
;
597 Controller::SubTitleTrackName(int n
)
601 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
604 const SubTitles
* subTitles
605 = fItem
->GetTrackSupplier()->SubTitleTrackForIndex(n
);
606 if (subTitles
== NULL
)
609 return subTitles
->Name();
619 //printf("Controller::Stop\n");
626 fAutoplay
= fAutoplaySetting
;
633 //printf("Controller::Play\n");
645 // printf("Controller::Pause\n");
651 fAutoplay
= fAutoplaySetting
;
656 Controller::TogglePlaying()
658 // printf("Controller::TogglePlaying\n");
662 if (InitCheck() == B_OK
) {
663 NodeManager::TogglePlaying();
665 fAutoplay
= IsPlaying() || fAutoplaySetting
;
671 Controller::PlaybackState()
675 return _PlaybackState(PlaybackManager::PlayMode());
680 Controller::TimeDuration()
689 Controller::TimePosition()
693 return _TimePosition();
698 Controller::SetVolume(float value
)
700 // printf("Controller::SetVolume %.4f\n", value);
703 value
= max_c(0.0, min_c(2.0, value
));
705 if (fVolume
!= value
) {
710 fAudioSupplier
->SetVolume(fVolume
);
712 _NotifyVolumeChanged(fVolume
);
717 Controller::VolumeUp()
719 // TODO: linear <-> exponential
720 SetVolume(Volume() + 0.05);
724 Controller::VolumeDown()
726 // TODO: linear <-> exponential
727 SetVolume(Volume() - 0.05);
731 Controller::ToggleMute()
738 fAudioSupplier
->SetVolume(0.0);
740 fAudioSupplier
->SetVolume(fVolume
);
742 _NotifyMutedChanged(fMuted
);
756 Controller::SetPosition(float value
)
760 return SetFramePosition(_FrameDuration() * value
);
765 Controller::SetFramePosition(int64 value
)
769 fPendingSeekRequests
++;
770 fRequestedSeekFrame
= max_c(0, min_c(_FrameDuration(), value
));
771 fSeekFrame
= fRequestedSeekFrame
;
773 int64 currentFrame
= CurrentFrame();
775 // Snap to a video keyframe, since that will be the fastest
776 // to display and seeking will feel more snappy. Note that we
777 // don't store this change in fSeekFrame, since we still want
778 // to report the originally requested seek frame in TimePosition()
779 // until we could reach that frame.
780 if (Duration() > 240 && fVideoTrackSupplier
!= NULL
781 && abs(value
- currentFrame
) > 5) {
782 fVideoTrackSupplier
->FindKeyFrameForFrame(&fSeekFrame
);
785 //printf("SetFramePosition(%lld) -> %lld (current: %lld, duration: %lld) "
786 //"(video: %p)\n", value, fSeekFrame, currentFrame, _FrameDuration(),
787 //fVideoTrackSupplier);
788 if (fSeekFrame
!= currentFrame
) {
789 int64 seekFrame
= fSeekFrame
;
790 SetCurrentFrame(fSeekFrame
);
791 // May trigger the notification and reset fSeekFrame,
792 // if next current frame == seek frame.
795 NotifySeekHandled(fRequestedSeekFrame
);
801 Controller::SetTimePosition(bigtime_t value
)
805 return SetPosition((float)value
/ TimeDuration());
813 Controller::HasFile()
815 // you need to hold the data lock
816 return fItem
!= NULL
&& fItem
->HasTrackSupplier();
821 Controller::GetFileFormatInfo(media_file_format
* fileFormat
)
823 // you need to hold the data lock
824 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
826 return fItem
->GetTrackSupplier()->GetFileFormatInfo(fileFormat
);
831 Controller::GetCopyright(BString
* copyright
)
833 // you need to hold the data lock
834 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
836 return fItem
->GetTrackSupplier()->GetCopyright(copyright
);
841 Controller::GetLocation(BString
* location
)
843 // you need to hold the data lock
844 if (fItem
.Get() == NULL
)
846 *location
= fItem
->LocationURI();
852 Controller::GetName(BString
* name
)
854 // you need to hold the data lock
855 if (fItem
.Get() == NULL
)
857 *name
= fItem
->Name();
863 Controller::GetEncodedVideoFormat(media_format
* format
)
865 // you need to hold the data lock
866 if (fVideoTrackSupplier
)
867 return fVideoTrackSupplier
->GetEncodedFormat(format
);
873 Controller::GetVideoCodecInfo(media_codec_info
* info
)
875 // you need to hold the data lock
876 if (fVideoTrackSupplier
)
877 return fVideoTrackSupplier
->GetCodecInfo(info
);
883 Controller::GetEncodedAudioFormat(media_format
* format
)
885 // you need to hold the data lock
886 if (fAudioTrackSupplier
)
887 return fAudioTrackSupplier
->GetEncodedFormat(format
);
893 Controller::GetAudioCodecInfo(media_codec_info
* info
)
895 // you need to hold the data lock
896 if (fAudioTrackSupplier
)
897 return fAudioTrackSupplier
->GetCodecInfo(info
);
903 Controller::GetMetaData(BMessage
* metaData
)
905 // you need to hold the data lock
906 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
908 return fItem
->GetTrackSupplier()->GetMetaData(metaData
);
913 Controller::GetVideoMetaData(int32 index
, BMessage
* metaData
)
915 // you need to hold the data lock
916 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
918 return fItem
->GetTrackSupplier()->GetVideoMetaData(index
, metaData
);
923 Controller::GetAudioMetaData(int32 index
, BMessage
* metaData
)
925 // you need to hold the data lock
926 if (fItem
== NULL
|| !fItem
->HasTrackSupplier())
928 return fItem
->GetTrackSupplier()->GetAudioMetaData(index
, metaData
);
936 Controller::SetVideoView(VideoView
*view
)
945 Controller::IsOverlayActive()
948 return fVideoView
->IsOverlayActive();
958 Controller::AddListener(Listener
* listener
)
962 if (listener
&& !fListeners
.HasItem(listener
))
963 return fListeners
.AddItem(listener
);
969 Controller::RemoveListener(Listener
* listener
)
973 fListeners
.RemoveItem(listener
);
977 // #pragma mark - Private
981 Controller::_AdoptGlobalSettings()
984 Settings::Default()->Get(settings
);
986 fAutoplaySetting
= settings
.autostart
;
988 fLoopMovies
= settings
.loopMovie
;
989 fLoopSounds
= settings
.loopSound
;
990 fBackgroundMovieVolumeMode
= settings
.backgroundMovieVolumeMode
;
995 Controller::_PlaybackState(int32 playingMode
) const
998 switch (playingMode
) {
999 case MODE_PLAYING_PAUSED_FORWARD
:
1000 case MODE_PLAYING_PAUSED_BACKWARD
:
1001 state
= PLAYBACK_STATE_PAUSED
;
1003 case MODE_PLAYING_FORWARD
:
1004 case MODE_PLAYING_BACKWARD
:
1005 state
= PLAYBACK_STATE_PLAYING
;
1009 state
= PLAYBACK_STATE_STOPPED
;
1017 Controller::_TimePosition() const
1022 // Check if we are still waiting to reach the seekframe,
1023 // pass the last pending seek frame back to the caller, so
1024 // that the view of the current frame/time from the outside
1025 // does not depend on the internal latency to reach requested
1026 // frames asynchronously.
1028 if (fPendingSeekRequests
> 0)
1029 frame
= fRequestedSeekFrame
;
1031 frame
= fCurrentFrame
;
1033 return frame
* fDuration
/ _FrameDuration();
1038 Controller::_FrameDuration() const
1040 // This should really be total frames (video frames at that)
1041 // TODO: It is not so nice that the MediaPlayer still measures
1042 // in video frames if only playing audio. Here for example, it will
1043 // return a duration of 0 if the audio clip happens to be shorter than
1044 // one video frame at 25 fps.
1045 return (int64
)((double)fDuration
* fVideoFrameRate
/ 1000000.0);
1049 // #pragma mark - Notifications
1053 Controller::_NotifyFileChanged(PlaylistItem
* item
, status_t result
) const
1055 BList
listeners(fListeners
);
1056 int32 count
= listeners
.CountItems();
1057 for (int32 i
= 0; i
< count
; i
++) {
1058 Listener
* listener
= (Listener
*)listeners
.ItemAtFast(i
);
1059 listener
->FileChanged(item
, result
);
1065 Controller::_NotifyFileFinished() 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
->FileFinished();
1077 Controller::_NotifyVideoTrackChanged(int32 index
) 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
->VideoTrackChanged(index
);
1089 Controller::_NotifyAudioTrackChanged(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
->AudioTrackChanged(index
);
1101 Controller::_NotifySubTitleTrackChanged(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
->SubTitleTrackChanged(index
);
1113 Controller::_NotifyVideoStatsChanged() 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
->VideoStatsChanged();
1125 Controller::_NotifyAudioStatsChanged() 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
->AudioStatsChanged();
1137 Controller::_NotifyPlaybackStateChanged(uint32 state
) 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
->PlaybackStateChanged(state
);
1149 Controller::_NotifyPositionChanged(float position
) 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
->PositionChanged(position
);
1161 Controller::_NotifySeekHandled(int64 seekFrame
) 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
->SeekHandled(seekFrame
);
1173 Controller::_NotifyVolumeChanged(float volume
) 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
->VolumeChanged(volume
);
1185 Controller::_NotifyMutedChanged(bool muted
) 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
->MutedChanged(muted
);
1197 Controller::NotifyPlayModeChanged(int32 mode
) const
1199 uint32 state
= _PlaybackState(mode
);
1201 fVideoView
->SetPlaying(state
== PLAYBACK_STATE_PLAYING
);
1202 _NotifyPlaybackStateChanged(state
);
1207 Controller::NotifyLoopModeChanged(int32 mode
) const
1213 Controller::NotifyLoopingEnabledChanged(bool enabled
) const
1219 Controller::NotifyVideoBoundsChanged(BRect bounds
) const
1225 Controller::NotifyFPSChanged(float fps
) const
1231 Controller::NotifyCurrentFrameChanged(int64 frame
) const
1233 fCurrentFrame
= frame
;
1234 bigtime_t timePosition
= _TimePosition();
1235 _NotifyPositionChanged((float)timePosition
/ fDuration
);
1237 if (fSubTitles
!= NULL
) {
1238 const SubTitle
* subTitle
= fSubTitles
->SubTitleAt(timePosition
);
1239 if (subTitle
!= NULL
)
1240 fVideoView
->SetSubTitle(subTitle
->text
.String());
1242 fVideoView
->SetSubTitle(NULL
);
1248 Controller::NotifySpeedChanged(float speed
) const
1254 Controller::NotifyFrameDropped() const
1256 // printf("Controller::NotifyFrameDropped()\n");
1261 Controller::NotifyStopFrameReached() const
1263 // Currently, this means we reached the end of the current
1264 // file and should play the next file
1265 _NotifyFileFinished();
1270 Controller::NotifySeekHandled(int64 seekedFrame
) const
1272 if (fPendingSeekRequests
== 0)
1275 fPendingSeekRequests
--;
1276 if (fPendingSeekRequests
== 0) {
1278 fRequestedSeekFrame
= -1;
1281 _NotifySeekHandled(seekedFrame
);