~cosmin.lupu/+junk/penguintv

« back to all changes in this revision

Viewing changes to penguintv/BTDownloader.py

  • Committer: cosmin.lupu at gmail
  • Date: 2010-04-27 16:47:43 UTC
  • Revision ID: cosmin.lupu@gmail.com-20100427164743-ds8xrqonipp5ovdf
initial packaging

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Written by Owen Williams
 
2
# see LICENSE for license information
 
3
 
 
4
from Downloader import *
 
5
 
 
6
from ptvbittorrent import download
 
7
from threading import Event
 
8
import time
 
9
import os, os.path
 
10
import ptvDB
 
11
import utils
 
12
import socket
 
13
 
 
14
#Downloader API:
 
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
 
26
                
 
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
 
32
                self._done = Event()
 
33
                self._start_time=time.time()
 
34
                self._last_update=self._start_time
 
35
                self._downTotal=0
 
36
                self._done_downloading = False
 
37
                                
 
38
        def download(self,args_unused):
 
39
                if not Downloader.download(self,args_unused):
 
40
                        #stopped before we began
 
41
                        return 
 
42
                params = ['--url' ,self.media['url']]+self._bt_params
 
43
                
 
44
                try:
 
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)
 
48
                        self.status = FAILURE
 
49
                        self.message = detail
 
50
                        self._finished_callback()       
 
51
                        return  
 
52
                except Exception, e:
 
53
                        print e
 
54
                        self.media['errormsg'] = _("There was an error downloading the torrent")
 
55
                        self.status = FAILURE
 
56
                        self.message = _("There was an error downloading the torrent")
 
57
                        self._finished_callback()
 
58
                        return
 
59
                if self.status not in [STOPPED,PAUSED]:
 
60
                        self.status = STOPPED
 
61
                self.message = ""
 
62
                self._finished_callback()
 
63
 
 
64
        def _chooseFile(self, default, size, saveas, dir):
 
65
                self.total_size=size
 
66
                dated_dir = utils.get_dated_dir()
 
67
                change=0
 
68
                if self.media['size']!=self.total_size:
 
69
                        self.media['size']=self.total_size
 
70
                        change = 1
 
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))
 
73
                        change = 1
 
74
                if change:
 
75
                        db = ptvDB.ptvDB()
 
76
                        db.set_media_filename(self.media['media_id'],self.media['file'])
 
77
                        db.set_media_size(self.media['media_id'],self.media['size'])
 
78
                        db.finish()
 
79
                        del db
 
80
                return os.path.join(self._media_dir, dated_dir, str(default))
 
81
        
 
82
        def _display(self, dict):
 
83
                if dict.has_key('downTotal'):
 
84
                        self._downTotal = dict['downTotal']
 
85
                
 
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)
 
90
                                 }
 
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
 
94
                        else:
 
95
                                self.message = _("Downloaded %(progress)s%% of %(size)s") % d
 
96
                        
 
97
                        if self._progress_callback() == 1:
 
98
                                self._done.set() 
 
99
                                
 
100
                else:
 
101
                        self.progress = 0
 
102
                        self.message = ""
 
103
                        if self._progress_callback() == 1:
 
104
                                self._done.set()
 
105
                
 
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
 
109
                                        self._done.set()
 
110
                                if time.time() - 60*60 >= self._start_time: #if it's been an hour, quit
 
111
                                        self._done.set()
 
112
                
 
113
        def _normalize_finished(self):
 
114
                if self._queue:
 
115
                        self.status = FINISHED_AND_PLAY
 
116
                else:
 
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
 
124
 
 
125
                
 
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"
 
130
                else:
 
131
                        self._done.set()
 
132
                        raise TorrentError(errormsg)
 
133
                
 
134
        def _newpath(self, path):
 
135
                pass
 
136
                #print "new path?: " +path
 
137
                
 
138
 
 
139
class NoDir(Exception):
 
140
        def __init__(self,durr):
 
141
                self.durr = durr
 
142
        def __str__(self):
 
143
                return "no such directory: "+self.durr
 
144
                
 
145
class TorrentError(Exception):
 
146
        def __init__(self,m):
 
147
                self.m = m
 
148
        def __str__(self):
 
149
                return self.m
 
150