Skip to content

Commit

Permalink
Merge pull request #6801 from xhaggi/builtin-seek-support
Browse files Browse the repository at this point in the history
  • Loading branch information
jenkins4kodi committed Apr 11, 2015
2 parents 6075002 + a69dde3 commit 7c04112
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 21 deletions.
12 changes: 12 additions & 0 deletions xbmc/interfaces/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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" },
Expand Down Expand Up @@ -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())
Expand Down
22 changes: 15 additions & 7 deletions xbmc/interfaces/json-rpc/PlayerOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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")
Expand All @@ -413,13 +416,18 @@ 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;

GetPropertyValue(player, "percentage", result["percentage"]);
GetPropertyValue(player, "time", result["time"]);
GetPropertyValue(player, "totaltime", result["totaltime"]);
return OK;
}

case Picture:
case None:
Expand Down
6 changes: 5 additions & 1 deletion xbmc/interfaces/json-rpc/schema/methods.json
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
]
}
],
Expand Down
2 changes: 1 addition & 1 deletion xbmc/interfaces/json-rpc/schema/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.24.0
6.25.0
56 changes: 44 additions & 12 deletions xbmc/utils/SeekHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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;

Expand Down
4 changes: 4 additions & 0 deletions xbmc/utils/SeekHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -43,6 +44,7 @@ class CSeekHandler : public ISettingCallback, public IActionListener
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();

Expand All @@ -69,4 +71,6 @@ class CSeekHandler : public ISettingCallback, public IActionListener
std::map<SeekType, std::vector<int> > m_forwardSeekSteps;
std::map<SeekType, std::vector<int> > m_backwardSeekSteps;
CStopWatch m_timer;

CCriticalSection m_critSection;
};

0 comments on commit 7c04112

Please sign in to comment.