* Moved the about alert handling into the application
* Simplified the handling of the first window and removed FirstWindow(), we can tell by fPlayerCount. * Both the above would fix a crash when requesting the about alert with the first window already gone. Respectively another player instance opening if fFirstWindow was reset to NULL after some recent revision. * Implemented restoring the current playlist, index and position in the file. * Devised a more robust way to solve asynchronous seeking. The Controller is now notified that a seek request has been handled with a dedicated hook. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34079 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -106,8 +106,7 @@ Controller::Controller()
|
|||||||
fPosition(0),
|
fPosition(0),
|
||||||
fDuration(0),
|
fDuration(0),
|
||||||
fVideoFrameRate(25.0),
|
fVideoFrameRate(25.0),
|
||||||
fSeekFrame(-1),
|
fSeekRequested(false),
|
||||||
fLastSeekEventTime(LONGLONG_MIN),
|
|
||||||
|
|
||||||
fGlobalSettingsListener(this),
|
fGlobalSettingsListener(this),
|
||||||
|
|
||||||
@@ -316,6 +315,8 @@ Controller::SetTo(const PlaylistItemRef& item)
|
|||||||
const media_format& audioTrackFormat = fAudioTrackSupplier->Format();
|
const media_format& audioTrackFormat = fAudioTrackSupplier->Format();
|
||||||
audioFrameRate = audioTrackFormat.u.raw_audio.frame_rate;
|
audioFrameRate = audioTrackFormat.u.raw_audio.frame_rate;
|
||||||
audioChannels = audioTrackFormat.u.raw_audio.channel_count;
|
audioChannels = audioTrackFormat.u.raw_audio.channel_count;
|
||||||
|
// if (fVideoTrackSupplier == NULL)
|
||||||
|
// fVideoFrameRate = audioFrameRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InitCheck() != B_OK) {
|
if (InitCheck() != B_OK) {
|
||||||
@@ -659,13 +660,33 @@ Controller::SetPosition(float value)
|
|||||||
{
|
{
|
||||||
BAutolock _(this);
|
BAutolock _(this);
|
||||||
|
|
||||||
fSeekFrame = (int32)(Duration() * value);
|
SetFramePosition(Duration() * value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Controller::SetFramePosition(int32 value)
|
||||||
|
{
|
||||||
|
printf("Controller::SetFramePosition(%ld)\n", value);
|
||||||
|
BAutolock _(this);
|
||||||
|
|
||||||
|
int32 seekFrame = max_c(0, min_c(Duration(), value));
|
||||||
int32 currentFrame = CurrentFrame();
|
int32 currentFrame = CurrentFrame();
|
||||||
if (fSeekFrame != currentFrame) {
|
if (seekFrame != currentFrame) {
|
||||||
SetCurrentFrame(fSeekFrame);
|
printf(" adjusted seek frame\n");
|
||||||
fLastSeekEventTime = system_time();
|
fSeekFrame = seekFrame;
|
||||||
} else
|
fSeekRequested = true;
|
||||||
fSeekFrame = -1;
|
SetCurrentFrame(seekFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Controller::SetTimePosition(bigtime_t value)
|
||||||
|
{
|
||||||
|
BAutolock _(this);
|
||||||
|
|
||||||
|
SetPosition((float)value / TimeDuration());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1009,11 +1030,11 @@ Controller::NotifyCurrentFrameChanged(int32 frame) const
|
|||||||
{
|
{
|
||||||
// check if we are still waiting to reach the seekframe,
|
// check if we are still waiting to reach the seekframe,
|
||||||
// don't pass the event on to the listeners in that case
|
// don't pass the event on to the listeners in that case
|
||||||
if ((system_time() - fLastSeekEventTime) < 1000000
|
if (fSeekRequested && fSeekFrame != frame)
|
||||||
&& fSeekFrame >= 0 && frame != fSeekFrame) {
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
fSeekFrame = -1;
|
fSeekFrame = -1;
|
||||||
|
fSeekRequested = false;
|
||||||
|
|
||||||
float position = 0.0;
|
float position = 0.0;
|
||||||
double duration = (double)fDuration * fVideoFrameRate / 1000000.0;
|
double duration = (double)fDuration * fVideoFrameRate / 1000000.0;
|
||||||
@@ -1045,3 +1066,11 @@ Controller::NotifyStopFrameReached() const
|
|||||||
_NotifyFileFinished();
|
_NotifyFileFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Controller::NotifySeekHandled() const
|
||||||
|
{
|
||||||
|
fSeekRequested = false;
|
||||||
|
fSeekFrame = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,6 +115,8 @@ public:
|
|||||||
void VolumeDown();
|
void VolumeDown();
|
||||||
void ToggleMute();
|
void ToggleMute();
|
||||||
void SetPosition(float value);
|
void SetPosition(float value);
|
||||||
|
void SetFramePosition(int32 frame);
|
||||||
|
void SetTimePosition(bigtime_t position);
|
||||||
|
|
||||||
bool HasFile();
|
bool HasFile();
|
||||||
status_t GetFileFormatInfo(
|
status_t GetFileFormatInfo(
|
||||||
@@ -166,6 +168,7 @@ private:
|
|||||||
virtual void NotifySpeedChanged(float speed) const;
|
virtual void NotifySpeedChanged(float speed) const;
|
||||||
virtual void NotifyFrameDropped() const;
|
virtual void NotifyFrameDropped() const;
|
||||||
virtual void NotifyStopFrameReached() const;
|
virtual void NotifyStopFrameReached() const;
|
||||||
|
virtual void NotifySeekHandled() const;
|
||||||
|
|
||||||
|
|
||||||
VideoView* fVideoView;
|
VideoView* fVideoView;
|
||||||
@@ -187,8 +190,9 @@ private:
|
|||||||
mutable bigtime_t fPosition;
|
mutable bigtime_t fPosition;
|
||||||
bigtime_t fDuration;
|
bigtime_t fDuration;
|
||||||
float fVideoFrameRate;
|
float fVideoFrameRate;
|
||||||
mutable int32 fSeekFrame;
|
|
||||||
bigtime_t fLastSeekEventTime;
|
mutable bool fSeekRequested;
|
||||||
|
mutable int32 fSeekFrame;
|
||||||
|
|
||||||
ListenerAdapter fGlobalSettingsListener;
|
ListenerAdapter fGlobalSettingsListener;
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ MainApp::MainApp()
|
|||||||
:
|
:
|
||||||
BApplication(kAppSig),
|
BApplication(kAppSig),
|
||||||
fPlayerCount(0),
|
fPlayerCount(0),
|
||||||
fFirstWindow(NULL),
|
|
||||||
fSettingsWindow(NULL),
|
fSettingsWindow(NULL),
|
||||||
|
|
||||||
fOpenFilePanel(NULL),
|
fOpenFilePanel(NULL),
|
||||||
@@ -94,25 +93,12 @@ MainApp::QuitRequested()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BWindow*
|
MainWin*
|
||||||
MainApp::FirstWindow()
|
|
||||||
{
|
|
||||||
BAutolock _(this);
|
|
||||||
if (fFirstWindow != NULL)
|
|
||||||
return fFirstWindow;
|
|
||||||
return NewWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BWindow*
|
|
||||||
MainApp::NewWindow()
|
MainApp::NewWindow()
|
||||||
{
|
{
|
||||||
BAutolock _(this);
|
BAutolock _(this);
|
||||||
fPlayerCount++;
|
fPlayerCount++;
|
||||||
BWindow* window = new MainWin(fFirstWindow == NULL);
|
return new(std::nothrow) MainWin(fPlayerCount == 1);
|
||||||
if (fFirstWindow == NULL)
|
|
||||||
fFirstWindow = window;
|
|
||||||
return window;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -157,7 +143,18 @@ MainApp::ReadyToRun()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make sure we have at least one window open
|
// make sure we have at least one window open
|
||||||
FirstWindow();
|
if (fPlayerCount == 0) {
|
||||||
|
MainWin* window = NewWindow();
|
||||||
|
if (window == NULL) {
|
||||||
|
PostMessage(B_QUIT_REQUESTED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BMessage lastPlaylistArchive;
|
||||||
|
if (_RestoreCurrentPlaylist(&lastPlaylistArchive) == B_OK)
|
||||||
|
window->OpenPlaylist(&lastPlaylistArchive);
|
||||||
|
|
||||||
|
window->Show();
|
||||||
|
}
|
||||||
|
|
||||||
// setup the settings window now, we need to have it
|
// setup the settings window now, we need to have it
|
||||||
fSettingsWindow = new SettingsWindow(BRect(150, 150, 450, 520));
|
fSettingsWindow = new SettingsWindow(BRect(150, 150, 450, 520));
|
||||||
@@ -175,13 +172,13 @@ MainApp::RefsReceived(BMessage* message)
|
|||||||
// ArgvReceived() but without MIME type check.
|
// ArgvReceived() but without MIME type check.
|
||||||
// For each file we create a new window and send it a
|
// For each file we create a new window and send it a
|
||||||
// B_REFS_RECEIVED message with a single file.
|
// B_REFS_RECEIVED message with a single file.
|
||||||
// If IsLaunching() is true, we use fFirstWindow as first
|
|
||||||
// window.
|
|
||||||
printf("MainApp::RefsReceived\n");
|
printf("MainApp::RefsReceived\n");
|
||||||
|
|
||||||
BWindow* window = NewWindow();
|
BWindow* window = NewWindow();
|
||||||
if (window)
|
if (window != NULL) {
|
||||||
|
window->Show();
|
||||||
window->PostMessage(message);
|
window->PostMessage(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -231,8 +228,6 @@ MainApp::MessageReceived(BMessage* message)
|
|||||||
&& message->FindBool("audio only", &audioOnly) == B_OK
|
&& message->FindBool("audio only", &audioOnly) == B_OK
|
||||||
&& message->FindRect("window frame", &windowFrame) == B_OK
|
&& message->FindRect("window frame", &windowFrame) == B_OK
|
||||||
&& message->FindInt64("creation time", &creationTime) == B_OK) {
|
&& message->FindInt64("creation time", &creationTime) == B_OK) {
|
||||||
if (window == fFirstWindow)
|
|
||||||
fFirstWindow = NULL;
|
|
||||||
if (audioOnly) {
|
if (audioOnly) {
|
||||||
if (!fAudioWindowFrameSaved
|
if (!fAudioWindowFrameSaved
|
||||||
|| creationTime < fLastSavedAudioWindowCreationTime) {
|
|| creationTime < fLastSavedAudioWindowCreationTime) {
|
||||||
@@ -245,6 +240,15 @@ MainApp::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store the playlist if there is one. Since the app is doing
|
||||||
|
// this, it is "atomic". If the user has multiple instances
|
||||||
|
// playing audio at the same time, the last instance which is
|
||||||
|
// quit wins.
|
||||||
|
BMessage playlistArchive;
|
||||||
|
if (message->FindMessage("playlist", &playlistArchive) == B_OK)
|
||||||
|
_StoreCurrentPlaylist(&playlistArchive);
|
||||||
|
|
||||||
// quit if this was the last player window
|
// quit if this was the last player window
|
||||||
fPlayerCount--;
|
fPlayerCount--;
|
||||||
if (fPlayerCount == 0)
|
if (fPlayerCount == 0)
|
||||||
@@ -340,7 +344,13 @@ MainApp::MessageReceived(BMessage* message)
|
|||||||
void
|
void
|
||||||
MainApp::AboutRequested()
|
MainApp::AboutRequested()
|
||||||
{
|
{
|
||||||
FirstWindow()->PostMessage(B_ABOUT_REQUESTED);
|
BAlert* alert = new BAlert("about", NAME"\n\n Written by Marcus Overhagen "
|
||||||
|
", Stephan Aßmus and Frederik Modéen", "Thanks");
|
||||||
|
alert->SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
|
||||||
|
// Make sure it is on top of any player windows that may have the
|
||||||
|
// floating all window feel.
|
||||||
|
alert->Go(NULL);
|
||||||
|
// asynchronous mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -508,6 +518,43 @@ MainApp::_HandleFilePanelResult(BFilePanel* panel, const BMessage* message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char* kCurrentPlaylistFilename = "MediaPlayer Current Playlist";
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MainApp::_StoreCurrentPlaylist(const BMessage* message) const
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
|
||||||
|
|| path.Append(kCurrentPlaylistFilename) != B_OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
|
||||||
|
if (file.InitCheck() != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
message->Flatten(&file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MainApp::_RestoreCurrentPlaylist(BMessage* message) const
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
|
||||||
|
|| path.Append(kCurrentPlaylistFilename) != B_OK) {
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
BFile file(path.Path(), B_READ_ONLY);
|
||||||
|
if (file.InitCheck() != B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
return message->Unflatten(&file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - main
|
// #pragma mark - main
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ enum {
|
|||||||
M_MEDIA_SERVER_QUIT = 'msqt'
|
M_MEDIA_SERVER_QUIT = 'msqt'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define NAME "MediaPlayer"
|
||||||
|
|
||||||
|
|
||||||
class BFilePanel;
|
class BFilePanel;
|
||||||
class SettingsWindow;
|
class SettingsWindow;
|
||||||
|
|
||||||
@@ -58,8 +62,7 @@ public:
|
|||||||
MainApp();
|
MainApp();
|
||||||
virtual ~MainApp();
|
virtual ~MainApp();
|
||||||
|
|
||||||
BWindow* FirstWindow();
|
MainWin* NewWindow();
|
||||||
BWindow* NewWindow();
|
|
||||||
int32 PlayerCount() const;
|
int32 PlayerCount() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -81,13 +84,20 @@ private:
|
|||||||
const char* defaultTitle,
|
const char* defaultTitle,
|
||||||
const char* defaultLabel);
|
const char* defaultLabel);
|
||||||
|
|
||||||
void _HandleOpenPanelResult(const BMessage* message);
|
void _HandleOpenPanelResult(
|
||||||
void _HandleSavePanelResult(const BMessage* message);
|
const BMessage* message);
|
||||||
|
void _HandleSavePanelResult(
|
||||||
|
const BMessage* message);
|
||||||
void _HandleFilePanelResult(BFilePanel* panel,
|
void _HandleFilePanelResult(BFilePanel* panel,
|
||||||
const BMessage* message);
|
const BMessage* message);
|
||||||
|
|
||||||
|
void _StoreCurrentPlaylist(
|
||||||
|
const BMessage* message) const;
|
||||||
|
status_t _RestoreCurrentPlaylist(
|
||||||
|
BMessage* message) const;
|
||||||
|
|
||||||
|
private:
|
||||||
int32 fPlayerCount;
|
int32 fPlayerCount;
|
||||||
BWindow* fFirstWindow;
|
|
||||||
SettingsWindow* fSettingsWindow;
|
SettingsWindow* fSettingsWindow;
|
||||||
|
|
||||||
BFilePanel* fOpenFilePanel;
|
BFilePanel* fOpenFilePanel;
|
||||||
|
|||||||
@@ -53,7 +53,6 @@
|
|||||||
#include "PlaylistWindow.h"
|
#include "PlaylistWindow.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
|
||||||
#define NAME "MediaPlayer"
|
|
||||||
#define MIN_WIDTH 250
|
#define MIN_WIDTH 250
|
||||||
|
|
||||||
|
|
||||||
@@ -129,7 +128,8 @@ MainWin::MainWin(bool isFirstWindow)
|
|||||||
fWidthAspect(0),
|
fWidthAspect(0),
|
||||||
fHeightAspect(0),
|
fHeightAspect(0),
|
||||||
fMouseDownTracking(false),
|
fMouseDownTracking(false),
|
||||||
fGlobalSettingsListener(this)
|
fGlobalSettingsListener(this),
|
||||||
|
fInitialSeekPosition(0)
|
||||||
{
|
{
|
||||||
// Handle window position and size depending on whether this is the
|
// Handle window position and size depending on whether this is the
|
||||||
// first window or not. Use the window size from the window that was
|
// first window or not. Use the window size from the window that was
|
||||||
@@ -218,8 +218,6 @@ MainWin::MainWin(bool isFirstWindow)
|
|||||||
AddShortcut('y', B_COMMAND_KEY, new BMessage(B_UNDO));
|
AddShortcut('y', B_COMMAND_KEY, new BMessage(B_UNDO));
|
||||||
AddShortcut('z', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(B_REDO));
|
AddShortcut('z', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(B_REDO));
|
||||||
AddShortcut('y', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(B_REDO));
|
AddShortcut('y', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(B_REDO));
|
||||||
|
|
||||||
Show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -367,7 +365,7 @@ MainWin::DispatchMessage(BMessage *msg, BHandler *handler)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MainWin::MessageReceived(BMessage *msg)
|
MainWin::MessageReceived(BMessage* msg)
|
||||||
{
|
{
|
||||||
// msg->PrintToStream();
|
// msg->PrintToStream();
|
||||||
switch (msg->what) {
|
switch (msg->what) {
|
||||||
@@ -549,19 +547,8 @@ MainWin::MessageReceived(BMessage *msg)
|
|||||||
ShowPlaylistWindow();
|
ShowPlaylistWindow();
|
||||||
break;
|
break;
|
||||||
case B_ABOUT_REQUESTED:
|
case B_ABOUT_REQUESTED:
|
||||||
{
|
be_app->PostMessage(msg);
|
||||||
BAlert *alert;
|
|
||||||
alert = new BAlert("about", NAME"\n\n Written by Marcus Overhagen "
|
|
||||||
", Stephan Aßmus and Frederik Modéen", "Thanks");
|
|
||||||
if (fAlwaysOnTop) {
|
|
||||||
_ToggleAlwaysOnTop();
|
|
||||||
alert->Go(NULL); // Asynchronous mode
|
|
||||||
_ToggleAlwaysOnTop();
|
|
||||||
} else {
|
|
||||||
alert->Go(NULL); // Asynchronous mode
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case M_FILE_CLOSE:
|
case M_FILE_CLOSE:
|
||||||
PostMessage(B_QUIT_REQUESTED);
|
PostMessage(B_QUIT_REQUESTED);
|
||||||
break;
|
break;
|
||||||
@@ -728,7 +715,7 @@ MainWin::QuitRequested()
|
|||||||
message.AddBool("audio only", !fHasVideo);
|
message.AddBool("audio only", !fHasVideo);
|
||||||
message.AddInt64("creation time", fCreationTime);
|
message.AddInt64("creation time", fCreationTime);
|
||||||
if (!fHasVideo && fHasAudio) {
|
if (!fHasVideo && fHasAudio) {
|
||||||
// store playlist and position if this is audio
|
// store playlist, current index and position if this is audio
|
||||||
BMessage playlistArchive;
|
BMessage playlistArchive;
|
||||||
|
|
||||||
BAutolock controllerLocker(fController);
|
BAutolock controllerLocker(fController);
|
||||||
@@ -737,6 +724,8 @@ MainWin::QuitRequested()
|
|||||||
|
|
||||||
BAutolock playlistLocker(fPlaylist);
|
BAutolock playlistLocker(fPlaylist);
|
||||||
if (fPlaylist->Archive(&playlistArchive) != B_OK
|
if (fPlaylist->Archive(&playlistArchive) != B_OK
|
||||||
|
|| playlistArchive.AddInt32("index",
|
||||||
|
fPlaylist->CurrentItemIndex()) != B_OK
|
||||||
|| message.AddMessage("playlist", &playlistArchive) != B_OK) {
|
|| message.AddMessage("playlist", &playlistArchive) != B_OK) {
|
||||||
fprintf(stderr, "Failed to store current playlist.\n");
|
fprintf(stderr, "Failed to store current playlist.\n");
|
||||||
}
|
}
|
||||||
@@ -756,6 +745,29 @@ MainWin::MenusBeginning()
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MainWin::OpenPlaylist(const BMessage* playlistArchive)
|
||||||
|
{
|
||||||
|
if (playlistArchive == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BAutolock _(this);
|
||||||
|
BAutolock playlistLocker(fPlaylist);
|
||||||
|
|
||||||
|
if (fPlaylist->Unarchive(playlistArchive) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int32 currentIndex;
|
||||||
|
if (playlistArchive->FindInt32("index", ¤tIndex) != B_OK)
|
||||||
|
currentIndex = 0;
|
||||||
|
fPlaylist->SetCurrentItemIndex(currentIndex);
|
||||||
|
|
||||||
|
playlistLocker.Unlock();
|
||||||
|
|
||||||
|
playlistArchive->FindInt64("position", (int64*)&fInitialSeekPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MainWin::OpenPlaylistItem(const PlaylistItemRef& item)
|
MainWin::OpenPlaylistItem(const PlaylistItemRef& item)
|
||||||
{
|
{
|
||||||
@@ -794,6 +806,8 @@ MainWin::OpenPlaylistItem(const PlaylistItemRef& item)
|
|||||||
fHasVideo = fController->VideoTrackCount() != 0;
|
fHasVideo = fController->VideoTrackCount() != 0;
|
||||||
fHasAudio = fController->AudioTrackCount() != 0;
|
fHasAudio = fController->AudioTrackCount() != 0;
|
||||||
SetTitle(item->Name().String());
|
SetTitle(item->Name().String());
|
||||||
|
fController->SetTimePosition(fInitialSeekPosition);
|
||||||
|
fInitialSeekPosition = 0;
|
||||||
}
|
}
|
||||||
_SetupWindow();
|
_SetupWindow();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ public:
|
|||||||
virtual bool QuitRequested();
|
virtual bool QuitRequested();
|
||||||
virtual void MenusBeginning();
|
virtual void MenusBeginning();
|
||||||
|
|
||||||
|
void OpenPlaylist(const BMessage* playlistArchive);
|
||||||
void OpenPlaylistItem(const PlaylistItemRef& item);
|
void OpenPlaylistItem(const PlaylistItemRef& item);
|
||||||
|
|
||||||
void ShowFileInfo();
|
void ShowFileInfo();
|
||||||
@@ -162,6 +163,7 @@ private:
|
|||||||
ListenerAdapter fGlobalSettingsListener;
|
ListenerAdapter fGlobalSettingsListener;
|
||||||
bool fCloseWhenDonePlayingMovie;
|
bool fCloseWhenDonePlayingMovie;
|
||||||
bool fCloseWhenDonePlayingSound;
|
bool fCloseWhenDonePlayingSound;
|
||||||
|
bigtime_t fInitialSeekPosition;
|
||||||
|
|
||||||
static int sNoVideoWidth;
|
static int sNoVideoWidth;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,9 +42,32 @@ struct PlaybackManager::PlayingState {
|
|||||||
int32 play_mode;
|
int32 play_mode;
|
||||||
int32 loop_mode;
|
int32 loop_mode;
|
||||||
bool looping_enabled;
|
bool looping_enabled;
|
||||||
|
bool is_seek_request;
|
||||||
int64 current_frame; // Playlist frame
|
int64 current_frame; // Playlist frame
|
||||||
int64 range_index; // playing range index of current_frame
|
int64 range_index; // playing range index of current_frame
|
||||||
int64 activation_frame; // absolute video frame
|
int64 activation_frame; // absolute video frame
|
||||||
|
|
||||||
|
PlayingState()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayingState(const PlayingState& other)
|
||||||
|
:
|
||||||
|
start_frame(other.start_frame),
|
||||||
|
end_frame(other.end_frame),
|
||||||
|
frame_count(other.frame_count),
|
||||||
|
first_visible_frame(other.first_visible_frame),
|
||||||
|
last_visible_frame(other.last_visible_frame),
|
||||||
|
max_frame_count(other.max_frame_count),
|
||||||
|
play_mode(other.play_mode),
|
||||||
|
loop_mode(other.loop_mode),
|
||||||
|
looping_enabled(other.looping_enabled),
|
||||||
|
is_seek_request(false),
|
||||||
|
current_frame(other.current_frame),
|
||||||
|
range_index(other.range_index),
|
||||||
|
activation_frame(other.activation_frame)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -116,6 +139,7 @@ PlaybackManager::Init(float frameRate, int32 loopingMode, bool loopingEnabled,
|
|||||||
state->play_mode = MODE_PLAYING_PAUSED_FORWARD;
|
state->play_mode = MODE_PLAYING_PAUSED_FORWARD;
|
||||||
state->loop_mode = loopingMode;
|
state->loop_mode = loopingMode;
|
||||||
state->looping_enabled = loopingEnabled;
|
state->looping_enabled = loopingEnabled;
|
||||||
|
state->is_seek_request = false;
|
||||||
state->current_frame = currentFrame;
|
state->current_frame = currentFrame;
|
||||||
state->activation_frame = 0;
|
state->activation_frame = 0;
|
||||||
fStates.AddItem(state);
|
fStates.AddItem(state);
|
||||||
@@ -356,10 +380,13 @@ PlaybackManager::DurationChanged()
|
|||||||
void
|
void
|
||||||
PlaybackManager::SetCurrentFrame(int64 frame)
|
PlaybackManager::SetCurrentFrame(int64 frame)
|
||||||
{
|
{
|
||||||
if (_LastState()->current_frame == frame)
|
if (_LastState()->current_frame == frame) {
|
||||||
|
NotifySeekHandled();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
PlayingState* newState = new PlayingState(*_LastState());
|
PlayingState* newState = new PlayingState(*_LastState());
|
||||||
newState->current_frame = frame;
|
newState->current_frame = frame;
|
||||||
|
newState->is_seek_request = true;
|
||||||
_PushState(newState, false);
|
_PushState(newState, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,7 +758,7 @@ PlaybackManager::GetPlaylistTimeInterval(bigtime_t startTime,
|
|||||||
bigtime_t endTimeForFrame = TimeForFrame(endFrame);
|
bigtime_t endTimeForFrame = TimeForFrame(endFrame);
|
||||||
endTime = min(endTime, endTimeForFrame);
|
endTime = min(endTime, endTimeForFrame);
|
||||||
bigtime_t intervalLength = endTime - startTime;
|
bigtime_t intervalLength = endTime - startTime;
|
||||||
|
|
||||||
// Finally determine the time bounds for the Playlist interval (depending
|
// Finally determine the time bounds for the Playlist interval (depending
|
||||||
// on the playing direction).
|
// on the playing direction).
|
||||||
switch (playingDirection) {
|
switch (playingDirection) {
|
||||||
@@ -741,7 +768,7 @@ PlaybackManager::GetPlaylistTimeInterval(bigtime_t startTime,
|
|||||||
// xStartTime = PlaylistTimeForFrame(xStartFrame)
|
// xStartTime = PlaylistTimeForFrame(xStartFrame)
|
||||||
// + startTime - TimeForFrame(startFrame);
|
// + startTime - TimeForFrame(startFrame);
|
||||||
// xEndTime = xStartTime + intervalLength;
|
// xEndTime = xStartTime + intervalLength;
|
||||||
|
|
||||||
// TODO: The current method does not handle the times the same way.
|
// TODO: The current method does not handle the times the same way.
|
||||||
// It may happen, that for the same performance time different
|
// It may happen, that for the same performance time different
|
||||||
// Playlist times (within a frame) are returned when passing it
|
// Playlist times (within a frame) are returned when passing it
|
||||||
@@ -829,7 +856,7 @@ return result;
|
|||||||
|
|
||||||
|
|
||||||
/*! Returns the Playlist frame for an Playlist time.
|
/*! Returns the Playlist frame for an Playlist time.
|
||||||
It holds PlaylistTimeForFrame(frame) <= time <
|
It holds PlaylistTimeForFrame(frame) <= time <
|
||||||
PlaylistTimeForFrame(frame + 1). */
|
PlaylistTimeForFrame(frame + 1). */
|
||||||
int64
|
int64
|
||||||
PlaybackManager::PlaylistFrameForTime(bigtime_t time) const
|
PlaybackManager::PlaylistFrameForTime(bigtime_t time) const
|
||||||
@@ -1053,7 +1080,14 @@ PlaybackManager::NotifyFrameDropped() const
|
|||||||
void
|
void
|
||||||
PlaybackManager::NotifyStopFrameReached() const
|
PlaybackManager::NotifyStopFrameReached() const
|
||||||
{
|
{
|
||||||
// not currently implemented in PlaybackListener interface
|
// not currently implemented in PlaybackListener interface
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PlaybackManager::NotifySeekHandled() const
|
||||||
|
{
|
||||||
|
// not currently implemented in PlaybackListener interface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1101,95 +1135,96 @@ PlaybackManager::_PushState(PlayingState* state, bool adjustCurrentFrame)
|
|||||||
// debugger("PlaybackManager::_PushState() used before Init()\n");
|
// debugger("PlaybackManager::_PushState() used before Init()\n");
|
||||||
|
|
||||||
TRACE("PlaybackManager::_PushState()\n");
|
TRACE("PlaybackManager::_PushState()\n");
|
||||||
if (state) {
|
if (state == NULL)
|
||||||
// unset fStopPlayingFrame
|
return;
|
||||||
int64 oldStopPlayingFrame = fStopPlayingFrame;
|
|
||||||
fStopPlayingFrame = -1;
|
// unset fStopPlayingFrame
|
||||||
// get last state
|
int64 oldStopPlayingFrame = fStopPlayingFrame;
|
||||||
PlayingState* lastState = _LastState();
|
fStopPlayingFrame = -1;
|
||||||
int64 activationFrame = max(max(state->activation_frame,
|
// get last state
|
||||||
lastState->activation_frame),
|
PlayingState* lastState = _LastState();
|
||||||
NextFrame());
|
int64 activationFrame = max(max(state->activation_frame,
|
||||||
|
lastState->activation_frame),
|
||||||
|
NextFrame());
|
||||||
TRACE(" state activation frame: %lld, last state activation frame: %lld, "
|
TRACE(" state activation frame: %lld, last state activation frame: %lld, "
|
||||||
"NextFrame(): %lld\n", state->activation_frame, lastState->activation_frame,
|
"NextFrame(): %lld\n", state->activation_frame, lastState->activation_frame,
|
||||||
NextFrame());
|
NextFrame());
|
||||||
|
|
||||||
int64 currentFrame = 0;
|
int64 currentFrame = 0;
|
||||||
// remember the current frame, if necessary
|
// remember the current frame, if necessary
|
||||||
if (adjustCurrentFrame)
|
if (adjustCurrentFrame)
|
||||||
currentFrame = PlaylistFrameAtFrame(activationFrame);
|
currentFrame = PlaylistFrameAtFrame(activationFrame);
|
||||||
// check whether it is active
|
// check whether it is active
|
||||||
// (NOTE: We may want to keep the last state, if it is not active,
|
// (NOTE: We may want to keep the last state, if it is not active,
|
||||||
// but then the new state should become active after the last one.
|
// but then the new state should become active after the last one.
|
||||||
// Thus we had to replace `NextFrame()' with `activationFrame'.)
|
// Thus we had to replace `NextFrame()' with `activationFrame'.)
|
||||||
if (lastState->activation_frame >= NextFrame()) {
|
if (lastState->activation_frame >= NextFrame()) {
|
||||||
// it isn't -- remove it
|
// it isn't -- remove it
|
||||||
fStates.RemoveItem(fStates.CountItems() - 1);
|
fStates.RemoveItem(fStates.CountItems() - 1);
|
||||||
TRACE("deleting last \n");
|
TRACE("deleting last \n");
|
||||||
PrintState(lastState);
|
PrintState(lastState);
|
||||||
delete lastState;
|
delete lastState;
|
||||||
} else {
|
} else {
|
||||||
// it is -- keep it
|
// it is -- keep it
|
||||||
}
|
}
|
||||||
// adjust the new state's current frame and activation frame
|
// adjust the new state's current frame and activation frame
|
||||||
if (adjustCurrentFrame)
|
if (adjustCurrentFrame)
|
||||||
state->current_frame = currentFrame;
|
state->current_frame = currentFrame;
|
||||||
int32 playingDirection = _PlayingDirectionFor(state);
|
int32 playingDirection = _PlayingDirectionFor(state);
|
||||||
if (playingDirection != 0) {
|
if (playingDirection != 0) {
|
||||||
state->current_frame
|
state->current_frame
|
||||||
= _NextFrameInRange(state, state->current_frame);
|
= _NextFrameInRange(state, state->current_frame);
|
||||||
} else {
|
} else {
|
||||||
// If not playing, we check at least, if the current frame lies
|
// If not playing, we check at least, if the current frame lies
|
||||||
// within the interval [0, max_frame_count).
|
// within the interval [0, max_frame_count).
|
||||||
if (state->current_frame >= state->max_frame_count)
|
if (state->current_frame >= state->max_frame_count)
|
||||||
state->current_frame = state->max_frame_count - 1;
|
state->current_frame = state->max_frame_count - 1;
|
||||||
if (state->current_frame < 0)
|
if (state->current_frame < 0)
|
||||||
state->current_frame = 0;
|
state->current_frame = 0;
|
||||||
}
|
}
|
||||||
state->range_index = _RangeFrameForFrame(state, state->current_frame);
|
state->range_index = _RangeFrameForFrame(state, state->current_frame);
|
||||||
state->activation_frame = activationFrame;
|
state->activation_frame = activationFrame;
|
||||||
fStates.AddItem(state);
|
fStates.AddItem(state);
|
||||||
PrintState(state);
|
PrintState(state);
|
||||||
TRACE("_PushState: state count: %ld\n", fStates.CountItems());
|
TRACE("_PushState: state count: %ld\n", fStates.CountItems());
|
||||||
// push a new speed info
|
// push a new speed info
|
||||||
SpeedInfo* speedInfo = new SpeedInfo(*_LastSpeedInfo());
|
SpeedInfo* speedInfo = new SpeedInfo(*_LastSpeedInfo());
|
||||||
if (playingDirection == 0)
|
if (playingDirection == 0)
|
||||||
speedInfo->speed = 1.0;
|
speedInfo->speed = 1.0;
|
||||||
else
|
else
|
||||||
speedInfo->speed = speedInfo->set_speed;
|
speedInfo->speed = speedInfo->set_speed;
|
||||||
speedInfo->activation_frame = state->activation_frame;
|
speedInfo->activation_frame = state->activation_frame;
|
||||||
_PushSpeedInfo(speedInfo);
|
_PushSpeedInfo(speedInfo);
|
||||||
// If the new state is a playing state and looping is turned off,
|
// If the new state is a playing state and looping is turned off,
|
||||||
// determine when playing shall stop.
|
// determine when playing shall stop.
|
||||||
if (playingDirection != 0 && !state->looping_enabled) {
|
if (playingDirection != 0 && !state->looping_enabled) {
|
||||||
int64 startFrame, endFrame, frameCount;
|
int64 startFrame, endFrame, frameCount;
|
||||||
_GetPlayingBoundsFor(state, startFrame, endFrame, frameCount);
|
_GetPlayingBoundsFor(state, startFrame, endFrame, frameCount);
|
||||||
if (playingDirection == -1)
|
if (playingDirection == -1)
|
||||||
swap(startFrame, endFrame);
|
swap(startFrame, endFrame);
|
||||||
// If we shall stop at the frame we start, set the current frame
|
// If we shall stop at the frame we start, set the current frame
|
||||||
// to the beginning of the range.
|
// to the beginning of the range.
|
||||||
// We have to take care, since this state may equal the one
|
// We have to take care, since this state may equal the one
|
||||||
// before (or probably differs in just one (unimportant)
|
// before (or probably differs in just one (unimportant)
|
||||||
// parameter). This happens for instance, if the user changes the
|
// parameter). This happens for instance, if the user changes the
|
||||||
// data or start/end frame... while playing. In this case setting
|
// data or start/end frame... while playing. In this case setting
|
||||||
// the current frame to the start frame is unwanted. Therefore
|
// the current frame to the start frame is unwanted. Therefore
|
||||||
// we check whether the previous state was intended to stop
|
// we check whether the previous state was intended to stop
|
||||||
// at the activation frame of this state.
|
// at the activation frame of this state.
|
||||||
if (oldStopPlayingFrame != state->activation_frame
|
if (oldStopPlayingFrame != state->activation_frame
|
||||||
&& state->current_frame == endFrame && frameCount > 1) {
|
&& state->current_frame == endFrame && frameCount > 1) {
|
||||||
state->current_frame = startFrame;
|
state->current_frame = startFrame;
|
||||||
state->range_index
|
state->range_index
|
||||||
= _RangeFrameForFrame(state, state->current_frame);
|
= _RangeFrameForFrame(state, state->current_frame);
|
||||||
}
|
|
||||||
if (playingDirection == 1) { // forward
|
|
||||||
fStopPlayingFrame = state->activation_frame
|
|
||||||
+ frameCount - state->range_index - 1;
|
|
||||||
} else { // backwards
|
|
||||||
fStopPlayingFrame = state->activation_frame
|
|
||||||
+ state->range_index;
|
|
||||||
}
|
|
||||||
_CheckStopPlaying();
|
|
||||||
}
|
}
|
||||||
|
if (playingDirection == 1) { // forward
|
||||||
|
fStopPlayingFrame = state->activation_frame
|
||||||
|
+ frameCount - state->range_index - 1;
|
||||||
|
} else { // backwards
|
||||||
|
fStopPlayingFrame = state->activation_frame
|
||||||
|
+ state->range_index;
|
||||||
|
}
|
||||||
|
_CheckStopPlaying();
|
||||||
}
|
}
|
||||||
TRACE("PlaybackManager::_PushState() done\n");
|
TRACE("PlaybackManager::_PushState() done\n");
|
||||||
}
|
}
|
||||||
@@ -1213,6 +1248,11 @@ PlaybackManager::_UpdateStates()
|
|||||||
TRACE("_UpdateStates: states removed: %ld, state count: %ld\n",
|
TRACE("_UpdateStates: states removed: %ld, state count: %ld\n",
|
||||||
firstActive, fStates.CountItems());
|
firstActive, fStates.CountItems());
|
||||||
}
|
}
|
||||||
|
PlayingState* currentState = _StateAt(firstActive);
|
||||||
|
if (currentState != NULL && currentState->is_seek_request) {
|
||||||
|
currentState->is_seek_request = false;
|
||||||
|
NotifySeekHandled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000-2008, Ingo Weinhold <ingo_weinhold@gmx.de>,
|
* Copyright (c) 2000-2008, Ingo Weinhold <ingo_weinhold@gmx.de>,
|
||||||
* Copyright (c) 2000-2008, Stephan Aßmus <superstippi@gmx.de>,
|
* Copyright (c) 2000-2008, Stephan Aßmus <superstippi@gmx.de>,
|
||||||
* All Rights Reserved. Distributed under the terms of the MIT license.
|
* All Rights Reserved. Distributed under the terms of the MIT license.
|
||||||
@@ -169,6 +169,7 @@ public:
|
|||||||
virtual void NotifySpeedChanged(float speed) const;
|
virtual void NotifySpeedChanged(float speed) const;
|
||||||
virtual void NotifyFrameDropped() const;
|
virtual void NotifyFrameDropped() const;
|
||||||
virtual void NotifyStopFrameReached() const;
|
virtual void NotifyStopFrameReached() const;
|
||||||
|
virtual void NotifySeekHandled() const;
|
||||||
|
|
||||||
// debugging
|
// debugging
|
||||||
void PrintState(PlayingState* state);
|
void PrintState(PlayingState* state);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008 Stephan Aßmus <superstippi@gmx.de>.
|
* Copyright 2008, Stephan Aßmus <superstippi@gmx.de>.
|
||||||
* Copyright 1998 Eric Shepherd.
|
* Copyright 1998, Eric Shepherd.
|
||||||
* All rights reserved. Distributed under the terms of the Be Sample Code
|
* All rights reserved. Distributed under the terms of the Be Sample Code
|
||||||
* license.
|
* license.
|
||||||
*/
|
*/
|
||||||
@@ -159,7 +159,7 @@ SettingsMessage::SetValue(const char* name, const BString& value)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
SettingsMessage::SetValue(const char* name, const BPoint& value)
|
SettingsMessage::SetValue(const char* name, const BPoint& value)
|
||||||
{
|
{
|
||||||
if (ReplacePoint(name, value) == B_OK)
|
if (ReplacePoint(name, value) == B_OK)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user