7 #include <QGlobalStatic>
8 #include <QCoreApplication>
14 #include "libmythbase/mythversion.h"
28 #define LOC QString("FrontendServices: ")
49 QStringList contexts = bindings->GetContexts();
51 for (
const QString & context : std::as_const(contexts))
54 QStringList ctxactions = bindings->GetActions(context);
57 for (
const QString & actions : std::as_const(ctxactions))
59 QString desc = actions +
"," + bindings->GetActionDescription(context, actions);
70 if (
action.startsWith(
"select", Qt::CaseInsensitive) &&
action.contains(
"_"))
98 qRegisterMetaType<FrontendStatus*>(
"FrontendStatus");
99 qRegisterMetaType<FrontendActionList*>(
"FrontendActionList");
122 QString key = Key.toLower();
126 QMetaEnum meta = QMetaEnum::fromType<Qt::Key>();
127 for (
int i = 0; i < meta.keyCount(); i++)
129 if (QByteArray(meta.key(i)).mid(4).toLower() == key)
131 keycode = meta.value(i);
137 if (!valid && key.size() == 1)
139 keycode = key.toLatin1()[0] & 0x7f;
145 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Unknown key: '%1'").arg(Key));
151 auto * event1 =
new QKeyEvent(QEvent::KeyPress, keycode, Qt::NoModifier,
"");
152 QCoreApplication::postEvent(mainwindow, event1);
153 auto * event2 =
new QKeyEvent(QEvent::KeyRelease, keycode, Qt::NoModifier,
"");
154 QCoreApplication::postEvent(mainwindow, event2);
155 LOG(VB_HTTP, LOG_INFO,
LOC + QString(
"Sent key: '%1'").arg(Key));
161 if (Message.isEmpty())
163 QStringList data(QString::number(
std::clamp(Timeout, 0U, 1000U)));
175 const QString& Message,
const QString& Origin,
176 const QString& Description,
const QString& Image,
177 const QString& Extra,
const QString& ProgressText,
178 float Progress, std::chrono::seconds Timeout,
179 bool Fullscreen,
uint Visibility,
186 Message, Origin.isNull() ? tr(
"FrontendServices") : Origin,
187 Description, Image, Extra, ProgressText, Progress, Timeout,
195 QHashIterator<QString,QStringList> contexts(s_actions->Descriptions());
196 while (contexts.hasNext())
199 if (!Context.isEmpty() && contexts.key() != Context)
203 QStringList actions = contexts.value();
204 for (
const QString &
action : std::as_const(actions))
206 QStringList split =
action.split(
",");
207 if (split.size() == 2)
208 result.insert(split[0], split[1]);
216 return s_actions->Descriptions().keys();
219 bool MythFrontendService::SendAction(
const QString&
Action,
const QString& Value,
uint Width,
uint Height)
224 if (!Value.isEmpty() && s_actions->ValueActions().contains(
Action))
234 if (!Width || !Height)
236 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid screenshot parameters.");
241 args << QString::number(Width) << QString::number(Height);
254 if (s_actions->Actions().contains(
Action) || s_actions->SelectActions().contains(
Action))
256 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Action '%1'' is invalid.").arg(
Action));
262 QDateTime starttime = StartTime;
264 if ((RecordedId <= 0) && (ChanId <= 0 || !StartTime.isValid()))
266 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Recorded ID or Channel ID and StartTime appears invalid.");
273 ChanId =
static_cast<int>(recInfo.
GetChanID());
281 QString message = QString(
"NETWORK_CONTROL STOP");
287 while (!timer.hasExpired(10000) && (
GetMythUI()->GetCurrentLocation().toLower() ==
"playback"))
288 std::this_thread::sleep_for(std::chrono::milliseconds(10));
291 if (
GetMythUI()->GetCurrentLocation().toLower() !=
"playbackbox")
296 while (!timer.hasExpired(10000) && (
GetMythUI()->GetCurrentLocation().toLower() !=
"playbackbox"))
297 std::this_thread::sleep_for(std::chrono::milliseconds(10));
301 std::this_thread::sleep_for(std::chrono::milliseconds(10));
304 if (
GetMythUI()->GetCurrentLocation().toLower() ==
"playbackbox")
306 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"PlayRecording, ChanID: %1 StartTime: %2")
307 .arg(ChanId).arg(starttime.toString(
Qt::ISODate)));
309 QString message = QString(
"NETWORK_CONTROL PLAY PROGRAM %1 %2 %3")
310 .arg(ChanId).arg(starttime.toString(
"yyyyMMddhhmmss"),
"12345");
324 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Ignoring PlayVideo request - frontend is busy."));
329 uint id = Id.toUInt(&ok);
332 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Invalid video Id."));
339 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Didn't find any video metadata."));
343 if (metadata->GetHost().isEmpty())
345 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"No host for video."));
349 QString mrl =
generate_file_url(
"Videos", metadata->GetHost(), metadata->GetFilename());
350 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"PlayVideo ID: %1 UseBookmark: %2 URL: '%3'")
351 .arg(
id).arg(UseBookmark).arg(mrl));
354 args << mrl << metadata->GetPlot() << metadata->GetTitle()
355 << metadata->GetSubtitle() << metadata->GetDirector()
356 << QString::number(metadata->GetSeason())
357 << QString::number(metadata->GetEpisode())
358 << metadata->GetInetRef() << QString::number(metadata->GetLength().count())
359 << QString::number(metadata->GetYear())
360 << QString::number(metadata->GetID())
361 << QString::number(
static_cast<int>(UseBookmark));
369 : m_Name(std::move(
Name)),
370 m_Version(std::move(Version)),
371 m_State(std::move(
State))
373 if (m_State.contains(
"chaptertimes") &&
374 #
if QT_VERSION < QT_VERSION_CHECK(6,0,0)
375 m_State[
"chaptertimes"].
type() == QVariant::List
377 m_State[
"chaptertimes"].typeId() == QMetaType::QVariantList
381 m_ChapterTimes = m_State[
"chaptertimes"].toList();
382 m_State.remove(
"chaptertimes");
385 if (m_State.contains(
"subtitletracks") &&
386 #
if QT_VERSION < QT_VERSION_CHECK(6,0,0)
387 m_State[
"subtitletracks"].
type() == QVariant::Map
389 m_State[
"subtitletracks"].typeId() == QMetaType::QVariantMap
393 m_SubtitleTracks = m_State[
"subtitletracks"].toMap();
394 m_State.remove(
"subtitletracks");
397 if (m_State.contains(
"audiotracks") &&
398 #
if QT_VERSION < QT_VERSION_CHECK(6,0,0)
399 m_State[
"audiotracks"].
type() == QVariant::Map
401 m_State[
"audiotracks"].typeId() == QMetaType::QVariantMap
405 m_AudioTracks = m_State[
"audiotracks"].toMap();
406 m_State.remove(
"audiotracks");
411 : m_ActionList(std::move(List))