diff options
author | jenkins4kodi <jenkins4kodi@users.noreply.github.com> | 2015-04-11 10:12:00 +0200 |
---|---|---|
committer | jenkins4kodi <jenkins4kodi@users.noreply.github.com> | 2015-04-11 10:12:00 +0200 |
commit | 7c04112418eaf26fec2220ad66cc081cefcc6c90 (patch) | |
tree | 22bde23a92885fceb20855b236d90fdf04294dfa | |
parent | 607500245bfa9c9b76187e23b017b28c3854afdf (diff) | |
parent | a69dde35a0ee4652a302e5783117a901e4e21b97 (diff) |
Merge pull request #6801 from xhaggi/builtin-seek-support
-rw-r--r-- | xbmc/interfaces/Builtins.cpp | 12 | ||||
-rw-r--r-- | xbmc/interfaces/json-rpc/PlayerOperations.cpp | 22 | ||||
-rw-r--r-- | xbmc/interfaces/json-rpc/schema/methods.json | 6 | ||||
-rw-r--r-- | xbmc/interfaces/json-rpc/schema/version.txt | 2 | ||||
-rw-r--r-- | xbmc/utils/SeekHandler.cpp | 56 | ||||
-rw-r--r-- | xbmc/utils/SeekHandler.h | 4 |
6 files changed, 81 insertions, 21 deletions
diff --git a/xbmc/interfaces/Builtins.cpp b/xbmc/interfaces/Builtins.cpp index ddb898326c..0e2644d900 100644 --- a/xbmc/interfaces/Builtins.cpp +++ b/xbmc/interfaces/Builtins.cpp @@ -22,6 +22,7 @@ #include "system.h" #include "utils/AlarmClock.h" #include "utils/Screenshot.h" +#include "utils/SeekHandler.h" #include "Application.h" #include "ApplicationMessenger.h" #include "Autorun.h" @@ -150,6 +151,7 @@ const BUILT_IN commands[] = { { "NotifyAll", true, "Notify all connected clients" }, { "Extract", true, "Extracts the specified archive" }, { "PlayMedia", true, "Play the specified media file (or playlist)" }, + { "Seek", true, "Performs a seek in seconds on the current playing media file" }, { "ShowPicture", true, "Display a picture by file path" }, { "SlideShow", true, "Run a slideshow from the specified directory" }, { "RecursiveSlideShow", true, "Run a slideshow from the specified directory, including all subdirs" }, @@ -813,6 +815,16 @@ int CBuiltins::Execute(const std::string& execString) } } } + else if (execute == "seek") + { + if (!params.size()) + { + CLog::Log(LOGERROR, "Seek called with empty parameter"); + return -3; + } + if (g_application.m_pPlayer->IsPlaying()) + CSeekHandler::Get().SeekSeconds(atoi(params[0].c_str())); + } else if (execute == "showpicture") { if (!params.size()) diff --git a/xbmc/interfaces/json-rpc/PlayerOperations.cpp b/xbmc/interfaces/json-rpc/PlayerOperations.cpp index 80d885ea4d..cd8e751fdc 100644 --- a/xbmc/interfaces/json-rpc/PlayerOperations.cpp +++ b/xbmc/interfaces/json-rpc/PlayerOperations.cpp @@ -47,6 +47,7 @@ #include "cores/playercorefactory/PlayerCoreConfig.h" #include "cores/playercorefactory/PlayerCoreFactory.h" #include "settings/MediaSettings.h" +#include "utils/SeekHandler.h" using namespace JSONRPC; using namespace PLAYLIST; @@ -392,16 +393,18 @@ JSONRPC_STATUS CPlayerOperations::Seek(const std::string &method, ITransportLaye { case Video: case Audio: + { if (!g_application.m_pPlayer->CanSeek()) return FailedToExecute; - - if (parameterObject["value"].isObject()) - g_application.SeekTime(ParseTimeInSeconds(parameterObject["value"])); - else if (IsType(parameterObject["value"], NumberValue)) - g_application.SeekPercentage(parameterObject["value"].asFloat()); - else if (parameterObject["value"].isString()) + + const CVariant& value = parameterObject["value"]; + if (IsType(value, NumberValue) || + (value.isObject() && value.isMember("percentage"))) + g_application.SeekPercentage(IsType(value, NumberValue) ? value.asFloat() : value["percentage"].asFloat()); + else if (value.isString() || + (value.isObject() && value.isMember("step"))) { - std::string step = parameterObject["value"].asString(); + std::string step = value.isString() ? value.asString() : value["step"].asString(); if (step == "smallforward") CBuiltins::Execute("playercontrol(smallskipforward)"); else if (step == "smallbackward") @@ -413,6 +416,10 @@ JSONRPC_STATUS CPlayerOperations::Seek(const std::string &method, ITransportLaye else return InvalidParams; } + else if (value.isObject() && value.isMember("seconds") && value.size() == 1) + CSeekHandler::Get().SeekSeconds(static_cast<int>(value["seconds"].asInteger())); + else if (value.isObject()) + g_application.SeekTime(ParseTimeInSeconds(value.isMember("time") ? value["time"] : value)); else return InvalidParams; @@ -420,6 +427,7 @@ JSONRPC_STATUS CPlayerOperations::Seek(const std::string &method, ITransportLaye GetPropertyValue(player, "time", result["time"]); GetPropertyValue(player, "totaltime", result["totaltime"]); return OK; + } case Picture: case None: diff --git a/xbmc/interfaces/json-rpc/schema/methods.json b/xbmc/interfaces/json-rpc/schema/methods.json index 1b82ee2203..7b2ede3eac 100644 --- a/xbmc/interfaces/json-rpc/schema/methods.json +++ b/xbmc/interfaces/json-rpc/schema/methods.json @@ -291,7 +291,11 @@ { "name": "value", "required": true, "type": [ { "$ref": "Player.Position.Percentage", "required": true, "description": "Percentage value to seek to" }, { "$ref": "Player.Position.Time", "required": true, "description": "Time to seek to" }, - { "type": "string", "enum": [ "smallforward", "smallbackward", "bigforward", "bigbackward" ], "required": true, "description": "Seek by predefined jumps" } + { "type": "string", "enum": [ "smallforward", "smallbackward", "bigforward", "bigbackward" ], "required": true, "description": "Seek by predefined jumps" }, + { "type": "object", "properties": { "percentage": { "$ref": "Player.Position.Percentage", "required": true, "description": "Percentage value to seek to" } }, "additionalProperties": false, "required": true }, + { "type": "object", "properties": { "time": { "$ref": "Player.Position.Time", "required": true, "description": "Time to seek to" } }, "additionalProperties": false, "required": true }, + { "type": "object", "properties": { "step": { "type": "string", "enum": [ "smallforward", "smallbackward", "bigforward", "bigbackward" ], "required": true, "description": "Seek by predefined jumps" } }, "additionalProperties": false, "required": true }, + { "type": "object", "properties": { "seconds": { "type": "integer", "required": true, "description": "Seek by the given number of seconds" } }, "additionalProperties": false, "required": true } ] } ], diff --git a/xbmc/interfaces/json-rpc/schema/version.txt b/xbmc/interfaces/json-rpc/schema/version.txt index 2496b04b84..961b1c8ecf 100644 --- a/xbmc/interfaces/json-rpc/schema/version.txt +++ b/xbmc/interfaces/json-rpc/schema/version.txt @@ -1 +1 @@ -6.24.0 +6.25.0 diff --git a/xbmc/utils/SeekHandler.cpp b/xbmc/utils/SeekHandler.cpp index ad34e2060a..dbc4d933c6 100644 --- a/xbmc/utils/SeekHandler.cpp +++ b/xbmc/utils/SeekHandler.cpp @@ -110,7 +110,7 @@ int CSeekHandler::GetSeekSeconds(bool forward, SeekType type) int seconds = 0; // when exceeding the selected amount of steps repeat/sum up the last step size - if ((size_t)abs(m_seekStep) <= seekSteps.size()) + if (static_cast<size_t>(abs(m_seekStep)) <= seekSteps.size()) seconds = seekSteps.at(abs(m_seekStep) - 1); else seconds = seekSteps.back() * (abs(m_seekStep) - seekSteps.size() + 1); @@ -120,13 +120,17 @@ int CSeekHandler::GetSeekSeconds(bool forward, SeekType type) void CSeekHandler::Seek(bool forward, float amount, float duration /* = 0 */, bool analogSeek /* = false */, SeekType type /* = SEEK_TYPE_VIDEO */) { + // abort if we do not have a play time or already perform a seek + if (g_infoManager.GetTotalPlayTime() == 0 || + g_infoManager.m_performingSeek) + return; + + CSingleLock lock(m_critSection); + // not yet seeking if (!m_requireSeek) { - if (g_infoManager.GetTotalPlayTime()) - m_percent = (float)g_infoManager.GetPlayTime() / g_infoManager.GetTotalPlayTime() * 0.1f; - else - m_percent = 0.0f; + m_percent = static_cast<float>(g_infoManager.GetPlayTime()) / g_infoManager.GetTotalPlayTime() * 0.1f; m_percentPlayTime = m_percent; // tell info manager that we have started a seek operation @@ -159,10 +163,7 @@ void CSeekHandler::Seek(bool forward, float amount, float duration /* = 0 */, bo int seekSeconds = GetSeekSeconds(forward, type); if (seekSeconds != 0) { - float percentPerSecond = 0.0f; - if (g_infoManager.GetTotalPlayTime()) - percentPerSecond = 100.0f / (float)g_infoManager.GetTotalPlayTime(); - + float percentPerSecond = 100.0f / static_cast<float>(g_infoManager.GetTotalPlayTime()); m_percent = m_percentPlayTime + percentPerSecond * seekSeconds; g_infoManager.SetSeekStepSize(seekSeconds); @@ -175,13 +176,44 @@ void CSeekHandler::Seek(bool forward, float amount, float duration /* = 0 */, bo } } - if (m_percent > 100.0f) m_percent = 100.0f; - if (m_percent < 0.0f) m_percent = 0.0f; + if (m_percent > 100.0f) + m_percent = 100.0f; + if (m_percent < 0.0f) + m_percent = 0.0f; } m_timer.StartZero(); } +void CSeekHandler::SeekSeconds(int seconds) +{ + // abort if we do not have a play time or already perform a seek + if (seconds == 0 || + g_infoManager.GetTotalPlayTime() == 0 || + g_infoManager.m_performingSeek) + return; + + CSingleLock lock(m_critSection); + + m_requireSeek = true; + m_seekDelay = 0; + + g_infoManager.SetSeeking(true); + g_infoManager.SetSeekStepSize(seconds); + + float percentPlayTime = static_cast<float>(g_infoManager.GetPlayTime()) / g_infoManager.GetTotalPlayTime() * 0.1f; + float percentPerSecond = 100.0f / static_cast<float>(g_infoManager.GetTotalPlayTime()); + + m_percent = percentPlayTime + percentPerSecond * seconds; + + if (m_percent > 100.0f) + m_percent = 100.0f; + if (m_percent < 0.0f) + m_percent = 0.0f; + + m_timer.StartZero(); +} + float CSeekHandler::GetPercent() const { return m_percent; @@ -194,7 +226,7 @@ bool CSeekHandler::InProgress() const void CSeekHandler::Process() { - if (m_timer.GetElapsedMilliseconds() > m_seekDelay && m_requireSeek) + if (m_timer.GetElapsedMilliseconds() >= m_seekDelay && m_requireSeek) { g_infoManager.m_performingSeek = true; diff --git a/xbmc/utils/SeekHandler.h b/xbmc/utils/SeekHandler.h index e9809651d3..7782bb05fd 100644 --- a/xbmc/utils/SeekHandler.h +++ b/xbmc/utils/SeekHandler.h @@ -24,6 +24,7 @@ #include "interfaces/IActionListener.h" #include "settings/Settings.h" #include "settings/lib/ISettingCallback.h" +#include "threads/CriticalSection.h" #include "utils/Stopwatch.h" enum SeekType @@ -43,6 +44,7 @@ public: virtual bool OnAction(const CAction &action); void Seek(bool forward, float amount, float duration = 0, bool analogSeek = false, SeekType type = SEEK_TYPE_VIDEO); + void SeekSeconds(int seconds); void Process(); void Reset(); @@ -69,4 +71,6 @@ private: std::map<SeekType, std::vector<int> > m_forwardSeekSteps; std::map<SeekType, std::vector<int> > m_backwardSeekSteps; CStopWatch m_timer; + + CCriticalSection m_critSection; }; |