[StreamServerSeek] Reverse-Proxy + Player
[enigma2-plugins.git] / streamserverseek / src / WebChilds / Stream.py
1 from twisted.web import resource, http, server
2
3 from enigma import eStreamServer, eServiceReference
4
5 from Components.config import config
6
7 import os.path
8
9 if os.path.isfile("/usr/lib/enigma2/python/Plugins/SystemPlugins/GstRtspServer/StreamServerControl.py"):
10         from Plugins.SystemPlugins.GstRtspServer.StreamServerControl import streamServerControl
11 else:
12         from Components.StreamServerControl import streamServerControl
13
14 from twisted.internet import reactor
15
16 import urllib
17
18 from Plugins.Extensions.StreamServerSeek.StreamServerSeek import StreamServerSeek
19
20 class StreamResource(resource.Resource):
21         isLeaf = True
22         validExt = ["ts", "trp", "avi", "divx", "f4v", "flv", "img", "ifo", "iso", "m2ts", "m4v", "mkv", "mov", "mp4", "mpeg", "mpg", "mts", "vob", "wmv", "bdmv", "asf", "stream", "webm"]
23         session = None
24         _request = None
25
26         def __init__(self, session):
27                 resource.Resource.__init__(self)
28                 self.session = session
29                 self.streamServerSeek = StreamServerSeek()
30
31         def _onTemporaryLiveMode(self):
32                 if self.streamServerSeek._isTemporaryLiveMode and self.streamServerSeek._temporaryLiveModeService:
33                         print "[StreamserverSeek] Entered temporary Live-Mode - playing service"
34                         service = eServiceReference(self.streamServerSeek._temporaryLiveModeService)
35                         self.session.nav.playService(service)
36                         print "[StreamserverSeek] service %s" % service
37                         self.streamServerSeek._isTemporaryLiveModeActive = True
38
39 #               self._request.finish()
40                 reactor.callLater(1, self.finishRequest)
41         
42         def finishRequest(self):
43                 self._request.finish()
44
45         def render(self, request):
46                 self._request = request
47
48                 request.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
49                 request.setHeader('Cache-Directive', 'no-cache');
50                 request.setHeader('Pragma-Directive', 'no-cache');
51                 request.setHeader('Pragma', 'no-cache');
52                 request.setHeader('Expires', '0');
53                 
54                 streamUrl = False
55                 length = len(request.postpath)
56                 if length > 0:
57                         if request.postpath[0] == 'rtsp':
58                                 streamUrl = "rtsp://%s/stream" % request.getRequestHostname()
59                         elif request.postpath[0] == 'hls':
60                                 if os.path.isfile("/usr/lib/enigma2/python/Plugins/SystemPlugins/GstRtspServer/StreamServerControl.py"):
61                                         streamUrl = "http://%s:%s/dream.m3u8" % (request.getRequestHostname(), config.streamserver.hls.port.value)
62                                 else:
63                                         streamUrl = "/streamserverseek/proxy/stream.m3u8"
64                         elif request.postpath[0] == 'player':
65                                 streamUrl = "/streamserverseek/player.html"
66                 
67                 if not streamUrl:
68                         request.setResponseCode(http.NOT_FOUND)
69                         return ""
70                 
71                 moviePath = ""
72                 movieNameWExt = ""
73                 i = 1
74                 while i < length:
75                         moviePath += "/%s" % request.postpath[i]
76                         movieNameWExt = request.postpath[i]
77                         i += 1
78                 
79                 movieSplit = movieNameWExt.split(".")
80                 movieName = ""
81                 movieExt = ""
82                 i = 0
83                 while i < (len(movieSplit) -1):
84                         movieName += movieSplit[i]
85                         i += 1
86                 
87                 movieExt = movieSplit[-1]
88                 
89                 print "[StreamserverSeek] moviePath %s" % moviePath
90                 print "[StreamserverSeek] movieName %s" % movieName
91                 print "[StreamserverSeek] movieExt %s" % movieExt
92                 
93                 if not os.path.isfile(moviePath):
94                         moviePath = moviePath.replace("+", " ")
95                         if i -1 < length:
96                                 movieNameWExt = request.postpath[i-1].replace("+", " ")
97                         if not os.path.isfile(moviePath):
98                                 request.setResponseCode(http.NOT_FOUND)
99                                 return ""
100
101                 if (len(movieSplit) < 2) or (movieExt not in self.validExt):
102                         request.setResponseCode(http.FORBIDDEN)
103                         return ""
104
105                 if "min" in request.args:
106                         try:
107                                 self.streamServerSeek._seekToMin = int(request.args["min"][0])
108                                 print "[StreamserverSeek] Will seek to %s" % self.streamServerSeek._seekToMin
109                         except Exception:
110                                 pass
111
112                 request.setHeader("Content-type", "")
113
114                 if movieExt == "ts":
115                         wait = False
116                         if self.streamServerSeek._isTemporaryLiveMode:
117                                 print "[StreamserverSeek] Requested service does not require Live-Mode, but Live-Mode is still active. End it!"
118                                 StreamServerSeek().endTemporaryLiveMode()
119                                 wait = True
120                         elif streamServerControl.getInputMode() != eStreamServer.INPUT_MODE_BACKGROUND:
121                                 print "[StreamserverSeek] Set input mode to BACKGROUND"
122                                 StreamServerSeek().forceInputMode(eStreamServer.INPUT_MODE_BACKGROUND)
123                                 wait = True
124                                 
125                         result = streamServerControl.setEncoderService(eServiceReference("1:0:0:0:0:0:0:0:0:0:" + urllib.quote(moviePath)))
126                         if result == streamServerControl.ENCODER_SERVICE_SET or result == streamServerControl.ENCODER_SERVICE_ALREADY_ACTIVE:
127                                 if not os.path.isfile("/usr/lib/enigma2/python/Plugins/SystemPlugins/GstRtspServer/StreamServerControl.py"):
128                                         self.streamServerSeek.doSeek()
129
130                         request.setHeader("Location", streamUrl)
131                         request.setResponseCode(http.FOUND)
132
133                         if wait:
134                                 reactor.callLater(1, self.finishRequest)
135                         else:
136                                 request.finish()
137
138                         return server.NOT_DONE_YET
139                 
140                 from Screens.Standby import inStandby
141                 if inStandby is None:
142                         if self.streamServerSeek._isTemporaryLiveMode:
143                                 print "[StreamserverSeek] Box already in temporary Live-Mode"
144                                 self.streamServerSeek._temporaryLiveModeService = "4097:0:0:0:0:0:0:0:0:0:" + urllib.quote(moviePath)
145                                 service = eServiceReference(self.streamServerSeek._temporaryLiveModeService)
146                                 if service.toCompareString() != self.session.nav.getCurrentServiceReference().toCompareString():
147                                         self.session.nav.playService(service)
148                                         print "[StreamserverSeek] service %s" % service
149                                 
150                                 print "[StreamserverSeek] Seek is now %s" % self.streamServerSeek._seekToMin
151                                 self.streamServerSeek.doSeek()
152
153                                 request.setHeader("Location", streamUrl)
154                                 request.setResponseCode(http.FOUND)
155                                 return ""
156                         else:
157                                 print "[StreamserverSeek] Requiring Live-Mode, but Box not in idle mode - do nothing"
158                                 request.setResponseCode(http.INTERNAL_SERVER_ERROR)
159                                 return ""
160                 else:
161                         streamServerControl.stopEncoderService()
162                         print "[StreamserverSeek] Switching on Box"
163                         self.streamServerSeek._tvLastService = config.tv.lastservice.value
164                         self.streamServerSeek._temporaryLiveModeService = "4097:0:0:0:0:0:0:0:0:0:" + urllib.quote(moviePath)
165                         inStandby.onClose.append(self._onTemporaryLiveMode)
166                         print "%s" % StreamServerSeek
167                         print "%s" % StreamServerSeek()
168                         StreamServerSeek().changeIdleMode(False)
169                         self.streamServerSeek._isTemporaryLiveMode = True
170                         
171                         if streamServerControl.getInputMode() != eStreamServer.INPUT_MODE_LIVE:
172                                 print "[StreamserverSeek] Set input mode to LIVE"
173                                 StreamServerSeek().forceInputMode(eStreamServer.INPUT_MODE_LIVE)
174
175                         request.setHeader("Location", streamUrl)
176                         request.setResponseCode(http.FOUND)
177
178                         return server.NOT_DONE_YET