1
# Written by Owen Williams
2
# see LICENSE for license information
4
from Downloader import *
6
from ptvbittorrent import download
7
from threading import Event
15
#constructor takes: media, params, resume, queue, progress_callback, finished_callback
16
# media: the media dic
17
# params: optional params, like for btdownloader
18
# resume: are we supposed to resume?
19
# queue: are we supposed queue for playback when download is finished? this variable is just passed around
20
# progress_callback: function to call for progress update.
21
# arg of this is: (media, progress as 0 < x < 1, and text formatted message of progress)
22
# the callback will return 1 if we should cancel download
23
# finished_callback: function to call when finished.
24
# args is: (media, status, message)
25
# where status is 0=failed, 1=success, 2=success and queue
27
class BTDownloader(Downloader):
28
def __init__(self, media, media_dir, params="", resume=False, queue=1, progress_callback=None, finished_callback=None):
29
#bit torrent always resumes if it can.
30
Downloader.__init__(self, media, media_dir, params, resume, queue, progress_callback, finished_callback)
31
self._bt_params = params
33
self._start_time=time.time()
34
self._last_update=self._start_time
36
self._done_downloading = False
38
def download(self,args_unused):
39
if not Downloader.download(self,args_unused):
40
#stopped before we began
42
params = ['--url' ,self.media['url']]+self._bt_params
45
download.download(params, self._chooseFile, self._display, self._normalize_finished, self._error, self._done, 80, self._newpath)
46
except socket.timeout, detail:
47
self.media['errormsg'] = str(detail)
50
self._finished_callback()
54
self.media['errormsg'] = _("There was an error downloading the torrent")
56
self.message = _("There was an error downloading the torrent")
57
self._finished_callback()
59
if self.status not in [STOPPED,PAUSED]:
62
self._finished_callback()
64
def _chooseFile(self, default, size, saveas, dir):
66
dated_dir = utils.get_dated_dir()
68
if self.media['size']!=self.total_size:
69
self.media['size']=self.total_size
71
if self.media['file']!=os.path.join(self._media_dir, dated_dir, str(default)):
72
self.media['file']=os.path.join(self._media_dir, dated_dir, str(default))
76
db.set_media_filename(self.media['media_id'],self.media['file'])
77
db.set_media_size(self.media['media_id'],self.media['size'])
80
return os.path.join(self._media_dir, dated_dir, str(default))
82
def _display(self, dict):
83
if dict.has_key('downTotal'):
84
self._downTotal = dict['downTotal']
86
if dict.has_key('fractionDone'):
87
self.progress = int(dict['fractionDone']*100.0)
88
d = {'progress':str(self.progress),
89
'size':utils.format_size(self.total_size)
91
if dict.has_key('timeEst'):
92
d['time']=utils.hours(dict['timeEst'])
93
self.message = _("Downloaded %(progress)s%% of %(size)s, %(time)s remaining.") % d
95
self.message = _("Downloaded %(progress)s%% of %(size)s") % d
97
if self._progress_callback() == 1:
103
if self._progress_callback() == 1:
106
if dict.has_key('upTotal'): #check to see if we should stop
107
if self._done_downloading:
108
if dict['upTotal'] >= self._downTotal: #if ratio is one, quit
110
if time.time() - 60*60 >= self._start_time: #if it's been an hour, quit
113
def _normalize_finished(self):
115
self.status = FINISHED_AND_PLAY
117
self.status = FINISHED
118
d = {'filename':self.media['file']}
119
self.message = _("Finished downloading %(filename)s") % d
120
self._finished_callback()
121
self._done_downloading = True
122
#don't stop uploading, we keep going until 1:1 or one hour
123
#FIXME: deal with directories just in case
126
def _error(self, errormsg):
127
#for some reason this isn't a fatal error
128
if errormsg=='rejected by tracker - This tracker requires new tracker protocol. Please use our Easy Downloader or check blogtorrent.com for updates.':
129
print "getting blogtorrent 'rejected by tracker' error, ignoring"
132
raise TorrentError(errormsg)
134
def _newpath(self, path):
136
#print "new path?: " +path
139
class NoDir(Exception):
140
def __init__(self,durr):
143
return "no such directory: "+self.durr
145
class TorrentError(Exception):
146
def __init__(self,m):