Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Frontend Services: Move action handling from MythFEXML to service.

- The 'helper' method GetActionTest remains in MythFEXML.
- Arguments are now capitalised for consistency with the rest of the
services API.
- the Frontend Remote Control is modified for the new urls and methods.

Old methods:

http://frontend-ip:6547/MythFE/SendAction?action=UP
http://frontend-

New methods:

http://frontend-ip:6547/Frontend/SendAction?Action=UP
http://frontend-
  • Loading branch information...
commit 9a90d31b789f7cab0ea33d7d8445b6d5b61d2ba8 1 parent 3f57e79
Mark Kendall authored
View
47 mythtv/libs/libmythservicecontracts/datacontracts/frontendActionList.h
@@ -0,0 +1,47 @@
+#ifndef FRONTENDACTIONLIST_H
+#define FRONTENDACTIONLIST_H
+
+#include "serviceexp.h"
+#include "datacontracthelper.h"
+
+namespace DTC
+{
+ class SERVICE_PUBLIC FrontendActionList : public QObject
+ {
+ Q_OBJECT
+ Q_CLASSINFO("version", "1.0");
+
+ Q_CLASSINFO("ActionList_type", "Action"); // is this legal?
+
+ Q_PROPERTY(QVariantMap ActionList READ ActionList DESIGNABLE true)
+
+ PROPERTYIMP_RO_REF(QVariantMap, ActionList)
+
+ public:
+ static void InitializeCustomTypes()
+ {
+ qRegisterMetaType<FrontendActionList>();
+ qRegisterMetaType<FrontendActionList*>();
+ }
+
+ public:
+ FrontendActionList(QObject *parent = 0) : QObject(parent)
+ {
+ }
+
+ FrontendActionList(const FrontendActionList &src)
+ {
+ Copy(src);
+ }
+
+ void Copy(const FrontendActionList &src)
+ {
+ m_ActionList = src.m_ActionList;
+ }
+ };
+};
+
+Q_DECLARE_METATYPE(DTC::FrontendActionList)
+Q_DECLARE_METATYPE(DTC::FrontendActionList*)
+
+#endif // FRONTENDACTIONLIST_H
View
2  mythtv/libs/libmythservicecontracts/libmythservicecontracts.pro
@@ -36,6 +36,7 @@ HEADERS += datacontracts/lineup.h datacontracts/captureCard.h
HEADERS += datacontracts/captureCardList.h datacontracts/recRule.h
HEADERS += datacontracts/recRuleList.h
HEADERS += datacontracts/frontendStatus.h
+HEADERS += datacontracts/frontendActionList.h
SOURCES += service.cpp
@@ -71,6 +72,7 @@ incDatacontracts.files += datacontracts/versionInfo.h datacontracts/line
incDatacontracts.files += datacontracts/captureCard.h datacontracts/captureCardList.h
incDatacontracts.files += datacontracts/recRule.h datacontracts/recRuleList.h
incDatacontracts.files += datacontracts/frontendStatus.h
+incDatacontracts.files += datacontracts/frontendActionList.h
INSTALLS += inc incServices incDatacontracts
View
6 mythtv/libs/libmythservicecontracts/services/frontendServices.h
@@ -3,6 +3,7 @@
#include "service.h"
#include "datacontracts/frontendStatus.h"
+#include "datacontracts/frontendActionList.h"
class SERVICE_PUBLIC FrontendServices : public Service
{
@@ -13,11 +14,16 @@ class SERVICE_PUBLIC FrontendServices : public Service
FrontendServices(QObject *parent = 0) : Service(parent)
{
DTC::FrontendStatus::InitializeCustomTypes();
+ DTC::FrontendActionList::InitializeCustomTypes();
}
public slots:
virtual DTC::FrontendStatus* GetStatus(void) = 0;
virtual bool SendMessage(const QString &Message) = 0;
+ virtual bool SendAction(const QString &Action,
+ const QString &File,
+ uint Width, uint Height) = 0;
+ virtual DTC::FrontendActionList* GetActionList(void) = 0;
};
#endif // FRONTENDSERVICES_H
View
139 mythtv/programs/mythfrontend/mythfexml.cpp
@@ -26,6 +26,8 @@
#include "keybindings.h"
+#include "services/frontend.h"
+
/////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////
@@ -61,8 +63,6 @@ MythFEXMLMethod MythFEXML::GetMethod(const QString &sURI)
{
if (sURI == "GetServDesc") return MFEXML_GetServiceDescription;
if (sURI == "GetScreenShot") return MFEXML_GetScreenShot;
- if (sURI == "SendAction") return MFEXML_Action;
- if (sURI == "GetActionList") return MFEXML_ActionList;
if (sURI == "GetActionTest") return MFEXML_ActionListTest;
if (sURI == "GetRemote") return MFEXML_GetRemote;
@@ -101,12 +101,6 @@ bool MythFEXML::ProcessRequest( HTTPRequest *pRequest )
case MFEXML_GetScreenShot:
GetScreenShot(pRequest);
break;
- case MFEXML_Action:
- SendAction(pRequest);
- break;
- case MFEXML_ActionList:
- GetActionList(pRequest);
- break;
case MFEXML_ActionListTest:
GetActionListTest(pRequest);
break;
@@ -159,59 +153,15 @@ void MythFEXML::GetScreenShot(HTTPRequest *pRequest)
pRequest->m_sFileName = sFileName;
}
-void MythFEXML::SendAction(HTTPRequest *pRequest)
-{
- QStringMap* map = &pRequest->m_mapParams;
- pRequest->m_eResponseType = ResponseTypeHTML;
- QString sText = map->value("action");
- uint pcount = map->size();
-
- LOG(VB_UPNP, LOG_INFO, QString("UPNP Action: %1 (total %2 params)")
- .arg(sText).arg(pcount));
-
- if (!IsValidAction(sText))
- return;
-
- if (pcount > 1)
- {
- bool valid = false;
- QStringList args;
- if (ACTION_SCREENSHOT == sText && 3 == pcount)
- {
- args << map->value("width");
- args << map->value("height");
- valid = true;
- }
- else if (ACTION_HANDLEMEDIA == sText && 2 == pcount)
- {
- args << map->value("file");
- valid = true;
- }
-
- if (valid)
- {
- MythEvent* me = new MythEvent(sText, args);
- qApp->postEvent(GetMythMainWindow(), me);
- return;
- }
-
- LOG(VB_UPNP, LOG_WARNING,
- "Failed to validate extra paramaters - ignoring");
- }
-
- QKeyEvent* ke = new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier, sText);
- qApp->postEvent(GetMythMainWindow(), (QEvent*)ke);
-}
-
static const QString PROCESS_ACTION =
" <script type =\"text/javascript\">\n"
" function postaction(action) {\n"
" var myForm = document.createElement(\"form\");\n"
" myForm.method =\"Post\";\n"
- " myForm.action =\"SendAction?\";\n"
+ " myForm.action =\"../Frontend/SendAction?\";\n"
" myForm.target =\"post_target\";\n"
" var myInput = document.createElement(\"input\");\n"
- " myInput.setAttribute(\"name\", \"action\");\n"
+ " myInput.setAttribute(\"name\", \"Action\");\n"
" myInput.setAttribute(\"value\", action);\n"
" myForm.appendChild(myInput);\n"
" document.body.appendChild(myForm);\n"
@@ -226,7 +176,7 @@ static const QString HIDDEN_IFRAME =
void MythFEXML::GetActionListTest(HTTPRequest *pRequest)
{
- InitActions();
+ Frontend::InitialiseActions();
pRequest->m_eResponseType = ResponseTypeHTML;
pRequest->m_mapRespHeaders[ "Cache-Control" ] = "no-cache=\"Ext\", max-age = 5000";
@@ -237,7 +187,7 @@ void MythFEXML::GetActionListTest(HTTPRequest *pRequest)
"<html>\n" << PROCESS_ACTION <<
" <body>\n" << HIDDEN_IFRAME;
- QHashIterator<QString,QStringList> contexts(m_actionDescriptions);
+ QHashIterator<QString,QStringList> contexts(Frontend::gActionDescriptions);
while (contexts.hasNext())
{
contexts.next();
@@ -260,46 +210,11 @@ void MythFEXML::GetActionListTest(HTTPRequest *pRequest)
}
-void MythFEXML::GetActionList(HTTPRequest *pRequest)
-{
- InitActions();
-
- pRequest->m_eResponseType = ResponseTypeXML;
- pRequest->m_mapRespHeaders[ "Cache-Control" ] = "no-cache=\"Ext\", max-age = 5000";
-
- QTextStream stream( &pRequest->m_response );
-
- stream << "<mythactions version=\"1\">";
-
- QHashIterator<QString,QStringList> contexts(m_actionDescriptions);
- while (contexts.hasNext())
- {
- contexts.next();
- stream << QString("<context name=\"%1\">")
- .arg(contexts.key());
- QStringList actions = contexts.value();
- foreach (QString action, actions)
- {
- QStringList split = action.split(",");
- if (split.size() == 2)
- {
- stream <<
- QString("<action name=\"%1\">%2</action>")
- .arg(split[0]).arg(split[1]);
- }
- }
- stream << "</context>";
- }
- stream << "</mythactions>";
-}
-
#define BUTTON(action,desc) \
QString(" <input class=\"bigb\" type=\"button\" value=\"%1\" onClick=\"postaction('%2');\"></input>\r\n").arg(action).arg(desc)
void MythFEXML::GetRemote(HTTPRequest *pRequest)
{
- InitActions();
-
pRequest->m_eResponseType = ResponseTypeHTML;
pRequest->m_mapRespHeaders[ "Cache-Control" ] = "no-cache=\"Ext\", max-age = 5000";
@@ -351,45 +266,3 @@ void MythFEXML::GetRemote(HTTPRequest *pRequest)
" </body>\n"
"</html>\n";
}
-
-bool MythFEXML::IsValidAction(const QString &action)
-{
- InitActions();
- if (m_actionList.contains(action))
- return true;
- LOG(VB_GENERAL, LOG_ERR, QString("UPNP Action: %1 is invalid").arg(action));
- return false;
-}
-
-void MythFEXML::InitActions(void)
-{
- static bool initialised = false;
- if (initialised)
- return;
-
- initialised = true;
- KeyBindings *bindings = new KeyBindings(gCoreContext->GetHostName());
- if (bindings)
- {
- QStringList contexts = bindings->GetContexts();
- contexts.sort();
- foreach (QString context, contexts)
- {
- m_actionDescriptions[context] = QStringList();
- QStringList ctx_actions = bindings->GetActions(context);
- ctx_actions.sort();
- m_actionList += ctx_actions;
- foreach (QString actions, ctx_actions)
- {
- QString desc = actions + "," +
- bindings->GetActionDescription(context, actions);
- m_actionDescriptions[context].append(desc);
- }
- }
- }
- m_actionList.removeDuplicates();
- m_actionList.sort();
-
- foreach (QString actions, m_actionList)
- LOG(VB_UPNP, LOG_INFO, QString("MythFEXML Action: %1").arg(actions));
-}
View
19 mythtv/programs/mythfrontend/mythfexml.h
@@ -17,8 +17,6 @@ typedef enum
MFEXML_Unknown = 0,
MFEXML_GetServiceDescription,
MFEXML_GetScreenShot,
- MFEXML_Action,
- MFEXML_ActionList,
MFEXML_ActionListTest,
MFEXML_GetRemote,
} MythFEXMLMethod;
@@ -30,9 +28,6 @@ class MythFEXML : public Eventing
QString m_sControlUrl;
QString m_sServiceDescFileName;
- QStringList m_actionList;
- QHash<QString,QStringList> m_actionDescriptions;
-
protected:
// Implement UPnpServiceImpl methods that we can
@@ -47,12 +42,8 @@ class MythFEXML : public Eventing
MythFEXMLMethod GetMethod( const QString &sURI );
void GetScreenShot ( HTTPRequest *pRequest );
- void SendAction ( HTTPRequest *pRequest );
- void GetActionList ( HTTPRequest *pRequest );
void GetActionListTest( HTTPRequest *pRequest );
void GetRemote ( HTTPRequest *pRequest );
- bool IsValidAction ( const QString &action );
- void InitActions ( void );
public:
MythFEXML( UPnpDevice *pDevice , const QString sSharePath);
@@ -61,18 +52,8 @@ class MythFEXML : public Eventing
virtual QStringList GetBasePaths();
bool ProcessRequest( HTTPRequest *pRequest );
-
- // Static methods shared with HttpStatus
-
};
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
#endif
View
116 mythtv/programs/mythfrontend/services/frontend.cpp
@@ -1,9 +1,20 @@
#include <QCoreApplication>
+#include <QKeyEvent>
+
+#include "mythcorecontext.h"
+#include "keybindings.h"
+#include "mythlogging.h"
#include "mythevent.h"
#include "mythuistatetracker.h"
#include "mythmainwindow.h"
+
#include "frontend.h"
+#define LOC QString("Frontend API: ")
+
+QStringList Frontend::gActionList = QStringList();
+QHash<QString,QStringList> Frontend::gActionDescriptions = QHash<QString,QStringList>();
+
DTC::FrontendStatus* Frontend::GetStatus(void)
{
DTC::FrontendStatus *status = new DTC::FrontendStatus();
@@ -20,3 +31,108 @@ bool Frontend::SendMessage(const QString &Message)
new MythEvent(MythEvent::MythUserMessage, Message));
return true;
}
+
+bool Frontend::SendAction(const QString &Action, const QString &File,
+ uint Width, uint Height)
+{
+ if (!IsValidAction(Action))
+ return false;
+
+ if (ACTION_HANDLEMEDIA == Action)
+ {
+ if (File.isEmpty())
+ {
+ LOG(VB_GENERAL, LOG_ERR, LOC + QString("No file specified."));
+ return false;
+ }
+
+ MythEvent* me = new MythEvent(Action, QStringList(File));
+ qApp->postEvent(GetMythMainWindow(), me);
+ return true;
+ }
+
+ if (ACTION_SCREENSHOT == Action)
+ {
+ if (!Width || !Height)
+ {
+ LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid screenshot parameters.");
+ return false;
+ }
+
+ QStringList args;
+ args << QString::number(Width) << QString::number(Height);
+ MythEvent* me = new MythEvent(Action, args);
+ qApp->postEvent(GetMythMainWindow(), me);
+ return true;
+ }
+
+ QKeyEvent* ke = new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier, Action);
+ qApp->postEvent(GetMythMainWindow(), (QEvent*)ke);
+ return true;
+}
+
+DTC::FrontendActionList* Frontend::GetActionList(void)
+{
+ DTC::FrontendActionList *list = new DTC::FrontendActionList();
+
+ InitialiseActions();
+
+ QHashIterator<QString,QStringList> contexts(gActionDescriptions);
+ while (contexts.hasNext())
+ {
+ contexts.next();
+ // TODO can we keep the context data with QMap<QString, QStringList>?
+ QStringList actions = contexts.value();
+ foreach (QString action, actions)
+ {
+ QStringList split = action.split(",");
+ if (split.size() == 2)
+ list->ActionList().insert(split[0], split[1]);
+ }
+ }
+ return list;
+}
+
+bool Frontend::IsValidAction(const QString &Action)
+{
+ InitialiseActions();
+ if (gActionList.contains(Action))
+ return true;
+
+ LOG(VB_GENERAL, LOG_ERR, LOC + QString("Action '%1'' is invalid.")
+ .arg(Action));
+ return false;
+}
+
+void Frontend::InitialiseActions(void)
+{
+ static bool initialised = false;
+ if (initialised)
+ return;
+
+ initialised = true;
+ KeyBindings *bindings = new KeyBindings(gCoreContext->GetHostName());
+ if (bindings)
+ {
+ QStringList contexts = bindings->GetContexts();
+ contexts.sort();
+ foreach (QString context, contexts)
+ {
+ gActionDescriptions[context] = QStringList();
+ QStringList ctx_actions = bindings->GetActions(context);
+ ctx_actions.sort();
+ gActionList += ctx_actions;
+ foreach (QString actions, ctx_actions)
+ {
+ QString desc = actions + "," +
+ bindings->GetActionDescription(context, actions);
+ gActionDescriptions[context].append(desc);
+ }
+ }
+ }
+ gActionList.removeDuplicates();
+ gActionList.sort();
+
+ foreach (QString actions, gActionList)
+ LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("Action: %1").arg(actions));
+}
View
12 mythtv/programs/mythfrontend/services/frontend.h
@@ -6,6 +6,8 @@
class Frontend : public FrontendServices
{
+ friend class MythFEXML;
+
Q_OBJECT
public:
@@ -14,6 +16,16 @@ class Frontend : public FrontendServices
public:
DTC::FrontendStatus* GetStatus(void);
bool SendMessage(const QString &Message);
+ bool SendAction(const QString &Action, const QString &File,
+ uint Width, uint Height);
+ DTC::FrontendActionList* GetActionList(void);
+
+ static bool IsValidAction(const QString &action);
+ static void InitialiseActions(void);
+
+ protected:
+ static QStringList gActionList;
+ static QHash<QString,QStringList> gActionDescriptions;
};
class ScriptableFrontend : public QObject
Please sign in to comment.
Something went wrong with that request. Please try again.