6 #include <QCoreApplication>
14 #include "libmythbase/mythversion.h"
30 #define LOC QString("Frontend API: ")
49 if (Message.isEmpty())
53 auto Timeout = std::chrono::seconds(TimeoutInt);
54 if (Timeout > 0s && Timeout < 1000s)
55 data << QString::number(Timeout.count());
64 const QString &Message,
65 const QString &Origin,
66 const QString &Description,
69 const QString &ProgressText,
76 if (Message.isEmpty())
84 Origin.isNull() ? tr(
"FrontendServices") : Origin,
85 Description, Image, Extra,
86 ProgressText, Progress, std::chrono::seconds(Timeout),
97 static const QStringList kValueActions =
105 if (!Value.isEmpty() && kValueActions.contains(
Action))
115 if (!Width || !Height)
117 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid screenshot parameters.");
122 args << QString::number(Width) << QString::number(Height);
129 auto* ke =
new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier,
Action);
135 const QDateTime &StartTime)
137 QDateTime starttime = StartTime;
139 if ((RecordedId <= 0) &&
140 (ChanId <= 0 || !StartTime.isValid()))
141 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
150 if (
GetMythUI()->GetCurrentLocation().toLower() ==
"playback")
152 QString message = QString(
"NETWORK_CONTROL STOP");
158 while (!timer.hasExpired(10000) &&
159 (
GetMythUI()->GetCurrentLocation().toLower() ==
"playback"))
160 std::this_thread::sleep_for(10ms);
163 if (
GetMythUI()->GetCurrentLocation().toLower() !=
"playbackbox")
169 while (!timer.hasExpired(10000) &&
170 (
GetMythUI()->GetCurrentLocation().toLower() !=
"playbackbox"))
171 std::this_thread::sleep_for(10ms);
175 std::this_thread::sleep_for(10ms);
178 if (
GetMythUI()->GetCurrentLocation().toLower() ==
"playbackbox")
180 LOG(VB_GENERAL, LOG_INFO,
LOC +
181 QString(
"PlayRecording, ChanID: %1 StartTime: %2")
182 .arg(ChanId).arg(starttime.toString(
Qt::ISODate)));
184 QString message = QString(
"NETWORK_CONTROL PLAY PROGRAM %1 %2 %3")
185 .arg(QString::number(ChanId),
186 starttime.toString(
"yyyyMMddhhmmss"),
201 LOG(VB_GENERAL, LOG_WARNING,
LOC +
202 QString(
"Ignoring PlayVideo request - frontend is busy."));
207 quint64
id = Id.toUInt(&ok);
210 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Invalid video Id."));
219 LOG(VB_GENERAL, LOG_WARNING,
LOC +
220 QString(
"Didn't find any video metadata."));
224 if (metadata->GetHost().isEmpty())
226 LOG(VB_GENERAL, LOG_WARNING,
LOC +
227 QString(
"No host for video."));
232 metadata->GetFilename());
233 LOG(VB_GENERAL, LOG_INFO,
LOC +
234 QString(
"PlayVideo, id: %1 usebookmark: %2 url: '%3'")
235 .arg(
id).arg(UseBookmark).arg(mrl));
238 args << mrl << metadata->GetPlot() << metadata->GetTitle()
239 << metadata->GetSubtitle() << metadata->GetDirector()
240 << QString::number(metadata->GetSeason())
241 << QString::number(metadata->GetEpisode())
242 << metadata->GetInetRef() << QString::number(metadata->GetLength().count())
243 << QString::number(metadata->GetYear())
244 << QString::number(metadata->GetID())
245 << QString::number(
static_cast<int>(UseBookmark));
266 while (contexts.hasNext())
269 if (!lContext.isEmpty() && contexts.key() != lContext)
273 QStringList actions = contexts.value();
274 for (
const QString &
action : qAsConst(actions))
276 QStringList split =
action.split(
",");
277 if (split.size() == 2)
278 list->ActionList().insert(split[0], split[1]);
291 if (
Action.startsWith(
"SELECTSUBTITLE_") ||
292 Action.startsWith(
"SELECTTTC_") ||
293 Action.startsWith(
"SELECTCC608_") ||
294 Action.startsWith(
"SELECTCC708_") ||
295 Action.startsWith(
"SELECTRAWTEXT_") ||
296 Action.startsWith(
"SELECTAUDIO_"))
301 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Action '%1'' is invalid.")
308 static bool s_initialised =
false;
312 s_initialised =
true;
316 QStringList contexts = bindings->GetContexts();
318 for (
const QString & context : qAsConst(contexts))
321 QStringList ctx_actions = bindings->GetActions(context);
324 for (
const QString & actions : qAsConst(ctx_actions))
326 QString desc = actions +
"," +
327 bindings->GetActionDescription(context, actions);
336 for (
const QString & actions : qAsConst(
gActionList))
337 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Action: %1").arg(actions));
344 QObject *keyDest =
nullptr;
345 QKeyEvent *
event =
nullptr;
346 QMap <QString, int> keyMap;
350 keyMap[
"up"] = Qt::Key_Up;
351 keyMap[
"down"] = Qt::Key_Down;
352 keyMap[
"left"] = Qt::Key_Left;
353 keyMap[
"right"] = Qt::Key_Right;
354 keyMap[
"home"] = Qt::Key_Home;
355 keyMap[
"end"] = Qt::Key_End;
356 keyMap[
"enter"] = Qt::Key_Enter;
357 keyMap[
"return"] = Qt::Key_Return;
358 keyMap[
"pageup"] = Qt::Key_PageUp;
359 keyMap[
"pagedown"] = Qt::Key_PageDown;
360 keyMap[
"escape"] = Qt::Key_Escape;
361 keyMap[
"tab"] = Qt::Key_Tab;
362 keyMap[
"backtab"] = Qt::Key_Backtab;
363 keyMap[
"space"] = Qt::Key_Space;
364 keyMap[
"backspace"] = Qt::Key_Backspace;
365 keyMap[
"insert"] = Qt::Key_Insert;
366 keyMap[
"delete"] = Qt::Key_Delete;
367 keyMap[
"plus"] = Qt::Key_Plus;
368 keyMap[
"comma"] = Qt::Key_Comma;
369 keyMap[
"minus"] = Qt::Key_Minus;
370 keyMap[
"underscore"] = Qt::Key_Underscore;
371 keyMap[
"period"] = Qt::Key_Period;
372 keyMap[
"numbersign"] = Qt::Key_NumberSign;
373 keyMap[
"poundsign"] = Qt::Key_NumberSign;
374 keyMap[
"hash"] = Qt::Key_NumberSign;
375 keyMap[
"bracketleft"] = Qt::Key_BracketLeft;
376 keyMap[
"bracketright"] = Qt::Key_BracketRight;
377 keyMap[
"backslash"] = Qt::Key_Backslash;
378 keyMap[
"dollar"] = Qt::Key_Dollar;
379 keyMap[
"percent"] = Qt::Key_Percent;
380 keyMap[
"ampersand"] = Qt::Key_Ampersand;
381 keyMap[
"parenleft"] = Qt::Key_ParenLeft;
382 keyMap[
"parenright"] = Qt::Key_ParenRight;
383 keyMap[
"asterisk"] = Qt::Key_Asterisk;
384 keyMap[
"question"] = Qt::Key_Question;
385 keyMap[
"slash"] = Qt::Key_Slash;
386 keyMap[
"colon"] = Qt::Key_Colon;
387 keyMap[
"semicolon"] = Qt::Key_Semicolon;
388 keyMap[
"less"] = Qt::Key_Less;
389 keyMap[
"equal"] = Qt::Key_Equal;
390 keyMap[
"greater"] = Qt::Key_Greater;
391 keyMap[
"f1"] = Qt::Key_F1;
392 keyMap[
"f2"] = Qt::Key_F2;
393 keyMap[
"f3"] = Qt::Key_F3;
394 keyMap[
"f4"] = Qt::Key_F4;
395 keyMap[
"f5"] = Qt::Key_F5;
396 keyMap[
"f6"] = Qt::Key_F6;
397 keyMap[
"f7"] = Qt::Key_F7;
398 keyMap[
"f8"] = Qt::Key_F8;
399 keyMap[
"f9"] = Qt::Key_F9;
400 keyMap[
"f10"] = Qt::Key_F10;
401 keyMap[
"f11"] = Qt::Key_F11;
402 keyMap[
"f12"] = Qt::Key_F12;
403 keyMap[
"f13"] = Qt::Key_F13;
404 keyMap[
"f14"] = Qt::Key_F14;
405 keyMap[
"f15"] = Qt::Key_F15;
406 keyMap[
"f16"] = Qt::Key_F16;
407 keyMap[
"f17"] = Qt::Key_F17;
408 keyMap[
"f18"] = Qt::Key_F18;
409 keyMap[
"f19"] = Qt::Key_F19;
410 keyMap[
"f20"] = Qt::Key_F20;
411 keyMap[
"f21"] = Qt::Key_F21;
412 keyMap[
"f22"] = Qt::Key_F22;
413 keyMap[
"f23"] = Qt::Key_F23;
414 keyMap[
"f24"] = Qt::Key_F24;
418 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"SendKey: No Key received"));
426 LOG(VB_GENERAL, LOG_ERR,
427 LOC + QString(
"SendKey: Application has no main window"));
431 if (keyMap.contains(sKey.toLower()))
433 keyCode = keyMap[sKey.toLower()];
436 else if (sKey.size() == 1)
438 keyCode = (int) sKey.toLatin1()[0] & 0x7f;
442 msg = QString(
"SendKey: Unknown Key = '%1'").arg(sKey);
448 event =
new QKeyEvent(QEvent::KeyPress, keyCode, Qt::NoModifier,
450 QCoreApplication::postEvent(keyDest, event);
452 event =
new QKeyEvent(QEvent::KeyRelease, keyCode, Qt::NoModifier,
454 QCoreApplication::postEvent(keyDest, event);
456 msg = QString(
"SendKey: Sent %1").arg(sKey);
459 LOG(VB_UPNP, LOG_INFO,
LOC + msg);