Let Process on the xmpp connection block for a while
[pyTivo.git] / plugins / webvideo / webvideo.py
blob35286d2c741956a98bd6ec08aa68a25a1ea143ef
1 from plugins.video.video import Video, VideoDetails
2 import mind
3 import config
5 import xmpp
7 import threading
8 import urllib2
9 import os.path
10 import shutil
11 import os.path
12 import os
13 import urlparse
14 import urllib
15 import xml.etree.ElementTree as ElementTree
16 import Queue
17 import logging
19 CLASS_NAME = 'WebVideo'
22 class WebVideo(Video):
24 CONTENT_TYPE = 'x-not-for/tivo'
26 def init(self):
27 self.__logger = logging.getLogger('pyTivo.webvideo')
28 self.work_queue = Queue.Queue()
29 self.download_thread_num = 1
30 self.in_progress = {}
31 self.in_progress_lock = threading.Lock()
33 self.startXMPP()
34 self.xmpp_cdsupdate()
35 self.startWorkerThreads()
37 def startXMPP(self):
38 m = mind.getMind()
39 xmpp_info = m.getXMPPLoginInfo()
41 jid=xmpp.protocol.JID(xmpp_info['username'] + '/pyTivo')
42 cl=xmpp.Client(
43 server=xmpp_info['server'],
44 port=xmpp_info['port'],
45 debug=[],
47 self.__logger.debug('Connecting to %s:%s' % (xmpp_info['server'], xmpp_info['port']))
48 cl.connect()
49 cl.RegisterHandler('message', self.processMessage)
50 self.__logger.debug('Loging in as %s/pyTivo' % xmpp_info['username'])
51 cl.auth(user=jid.getNode(), password=config.getTivoPassword(), resource='pyTivo')
53 cl.sendInitPresence(requestRoster=0)
55 for user_name in xmpp_info['presence_list']:
56 self.__logger.debug('Sending presence to %s' % user_name)
57 jid=xmpp.protocol.JID(user_name)
58 cl.sendPresence(jid)
60 t = threading.Thread(target=self.processXMPP, args=(cl,))
61 t.setDaemon(True)
62 t.start()
64 def startWorkerThreads(self):
65 for i in range(self.download_thread_num):
66 t = threading.Thread(target=self.processDlRequest)
67 t.setDaemon(True)
68 t.start()
70 def processXMPP(self, client):
71 while client.Process(3):
72 pass
74 def processMessage(self, sess, mess):
75 self.__logger.debug('Got message\n %s' % mess.getBody())
76 xmpp_action = ElementTree.fromstring(mess.getBody())
78 method_name = 'xmpp_' + xmpp_action.findtext('action').lower()
79 if not hasattr(self, method_name):
80 return False
82 method = getattr(self, method_name)
83 method(xmpp_action)
85 def xmpp_cdsupdate(self, xml=None):
86 m = mind.getMind()
88 self.in_progress_lock.acquire()
89 try:
90 for request in m.getDownloadRequests():
91 if not request['bodyOfferId'] in self.in_progress:
92 self.__logger.debug('Adding request to queue, %s' % request)
93 self.in_progress[request['bodyOfferId']] = True
94 self.work_queue.put(request)
95 finally:
96 self.in_progress_lock.release()
98 def processDlRequest(self):
100 while True:
101 data = self.work_queue.get()
103 for share_name, settings in config.getShares():
104 if settings['type'] == 'webvideo':
105 break
106 self.__logger.debug('Processing request: %s' % data)
108 path = settings['path']
109 file_name = os.path.join(path, '%s-%s' % (data['bodyOfferId'] ,data['url'].split('/')[-1]))
111 self.downloadFile(data['url'], file_name)
113 tsn = data['bodyId']
114 file_info = VideoDetails()
115 file_info.update(self.metadata_full(file_name, tsn))
117 import socket
118 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
119 s.connect(('tivo.com',123))
120 ip = s.getsockname()[0]
121 port = config.getPort()
123 data['url'] = 'http://%s:%s' % (ip, port) + urllib.quote('/%s/%s' % (share_name, os.path.split(file_name)[-1]))
124 data['duration'] = file_info['duration'] / 1000
125 data['size'] = file_info['size']
127 self.__logger.debug('Complete request: %s' % data)
129 m = mind.getMind()
130 m.completeDownloadRequest(data)
132 self.in_progress_lock.acquire()
133 try:
134 del self.in_progress[data['bodyOfferId']]
135 finally:
136 self.in_progress_lock.release()
138 def downloadFile(self, url, file_path):
139 self.__logger.info('Downloading %s to %s' % (url, file_path))
141 outfile = open(file_path, 'awb')
142 size = os.path.getsize(file_path)
143 r = urllib2.Request(url)
144 if size:
145 r.add_header('Range', 'bytes=%s-' % size)
147 try:
148 infile = urllib2.urlopen(r)
149 except urllib2.HTTPError, e:
150 if not e.code == 416:
151 raise
152 infile = urllib2.urlopen(url)
153 if int(infile.info()['Content-Length']) == size:
154 self.__logger.debug('File was alraedy done. %s' % url)
155 return
156 else:
157 self.__logger.debug('File was not done byut could not resume. %s' % url)
158 outfile.close()
159 outfile = open(file_path, 'wb')
161 shutil.copyfileobj(infile, outfile, 8192)
163 self.__logger.info('Done downloading %s to %s' % (url, file_path))
165 def send_file(self, handler, container, name):
166 Video.send_file(self, handler, container, name)
168 o = urlparse.urlparse("http://fake.host" + handler.path)
169 path = urllib.unquote(o[2])
170 file_path = container['path'] + path[len(name) + 1:]
171 if os.path.exists(file_path):
172 self.__logger.info('Deleting file %s' % file_path)
173 os.unlink(file_path)