aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxhaggi <sascha.woo@gmail.com>2014-09-24 15:03:50 +0200
committerxhaggi <sascha.woo@gmail.com>2015-02-08 17:46:21 +0100
commitface9ead060c964f0bae4c3b6179ea36d98708a5 (patch)
treec75708431356a5e623d31ff3007b1c6006315daf
parentcc9ed5f04471237e36c8350c8933556a348f8fe8 (diff)
[seek] adds additive seek support
-rwxr-xr-xlanguage/English/strings.po28
-rw-r--r--system/settings/settings.xml30
-rw-r--r--xbmc/Application.cpp5
-rw-r--r--xbmc/settings/AdvancedSettings.cpp22
-rw-r--r--xbmc/settings/AdvancedSettings.h1
-rw-r--r--xbmc/settings/Settings.cpp9
-rw-r--r--xbmc/utils/SeekHandler.cpp141
-rw-r--r--xbmc/utils/SeekHandler.h28
8 files changed, 239 insertions, 25 deletions
diff --git a/language/English/strings.po b/language/English/strings.po
index 0c4d57dfdc..a1cb5ccfa4 100755
--- a/language/English/strings.po
+++ b/language/English/strings.po
@@ -6432,7 +6432,19 @@ msgctxt "#13555"
msgid "%d Minutes"
msgstr ""
-#empty strings from id 13556 to 13599
+#. Label of a setting that allows to select the skip step sizes to use for skipping
+#: system/settings/settings.xml
+msgctxt "#13556"
+msgid "Skip steps"
+msgstr ""
+
+#. Name of a setting to configure the time to wait for subsequent keypresses in order to apply additive skipping
+#: system/settings/settings.xml
+msgctxt "#13557"
+msgid "Skip delay"
+msgstr ""
+
+#empty strings from id 13557 to 13599
#: system/settings/darwin.xml
msgctxt "#13600"
@@ -16193,7 +16205,19 @@ msgctxt "#37041"
msgid "Use audio streams that are flagged as "default" (and match the preferred language) regardless of the number of channels or the used codec."
msgstr ""
-#empty strings from id 37042 to 38009
+#. Description of setting "Videos -> Playback -> Skip steps"
+#: system/settings/settings.xml
+msgctxt "#37042"
+msgid "Defines which step sizes to use when pressing the skip buttons. If more steps are selected for a skip direction, these can be applied by subsequent presses on the skip button within the defined skip delay. Forward (positive) and backward (negative) steps can be defined independently."
+msgstr ""
+
+#. Description of setting "Videos -> Playback -> Skip delay"
+#: system/settings/settings.xml
+msgctxt "#37043"
+msgid "Defines the time to wait for subsequent key presses before performing the skip. Only applies when using smart skipping (when using more than one skip step for a direction)."
+msgstr ""
+
+#empty strings from id 37044 to 38009
#: system/settings/rbp.xml
msgctxt "#38010"
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index 2d3ebd82bb..113be3f037 100644
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -405,6 +405,32 @@
</setting>
</group>
<group id="2">
+ <setting id="videoplayer.seeksteps" type="list[integer]" label="13556" help="37042">
+ <level>2</level>
+ <default>-1800,-900,-600,-300,-180,-60,-30,-15,-7,15,30,60,180,300,600,900,1800</default>
+ <constraints>
+ <options>videoseeksteps</options>
+ <delimiter>,</delimiter>
+ <minimumItems>2</minimumItems>
+ </constraints>
+ <control type="list" format="string">
+ <multiselect>true</multiselect>
+ </control>
+ </setting>
+ <setting id="videoplayer.seekdelay" type="integer" label="13557" help="37043">
+ <level>2</level>
+ <default>1000</default>
+ <constraints>
+ <minimum>500</minimum>
+ <step>250</step>
+ <maximum>3000</maximum>
+ </constraints>
+ <control type="spinner" format="string">
+ <formatlabel>14046</formatlabel>
+ </control>
+ </setting>
+ </group>
+ <group id="3">
<setting id="videoplayer.adjustrefreshrate" type="integer" label="170" help="36164">
<level>2</level>
<default>0</default> <!-- ADJUST_REFRESHRATE_OFF -->
@@ -476,7 +502,7 @@
<control type="spinner" format="string" />
</setting>
</group>
- <group id="3">
+ <group id="4">
<setting id="videoplayer.teletextenabled" type="boolean" label="23050" help="36174">
<level>1</level>
<default>true</default>
@@ -491,7 +517,7 @@
<control type="toggle" />
</setting>
</group>
- <group id="4">
+ <group id="5">
<setting id="videoplayer.stereoscopicplaybackmode" type="integer" label="36520" help="36537">
<level>2</level>
<default>0</default>
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
index 82eb587ea0..f63d61f770 100644
--- a/xbmc/Application.cpp
+++ b/xbmc/Application.cpp
@@ -295,7 +295,7 @@ CApplication::CApplication(void)
, m_progressTrackingItem(new CFileItem)
, m_videoInfoScanner(new CVideoInfoScanner)
, m_musicInfoScanner(new CMusicInfoScanner)
- , m_seekHandler(new CSeekHandler)
+ , m_seekHandler(&CSeekHandler::Get())
, m_playerController(new CPlayerController)
{
m_network = NULL;
@@ -364,7 +364,6 @@ CApplication::~CApplication(void)
#endif
delete m_dpms;
- delete m_seekHandler;
delete m_playerController;
delete m_pInertialScrollingHandler;
delete m_pPlayer;
@@ -2666,7 +2665,7 @@ bool CApplication::OnAction(const CAction &action)
if (m_pPlayer->IsPlaying() && action.GetAmount() && (action.GetID() == ACTION_ANALOG_SEEK_FORWARD || action.GetID() == ACTION_ANALOG_SEEK_BACK))
{
if (!m_pPlayer->CanSeek()) return false;
- m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat());
+ m_seekHandler->Seek(action.GetID() == ACTION_ANALOG_SEEK_FORWARD, action.GetAmount(), action.GetRepeat(), true);
return true;
}
if (action.GetID() == ACTION_GUIPROFILE_BEGIN)
diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp
index 02ea40cfc4..d49da594de 100644
--- a/xbmc/settings/AdvancedSettings.cpp
+++ b/xbmc/settings/AdvancedSettings.cpp
@@ -143,6 +143,18 @@ void CAdvancedSettings::Initialize()
m_videoPercentSeekBackward = -2;
m_videoPercentSeekForwardBig = 10;
m_videoPercentSeekBackwardBig = -10;
+
+ m_videoSeekSteps.clear();
+ m_videoSeekSteps.push_back(7);
+ m_videoSeekSteps.push_back(15);
+ m_videoSeekSteps.push_back(30);
+ m_videoSeekSteps.push_back(60);
+ m_videoSeekSteps.push_back(180);
+ m_videoSeekSteps.push_back(300);
+ m_videoSeekSteps.push_back(600);
+ m_videoSeekSteps.push_back(900);
+ m_videoSeekSteps.push_back(1800);
+
m_videoBlackBarColour = 0;
m_videoPPFFmpegDeint = "linblenddeint";
m_videoPPFFmpegPostProc = "ha:128:7,va,dr";
@@ -560,6 +572,16 @@ void CAdvancedSettings::ParseSettingsFile(const std::string &file)
XMLUtils::GetInt(pElement, "timeseekbackward", m_videoTimeSeekBackward, -6000, 0);
XMLUtils::GetInt(pElement, "timeseekforwardbig", m_videoTimeSeekForwardBig, 0, 6000);
XMLUtils::GetInt(pElement, "timeseekbackwardbig", m_videoTimeSeekBackwardBig, -6000, 0);
+
+ std::string seekSteps;
+ XMLUtils::GetString(pRootElement, "seeksteps", seekSteps);
+ if (!seekSteps.empty())
+ {
+ m_videoSeekSteps.clear();
+ std::vector<string> steps = StringUtils::Split(seekSteps, ',');
+ for(std::vector<string>::iterator it = steps.begin(); it != steps.end(); ++it)
+ m_videoSeekSteps.push_back(atoi((*it).c_str()));
+ }
XMLUtils::GetInt(pElement, "percentseekforward", m_videoPercentSeekForward, 0, 100);
XMLUtils::GetInt(pElement, "percentseekbackward", m_videoPercentSeekBackward, -100, 0);
diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h
index dad2c45b28..9194adb50c 100644
--- a/xbmc/settings/AdvancedSettings.h
+++ b/xbmc/settings/AdvancedSettings.h
@@ -161,6 +161,7 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler
int m_videoPercentSeekBackward;
int m_videoPercentSeekForwardBig;
int m_videoPercentSeekBackwardBig;
+ std::vector<int> m_videoSeekSteps;
std::string m_videoPPFFmpegDeint;
std::string m_videoPPFFmpegPostProc;
bool m_videoVDPAUtelecine;
diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp
index c6ff2f543d..287118595e 100644
--- a/xbmc/settings/Settings.cpp
+++ b/xbmc/settings/Settings.cpp
@@ -79,6 +79,7 @@
#include "utils/SystemInfo.h"
#include "utils/Weather.h"
#include "utils/XBMCTinyXML.h"
+#include "utils/SeekHandler.h"
#include "view/ViewStateSettings.h"
#include "windowing/WindowingFactory.h"
#include "input/InputManager.h"
@@ -244,6 +245,7 @@ void CSettings::Uninitialize()
m_settingsManager->UnregisterSettingOptionsFiller("stereoscopicmodes");
m_settingsManager->UnregisterSettingOptionsFiller("preferedstereoscopicviewmodes");
m_settingsManager->UnregisterSettingOptionsFiller("monitors");
+ m_settingsManager->UnregisterSettingOptionsFiller("videoseeksteps");
m_settingsManager->UnregisterSettingOptionsFiller("shutdownstates");
m_settingsManager->UnregisterSettingOptionsFiller("startupwindows");
m_settingsManager->UnregisterSettingOptionsFiller("streamlanguages");
@@ -262,6 +264,7 @@ void CSettings::Uninitialize()
m_settingsManager->UnregisterCallback(&g_advancedSettings);
m_settingsManager->UnregisterCallback(&CMediaSettings::Get());
m_settingsManager->UnregisterCallback(&CDisplaySettings::Get());
+ m_settingsManager->UnregisterCallback(&CSeekHandler::Get());
m_settingsManager->UnregisterCallback(&CStereoscopicsManager::Get());
m_settingsManager->UnregisterCallback(&g_application);
m_settingsManager->UnregisterCallback(&g_audioManager);
@@ -588,6 +591,7 @@ void CSettings::InitializeOptionFillers()
m_settingsManager->RegisterSettingOptionsFiller("stereoscopicmodes", CDisplaySettings::SettingOptionsStereoscopicModesFiller);
m_settingsManager->RegisterSettingOptionsFiller("preferedstereoscopicviewmodes", CDisplaySettings::SettingOptionsPreferredStereoscopicViewModesFiller);
m_settingsManager->RegisterSettingOptionsFiller("monitors", CDisplaySettings::SettingOptionsMonitorsFiller);
+ m_settingsManager->RegisterSettingOptionsFiller("videoseeksteps", CSeekHandler::SettingOptionsSeekStepsFiller);
m_settingsManager->RegisterSettingOptionsFiller("shutdownstates", CPowerManager::SettingOptionsShutdownStatesFiller);
m_settingsManager->RegisterSettingOptionsFiller("startupwindows", ADDON::CSkinInfo::SettingOptionsStartupWindowsFiller);
m_settingsManager->RegisterSettingOptionsFiller("streamlanguages", CLangInfo::SettingOptionsStreamLanguagesFiller);
@@ -683,6 +687,11 @@ void CSettings::InitializeISettingCallbacks()
settingSet.insert("videoscreen.monitor");
settingSet.insert("videoscreen.preferedstereoscopicmode");
m_settingsManager->RegisterCallback(&CDisplaySettings::Get(), settingSet);
+
+ settingSet.clear();
+ settingSet.insert("videoplayer.seekdelay");
+ settingSet.insert("videoplayer.seeksteps");
+ m_settingsManager->RegisterCallback(&CSeekHandler::Get(), settingSet);
settingSet.clear();
settingSet.insert("videoscreen.stereoscopicmode");
diff --git a/xbmc/utils/SeekHandler.cpp b/xbmc/utils/SeekHandler.cpp
index 9c4e101800..9bea0a304f 100644
--- a/xbmc/utils/SeekHandler.cpp
+++ b/xbmc/utils/SeekHandler.cpp
@@ -19,51 +19,135 @@
*/
#include "SeekHandler.h"
+#include "guilib/LocalizeStrings.h"
#include "GUIInfoManager.h"
#include "Application.h"
+#include "settings/AdvancedSettings.h"
+#include "settings/Settings.h"
+#include "settings/lib/Setting.h"
+#include "utils/log.h"
+#include "utils/StringUtils.h"
CSeekHandler::CSeekHandler()
-: m_requireSeek(false),
- m_percent(0.0f)
+: m_seekDelay(500),
+ m_requireSeek(false),
+ m_percent(0.0f),
+ m_percentPlayTime(0.0f),
+ m_analogSeek(false),
+ m_seekStep(0)
{
}
+CSeekHandler::~CSeekHandler()
+{
+}
+
+CSeekHandler& CSeekHandler::Get()
+{
+ static CSeekHandler instance;
+ return instance;
+}
+
void CSeekHandler::Reset()
{
m_requireSeek = false;
m_percent = 0;
+ m_seekStep = 0;
+ m_seekDelay = CSettings::Get().GetInt("videoplayer.seekdelay");
+
+ std::vector<CVariant> seekSteps = CSettings::Get().GetList("videoplayer.seeksteps");
+ m_forwardSeekSteps.clear();
+ m_backwardSeekSteps.clear();
+ for (std::vector<CVariant>::iterator it = seekSteps.begin(); it != seekSteps.end(); ++it) {
+ int stepSeconds = (*it).asInteger();
+ if (stepSeconds < 0)
+ m_backwardSeekSteps.insert(m_backwardSeekSteps.begin(), stepSeconds);
+ else
+ m_forwardSeekSteps.push_back(stepSeconds);
+ }
}
-void CSeekHandler::Seek(bool forward, float amount, float duration)
+int CSeekHandler::GetSeekSeconds(bool forward)
{
+ m_seekStep = m_seekStep + (forward ? 1 : -1);
+
+ int seconds = 0;
+ if (m_seekStep > 0)
+ {
+ // when exceeding the selected amount of steps repeat/sum up the last step size
+ if ((size_t)m_seekStep <= m_forwardSeekSteps.size())
+ seconds = m_forwardSeekSteps.at(m_seekStep - 1);
+ else
+ seconds = m_forwardSeekSteps.back() * (m_seekStep - m_forwardSeekSteps.size() + 1);
+ }
+ else if (m_seekStep < 0)
+ {
+ // when exceeding the selected amount of steps repeat/sum up the last step size
+ if ((size_t)m_seekStep*-1 <= m_backwardSeekSteps.size())
+ seconds = m_backwardSeekSteps.at((m_seekStep*-1) - 1);
+ else
+ seconds = m_backwardSeekSteps.back() * ((m_seekStep*-1) - m_backwardSeekSteps.size() + 1);
+ }
+
+ return seconds;
+}
+
+void CSeekHandler::Seek(bool forward, float amount, float duration /* = 0 */, bool analogSeek /* = false */)
+{
+ // not yet seeking
if (!m_requireSeek)
- { // not yet seeking
+ {
if (g_infoManager.GetTotalPlayTime())
m_percent = (float)g_infoManager.GetPlayTime() / g_infoManager.GetTotalPlayTime() * 0.1f;
else
m_percent = 0.0f;
+ m_percentPlayTime = m_percent;
// tell info manager that we have started a seek operation
m_requireSeek = true;
g_infoManager.SetSeeking(true);
+ m_seekStep = 0;
+ m_analogSeek = analogSeek;
+
+ if (!analogSeek)
+ {
+ // don't apply a seek delay if only one seek step for the given direction exists
+ if ((m_backwardSeekSteps.size() == 1 && forward == false) ||
+ (m_forwardSeekSteps.size() == 1 && forward == true))
+ m_seekDelay = 0;
+ }
}
+
// calculate our seek amount
if (!g_infoManager.m_performingSeek)
{
- //100% over 1 second.
- float speed = 100.0f;
- if( duration )
- speed *= duration;
- else
- speed /= g_infoManager.GetFPS();
+ if (analogSeek)
+ {
+ //100% over 1 second.
+ float speed = 100.0f;
+ if( duration )
+ speed *= duration;
+ else
+ speed /= g_infoManager.GetFPS();
- if (forward)
- m_percent += amount * amount * speed;
+ if (forward)
+ m_percent += amount * amount * speed;
+ else
+ m_percent -= amount * amount * speed;
+ }
else
- m_percent -= amount * amount * speed;
+ {
+ float percentPerSecond = 0.0f;
+ if (g_infoManager.GetTotalPlayTime())
+ percentPerSecond = 100.0f / (float)g_infoManager.GetTotalPlayTime();
+
+ m_percent = m_percentPlayTime + percentPerSecond * GetSeekSeconds(forward);
+ }
+
if (m_percent > 100.0f) m_percent = 100.0f;
if (m_percent < 0.0f) m_percent = 0.0f;
}
+
m_timer.StartZero();
}
@@ -79,16 +163,45 @@ bool CSeekHandler::InProgress() const
void CSeekHandler::Process()
{
- if (m_timer.GetElapsedMilliseconds() > time_before_seek)
+ if (m_timer.GetElapsedMilliseconds() > m_seekDelay)
{
if (!g_infoManager.m_performingSeek && m_timer.GetElapsedMilliseconds() > time_for_display) // TODO: Why?
g_infoManager.SetSeeking(false);
+
if (m_requireSeek)
{
g_infoManager.m_performingSeek = true;
+
+ // calculate the seek time
double time = g_infoManager.GetTotalPlayTime() * m_percent * 0.01;
+
g_application.SeekTime(time);
m_requireSeek = false;
}
}
}
+
+void CSeekHandler::SettingOptionsSeekStepsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data)
+{
+ std::string label;
+ for (std::vector<int>::iterator it = g_advancedSettings.m_videoSeekSteps.begin(); it != g_advancedSettings.m_videoSeekSteps.end(); ++it) {
+ int seconds = *it;
+ if (seconds > 60)
+ label = StringUtils::Format(g_localizeStrings.Get(14044).c_str(), seconds / 60);
+ else
+ label = StringUtils::Format(g_localizeStrings.Get(14045).c_str(), seconds);
+
+ list.insert(list.begin(), make_pair("-" + label, seconds*-1));
+ list.push_back(make_pair(label, seconds));
+ }
+}
+
+void CSeekHandler::OnSettingChanged(const CSetting *setting)
+{
+ if (setting == NULL)
+ return;
+
+ if (setting->GetId() == "videoplayer.seekdelay" ||
+ setting->GetId() == "videoplayer.seeksteps")
+ Reset();
+}
diff --git a/xbmc/utils/SeekHandler.h b/xbmc/utils/SeekHandler.h
index 68e7820c84..4f80140db6 100644
--- a/xbmc/utils/SeekHandler.h
+++ b/xbmc/utils/SeekHandler.h
@@ -19,23 +19,43 @@
*
*/
+#include <vector>
+#include "settings/Settings.h"
+#include "settings/lib/ISettingCallback.h"
#include "utils/Stopwatch.h"
-class CSeekHandler
+class CSeekHandler : public ISettingCallback
{
public:
- CSeekHandler();
+ static CSeekHandler& Get();
+
+ static void SettingOptionsSeekStepsFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current, void *data);
+
+ virtual void OnSettingChanged(const CSetting *setting);
- void Seek(bool forward, float amount, float duration = 0);
+ void Seek(bool forward, float amount, float duration = 0, bool analogSeek = false);
void Process();
void Reset();
float GetPercent() const;
bool InProgress() const;
+
+protected:
+ CSeekHandler();
+ CSeekHandler(const CSeekHandler&);
+ CSeekHandler& operator=(CSeekHandler const&);
+ virtual ~CSeekHandler();
+
private:
- static const int time_before_seek = 500;
static const int time_for_display = 2000; // TODO: WTF?
+ int GetSeekSeconds(bool forward);
+ int m_seekDelay;
bool m_requireSeek;
float m_percent;
+ float m_percentPlayTime;
+ bool m_analogSeek;
+ int m_seekStep;
+ std::vector<int> m_forwardSeekSteps;
+ std::vector<int> m_backwardSeekSteps;
CStopWatch m_timer;
};