00001
00002
00003
00004
00005
00006
00007
00008
00010
00011 #include <QTextStream>
00012
00013 #include "upnpsubscription.h"
00014 #include "mediarenderer.h"
00015 #include "mythversion.h"
00016 #include "upnpscanner.h"
00017 #include "mythfexml.h"
00018 #include "compat.h"
00019 #include "mythmiscutil.h"
00020
00021 #include "serviceHosts/frontendServiceHost.h"
00022
00023 class MythFrontendStatus : public HttpServerExtension
00024 {
00025 public:
00026 MythFrontendStatus(const QString &sSharePath)
00027 : HttpServerExtension("MythFrontendStatus", sSharePath) { }
00028
00029 virtual QStringList GetBasePaths() { return QStringList( "/" ); }
00030
00031 virtual bool ProcessRequest(HTTPRequest *pRequest)
00032 {
00033 if (!pRequest)
00034 return false;
00035
00036 if (pRequest->m_sBaseUrl != "/")
00037 return false;
00038
00039 if (pRequest->m_sMethod == "getDeviceDesc")
00040 return false;
00041
00042 pRequest->m_eResponseType = ResponseTypeHTML;
00043 pRequest->m_mapRespHeaders["Cache-Control"] =
00044 "no-cache=\"Ext\", max-age = 5000";
00045
00046 SSDPCacheEntries* cache = NULL;
00047 QString ipaddress = QString();
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 if (!UPnp::g_IPAddrList.isEmpty())
00058 ipaddress = UPnp::g_IPAddrList.at(0);
00059
00060 QString hostname = gCoreContext->GetHostName();
00061 QDateTime qdtNow = QDateTime::currentDateTime();
00062 QString masterhost = gCoreContext->GetMasterHostName();
00063 QString masterip = gCoreContext->GetSetting("MasterServerIP");
00064 QString masterport = gCoreContext->GetSettingOnHost("BackendStatusPort",
00065 masterhost, "6544");
00066
00067 QTextStream stream ( &pRequest->m_response );
00068 stream.setCodec("UTF-8");
00069
00070 stream
00071 << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
00072 << "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\r\n"
00073 << "<html xmlns=\"http://www.w3.org/1999/xhtml\""
00074 << " xml:lang=\"en\" lang=\"en\">\r\n"
00075 << "<head>\r\n"
00076 << " <meta http-equiv=\"Content-Type\""
00077 << "content=\"text/html; charset=UTF-8\" />\r\n"
00078 << " <title>MythFrontend Status - "
00079 << MythDateTimeToString(qdtNow, kDateTimeShort) << " - "
00080 << MYTH_BINARY_VERSION << "</title>\r\n"
00081 << " <link rel=\"stylesheet\" href=\"/css/site.css\" type=\"text/css\">\r\n"
00082 << " <link rel=\"stylesheet\" href=\"/css/Status.css\" type=\"text/css\">\r\n"
00083 << "</head>\r\n"
00084 << "<body>\r\n\r\n"
00085 << " <h1 class=\"status\">MythFrontend Status</h1>\r\n";
00086
00087
00088 stream
00089 << " <div class=\"content\">\r\n"
00090 << " <h2 class=\"status\">This Frontend</h2>\r\n"
00091 << "Name : " << hostname << "<br />\r\n"
00092 << "Version : " << MYTH_BINARY_VERSION << "\r\n"
00093 << " </div>\r\n";
00094
00095
00096
00097
00098
00099
00100
00101 cache = SSDP::Find("urn:schemas-mythtv-org:service:MythFrontend:1");
00102 if (cache)
00103 {
00104 stream
00105 << " <div class=\"content\">\r\n"
00106 << " <h2 class=\"status\">Other Frontends</h2>\r\n";
00107
00108 EntryMap map;
00109 cache->GetEntryMap(map);
00110 cache->Release();
00111 cache = NULL;
00112
00113 QMapIterator< QString, DeviceLocation * > i(map);
00114 while (i.hasNext())
00115 {
00116 i.next();
00117 QUrl url(i.value()->m_sLocation);
00118 if (url.host() != ipaddress)
00119 {
00120 stream << "<br />" << url.host() << " (<a href=\""
00121 << url.toString(QUrl::RemovePath)
00122 << "\">Status page</a>)\r\n";
00123 }
00124 i.value()->Release();
00125 }
00126 stream << " </div>\r\n";
00127 }
00128
00129
00130 stream
00131 << " <div class=\"content\">\r\n"
00132 << " <h2 class=\"status\">MythTV Backends</h2>\r\n"
00133 << "Master: " << masterhost << " (<a href=\"http://"
00134 << masterip << ":" << masterport
00135 << "\">Status page</a>)\r\n";
00136
00137
00138 cache = SSDP::Find("urn:schemas-mythtv-org:device:SlaveMediaServer:1");
00139 if (cache)
00140 {
00141 EntryMap map;
00142 cache->GetEntryMap(map);
00143 cache->Release();
00144 cache = NULL;
00145
00146 QMapIterator< QString, DeviceLocation * > i(map);
00147 while (i.hasNext())
00148 {
00149 i.next();
00150 QUrl url(i.value()->m_sLocation);
00151 stream << "<br />" << "Slave: " << url.host()
00152 << " (<a href=\""
00153 << url.toString(QUrl::RemovePath)
00154 << "\">Status page</a>)\r\n";
00155 i.value()->Release();
00156 }
00157 }
00158
00159 stream
00160 << " </div>\r\n";
00161
00162 stream
00163 << " <div class=\"content\">\r\n"
00164 << " <h2 class=\"status\">Services</h2>\r\n"
00165 << " <a href=\"MythFE/GetRemote\">Remote Control</a>\r\n"
00166 << " </div>\r\n";
00167
00168 double load[3];
00169 if (getloadavg(load, 3) != -1)
00170 {
00171 stream
00172 << " <div class=\"content\">\r\n"
00173 << " <h2 class=\"status\">Machine Information</h2>\r\n"
00174 << " <div class=\"loadstatus\">\r\n"
00175 << " This machine's load average:"
00176 << "\r\n <ul>\r\n <li>"
00177 << "1 Minute: " << QString::number(load[0]) << "</li>\r\n"
00178 << " <li>5 Minutes: " << QString::number(load[1]) << "</li>\r\n"
00179 << " <li>15 Minutes: " << QString::number(load[2])
00180 << "</li>\r\n </ul>\r\n"
00181 << " </div>\r\n"
00182 << " </div>\r\n";
00183 }
00184
00185 stream << "</body>\r\n</html>\r\n";
00186 stream.flush();
00187
00188 return true;
00189 }
00190 };
00191
00194
00195
00196
00199
00201
00203
00204 MediaRenderer::MediaRenderer()
00205 {
00206 LOG(VB_UPNP, LOG_INFO, "MediaRenderer::Begin");
00207
00208
00209
00210
00211
00212 SetConfiguration( new XmlConfiguration( "config.xml" ));
00213
00214
00215
00216
00217
00218 int nPort = g_pConfig->GetValue( "UPnP/MythFrontend/ServicePort", 6547 );
00219
00220 m_pHttpServer = new HttpServer();
00221
00222 if (!m_pHttpServer)
00223 return;
00224
00225 if (!m_pHttpServer->listen(nPort))
00226 {
00227 LOG(VB_GENERAL, LOG_ERR, "MediaRenderer::HttpServer Create Error");
00228 delete m_pHttpServer;
00229 m_pHttpServer = NULL;
00230 return;
00231 }
00232
00233
00234
00235
00236
00237 if (Initialize( nPort, m_pHttpServer ))
00238 {
00239
00240
00241
00242
00243 LOG(VB_UPNP, LOG_INFO, "MediaRenderer::Creating UPnp Description");
00244
00245 UPnpDevice &device = g_UPnpDeviceDesc.m_rootDevice;
00246
00247 device.m_sDeviceType = "urn:schemas-upnp-org:device:MediaRenderer:1";
00248 device.m_sFriendlyName = "MythTV AV Renderer";
00249 device.m_sManufacturer = "MythTV";
00250 device.m_sManufacturerURL = "http://www.mythtv.org";
00251 device.m_sModelDescription = "MythTV AV Media Renderer";
00252 device.m_sModelName = "MythTV AV Media Renderer";
00253 device.m_sModelURL = "http://www.mythtv.org";
00254 device.m_sUPC = "";
00255 device.m_sPresentationURL = "/";
00256
00257
00258
00259
00260
00261 LOG(VB_UPNP, LOG_INFO,
00262 "MediaRenderer::Registering MythFrontendStatus service.");
00263 m_pHttpServer->RegisterExtension(
00264 new MythFrontendStatus(m_pHttpServer->GetSharePath()));
00265
00266 QString sSinkProtocols = "http-get:*:image/gif:*,"
00267 "http-get:*:image/jpeg:*,"
00268 "http-get:*:image/png:*,"
00269 "http-get:*:video/avi:*,"
00270 "http-get:*:audio/mpeg:*,"
00271 "http-get:*:audio/wav:*,"
00272 "http-get:*:video/mpeg:*,"
00273 "http-get:*:video/nupplevideo:*,"
00274 "http-get:*:video/x-ms-wmv:*";
00275
00276
00277
00278 LOG(VB_UPNP, LOG_INFO, "MediaRenderer::Registering MythFEXML Service.");
00279 m_pHttpServer->RegisterExtension(
00280 new MythFEXML(RootDevice(), m_pHttpServer->GetSharePath()));
00281
00282 LOG(VB_UPNP, LOG_INFO, "MediaRenderer::Registering Status Service.");
00283 m_pHttpServer->RegisterExtension(new FrontendServiceHost(m_pHttpServer->GetSharePath()));
00284
00285 #if 0
00286 LOG(VB_UPNP, LOG_INFO,
00287 "MediaRenderer::Registering AVTransport Service.");
00288 m_pUPnpAVT = new UPnpAVTransport( RootDevice() );
00289 m_pHttpServer->RegisterExtension( m_pUPnpAVT );
00290 #endif
00291
00292 LOG(VB_UPNP, LOG_INFO, "MediaRenderer::Registering CMGR Service.");
00293
00294 m_pUPnpCMGR = new UPnpCMGR(
00295 RootDevice(), m_pHttpServer->GetSharePath(), "", sSinkProtocols);
00296 m_pHttpServer->RegisterExtension( m_pUPnpCMGR );
00297
00298 #if 0
00299 LOG(VB_UPNP, LOG_INFO,
00300 "MediaRenderer::Registering RenderingControl Service.");
00301 m_pUPnpRCTL= new UPnpRCTL( RootDevice() );
00302 m_pHttpServer->RegisterExtension( m_pUPnpRCTL );
00303 #endif
00304
00305 UPNPSubscription *subscription = NULL;
00306 if (getenv("MYTHTV_UPNPSCANNER"))
00307 {
00308 LOG(VB_UPNP, LOG_INFO,
00309 "MediaRenderer: Registering subscription service.");
00310
00311 subscription = new UPNPSubscription(
00312 m_pHttpServer->GetSharePath(), nPort);
00313 m_pHttpServer->RegisterExtension(subscription);
00314 }
00315
00316 Start();
00317
00318
00319 if (subscription)
00320 UPNPScanner::Enable(true, subscription);
00321
00322
00323
00324 SSDP::Instance()->PerformSearch("ssdp:all");
00325 }
00326 else
00327 {
00328 LOG(VB_GENERAL, LOG_ERR,
00329 "MediaRenderer::Unable to Initialize UPnp Stack");
00330 }
00331
00332 LOG(VB_UPNP, LOG_INFO, "MediaRenderer::End");
00333 }
00334
00336
00338
00339 MediaRenderer::~MediaRenderer()
00340 {
00341 UPNPScanner::Enable(false);
00342 delete m_pHttpServer;
00343 }