MythTV  master
mediaserver.cpp
Go to the documentation of this file.
1 // Program Name: mediaserver.cpp
3 //
4 // Purpose - uPnp Media Server main Class
5 //
6 // Created By : David Blain Created On : Jan. 15, 2007
7 // Modified By : Modified On:
8 //
10 
11 #include "libmythbase/mythconfig.h"
12 
13 // Qt
14 #include <QNetworkInterface>
15 #include <QNetworkProxy>
16 #if CONFIG_QTSCRIPT
17 #include <QScriptEngine>
18 #endif
19 
20 // MythTV
21 #ifdef USING_LIBDNS_SD
23 #endif
24 #include "libmythbase/mythdb.h"
25 #include "libmythbase/mythdirs.h"
26 #include "libmythupnp/htmlserver.h"
27 
28 // MythBackend
29 #include "httpconfig.h"
30 #include "internetContent.h"
31 #include "mediaserver.h"
32 #include "upnpcdsmusic.h"
33 #include "upnpcdstv.h"
34 #include "upnpcdsvideo.h"
35 
45 
48 //
49 // UPnp Class implementaion
50 //
53 
55 //
57 
59  m_sSharePath(GetShareDir())
60 {
61  LOG(VB_UPNP, LOG_INFO, "MediaServer()");
62 }
63 
64 void MediaServer::Init(bool bIsMaster, bool bDisableUPnp /* = false */)
65 {
66  LOG(VB_UPNP, LOG_INFO, "MediaServer::Init(): Begin");
67 
68  int nPort = GetMythDB()->GetNumSetting("BackendStatusPort", 6544);
69  int nSSLPort = GetMythDB()->GetNumSetting("BackendSSLPort", nPort + 10);
70  int nWSPort = nPort + 5;
71  // UPNP port is now status port + 6 (default 6550)
72  nPort += 6;
73  nSSLPort += 6;
74 
75  auto *pHttpServer = new HttpServer();
76 
77  if (!pHttpServer->isListening())
78  {
79  pHttpServer->setProxy(QNetworkProxy::NoProxy);
80  // HTTP
81  if (!pHttpServer->listen(nPort))
82  {
83  LOG(VB_GENERAL, LOG_ERR, "MediaServer: HttpServer Create Error");
84  delete pHttpServer;
85  pHttpServer = nullptr;
86  return;
87  }
88 
89 #ifndef QT_NO_OPENSSL
90  // HTTPS (SSL)
91  if (!pHttpServer->listen(nSSLPort, true, kSSLServer))
92  {
93  LOG(VB_GENERAL, LOG_ERR, "MediaServer: HttpServer failed to create SSL server");
94  }
95 #endif
96  }
97 
99 
101  {
102  if (!m_webSocketServer->listen(nWSPort))
103  {
104  LOG(VB_GENERAL, LOG_ERR, "MediaServer: WebSocketServer Create Error");
105  }
106  }
107 
108  QString sFileName = GetMythDB()->GetSetting("upnpDescXmlPath", m_sSharePath);
109 
110  if ( bIsMaster )
111  sFileName += "devicemaster.xml";
112  else
113  sFileName += "deviceslave.xml";
114 
115  // ------------------------------------------------------------------
116  // Make sure our device Description is loaded.
117  // ------------------------------------------------------------------
118 
119  LOG(VB_UPNP, LOG_INFO,
120  "MediaServer: Loading UPnp Description " + sFileName);
121 
122  g_UPnpDeviceDesc.Load( sFileName );
123 
124  // ------------------------------------------------------------------
125  // Register Http Server Extensions...
126  // ------------------------------------------------------------------
127 
128  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering Http Server Extensions.");
129 
130  auto *pHtmlServer =
131  new HtmlServerExtension(m_sSharePath + "html", "backend_");
132  pHttpServer->RegisterExtension( pHtmlServer );
133  pHttpServer->RegisterExtension( new HttpConfig() );
134  pHttpServer->RegisterExtension( new InternetContent ( m_sSharePath ));
135 
136  pHttpServer->RegisterExtension( new MythServiceHost ( m_sSharePath ));
137  pHttpServer->RegisterExtension( new GuideServiceHost ( m_sSharePath ));
138  pHttpServer->RegisterExtension( new ContentServiceHost( m_sSharePath ));
139  pHttpServer->RegisterExtension( new DvrServiceHost ( m_sSharePath ));
140  pHttpServer->RegisterExtension( new ChannelServiceHost( m_sSharePath ));
141  pHttpServer->RegisterExtension( new VideoServiceHost ( m_sSharePath ));
142  pHttpServer->RegisterExtension( new MusicServiceHost ( m_sSharePath ));
143  pHttpServer->RegisterExtension( new CaptureServiceHost( m_sSharePath ));
144  pHttpServer->RegisterExtension( new ImageServiceHost ( m_sSharePath ));
145 
146 
147  // ------------------------------------------------------------------
148  // Register Service Types with Scripting Engine
149  //
150  // -=>NOTE: We need to know the actual type at compile time for this
151  // to work, so it needs to be done here. I'm still looking
152  // into ways that we may encapsulate this in the service
153  // classes. - dblain
154  // ------------------------------------------------------------------
155 
156 #if CONFIG_QTSCRIPT
157  QScriptEngine* pEngine = pHtmlServer->ScriptEngine();
158 
159  pEngine->globalObject().setProperty("Myth" ,
160  pEngine->scriptValueFromQMetaObject< ScriptableMyth >() );
161  pEngine->globalObject().setProperty("Guide" ,
162  pEngine->scriptValueFromQMetaObject< ScriptableGuide >() );
163  pEngine->globalObject().setProperty("Content",
164  pEngine->scriptValueFromQMetaObject< ScriptableContent >() );
165  pEngine->globalObject().setProperty("Dvr" ,
166  pEngine->scriptValueFromQMetaObject< ScriptableDvr >() );
167  pEngine->globalObject().setProperty("Channel",
168  pEngine->scriptValueFromQMetaObject< ScriptableChannel >() );
169  pEngine->globalObject().setProperty("Video" ,
170  pEngine->scriptValueFromQMetaObject< ScriptableVideo >() );
171  pEngine->globalObject().setProperty("Music" ,
172  pEngine->scriptValueFromQMetaObject< ScriptableVideo >() );
173  pEngine->globalObject().setProperty("Capture" ,
174  pEngine->scriptValueFromQMetaObject< ScriptableCapture >() );
175  pEngine->globalObject().setProperty("Image" ,
176  pEngine->scriptValueFromQMetaObject< ScriptableImage >() );
177 #endif
178 
179  // ------------------------------------------------------------------
180 
181  if (bDisableUPnp)
182  {
183  LOG(VB_GENERAL, LOG_NOTICE,
184  "*** The UPNP service has been DISABLED with the "
185  "--noupnp option ***");
186  return;
187  }
188 
189  QList<QHostAddress> IPAddrList = ServerPool::DefaultListen();
190  if (IPAddrList.contains(QHostAddress(QHostAddress::AnyIPv4)))
191  {
192  IPAddrList.removeAll(QHostAddress(QHostAddress::AnyIPv4));
193  IPAddrList.removeAll(QHostAddress(QHostAddress::AnyIPv6));
194  IPAddrList.append(QNetworkInterface::allAddresses());
195  }
196 
197  if (IPAddrList.isEmpty())
198  {
199  LOG(VB_GENERAL, LOG_ERR,
200  "MediaServer: No Listenable IP Addresses found - "
201  "Disabling UPnP");
202  return;
203  }
204 
205  // ----------------------------------------------------------------------
206  // Initialize UPnp Stack
207  // ----------------------------------------------------------------------
208 
209  if (Initialize( IPAddrList, nPort, pHttpServer ))
210  {
211 
212  // ------------------------------------------------------------------
213  // Register any HttpServerExtensions... Only The Master Backend
214  // ------------------------------------------------------------------
215 
216  if (bIsMaster)
217  {
218  QString sSourceProtocols = GetSourceProtocolInfos().join(",");
219 
220  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering MS_MediaReceiverRegistrar Service.");
221 
223  m_sSharePath ) );
224 
225  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering ConnnectionManager Service.");
226 
228  m_sSharePath, sSourceProtocols );
230 
231  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering ContentDirectory Service.");
232 
235 
236  // ----------------------------------------------------------------
237  // Register CDS Extensions
238  // ----------------------------------------------------------------
239 
240  LOG(VB_UPNP, LOG_INFO,
241  "MediaServer: Registering UPnpCDSTv Extension");
242 
244 
245  LOG(VB_UPNP, LOG_INFO,
246  "MediaServer: Registering UPnpCDSMusic Extension");
247 
249 
250  LOG(VB_UPNP, LOG_INFO,
251  "MediaServer: Registering UPnpCDSVideo Extension");
252 
254  }
255 
256 #if 0
257  LOG(VB_UPNP, LOG_INFO, "MediaServer::Adding Context Listener");
258 
259  gCoreContext->addListener( this );
260 #endif
261 
262  Start();
263 
264 #ifdef USING_LIBDNS_SD
265  // advertise using Bonjour
266  if (gCoreContext)
267  {
268  m_bonjour = new BonjourRegister();
269  if (m_bonjour)
270  {
271  QByteArray name("Mythbackend on ");
272  name.append(gCoreContext->GetHostName().toUtf8());
273  QByteArray txt(bIsMaster ? "\x06master" : "\x05slave");
274  m_bonjour->Register(nPort, "_mythbackend._tcp", name, txt);
275  }
276  }
277 #endif
278  }
279 
280  LOG(VB_UPNP, LOG_INFO, "MediaServer::Init(): End");
281 }
282 
284 //
286 
288 {
289  // -=>TODO: Need to check to see if calling this more than once is ok.
290 
291 #if 0
293 #endif
294 
295  delete m_webSocketServer;
296  delete m_pHttpServer;
297 
298 #ifdef USING_LIBDNS_SD
299  delete m_bonjour;
300 #endif
301 }
302 
304 //
306 #if 0
307 void MediaServer::customEvent( QEvent *e )
308 {
309  if (MythEvent::Type(e->type()) == MythEvent::MythEventMessage)
310  {
311  MythEvent *me = static_cast<MythEvent *>(e);
312  QString message = me->Message();
313 
314  //-=>TODO: Need to handle events to notify clients of changes
315  }
316 }
317 #endif
318 //
321 
323 {
324  m_pUPnpCDS->RegisterExtension( pExtension );
325 }
326 
328 //
330 
332 {
333  m_pUPnpCDS->UnregisterExtension( pExtension );
334 }
ContentServiceHost
Definition: contentServiceHost.h:42
mythServiceHost.h
UPnpCDSExtension
Definition: upnpcds.h:203
mythdb.h
GetSourceProtocolInfos
QStringList GetSourceProtocolInfos()
Return a QStringList containing the supported Source Protocols.
Definition: upnputil.cpp:86
UPnpMSRR
Definition: upnpmsrr.h:29
upnpcdsvideo.h
UPnp::Start
virtual void Start()
Definition: upnp.cpp:144
HttpServer::RegisterExtension
void RegisterExtension(HttpServerExtension *pExtension)
Definition: httpserver.cpp:321
ServerPool::isListening
bool isListening(void) const
Definition: serverpool.h:92
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
MediaServer::m_pUPnpCMGR
UPnpCMGR * m_pUPnpCMGR
Definition: mediaserver.h:44
InternetContent
Definition: internetContent.h:29
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
BonjourRegister
Definition: bonjourregister.h:11
musicServiceHost.h
MediaServer::RegisterExtension
void RegisterExtension(UPnpCDSExtension *pExtension)
Definition: mediaserver.cpp:322
GetMythDB
MythDB * GetMythDB(void)
Definition: mythdb.cpp:50
mythdirs.h
ImageServiceHost
Definition: imageServiceHost.h:32
MythEvent::Message
const QString & Message() const
Definition: mythevent.h:65
UPnp::Initialize
bool Initialize(int nServicePort, HttpServer *pHttpServer)
Definition: upnp.cpp:74
MythObservable::addListener
void addListener(QObject *listener)
Add a listener to the observable.
Definition: mythobservable.cpp:38
kSSLServer
@ kSSLServer
Definition: serverpool.h:33
upnpcdstv.h
CaptureServiceHost
Definition: captureServiceHost.h:42
contentServiceHost.h
MediaServer::m_sSharePath
QString m_sSharePath
Definition: mediaserver.h:46
httpconfig.h
channelServiceHost.h
UPnpCDS
Definition: upnpcds.h:282
UPnpCDS::UnregisterExtension
void UnregisterExtension(UPnpCDSExtension *pExtension)
Definition: upnpcds.cpp:186
GuideServiceHost
Definition: guideServiceHost.h:42
bonjourregister.h
GetShareDir
QString GetShareDir(void)
Definition: mythdirs.cpp:254
MediaServer::UnregisterExtension
void UnregisterExtension(UPnpCDSExtension *pExtension)
Definition: mediaserver.cpp:331
HtmlServerExtension
Definition: htmlserver.h:29
captureServiceHost.h
ServerPool::DefaultListen
static QList< QHostAddress > DefaultListen(void)
Definition: serverpool.cpp:305
htmlserver.h
VideoServiceHost
Definition: videoServiceHost.h:42
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
MediaServer::Init
void Init(bool bIsMaster, bool bDisableUPnp=false)
Definition: mediaserver.cpp:64
UPnpCDSTv
Definition: upnpcdstv.h:20
MediaServer::MediaServer
MediaServer()
Definition: mediaserver.cpp:58
MythServiceHost
Definition: mythServiceHost.h:42
UPnpCMGR
Definition: upnpcmgr.h:48
UPnp::RootDevice
static UPnpDevice * RootDevice()
Definition: upnp.h:126
MediaServer::m_pUPnpCDS
UPnpCDS * m_pUPnpCDS
Definition: mediaserver.h:43
mediaserver.h
videoServiceHost.h
UPnpDeviceDesc::Load
bool Load(const QString &sFileName)
Definition: upnpdevice.cpp:45
internetContent.h
UPnpCDSVideo
Definition: upnpcdsvideo.h:23
HttpServer
Definition: httpserver.h:112
MediaServer::~MediaServer
~MediaServer() override
Definition: mediaserver.cpp:287
ServerPool::listen
bool listen(QList< QHostAddress > addrs, quint16 port, bool requireall=true, PoolServerType type=kTCPServer)
Definition: serverpool.cpp:395
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:842
UPnpCDSMusic
Definition: upnpcdsmusic.h:22
UPnp::m_pHttpServer
HttpServer * m_pHttpServer
Definition: upnp.h:104
upnpcdsmusic.h
WebSocketServer
The WebSocket server, which listens for connections.
Definition: websocket.h:38
MediaServer::m_webSocketServer
WebSocketServer * m_webSocketServer
Definition: mediaserver.h:39
dvrServiceHost.h
UPnpCDS::RegisterExtension
void RegisterExtension(UPnpCDSExtension *pExtension)
Definition: upnpcds.cpp:167
imageServiceHost.h
UPnp::g_UPnpDeviceDesc
static UPnpDeviceDesc g_UPnpDeviceDesc
Definition: upnp.h:109
HttpConfig
Definition: httpconfig.h:11
ChannelServiceHost
Definition: channelServiceHost.h:42
guideServiceHost.h
MythObservable::removeListener
void removeListener(QObject *listener)
Remove a listener to the observable.
Definition: mythobservable.cpp:55
MusicServiceHost
Definition: musicServiceHost.h:25
DvrServiceHost
Definition: dvrServiceHost.h:42