pull/1/head
DiMartinoXBMC 2015-07-26 21:44:46 +03:00
parent 6a055fbe98
commit 390dbcd9f3
5 changed files with 179 additions and 90 deletions

View File

@ -25,18 +25,17 @@ import hashlib
import re
from StringIO import StringIO
import gzip
import sys
import xbmc
import xbmcgui
import xbmcvfs
import Localization
from functions import file_encode, isSubtitle, DownloadDB, log, debug
from functions import file_encode, isSubtitle, DownloadDB, log, debug, is_writable
from platform_pulsar import get_platform
class Libtorrent:
torrentFile = None
magnetLink = None
storageDirectory = ''
startPart = 0
endPart = 0
partOffset = 0
@ -45,9 +44,19 @@ class Libtorrent:
downloadThread = None
threadComplete = False
lt = None
save_resume_data = None
def __init__(self, storageDirectory='', torrentFile='', torrentFilesDirectory='torrents'):
self.platform = get_platform()
self.storageDirectory = storageDirectory
self.torrentFilesPath = os.path.join(self.storageDirectory, torrentFilesDirectory) + os.sep
if not is_writable(self.storageDirectory):
xbmcgui.Dialog().ok(Localization.localize('Torrenter v2'),
Localization.localize('Your storage path is not writable or not local! Please change it in settings!'),
Localization.localize(self.storageDirectory))
sys.exit(1)
try:
import libtorrent
@ -69,8 +78,6 @@ class Libtorrent:
Localization.localize(self.platform["message"][1]))
return
self.storageDirectory = storageDirectory
self.torrentFilesPath = os.path.join(self.storageDirectory, torrentFilesDirectory) + os.sep
if xbmcvfs.exists(torrentFile):
self.torrentFile = torrentFile
e=self.lt.bdecode(xbmcvfs.File(self.torrentFile,'rb').read())
@ -232,9 +239,21 @@ class Libtorrent:
return subs
def setUploadLimit(self, bytesPerSecond):
try:
session_settings = self.session.get_settings()
session_settings['upload_rate_limit'] = int(bytesPerSecond)
self.session.set_settings(session_settings)
except:
#0.16 compatibility
self.session.set_upload_rate_limit(int(bytesPerSecond))
def setDownloadLimit(self, bytesPerSecond):
try:
session_settings = self.session.get_settings()
session_settings['download_rate_limit'] = int(bytesPerSecond)
self.session.set_settings(session_settings)
except:
#0.16 compatibility
self.session.set_download_rate_limit(int(bytesPerSecond))
def md5(self, string):
@ -306,19 +325,16 @@ class Libtorrent:
return
def initSession(self):
try:
self.session.remove_torrent(self.torrentHandle)
except:
pass
self.session = self.lt.session()
self.session.set_alert_mask(self.lt.alert.category_t.error_notification | self.lt.alert.category_t.status_notification | self.lt.alert.category_t.storage_notification)
#self.session.set_alert_mask(self.lt.alert.category_t.all_categories)
self.session.start_dht()
self.session.add_dht_router("router.bittorrent.com", 6881)
self.session.add_dht_router("router.utorrent.com", 6881)
self.session.add_dht_router("router.bitcomet.com", 6881)
self.session.start_lsd()
self.session.start_upnp()
self.session.start_natpmp()
#self.session.start_lsd()
#self.session.start_upnp()
#self.session.start_natpmp()
self.session.listen_on(6881, 6891)
#tribler example never tested
@ -331,8 +347,25 @@ class Libtorrent:
#self.session.add_extension("smart_ban")
# Session settings
session_settings = self.session.settings()
try:
session_settings = self.session.get_settings()
#
session_settings['announce_to_all_tiers'] = True
session_settings['announce_to_all_trackers'] = True
session_settings['connection_speed'] = 100
session_settings['peer_connect_timeout'] = 2
session_settings['rate_limit_ip_overhead'] = True
session_settings['request_timeout'] = 1
session_settings['torrent_connect_boost'] = 100
session_settings['user_agent'] = 'uTorrent/3430(40298)'
#session_settings['cache_size'] = 0
#session_settings['use_read_cache'] = False
except:
#0.15 compatibility
log('[initSession]: Session settings 0.15 compatibility')
session_settings = self.session.settings()
session_settings.announce_to_all_tiers = True
session_settings.announce_to_all_trackers = True
session_settings.connection_speed = 100
@ -346,7 +379,7 @@ class Libtorrent:
def encryptSession(self):
# Encryption settings
print '[Torrenter v2]: Encryption enabling...'
log('Encryption enabling...')
try:
encryption_settings = self.lt.pe_settings()
encryption_settings.out_enc_policy = self.lt.enc_policy(self.lt.enc_policy.forced)
@ -354,22 +387,26 @@ class Libtorrent:
encryption_settings.allowed_enc_level = self.lt.enc_level.both
encryption_settings.prefer_rc4 = True
self.session.set_pe_settings(encryption_settings)
print '[Torrenter v2]: Encryption on!'
log('Encryption on!')
except Exception, e:
print '[Torrenter v2]: Encryption failed! Exception: ' + str(e)
log('Encryption failed! Exception: ' + str(e))
pass
def startSession(self):
if None == self.magnetLink:
self.torrentHandle = self.session.add_torrent({'ti': self.torrentFileInfo,
if self.magnetLink:
self.torrentFileInfo = self.getMagnetInfo()
torrent_info={'ti': self.torrentFileInfo,
'save_path': self.storageDirectory,
'flags': 0x300,
#'storage_mode': self.lt.storage_mode_t(1),
'paused': False,
#'auto_managed': False,
#'storage_mode': self.lt.storage_mode_t.storage_mode_allocate,
})
else:
self.torrentFileInfo = self.getMagnetInfo()
#'duplicate_is_error': True
}
if self.save_resume_data:
log('loading resume data')
torrent_info['resume_data']=self.save_resume_data
self.torrentHandle = self.session.add_torrent(torrent_info)
self.torrentHandle.set_sequential_download(True)
self.torrentHandle.set_max_connections(60)
self.torrentHandle.set_max_uploads(-1)
@ -419,15 +456,30 @@ class Libtorrent:
self.session.remove_torrent(self.torrentHandle)
except:
log('RuntimeError: invalid torrent handle used')
self.session.stop_natpmp()
self.session.stop_upnp()
self.session.stop_lsd()
#self.session.stop_natpmp()
#self.session.stop_upnp()
#self.session.stop_lsd()
self.session.stop_dht()
def resume_data(self):
self.torrentHandle.save_resume_data()
received=False
while not received:
self.session.wait_for_alert(1000)
a = self.session.pop_alert()
log('[save_resume_data]: ['+str(type(a))+'] the alert '+str(a)+' is received')
if type(a) == self.lt.save_resume_data_alert:
received = True
debug('[save_resume_data]: '+str(dir(a)))
self.save_resume_data=self.lt.bencode(a.resume_data)
log('[save_resume_data]: the torrent resume data are saved')
def debug(self):
try:
# print str(self.getFilePath(0))
s = self.torrentHandle.status()
#get_cache_status=self.session.get_cache_status()
#log('get_cache_status - %s/%s' % (str(get_cache_status.blocks_written), str(get_cache_status.blocks_read)))
# get_settings=self.torrentHandle.status
# print s.num_pieces
# priorities = self.torrentHandle.piece_priorities()
@ -438,15 +490,23 @@ class Libtorrent:
'downloading', 'finished', 'seeding', 'allocating']
log('[%s] %.2f%% complete (down: %.1f kb/s up: %.1f kB/s peers: %d) %s %s %s' % \
(self.lt.version, s.progress * 100, s.download_rate / 1000,
s.upload_rate / 1000, s.num_peers, state_str[s.state],
self.get_debug_info('dht_state'), self.get_debug_info('trackers_sum')))
s.upload_rate / 1000, s.num_peers, state_str[s.state], self.get_debug_info('dht_state'), self.get_debug_info('trackers_sum')))
#log('%s %s' % (self.get_debug_info('dht_state'), self.get_debug_info('trackers_sum')))
debug('TRACKERS:' +str(self.torrentHandle.trackers()))
received=self.session.pop_alert()
while received:
debug('[debug]: ['+str(type(received))+'] the alert '+str(received)+' is received')
#if type(received) == self.lt.torrent_finished_alert:
# self.session.pause()
received = self.session.pop_alert()
#log('is_dht_running:' +str(self.session.is_dht_running()))
#log('dht_state:' +str(self.session.dht_state()))
#i = 0
# for t in s.pieces:
# if t: i=i+1
# print str(self.session.pop_alert())
#print str(self.session.pop_alert())
# print str(s.pieces[self.startPart:self.endPart])
# print 'True pieces: %d' % i
# print s.current_tracker
@ -469,10 +529,13 @@ class Libtorrent:
for url, fails, verified in trackers:
fails_sum+=fails
if verified: verified_sum+=1
result=result+'Trakers: verified %d/%d, fails=%d' %(verified_sum, len(trackers)-1, fails_sum)
result=result+'Trackers: verified %d/%d, fails=%d' %(verified_sum, len(trackers)-1, fails_sum)
if info=='dht_state':
is_dht_running='ON' if self.session.is_dht_running() else 'OFF'
try:
nodes=self.session.dht_state().get('nodes')
except:
nodes=None
nodes=len(nodes) if nodes else 0
result='DHT: %s (%d)' % (is_dht_running, nodes)
return result

