Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[builtin] adds new builtin for seeking #6801

Merged
merged 5 commits into from
Apr 11, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
};