00001
00002
00003
00004
00005
00007
00008 #include "mythfexml.h"
00009
00010 #include "mythcorecontext.h"
00011 #include "mythmiscutil.h"
00012 #include "mythdbcon.h"
00013
00014 #include "mythmainwindow.h"
00015
00016 #include <QTextStream>
00017 #include <QCoreApplication>
00018 #include <QTextStream>
00019 #include <QDir>
00020 #include <QFile>
00021 #include <QRegExp>
00022 #include <QBuffer>
00023 #include <QKeyEvent>
00024
00025 #include "../../config.h"
00026
00027 #include "keybindings.h"
00028
00029 #include "services/frontend.h"
00030
00032
00034
00035 MythFEXML::MythFEXML( UPnpDevice *pDevice , const QString sSharePath)
00036 : Eventing( "MythFEXML", "MYTHTV_Event", sSharePath)
00037 {
00038
00039 QString sUPnpDescPath =
00040 UPnp::GetConfiguration()->GetValue( "UPnP/DescXmlPath", m_sSharePath );
00041
00042 m_sServiceDescFileName = sUPnpDescPath + "MFEXML_scpd.xml";
00043 m_sControlUrl = "/MythFE";
00044
00045
00046
00047 RegisterService( pDevice );
00048 }
00049
00051
00053
00054 MythFEXML::~MythFEXML()
00055 {
00056 }
00057
00059
00061
00062 MythFEXMLMethod MythFEXML::GetMethod(const QString &sURI)
00063 {
00064 if (sURI == "GetServDesc") return MFEXML_GetServiceDescription;
00065 if (sURI == "GetScreenShot") return MFEXML_GetScreenShot;
00066 if (sURI == "GetActionTest") return MFEXML_ActionListTest;
00067 if (sURI == "GetRemote") return MFEXML_GetRemote;
00068
00069 return( MFEXML_Unknown );
00070 }
00071
00073
00075
00076 QStringList MythFEXML::GetBasePaths()
00077 {
00078 return Eventing::GetBasePaths() << m_sControlUrl;
00079 }
00080
00082
00084
00085 bool MythFEXML::ProcessRequest( HTTPRequest *pRequest )
00086 {
00087 if (!pRequest)
00088 return false;
00089
00090 if (pRequest->m_sBaseUrl != m_sControlUrl)
00091 return false;
00092
00093 LOG(VB_UPNP, LOG_INFO, QString("MythFEXML::ProcessRequest: %1 : %2")
00094 .arg(pRequest->m_sMethod).arg(pRequest->m_sRawRequest));
00095
00096 switch(GetMethod(pRequest->m_sMethod))
00097 {
00098 case MFEXML_GetServiceDescription:
00099 pRequest->FormatFileResponse(m_sServiceDescFileName);
00100 break;
00101 case MFEXML_GetScreenShot:
00102 GetScreenShot(pRequest);
00103 break;
00104 case MFEXML_ActionListTest:
00105 GetActionListTest(pRequest);
00106 break;
00107 case MFEXML_GetRemote:
00108 GetRemote(pRequest);
00109 break;
00110 default:
00111 UPnp::FormatErrorResponse(pRequest, UPnPResult_InvalidAction);
00112 }
00113 return true;
00114 }
00115
00116
00117
00118
00119
00121
00123
00124 void MythFEXML::GetScreenShot(HTTPRequest *pRequest)
00125 {
00126 pRequest->m_eResponseType = ResponseTypeFile;
00127
00128
00129 int nWidth = pRequest->m_mapParams[ "width" ].toInt();
00130 int nHeight = pRequest->m_mapParams[ "height" ].toInt();
00131 QString sFormat = pRequest->m_mapParams[ "format" ];
00132
00133 if (sFormat.isEmpty())
00134 sFormat = "png";
00135
00136 if (sFormat != "jpg" && sFormat != "png")
00137 {
00138 LOG(VB_GENERAL, LOG_ERR, "Invalid screen shot format: " + sFormat);
00139 return;
00140 }
00141
00142 LOG(VB_GENERAL, LOG_INFO,
00143 QString("Screen shot requested (%1x%2), format %3")
00144 .arg(nWidth).arg(nHeight).arg(sFormat));
00145
00146 QString sFileName = QString("/%1/myth-screenshot-XML.%2")
00147 .arg(gCoreContext->GetSetting("ScreenShotPath","/tmp"))
00148 .arg(sFormat);
00149
00150 MythMainWindow *window = GetMythMainWindow();
00151 window->RemoteScreenShot(sFileName, nWidth, nHeight);
00152
00153 pRequest->m_sFileName = sFileName;
00154 }
00155
00156 static const QString PROCESS_ACTION =
00157 " <script type =\"text/javascript\">\n"
00158 " function postaction(action) {\n"
00159 " var myForm = document.createElement(\"form\");\n"
00160 " myForm.method =\"Post\";\n"
00161 " myForm.action =\"../Frontend/SendAction?\";\n"
00162 " myForm.target =\"post_target\";\n"
00163 " var myInput = document.createElement(\"input\");\n"
00164 " myInput.setAttribute(\"name\", \"Action\");\n"
00165 " myInput.setAttribute(\"value\", action);\n"
00166 " myForm.appendChild(myInput);\n"
00167 " document.body.appendChild(myForm);\n"
00168 " myForm.submit();\n"
00169 " document.body.removeChild(myForm);\n"
00170 " }\n"
00171 " </script>\n";
00172
00173 static const QString HIDDEN_IFRAME =
00174 " <iframe id=\"hidden_target\" name=\"post_target\" src=\"\""
00175 " style=\"width:0;height:0;border:0px solid #fff;\"></iframe>\n";
00176
00177 void MythFEXML::GetActionListTest(HTTPRequest *pRequest)
00178 {
00179 Frontend::InitialiseActions();
00180
00181 pRequest->m_eResponseType = ResponseTypeHTML;
00182 pRequest->m_mapRespHeaders[ "Cache-Control" ] = "no-cache=\"Ext\", max-age = 5000";
00183
00184 QTextStream stream( &pRequest->m_response );
00185
00186 stream <<
00187 "<html>\n" << PROCESS_ACTION <<
00188 " <body>\n" << HIDDEN_IFRAME;
00189
00190 QHashIterator<QString,QStringList> contexts(Frontend::gActionDescriptions);
00191 while (contexts.hasNext())
00192 {
00193 contexts.next();
00194 QStringList actions = contexts.value();
00195 foreach (QString action, actions)
00196 {
00197 QStringList split = action.split(",");
00198 if (split.size() == 2)
00199 {
00200 stream <<
00201 QString(" <div>%1 <input type=\"button\" value=\"%2\" onClick=\"postaction('%2');\"></input> %3</div>\n")
00202 .arg(contexts.key()).arg(split[0]).arg(split[1]);
00203 }
00204 }
00205 }
00206
00207 stream <<
00208 " </body>\n"
00209 "</html>\n";
00210
00211 }
00212
00213 #define BUTTON(action,desc) \
00214 QString(" <input class=\"bigb\" type=\"button\" value=\"%1\" onClick=\"postaction('%2');\"></input>\r\n").arg(action).arg(desc)
00215
00216 void MythFEXML::GetRemote(HTTPRequest *pRequest)
00217 {
00218 pRequest->m_eResponseType = ResponseTypeHTML;
00219 pRequest->m_mapRespHeaders[ "Cache-Control" ] = "no-cache=\"Ext\", max-age = 5000";
00220
00221 QTextStream stream( &pRequest->m_response );
00222
00223 stream <<
00224 "<html>\n" << PROCESS_ACTION <<
00225 " <style type=\"text/css\" title=\"Default\" media=\"all\">\r\n"
00226 " <!--\r\n"
00227 " body {\r\n"
00228 " margin: 0px;\r\n"
00229 " width : 310px;\r\n"
00230 " }\r\n"
00231 " -->\r\n"
00232 " .bigb {\r\n"
00233 " width : 100px;\r\n"
00234 " height: 50px;\r\n"
00235 " margin: 0px;\r\n"
00236 " text-align: center;\r\n"
00237 " }\r\n"
00238 " </style>\r\n"
00239 " <title>MythFrontend Control</title>\r\n" <<
00240 " <body>\n" << HIDDEN_IFRAME;
00241
00242 stream <<
00243 " <div>\r\n" <<
00244 BUTTON("1","1") << BUTTON("2","2") << BUTTON("3","3") <<
00245 " </div>\r\n" <<
00246 " <div>\r\n" <<
00247 BUTTON("4","4") << BUTTON("5","5") << BUTTON("6","6") <<
00248 " </div>\r\n" <<
00249 " <div>\r\n" <<
00250 BUTTON("7","7") << BUTTON("8","8") << BUTTON("9","9") <<
00251 " </div>\r\n" <<
00252 " <div>\r\n" <<
00253 BUTTON("MENU","MENU") << BUTTON("0","0") << BUTTON("INFO","INFO") <<
00254 " </div>\r\n" <<
00255 " <div>\r\n" <<
00256 BUTTON("Back","ESCAPE") << BUTTON("^","UP") << BUTTON("MUTE","MUTE") <<
00257 " </div>\r\n" <<
00258 " <div>\r\n" <<
00259 BUTTON("<","LEFT") << BUTTON("Enter","SELECT") << BUTTON(">","RIGHT") <<
00260 " </div>\r\n" <<
00261 " <div>\r\n" <<
00262 BUTTON("<<","JUMPRWND") << BUTTON("v","DOWN") << BUTTON(">>","JUMPFFWD") <<
00263 " </div>\r\n";
00264
00265 stream <<
00266 " </body>\n"
00267 "</html>\n";
00268 }