View File

@ -266,6 +266,7 @@ def localize(text):
'Torrenter Tracker Install':'Установка трекеров в Torrenter',
'Ask to save':'Спросить о сохранении',
'Would you like to save this file?':'Хотите сохранить данный файл?',
'Your storage path is not writable or not local! Please change it in settings!':'Ваше хранилище не доступно для записи или не локально! Измените в настройках!',
},
'uk': {

View File

@ -30,7 +30,7 @@ import Downloader
import xbmcgui
import xbmcvfs
import Localization
from functions import calculate, showMessage, clearStorage, DownloadDB, get_ids_video
from functions import calculate, showMessage, clearStorage, DownloadDB, get_ids_video, log, debug
ROOT = sys.modules["__main__"].__root__
RESOURCES_PATH = os.path.join(ROOT, 'resources')
@ -140,7 +140,7 @@ class TorrentPlayer(xbmc.Player):
self.userStorageDirectory = userStorageDirectory
self.torrentUrl = torrentUrl
xbmc.Player.__init__(self)
print ("[TorrentPlayer] Initalized")
log("[TorrentPlayer] Initalized")
self.params = params
self.get = self.params.get
self.contentId = int(self.get("url"))
@ -157,35 +157,37 @@ class TorrentPlayer(xbmc.Player):
if self.buffer():
while True:
if self.setup_play():
# print '************************************* GOING LOOP'
#self.torrent.continueSession(self.contentId)
debug('************************************* GOING LOOP')
self.torrent.startSession()
self.torrent.continueSession(self.contentId)
self.loop()
else:
break
# print '************************************* GO NEXT?'
debug('************************************* GO NEXT?')
if self.next_dl and self.next_dling and isinstance(self.next_contentId, int) and self.iterator == 100:
self.contentId = self.next_contentId
continue
# print '************************************* NO! break'
debug('************************************* NO! break')
break
self.torrent.stopSession()
self.torrent.threadComplete = True
self.torrent.checkThread()
if '1' != self.__settings__.getSetting("keep_files") and 'Saved Files' not in self.userStorageDirectory:
xbmc.sleep(1000)
clearStorage(self.userStorageDirectory)
else:
if self.seeding_status:
showMessage(Localization.localize('Information'),
Localization.localize('Torrent is seeding. To stop it use Download Status.'), forced=True)
showMessage(self.localize('Information'),
self.localize('Torrent is seeding. To stop it use Download Status.'), forced=True)
else:
if self.seeding: self.db_delete()
showMessage(Localization.localize('Information'),
Localization.localize('Torrent downloading is stopped.'), forced=True)
showMessage(self.localize('Information'),
self.localize('Torrent downloading is stopped.'), forced=True)
def init(self):
self.next_dl = True if self.__settings__.getSetting('next_dl') == 'true' and self.ids_video else False
print '[TorrentPlayer]: init - ' + str(self.next_dl)
log('[TorrentPlayer]: init - ' + str(self.next_dl))
self.next_contentId = False
self.display_name = ''
self.downloadedSize = 0
@ -212,21 +214,21 @@ class TorrentPlayer(xbmc.Player):
self.torrent.status = False
self.fullSize = self.torrent.getFileSize(self.contentId)
Offset = calculate(self.fullSize)
# print 'Offset: '+str(Offset)
debug('Offset: '+str(Offset))
# mp4 fix
label = os.path.basename(self.torrent.getFilePath(self.contentId))
isMP4 = False
if '.' in label and str(label.split('.')[-1]).lower() == 'mp4':
isMP4 = True
# print 'setup_torrent: '+str((self.contentId, Offset, isMP4, label, ext))
debug('setup_torrent: '+str((self.contentId, Offset, isMP4, label)))
self.torrent.continueSession(self.contentId, Offset=Offset, isMP4=isMP4)
def buffer(self):
iterator = 0
progressBar = xbmcgui.DialogProgress()
progressBar.create(Localization.localize('Please Wait') + str(' [%s]' % str(self.torrent.lt.version)),
Localization.localize('Seeds searching.'))
progressBar.create(self.localize('Please Wait') + str(' [%s]' % str(self.torrent.lt.version)),
self.localize('Seeds searching.'))
if self.subs_dl:
subs = self.torrent.getSubsIds(os.path.basename(self.torrent.getFilePath(self.contentId)))
if len(subs) > 0:
@ -242,41 +244,43 @@ class TorrentPlayer(xbmc.Player):
if status.state == 0 or (status.progress == 0 and status.num_pieces > 0):
iterator = int(status.num_pieces * 100 / num_pieces)
if iterator > 99: iterator = 99
progressBar.update(iterator, Localization.localize('Checking preloaded files...'), ' ', ' ')
progressBar.update(iterator, self.localize('Checking preloaded files...'), ' ', ' ')
elif status.state == 3:
dialogText = Localization.localize('Preloaded: ') + str(downloadedSize / 1024 / 1024) + ' MB / ' + str(
dialogText = self.localize('Preloaded: ') + str(downloadedSize / 1024 / 1024) + ' MB / ' + str(
self.fullSize / 1024 / 1024) + ' MB'
peersText = ' [%s: %s; %s: %s]' % (
Localization.localize('Seeds'), str(self.torrent.getSeeds()), Localization.localize('Peers'),
self.localize('Seeds'), str(self.torrent.getSeeds()), self.localize('Peers'),
str(self.torrent.getPeers()),)
speedsText = '%s: %s Mbit/s; %s: %s Mbit/s' % (
Localization.localize('Downloading'), str(self.torrent.getDownloadRate() * 8 / 1000000),
Localization.localize('Uploading'), str(self.torrent.getUploadRate() * 8 / 1000000))
self.localize('Downloading'), str(self.torrent.getDownloadRate() * 8 / 1000000),
self.localize('Uploading'), str(self.torrent.getUploadRate() * 8 / 1000000))
if self.debug:
peersText=peersText + ' ' + self.torrent.get_debug_info('dht_state')
dialogText=dialogText.replace(Localization.localize('Preloaded: '),'') + ' ' + self.torrent.get_debug_info('trackers_sum')
progressBar.update(iterator, Localization.localize('Seeds searching.') + peersText, dialogText,
dialogText=dialogText.replace(self.localize('Preloaded: '),'') + ' ' + self.torrent.get_debug_info('trackers_sum')
progressBar.update(iterator, self.localize('Seeds searching.') + peersText, dialogText,
speedsText)
else:
progressBar.update(iterator, Localization.localize('UNKNOWN STATUS'), ' ', ' ')
progressBar.update(iterator, self.localize('UNKNOWN STATUS'), ' ', ' ')
if progressBar.iscanceled():
progressBar.update(0)
progressBar.close()
self.torrent.threadComplete = True
self.torrent.checkThread()
return
#self.torrent.torrentHandle.flush_cache()
self.torrent.resume_data()
self.torrent.session.remove_torrent(self.torrent.torrentHandle)
progressBar.update(0)
progressBar.close()
self.torrent.continueSession(self.contentId)
return True
def setup_subs(self, label, path):
iterator = 0
subs = self.torrent.getSubsIds(label)
# print str(subs)
debug('[setup_subs] subs: '+str(subs))
if len(subs) > 0:
showMessage(Localization.localize('Information'),
Localization.localize('Downloading and copy subtitles. Please wait.'), forced=True)
showMessage(self.localize('Information'),
self.localize('Downloading and copy subtitles. Please wait.'), forced=True)
for ind, title in subs:
self.torrent.continueSession(ind)
while iterator < 100:
@ -292,7 +296,7 @@ class TorrentPlayer(xbmc.Player):
ext = temp.split('.')[-1]
temp = temp[:len(temp) - len(ext) - 1] + '.' + addition + '.' + ext
newFileName = os.path.join(os.path.dirname(path), temp)
# print str((os.path.join(os.path.dirname(os.path.dirname(path)),title),newFileName))
debug('[setup_subs]: '+str((os.path.join(os.path.dirname(os.path.dirname(path)),title),newFileName)))
if not xbmcvfs.exists(newFileName):
xbmcvfs.copy(os.path.join(os.path.dirname(os.path.dirname(path)), title), newFileName)
@ -326,7 +330,7 @@ class TorrentPlayer(xbmc.Player):
'season': int(seasonId),
'tvshowtitle': title})
except:
print '[TorrentPlayer] Operation INFO failed!'
log('[TorrentPlayer] Operation INFO failed!')
thumbnail = self.get("thumbnail")
if thumbnail:
@ -354,7 +358,7 @@ class TorrentPlayer(xbmc.Player):
def onPlayBackStarted(self):
for f in self.on_playback_started:
f()
print(str(("video", "play", self.display_name)))
log('[onPlayBackStarted]: '+(str(("video", "play", self.display_name))))
def onPlayBackResumed(self):
for f in self.on_playback_resumed:
@ -364,12 +368,12 @@ class TorrentPlayer(xbmc.Player):
def onPlayBackPaused(self):
for f in self.on_playback_paused:
f()
print(str(("video", "pause", self.display_name)))
log('[onPlayBackPaused]: '+(str(("video", "pause", self.display_name))))
def onPlayBackStopped(self):
for f in self.on_playback_stopped:
f()
print(str(("video", "stop", self.display_name)))
log('[onPlayBackStopped]: '+(str(("video", "stop", self.display_name))))
@contextmanager
def attach(self, callback, *events):
@ -403,7 +407,7 @@ class TorrentPlayer(xbmc.Player):
self.next_contentId = int(self.ids_video[next_contentId_index])
else:
self.next_contentId = False
# print str(self.next_contentId)+'xxxxxx23'
debug('[loop] next_contentId: '+str(self.next_contentId))
if not self.seeding_run and self.iterator == 100 and self.seeding:
self.seeding_run = True
self.seed(self.contentId)
@ -411,8 +415,8 @@ class TorrentPlayer(xbmc.Player):
# xbmc.sleep(7000)
if self.iterator == 100 and self.next_dl and not self.next_dling and isinstance(self.next_contentId,
int) and self.next_contentId != False:
showMessage(Localization.localize('Torrent Downloading'),
Localization.localize('Starting download next episode!'), forced=True)
showMessage(self.localize('Torrent Downloading'),
self.localize('Starting download next episode!'), forced=True)
self.torrent.stopSession()
# xbmc.sleep(1000)
path = self.torrent.getFilePath(self.next_contentId)
@ -422,10 +426,10 @@ class TorrentPlayer(xbmc.Player):
def _get_status_lines(self, s):
return [
self.display_name.decode('utf-8'),
"%.2f%% %s %s %s" % (s.progress * 100, Localization.localize(STATE_STRS[s.state]).decode('utf-8'), self.torrent.get_debug_info('dht_state'), self.torrent.get_debug_info('trackers_sum')),
"D:%.2f%s U:%.2f%s S:%d P:%d" % (s.download_rate / 1000, Localization.localize('kb/s').decode('utf-8'),
s.upload_rate / 1000, Localization.localize('kb/s').decode('utf-8'),
self.display_name.decode('utf-8')+'; '+self.torrent.get_debug_info('dht_state'),
"%.2f%% %s; %s" % (s.progress * 100, self.localize(STATE_STRS[s.state]).decode('utf-8'), self.torrent.get_debug_info('trackers_sum')),
"D:%.2f%s U:%.2f%s S:%d P:%d" % (s.download_rate / 1000, self.localize('kb/s').decode('utf-8'),
s.upload_rate / 1000, self.localize('kb/s').decode('utf-8'),
s.num_seeds, s.num_peers)
]
@ -450,3 +454,9 @@ class TorrentPlayer(xbmc.Player):
contentList.append((filedict.get('title'), str(filedict.get('ind'))))
contentList = sorted(contentList, key=lambda x: x[0])
return get_ids_video(contentList)
def localize(self, string):
try:
return Localization.localize(string)
except:
return string

View File

@ -1,5 +1,9 @@
English changelog at http://bit.ly/1MfSVUP
[B]Version 2.3.5[/B]
[+] Проигрыватель: Уменьшена просадка после загрузки буфера
[+] Проигрыватель: Проверка на запись хранилища
[B]Version 2.3.4[/B]
[+] Проигрыватель: Новая настройка - спрашивать о сохранении файла
[+] Списки Медиа: Исправлен TheMovieDB для python 2.6

View File

@ -131,13 +131,16 @@ def log(msg):
xbmc.log("### [%s]: %s" % (__plugin__,'ERROR LOG',), level=xbmc.LOGNOTICE )
def debug(msg):
def debug(msg, forced=False):
level=xbmc.LOGDEBUG
if getSettingAsBool('debug') and forced:
level=xbmc.LOGNOTICE
try:
xbmc.log("### [%s]: %s" % (__plugin__,msg,), level=xbmc.LOGDEBUG )
xbmc.log("### [%s]: %s" % (__plugin__,msg,), level=level )
except UnicodeEncodeError:
xbmc.log("### [%s]: %s" % (__plugin__,msg.encode("utf-8", "ignore"),), level=xbmc.LOGDEBUG )
xbmc.log("### [%s]: %s" % (__plugin__,msg.encode("utf-8", "ignore"),), level=level )
except:
xbmc.log("### [%s]: %s" % (__plugin__,'ERROR DEBUG',), level=xbmc.LOGDEBUG )
xbmc.log("### [%s]: %s" % (__plugin__,'ERROR DEBUG',), level=level )
def showMessage(heading, message, times=10000, forced=False):
@ -1115,6 +1118,7 @@ class Searchers():
addons_dir = os.path.join(xbmc.translatePath('special://home'),'addons')
addons_dirsList = xbmcvfs.listdir(addons_dir)[0]
for searcherDir in addons_dirsList:
#if len(searchersDict)>1: break
if re.match('^torrenter\.searcher\.(\w+)$', searcherDir):
name=searcherDir.replace('torrenter.searcher.', '')
path=os.path.join(addons_dir, searcherDir)
@ -1122,7 +1126,6 @@ class Searchers():
'path':path,
'searcher':os.path.join(path,name+'.py'),
'type':'external'}
#if len(searchersDict)>1: break
return searchersDict
def dic(self, providers=[]):
@ -1864,7 +1867,6 @@ def windows_check():
"""
return platform.system() in ('Windows', 'Microsoft')
def vista_check():
import platform
"""
@ -1873,3 +1875,12 @@ def vista_check():
:rtype: bool
"""
return platform.release() == "Vista"
def is_writable(path):
try:
open(os.path.join(path, 'temp'), 'w')
except:
return False
else:
os.remove(os.path.join(path, 'temp'))
return True