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 
72  auto *pHttpServer = new HttpServer();
73 
74  if (!pHttpServer->isListening())
75  {
76  pHttpServer->setProxy(QNetworkProxy::NoProxy);
77  // HTTP
78  if (!pHttpServer->listen(nPort))
79  {
80  LOG(VB_GENERAL, LOG_ERR, "MediaServer: HttpServer Create Error");
81  delete pHttpServer;
82  pHttpServer = nullptr;
83  return;
84  }
85 
86 #ifndef QT_NO_OPENSSL
87  // HTTPS (SSL)
88  if (!pHttpServer->listen(nSSLPort, true, kSSLServer))
89  {
90  LOG(VB_GENERAL, LOG_ERR, "MediaServer: HttpServer failed to create SSL server");
91  }
92 #endif
93  }
94 
96 
98  {
99  if (!m_webSocketServer->listen(nWSPort))
100  {
101  LOG(VB_GENERAL, LOG_ERR, "MediaServer: WebSocketServer Create Error");
102  }
103  }
104 
105  QString sFileName = GetMythDB()->GetSetting("upnpDescXmlPath", m_sSharePath);
106 
107  if ( bIsMaster )
108  sFileName += "devicemaster.xml";
109  else
110  sFileName += "deviceslave.xml";
111 
112  // ------------------------------------------------------------------
113  // Make sure our device Description is loaded.
114  // ------------------------------------------------------------------
115 
116  LOG(VB_UPNP, LOG_INFO,
117  "MediaServer: Loading UPnp Description " + sFileName);
118 
119  g_UPnpDeviceDesc.Load( sFileName );
120 
121  // ------------------------------------------------------------------
122  // Register Http Server Extensions...
123  // ------------------------------------------------------------------
124 
125  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering Http Server Extensions.");
126 
127  auto *pHtmlServer =
128  new HtmlServerExtension(m_sSharePath + "html", "backend_");
129  pHttpServer->RegisterExtension( pHtmlServer );
130  pHttpServer->RegisterExtension( new HttpConfig() );
131  pHttpServer->RegisterExtension( new InternetContent ( m_sSharePath ));
132 
133  pHttpServer->RegisterExtension( new MythServiceHost ( m_sSharePath ));
134  pHttpServer->RegisterExtension( new GuideServiceHost ( m_sSharePath ));
135  pHttpServer->RegisterExtension( new ContentServiceHost( m_sSharePath ));
136  pHttpServer->RegisterExtension( new DvrServiceHost ( m_sSharePath ));
137  pHttpServer->RegisterExtension( new ChannelServiceHost( m_sSharePath ));
138  pHttpServer->RegisterExtension( new VideoServiceHost ( m_sSharePath ));
139  pHttpServer->RegisterExtension( new MusicServiceHost ( m_sSharePath ));
140  pHttpServer->RegisterExtension( new CaptureServiceHost( m_sSharePath ));
141  pHttpServer->RegisterExtension( new ImageServiceHost ( m_sSharePath ));
142 
143 
144  // ------------------------------------------------------------------
145  // Register Service Types with Scripting Engine
146  //
147  // -=>NOTE: We need to know the actual type at compile time for this
148  // to work, so it needs to be done here. I'm still looking
149  // into ways that we may encapsulate this in the service
150  // classes. - dblain
151  // ------------------------------------------------------------------
152 
153 #if CONFIG_QTSCRIPT
154  QScriptEngine* pEngine = pHtmlServer->ScriptEngine();
155 
156  pEngine->globalObject().setProperty("Myth" ,
157  pEngine->scriptValueFromQMetaObject< ScriptableMyth >() );
158  pEngine->globalObject().setProperty("Guide" ,
159  pEngine->scriptValueFromQMetaObject< ScriptableGuide >() );
160  pEngine->globalObject().setProperty("Content",
161  pEngine->scriptValueFromQMetaObject< ScriptableContent >() );
162  pEngine->globalObject().setProperty("Dvr" ,
163  pEngine->scriptValueFromQMetaObject< ScriptableDvr >() );
164  pEngine->globalObject().setProperty("Channel",
165  pEngine->scriptValueFromQMetaObject< ScriptableChannel >() );
166  pEngine->globalObject().setProperty("Video" ,
167  pEngine->scriptValueFromQMetaObject< ScriptableVideo >() );
168  pEngine->globalObject().setProperty("Music" ,
169  pEngine->scriptValueFromQMetaObject< ScriptableVideo >() );
170  pEngine->globalObject().setProperty("Capture" ,
171  pEngine->scriptValueFromQMetaObject< ScriptableCapture >() );
172  pEngine->globalObject().setProperty("Image" ,
173  pEngine->scriptValueFromQMetaObject< ScriptableImage >() );
174 #endif
175 
176  // ------------------------------------------------------------------
177 
178  if (bDisableUPnp)
179  {
180  LOG(VB_GENERAL, LOG_NOTICE,
181  "*** The UPNP service has been DISABLED with the "
182  "--noupnp option ***");
183  return;
184  }
185 
186  QList<QHostAddress> IPAddrList = ServerPool::DefaultListen();
187  if (IPAddrList.contains(QHostAddress(QHostAddress::AnyIPv4)))
188  {
189  IPAddrList.removeAll(QHostAddress(QHostAddress::AnyIPv4));
190  IPAddrList.removeAll(QHostAddress(QHostAddress::AnyIPv6));
191  IPAddrList.append(QNetworkInterface::allAddresses());
192  }
193 
194  if (IPAddrList.isEmpty())
195  {
196  LOG(VB_GENERAL, LOG_ERR,
197  "MediaServer: No Listenable IP Addresses found - "
198  "Disabling UPnP");
199  return;
200  }
201 
202  // ----------------------------------------------------------------------
203  // Initialize UPnp Stack
204  // ----------------------------------------------------------------------
205 
206  if (Initialize( IPAddrList, nPort, pHttpServer ))
207  {
208 
209  // ------------------------------------------------------------------
210  // Register any HttpServerExtensions... Only The Master Backend
211  // ------------------------------------------------------------------
212 
213  if (bIsMaster)
214  {
215  QString sSourceProtocols = GetSourceProtocolInfos().join(",");
216 
217  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering MS_MediaReceiverRegistrar Service.");
218 
220  m_sSharePath ) );
221 
222  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering ConnnectionManager Service.");
223 
225  m_sSharePath, sSourceProtocols );
227 
228  LOG(VB_UPNP, LOG_INFO, "MediaServer: Registering ContentDirectory Service.");
229 
232 
233  // ----------------------------------------------------------------
234  // Register CDS Extensions
235  // ----------------------------------------------------------------
236 
237  LOG(VB_UPNP, LOG_INFO,
238  "MediaServer: Registering UPnpCDSTv Extension");
239 
241 
242  LOG(VB_UPNP, LOG_INFO,
243  "MediaServer: Registering UPnpCDSMusic Extension");
244 
246 
247  LOG(VB_UPNP, LOG_INFO,
248  "MediaServer: Registering UPnpCDSVideo Extension");
249 
251  }
252 
253 #if 0
254  LOG(VB_UPNP, LOG_INFO, "MediaServer::Adding Context Listener");
255 
256  gCoreContext->addListener( this );
257 #endif
258 
259  Start();
260 
261 #ifdef USING_LIBDNS_SD
262  // advertise using Bonjour
263  if (gCoreContext)
264  {
265  m_bonjour = new BonjourRegister();
266  if (m_bonjour)
267  {
268  QByteArray name("Mythbackend on ");
269  name.append(gCoreContext->GetHostName().toUtf8());
270  QByteArray txt(bIsMaster ? "\x06master" : "\x05slave");
271  m_bonjour->Register(nPort, "_mythbackend._tcp", name, txt);
272  }
273  }
274 #endif
275  }
276 
277  LOG(VB_UPNP, LOG_INFO, "MediaServer::Init(): End");
278 }
279 
281 //
283 
285 {
286  // -=>TODO: Need to check to see if calling this more than once is ok.
287 
288 #if 0
290 #endif
291 
292  delete m_webSocketServer;
293  delete m_pHttpServer;
294 
295 #ifdef USING_LIBDNS_SD
296  delete m_bonjour;
297 #endif
298 }
299 
301 //
303 #if 0
304 void MediaServer::customEvent( QEvent *e )
305 {
306  if (MythEvent::Type(e->type()) == MythEvent::MythEventMessage)
307  {
308  MythEvent *me = static_cast<MythEvent *>(e);
309  QString message = me->Message();
310 
311  //-=>TODO: Need to handle events to notify clients of changes
312  }
313 }
314 #endif
315 //
318 
320 {
321  m_pUPnpCDS->RegisterExtension( pExtension );
322 }
323 
325 //
327 
329 {
330  m_pUPnpCDS->UnregisterExtension( pExtension );
331 }
ContentServiceHost
Definition: contentServiceHost.h:42
mythServiceHost.h
kSSLServer
@ kSSLServer
Definition: serverpool.h:33
MythEvent::MythEventMessage
static Type MythEventMessage
Definition: mythevent.h:79
UPnpCDSExtension
Definition: upnpcds.h:203
mythdb.h
GetSourceProtocolInfos
QStringList GetSourceProtocolInfos()
Return a QStringList containing the supported Source Protocols.
Definition: upnputil.cpp:90
UPnpMSRR
Definition: upnpmsrr.h:29
upnpcdsvideo.h
UPnp::Start
virtual void Start()
Definition: upnp.cpp:143
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:319
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
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:222
MediaServer::UnregisterExtension
void UnregisterExtension(UPnpCDSExtension *pExtension)
Definition: mediaserver.cpp:328
HtmlServerExtension
Definition: htmlserver.h:29
captureServiceHost.h
ServerPool::DefaultListen
static QList< QHostAddress > DefaultListen(void)
Definition: serverpool.cpp:301
htmlserver.h
VideoServiceHost
Definition: videoServiceHost.h:42
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:54
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:51
internetContent.h
UPnpCDSVideo
Definition: upnpcdsvideo.h:23
HttpServer
Definition: httpserver.h:112
MediaServer::~MediaServer
~MediaServer() override
Definition: mediaserver.cpp:284
ServerPool::listen
bool listen(QList< QHostAddress > addrs, quint16 port, bool requireall=true, PoolServerType type=kTCPServer)
Definition: serverpool.cpp:391
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:836
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