diff options
author | xhaggi <sascha.woo@gmail.com> | 2014-09-24 15:03:50 +0200 |
---|---|---|
committer | xhaggi <sascha.woo@gmail.com> | 2015-02-08 17:46:21 +0100 |
commit | face9ead060c964f0bae4c3b6179ea36d98708a5 (patch) | |
tree | c75708431356a5e623d31ff3007b1c6006315daf | |
parent | cc9ed5f04471237e36c8350c8933556a348f8fe8 (diff) |
[seek] adds additive seek support
-rwxr-xr-x | language/English/strings.po | 28 | ||||
-rw-r--r-- | system/settings/settings.xml | 30 | ||||
-rw-r--r-- | xbmc/Application.cpp | 5 | ||||
-rw-r--r-- | xbmc/settings/AdvancedSettings.cpp | 22 | ||||
-rw-r--r-- | xbmc/settings/AdvancedSettings.h | 1 | ||||
-rw-r--r-- | xbmc/settings/Settings.cpp | 9 | ||||
-rw-r--r-- | xbmc/utils/SeekHandler.cpp | 141 | ||||
-rw-r--r-- | xbmc/utils/SeekHandler.h | 28 |
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 ¤t, 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 ¤t, 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; }; |