From d4806992aef33492c7a1dd623678dd3d03492158 Mon Sep 17 00:00:00 2001
From: Julien Lepiller <julien@lepiller.eu>
Date: Sat, 20 Sep 2014 20:36:51 +0200
Subject: [PATCH] MediaPlayer: remember position and volume
---
src/apps/mediaplayer/Controller.cpp | 52 +++++++++++++++++++++-
src/apps/mediaplayer/Controller.h | 4 ++
src/apps/mediaplayer/MainWin.cpp | 11 ++++-
src/apps/mediaplayer/playlist/FilePlaylistItem.cpp | 32 ++++++++++++-
src/apps/mediaplayer/playlist/FilePlaylistItem.h | 7 ++-
src/apps/mediaplayer/playlist/PlaylistItem.cpp | 29 ++++++++++++
src/apps/mediaplayer/playlist/PlaylistItem.h | 16 ++++++-
src/apps/mediaplayer/settings/Settings.cpp | 5 +++
src/apps/mediaplayer/settings/Settings.h | 6 +++
src/apps/mediaplayer/settings/SettingsWindow.cpp | 12 +++++
src/apps/mediaplayer/settings/SettingsWindow.h | 1 +
11 files changed, 170 insertions(+), 5 deletions(-)
diff --git a/src/apps/mediaplayer/Controller.cpp b/src/apps/mediaplayer/Controller.cpp
index 5176a3d..4ffc100 100644
a
|
b
|
|
29 | 29 | |
30 | 30 | #include <Autolock.h> |
31 | 31 | #include <Bitmap.h> |
| 32 | #include <Catalog.h> |
32 | 33 | #include <Debug.h> |
33 | 34 | #include <Path.h> |
34 | 35 | #include <Window.h> // for debugging only |
… |
… |
|
50 | 51 | #include "TrackSupplier.h" |
51 | 52 | #include "VideoTrackSupplier.h" |
52 | 53 | |
| 54 | #undef B_TRANSLATION_CONTEXT |
| 55 | #define B_TRANSLATION_CONTEXT "MediaPlayer-Controller" |
| 56 | #define MIN_WIDTH 250 |
| 57 | |
53 | 58 | using std::nothrow; |
54 | 59 | |
55 | 60 | |
… |
… |
Controller::SetToAsync(const PlaylistItemRef& item)
|
219 | 224 | return B_OK; |
220 | 225 | } |
221 | 226 | |
222 | | |
223 | 227 | status_t |
224 | 228 | Controller::SetTo(const PlaylistItemRef& item) |
225 | 229 | { |
… |
… |
Controller::TimePosition()
|
679 | 683 | return _TimePosition(); |
680 | 684 | } |
681 | 685 | |
| 686 | status_t |
| 687 | Controller::SaveState(bool reset) |
| 688 | { |
| 689 | if (fItem.Get() == NULL) |
| 690 | return B_OK; |
| 691 | if (reset) |
| 692 | fCurrentFrame = 0; |
| 693 | status_t status = fItem.Get()->SetLastVolume(fVolume); |
| 694 | if (status == B_OK) |
| 695 | status = fItem.Get()->SetLastFrame(fCurrentFrame); |
| 696 | else |
| 697 | fItem.Get()->SetLastFrame(fCurrentFrame); |
| 698 | return status; |
| 699 | } |
| 700 | |
| 701 | void |
| 702 | Controller::RestoreState() |
| 703 | { |
| 704 | PlaylistItem *item =fItem.Get(); |
| 705 | if (item == NULL) |
| 706 | return; |
| 707 | |
| 708 | Pause(); |
| 709 | |
| 710 | if (item->LastFrame() > 0) { |
| 711 | bool resume = fResume == mpSettings::RESUME_ALWAYS; |
| 712 | if (fResume == mpSettings::RESUME_ASK) { |
| 713 | BString label; |
| 714 | int32 time = (int32)((float)item->LastFrame() * TimeDuration() / (1000000*_FrameDuration())); |
| 715 | label.SetToFormat(B_TRANSLATE("Do you want to resume %s at %dm%ds?"), |
| 716 | item->Name().String(), time/60, time%60); |
| 717 | BAlert *alert = new BAlert(B_TRANSLATE("Resume?"), label, B_TRANSLATE("Resume"), B_TRANSLATE("Reset")); |
| 718 | resume = alert->Go() == 0; |
| 719 | } |
| 720 | |
| 721 | if (resume) |
| 722 | SetFramePosition(item->LastFrame()); |
| 723 | } |
| 724 | |
| 725 | float lastVolume = item->LastVolume(); |
| 726 | if (lastVolume >= 0) |
| 727 | SetVolume(lastVolume); |
| 728 | |
| 729 | Play(); |
| 730 | } |
682 | 731 | |
683 | 732 | void |
684 | 733 | Controller::SetVolume(float value) |
… |
… |
Controller::_AdoptGlobalSettings()
|
974 | 1023 | fLoopMovies = settings.loopMovie; |
975 | 1024 | fLoopSounds = settings.loopSound; |
976 | 1025 | fBackgroundMovieVolumeMode = settings.backgroundMovieVolumeMode; |
| 1026 | fResume = settings.resume; |
977 | 1027 | } |
978 | 1028 | |
979 | 1029 | |
diff --git a/src/apps/mediaplayer/Controller.h b/src/apps/mediaplayer/Controller.h
index 1eeda17..451d55a 100644
a
|
b
|
|
22 | 22 | #define __CONTROLLER_H |
23 | 23 | |
24 | 24 | |
| 25 | #include <Alert.h> |
25 | 26 | #include <Entry.h> |
26 | 27 | #include <MediaDefs.h> |
27 | 28 | #include <MediaFormats.h> |
… |
… |
public:
|
115 | 116 | |
116 | 117 | bigtime_t TimeDuration(); |
117 | 118 | bigtime_t TimePosition(); |
| 119 | status_t SaveState(bool reset = false); |
| 120 | void RestoreState(); |
118 | 121 | |
119 | 122 | virtual void SetVolume(float factor); |
120 | 123 | float Volume(); |
… |
… |
private:
|
224 | 227 | bool fLoopMovies; |
225 | 228 | bool fLoopSounds; |
226 | 229 | uint32 fBackgroundMovieVolumeMode; |
| 230 | uint32 fResume; |
227 | 231 | |
228 | 232 | BList fListeners; |
229 | 233 | }; |
diff --git a/src/apps/mediaplayer/MainWin.cpp b/src/apps/mediaplayer/MainWin.cpp
index 3229867..f5eb7e7 100644
a
|
b
|
MainWin::MessageReceived(BMessage* msg)
|
697 | 697 | { |
698 | 698 | BAutolock _(fPlaylist); |
699 | 699 | |
| 700 | //The file is finished. Open at start next time. |
| 701 | fController->SaveState(true); |
| 702 | |
700 | 703 | bool hadNext = fPlaylist->SetCurrentItemIndex( |
701 | 704 | fPlaylist->CurrentItemIndex() + 1); |
702 | 705 | if (!hadNext) { |
… |
… |
MainWin::MessageReceived(BMessage* msg)
|
799 | 802 | float volume; |
800 | 803 | if (msg->FindFloat("volume", &volume) == B_OK) |
801 | 804 | fControls->SetVolume(volume); |
| 805 | fController->SaveState(); |
802 | 806 | break; |
803 | 807 | } |
804 | 808 | case MSG_CONTROLLER_MUTED_CHANGED: |
… |
… |
MainWin::WindowActivated(bool active)
|
1067 | 1071 | bool |
1068 | 1072 | MainWin::QuitRequested() |
1069 | 1073 | { |
| 1074 | fController->SaveState(); |
1070 | 1075 | BMessage message(M_PLAYER_QUIT); |
1071 | 1076 | GetQuitMessage(&message); |
1072 | 1077 | be_app->PostMessage(&message); |
… |
… |
MainWin::_PlaylistItemOpened(const PlaylistItemRef& item, status_t result)
|
1401 | 1406 | } |
1402 | 1407 | fController->SetTimePosition(fInitialSeekPosition); |
1403 | 1408 | fInitialSeekPosition = 0; |
| 1409 | |
| 1410 | if (fPlaylist->CountItems() == 1) |
| 1411 | fController->RestoreState(); |
1404 | 1412 | } |
1405 | 1413 | _SetupWindow(); |
1406 | 1414 | |
… |
… |
MainWin::_Wind(bigtime_t howMuch, int64 frames)
|
2452 | 2460 | } else if (seekTime > fController->TimeDuration()) { |
2453 | 2461 | fInitialSeekPosition = 0; |
2454 | 2462 | PostMessage(M_SKIP_NEXT); |
2455 | | } else |
| 2463 | } else { |
2456 | 2464 | fController->SetTimePosition(seekTime); |
| 2465 | } |
2457 | 2466 | } |
2458 | 2467 | |
2459 | 2468 | fController->Unlock(); |
diff --git a/src/apps/mediaplayer/playlist/FilePlaylistItem.cpp b/src/apps/mediaplayer/playlist/FilePlaylistItem.cpp
index 4b1cafd..cd41216 100644
a
|
b
|
status_t
|
190 | 190 | FilePlaylistItem::SetAttribute(const Attribute& attribute, |
191 | 191 | const int64& value) |
192 | 192 | { |
| 193 | if (attribute == ATTR_INT64_FRAME) |
| 194 | return _SetAttribute("Media:Frame", B_INT64_TYPE, &value, |
| 195 | sizeof(int64)); |
| 196 | |
193 | 197 | return B_NOT_SUPPORTED; |
194 | 198 | } |
195 | 199 | |
… |
… |
status_t
|
198 | 202 | FilePlaylistItem::GetAttribute(const Attribute& attribute, |
199 | 203 | int64& value) const |
200 | 204 | { |
| 205 | if (attribute == ATTR_INT64_FRAME) |
| 206 | return _GetAttribute("Media:Frame", B_INT64_TYPE, &value, |
| 207 | sizeof(int64)); |
| 208 | |
| 209 | return B_NOT_SUPPORTED; |
| 210 | } |
| 211 | |
| 212 | status_t |
| 213 | FilePlaylistItem::SetAttribute(const Attribute& attribute, |
| 214 | const float& value) |
| 215 | { |
| 216 | if (attribute == ATTR_FLOAT_VOLUME) |
| 217 | return _SetAttribute("Media:Volume", B_FLOAT_TYPE, &value, |
| 218 | sizeof(float)); |
| 219 | |
| 220 | return B_NOT_SUPPORTED; |
| 221 | } |
| 222 | |
| 223 | status_t |
| 224 | FilePlaylistItem::GetAttribute(const Attribute& attribute, |
| 225 | float& value) const |
| 226 | { |
| 227 | if (attribute == ATTR_FLOAT_VOLUME) |
| 228 | return _GetAttribute("Media:Volume", B_FLOAT_TYPE, &value, |
| 229 | sizeof(float)); |
| 230 | |
201 | 231 | return B_NOT_SUPPORTED; |
202 | 232 | } |
203 | 233 | |
… |
… |
FilePlaylistItem::_SetAttribute(const char* attrName, type_code type,
|
407 | 437 | |
408 | 438 | status_t |
409 | 439 | FilePlaylistItem::_GetAttribute(const char* attrName, type_code type, |
410 | | void* data, size_t size) |
| 440 | void* data, size_t size) const |
411 | 441 | { |
412 | 442 | BEntry entry(&fRefs[0], true); |
413 | 443 | BNode node(&entry); |
diff --git a/src/apps/mediaplayer/playlist/FilePlaylistItem.h b/src/apps/mediaplayer/playlist/FilePlaylistItem.h
index a0c4da4..126cf78 100644
a
|
b
|
public:
|
43 | 43 | const int64& value); |
44 | 44 | virtual status_t GetAttribute(const Attribute& attribute, |
45 | 45 | int64& value) const; |
| 46 | |
| 47 | virtual status_t SetAttribute(const Attribute& attribute, |
| 48 | const float& value); |
| 49 | virtual status_t GetAttribute(const Attribute& attribute, |
| 50 | float& value) const; |
46 | 51 | |
47 | 52 | // methods |
48 | 53 | virtual BString LocationURI() const; |
… |
… |
private:
|
67 | 72 | size_t size); |
68 | 73 | status_t _GetAttribute(const char* attrName, |
69 | 74 | type_code type, void* data, |
70 | | size_t size); |
| 75 | size_t size) const; |
71 | 76 | status_t _MoveIntoTrash(vector<entry_ref>* refs, |
72 | 77 | vector<BString>* namesInTrash); |
73 | 78 | status_t _RestoreFromTrash(vector<entry_ref>* refs, |
diff --git a/src/apps/mediaplayer/playlist/PlaylistItem.cpp b/src/apps/mediaplayer/playlist/PlaylistItem.cpp
index fde90a8..de91700 100644
a
|
b
|
PlaylistItem::TrackNumber() const
|
106 | 106 | return trackNumber; |
107 | 107 | } |
108 | 108 | |
| 109 | int64 |
| 110 | PlaylistItem::LastFrame() const |
| 111 | { |
| 112 | int64 lastFrame; |
| 113 | if (GetAttribute(ATTR_INT64_FRAME, lastFrame) != B_OK) |
| 114 | lastFrame = 0; |
| 115 | return lastFrame; |
| 116 | } |
| 117 | |
| 118 | float |
| 119 | PlaylistItem::LastVolume() const |
| 120 | { |
| 121 | float lastVolume; |
| 122 | if (GetAttribute(ATTR_FLOAT_VOLUME, lastVolume) != B_OK) |
| 123 | lastVolume = -1; |
| 124 | return lastVolume; |
| 125 | } |
| 126 | |
| 127 | status_t |
| 128 | PlaylistItem::SetLastFrame(int64 value) |
| 129 | { |
| 130 | return SetAttribute(ATTR_INT64_FRAME, value); |
| 131 | } |
| 132 | |
| 133 | status_t |
| 134 | PlaylistItem::SetLastVolume(float value) |
| 135 | { |
| 136 | return SetAttribute(ATTR_FLOAT_VOLUME, value); |
| 137 | } |
109 | 138 | |
110 | 139 | void |
111 | 140 | PlaylistItem::SetPlaybackFailed() |
diff --git a/src/apps/mediaplayer/playlist/PlaylistItem.h b/src/apps/mediaplayer/playlist/PlaylistItem.h
index b896df5..a34f9a7 100644
a
|
b
|
public:
|
53 | 53 | |
54 | 54 | ATTR_INT32_TRACK = 'trck', |
55 | 55 | ATTR_INT32_YEAR = 'year', |
56 | | ATTR_INT32_RATING = 'rtng' |
| 56 | ATTR_INT32_RATING = 'rtng', |
| 57 | |
| 58 | ATTR_INT64_FRAME = 'fram', |
| 59 | |
| 60 | ATTR_FLOAT_VOLUME = 'volu' |
57 | 61 | } Attribute; |
58 | 62 | |
59 | 63 | virtual status_t SetAttribute(const Attribute& attribute, |
… |
… |
public:
|
70 | 74 | const int64& value) = 0; |
71 | 75 | virtual status_t GetAttribute(const Attribute& attribute, |
72 | 76 | int64& value) const = 0; |
| 77 | |
| 78 | virtual status_t SetAttribute(const Attribute& attribute, |
| 79 | const float& value) = 0; |
| 80 | virtual status_t GetAttribute(const Attribute& attribute, |
| 81 | float& value) const = 0; |
73 | 82 | |
74 | 83 | // convenience access to attributes |
75 | 84 | BString Name() const; |
… |
… |
public:
|
78 | 87 | BString Title() const; |
79 | 88 | |
80 | 89 | int32 TrackNumber() const; |
| 90 | int64 LastFrame() const; |
| 91 | float LastVolume() const; |
| 92 | |
| 93 | status_t SetLastFrame(int64 value); |
| 94 | status_t SetLastVolume(float value); |
81 | 95 | |
82 | 96 | // methods |
83 | 97 | virtual BString LocationURI() const = 0; |
diff --git a/src/apps/mediaplayer/settings/Settings.cpp b/src/apps/mediaplayer/settings/Settings.cpp
index 7f1d00d..a4b22f9 100644
a
|
b
|
mpSettings::operator!=(const mpSettings& other) const
|
26 | 26 | || useOverlays != other.useOverlays |
27 | 27 | || scaleBilinear != other.scaleBilinear |
28 | 28 | || scaleFullscreenControls != other.scaleFullscreenControls |
| 29 | || resume != other.resume |
29 | 30 | || subtitleSize != other.subtitleSize |
30 | 31 | || subtitlePlacement != other.subtitlePlacement |
31 | 32 | || backgroundMovieVolumeMode != other.backgroundMovieVolumeMode |
… |
… |
Settings::Get(mpSettings& settings) const
|
61 | 62 | settings.scaleFullscreenControls |
62 | 63 | = fSettingsMessage.GetValue("scaleFullscreenControls", true); |
63 | 64 | |
| 65 | settings.resume |
| 66 | = fSettingsMessage.GetValue("resume", |
| 67 | (uint32)mpSettings::RESUME_ASK); |
64 | 68 | settings.subtitleSize |
65 | 69 | = fSettingsMessage.GetValue("subtitleSize", |
66 | 70 | (uint32)mpSettings::SUBTITLE_SIZE_MEDIUM); |
… |
… |
Settings::Update(const mpSettings& settings)
|
95 | 99 | fSettingsMessage.SetValue("scaleFullscreenControls", |
96 | 100 | settings.scaleFullscreenControls); |
97 | 101 | |
| 102 | fSettingsMessage.SetValue("resume", settings.resume); |
98 | 103 | fSettingsMessage.SetValue("subtitleSize", settings.subtitleSize); |
99 | 104 | fSettingsMessage.SetValue("subtitlePlacement", settings.subtitlePlacement); |
100 | 105 | |
diff --git a/src/apps/mediaplayer/settings/Settings.h b/src/apps/mediaplayer/settings/Settings.h
index f8b3590..5dbc499 100644
a
|
b
|
struct mpSettings {
|
34 | 34 | BG_MOVIES_HALF_VLUME = 1, |
35 | 35 | BG_MOVIES_MUTED = 2 |
36 | 36 | }; |
| 37 | enum { |
| 38 | RESUME_NEVER = 0, |
| 39 | RESUME_ASK = 1, |
| 40 | RESUME_ALWAYS = 2 |
| 41 | }; |
37 | 42 | |
38 | 43 | bool autostart; |
39 | 44 | bool closeWhenDonePlayingMovie; |
… |
… |
struct mpSettings {
|
43 | 48 | bool useOverlays; |
44 | 49 | bool scaleBilinear; |
45 | 50 | bool scaleFullscreenControls; |
| 51 | uint32 resume; |
46 | 52 | uint32 subtitleSize; |
47 | 53 | uint32 subtitlePlacement; |
48 | 54 | uint32 backgroundMovieVolumeMode; |
diff --git a/src/apps/mediaplayer/settings/SettingsWindow.cpp b/src/apps/mediaplayer/settings/SettingsWindow.cpp
index ea1cc17..d3eaa62 100644
a
|
b
|
SettingsWindow::SettingsWindow(BRect frame)
|
99 | 99 | B_TRANSLATE("Scale controls in full screen mode"), |
100 | 100 | new BMessage(M_SETTINGS_CHANGED)); |
101 | 101 | |
| 102 | fResumeOP = new BOptionPopUp("resume", |
| 103 | B_TRANSLATE("Resume:"), new BMessage(M_SETTINGS_CHANGED)); |
| 104 | fResumeOP->AddOption( |
| 105 | B_TRANSLATE("never"), mpSettings::RESUME_NEVER); |
| 106 | fResumeOP->AddOption( |
| 107 | B_TRANSLATE("ask every time"), mpSettings::RESUME_ASK); |
| 108 | fResumeOP->AddOption( |
| 109 | B_TRANSLATE("always"), mpSettings::RESUME_ALWAYS); |
| 110 | |
102 | 111 | fSubtitleSizeOP = new BOptionPopUp("subtitleSize", |
103 | 112 | B_TRANSLATE("Subtitle size:"), new BMessage(M_SETTINGS_CHANGED)); |
104 | 113 | fSubtitleSizeOP->AddOption( |
… |
… |
SettingsWindow::SettingsWindow(BRect frame)
|
156 | 165 | .End() |
157 | 166 | .Add(fLoopMoviesCB) |
158 | 167 | .Add(fLoopSoundsCB) |
| 168 | .Add(fResumeOP) |
159 | 169 | .End() |
160 | 170 | .End() |
161 | 171 | .AddStrut(kSpacing) |
… |
… |
SettingsWindow::AdoptSettings()
|
270 | 280 | fScaleBilinearCB->SetValue(fSettings.scaleBilinear); |
271 | 281 | fScaleFullscreenControlsCB->SetValue(fSettings.scaleFullscreenControls); |
272 | 282 | |
| 283 | fResumeOP->SetValue(fSettings.resume); |
273 | 284 | fSubtitleSizeOP->SetValue(fSettings.subtitleSize); |
274 | 285 | fSubtitlePlacementOP->SetValue(fSettings.subtitlePlacement); |
275 | 286 | |
… |
… |
SettingsWindow::ApplySettings()
|
300 | 311 | fSettings.scaleFullscreenControls |
301 | 312 | = fScaleFullscreenControlsCB->Value() == B_CONTROL_ON; |
302 | 313 | |
| 314 | fSettings.resume = fResumeOP->Value(); |
303 | 315 | fSettings.subtitleSize = fSubtitleSizeOP->Value(); |
304 | 316 | fSettings.subtitlePlacement = fSubtitlePlacementOP->Value(); |
305 | 317 | |
diff --git a/src/apps/mediaplayer/settings/SettingsWindow.h b/src/apps/mediaplayer/settings/SettingsWindow.h
index 6285620..312927a 100644
a
|
b
|
private:
|
47 | 47 | BCheckBox* fScaleBilinearCB; |
48 | 48 | BCheckBox* fScaleFullscreenControlsCB; |
49 | 49 | |
| 50 | BOptionPopUp* fResumeOP; |
50 | 51 | BOptionPopUp* fSubtitleSizeOP; |
51 | 52 | BOptionPopUp* fSubtitlePlacementOP; |
52 | 53 | |