From 7aea2c3513bae23ad14c19e00319bd7b71f70ce3 Mon Sep 17 00:00:00 2001
From: Julien Lepiller <julien@lepiller.eu>
Date: Tue, 29 Apr 2014 18:44:47 +0200
Subject: [PATCH] Mediaplayer: resume at latest position and restore volume
---
src/apps/mediaplayer/Controller.cpp | 47 +++++++++++++++++++++-
src/apps/mediaplayer/Controller.h | 4 ++
src/apps/mediaplayer/MainWin.cpp | 11 ++++-
src/apps/mediaplayer/playlist/FilePlaylistItem.cpp | 20 ++++++++-
src/apps/mediaplayer/playlist/FilePlaylistItem.h | 2 +-
src/apps/mediaplayer/playlist/PlaylistItem.cpp | 30 ++++++++++++++
src/apps/mediaplayer/playlist/PlaylistItem.h | 9 ++++-
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, 141 insertions(+), 6 deletions(-)
diff --git a/src/apps/mediaplayer/Controller.cpp b/src/apps/mediaplayer/Controller.cpp
index 5176a3d..f6666b4 100644
a
|
b
|
Controller::SetToAsync(const PlaylistItemRef& item)
|
219 | 219 | return B_OK; |
220 | 220 | } |
221 | 221 | |
222 | | |
223 | 222 | status_t |
224 | 223 | Controller::SetTo(const PlaylistItemRef& item) |
225 | 224 | { |
… |
… |
Controller::TimePosition()
|
679 | 678 | return _TimePosition(); |
680 | 679 | } |
681 | 680 | |
| 681 | status_t |
| 682 | Controller::SaveState(bool reset) |
| 683 | { |
| 684 | if(fItem.Get() == NULL) |
| 685 | return B_OK; |
| 686 | if(reset) |
| 687 | fCurrentFrame = 0; |
| 688 | status_t status = fItem.Get()->SetLastVolume(50*fVolume); |
| 689 | if(status == B_OK) |
| 690 | status = fItem.Get()->SetLastFrame(fCurrentFrame); |
| 691 | else |
| 692 | fItem.Get()->SetLastFrame(fCurrentFrame); |
| 693 | return status; |
| 694 | } |
| 695 | |
| 696 | void |
| 697 | Controller::RestoreState() |
| 698 | { |
| 699 | PlaylistItem *item =fItem.Get(); |
| 700 | if(item == NULL) |
| 701 | return; |
| 702 | |
| 703 | Pause(); |
| 704 | |
| 705 | if(item->LastFrame() > 0) { |
| 706 | bool resume = fResume == mpSettings::RESUME_ALWAYS; |
| 707 | if(fResume == mpSettings::RESUME_ASK) { |
| 708 | BString label = "Do you want to resume "; |
| 709 | int32 time = (int32)((float)item->LastFrame() * TimeDuration() / (1000000*_FrameDuration())); |
| 710 | label << item->Name() << " at " << (time/60) << "m" << (time%60) << "s?"; |
| 711 | BAlert *alert = new BAlert("Resume?", label, "Resume", "Reset"); |
| 712 | resume = alert->Go() == 0; |
| 713 | } |
| 714 | |
| 715 | if(resume) |
| 716 | SetFramePosition(item->LastFrame()); |
| 717 | } |
| 718 | |
| 719 | int32 lastVolume = item->LastVolume(); |
| 720 | if(lastVolume >= 0) |
| 721 | SetVolume((float)lastVolume/50); |
| 722 | |
| 723 | Play(); |
| 724 | } |
| 725 | |
682 | 726 | |
683 | 727 | void |
684 | 728 | Controller::SetVolume(float value) |
… |
… |
Controller::_AdoptGlobalSettings()
|
974 | 1018 | fLoopMovies = settings.loopMovie; |
975 | 1019 | fLoopSounds = settings.loopSound; |
976 | 1020 | fBackgroundMovieVolumeMode = settings.backgroundMovieVolumeMode; |
| 1021 | fResume = settings.resume; |
977 | 1022 | } |
978 | 1023 | |
979 | 1024 | |
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 6038a61..d4aa8a5 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..5eb7e24 100644
a
|
b
|
FilePlaylistItem::SetAttribute(const Attribute& attribute,
|
171 | 171 | case ATTR_INT32_RATING: |
172 | 172 | return _SetAttribute("Media:Rating", B_INT32_TYPE, &value, |
173 | 173 | sizeof(int32)); |
| 174 | case ATTR_INT32_FRAME: |
| 175 | return _SetAttribute("Media:Frame", B_INT32_TYPE, &value, |
| 176 | sizeof(int32)); |
| 177 | case ATTR_INT32_VOLUME: |
| 178 | return _SetAttribute("Media:Volume", B_INT32_TYPE, &value, |
| 179 | sizeof(int32)); |
174 | 180 | |
175 | 181 | default: |
176 | 182 | return B_NOT_SUPPORTED; |
… |
… |
status_t
|
182 | 188 | FilePlaylistItem::GetAttribute(const Attribute& attribute, |
183 | 189 | int32& value) const |
184 | 190 | { |
185 | | return B_NOT_SUPPORTED; |
| 191 | switch (attribute) { |
| 192 | case ATTR_INT32_FRAME: |
| 193 | return _GetAttribute("Media:Frame", B_INT32_TYPE, &value, |
| 194 | sizeof(int32)); |
| 195 | case ATTR_INT32_VOLUME: |
| 196 | return _GetAttribute("Media:Volume", B_INT32_TYPE, &value, |
| 197 | sizeof(int32)); |
| 198 | |
| 199 | default: |
| 200 | return B_NOT_SUPPORTED; |
| 201 | } |
186 | 202 | } |
187 | 203 | |
188 | 204 | |
… |
… |
FilePlaylistItem::_SetAttribute(const char* attrName, type_code type,
|
407 | 423 | |
408 | 424 | status_t |
409 | 425 | FilePlaylistItem::_GetAttribute(const char* attrName, type_code type, |
410 | | void* data, size_t size) |
| 426 | void* data, size_t size) const |
411 | 427 | { |
412 | 428 | BEntry entry(&fRefs[0], true); |
413 | 429 | BNode node(&entry); |
diff --git a/src/apps/mediaplayer/playlist/FilePlaylistItem.h b/src/apps/mediaplayer/playlist/FilePlaylistItem.h
index a0c4da4..fb72f9e 100644
a
|
b
|
private:
|
67 | 67 | size_t size); |
68 | 68 | status_t _GetAttribute(const char* attrName, |
69 | 69 | type_code type, void* data, |
70 | | size_t size); |
| 70 | size_t size) const; |
71 | 71 | status_t _MoveIntoTrash(vector<entry_ref>* refs, |
72 | 72 | vector<BString>* namesInTrash); |
73 | 73 | 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..71cfec9 100644
a
|
b
|
PlaylistItem::TrackNumber() const
|
106 | 106 | return trackNumber; |
107 | 107 | } |
108 | 108 | |
| 109 | int32 |
| 110 | PlaylistItem::LastFrame() const |
| 111 | { |
| 112 | int32 lastFrame; |
| 113 | if(GetAttribute(ATTR_INT32_FRAME, lastFrame) != B_OK) |
| 114 | lastFrame = 0; |
| 115 | return lastFrame; |
| 116 | } |
| 117 | |
| 118 | int32 |
| 119 | PlaylistItem::LastVolume() const |
| 120 | { |
| 121 | int32 lastVolume; |
| 122 | if(GetAttribute(ATTR_INT32_VOLUME, lastVolume) != B_OK) |
| 123 | lastVolume = -1; |
| 124 | return lastVolume; |
| 125 | } |
| 126 | |
| 127 | status_t |
| 128 | PlaylistItem::SetLastFrame(int32 value) |
| 129 | { |
| 130 | return SetAttribute(ATTR_INT32_FRAME, value); |
| 131 | } |
| 132 | |
| 133 | status_t |
| 134 | PlaylistItem::SetLastVolume(int32 value) |
| 135 | { |
| 136 | return SetAttribute(ATTR_INT32_VOLUME, value); |
| 137 | } |
| 138 | |
109 | 139 | |
110 | 140 | void |
111 | 141 | PlaylistItem::SetPlaybackFailed() |
diff --git a/src/apps/mediaplayer/playlist/PlaylistItem.h b/src/apps/mediaplayer/playlist/PlaylistItem.h
index b896df5..b7d3528 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 | ATTR_INT32_FRAME = 'fram', |
| 58 | ATTR_INT32_VOLUME = 'volu' |
57 | 59 | } Attribute; |
58 | 60 | |
59 | 61 | virtual status_t SetAttribute(const Attribute& attribute, |
… |
… |
public:
|
78 | 80 | BString Title() const; |
79 | 81 | |
80 | 82 | int32 TrackNumber() const; |
| 83 | int32 LastFrame() const; |
| 84 | int32 LastVolume() const; |
| 85 | |
| 86 | status_t SetLastFrame(int32 value); |
| 87 | status_t SetLastVolume(int32 value); |
81 | 88 | |
82 | 89 | // methods |
83 | 90 | 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 | |