diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 88d090a..8192bf8 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,37 +2,11 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + @@ -62,11 +36,11 @@ - + - - + + @@ -74,25 +48,59 @@ - - + + + + + + + + + + + + + + - + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -101,30 +109,63 @@ - + + + + + + + + + + + + + + + + - - + - - + + + + + + + + + + + + + + + + + + + + + @@ -132,18 +173,6 @@ - - - - - - - - - - - - @@ -165,25 +194,58 @@ - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + + + @@ -198,18 +260,6 @@ - - - - - - - - - - - - @@ -242,8 +292,6 @@ @@ -327,6 +377,8 @@ + + @@ -345,10 +397,22 @@ + + + + + + + + - - @@ -360,13 +424,13 @@ + + + - - - @@ -530,12 +594,6 @@ @@ -835,7 +899,7 @@ - + @@ -865,7 +929,6 @@ - @@ -890,7 +953,8 @@ - @@ -899,38 +963,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1064,13 +1096,6 @@ - - - - - - - @@ -1092,23 +1117,6 @@ - - - - - - - - - - - - - - - - - @@ -1158,14 +1166,6 @@ - - - - - - - - @@ -1194,24 +1194,6 @@ - - - - - - - - - - - - - - - - - - @@ -1239,17 +1221,6 @@ - - - - - - - - - - - @@ -1257,16 +1228,6 @@ - - - - - - - - - - @@ -1274,46 +1235,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Anteoloader.py b/Anteoloader.py new file mode 100644 index 0000000..2ea4578 --- /dev/null +++ b/Anteoloader.py @@ -0,0 +1,237 @@ +# -*- coding: utf-8 -*- +''' + Torrenter v2 plugin for XBMC/Kodi + Copyright (C) 2012-2015 Vadim Skorba v1 - DiMartino v2 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +''' + +import thread +import os +import urllib2 +import hashlib +import re +from StringIO import StringIO +import gzip +import sys +from contextlib import closing + +import xbmc +import xbmcgui +import xbmcvfs +import xbmcplugin +import Localization +from functions import file_encode, isSubtitle, DownloadDB, log, debug, is_writable, unquote +from torrent2http import State, Engine, MediaType + +class Anteoloader: + magnetLink = None + startPart = 0 + endPart = 0 + partOffset = 0 + torrentHandle = None + session = None + engine = None + downloadThread = None + threadComplete = False + + def __init__(self, storageDirectory='', torrentFile='', torrentFilesDirectory='torrents'): + self.storageDirectory = storageDirectory + self.torrentFilesPath = os.path.join(self.storageDirectory, torrentFilesDirectory) + os.sep + if not is_writable(self.storageDirectory): + xbmcgui.Dialog().ok(self.localize('Torrenter v2'), + self.localize('Your storage path is not writable or not local! Please change it in settings!'), + self.localize(self.storageDirectory)) + + sys.exit(1) + + #pre settings + self.pre_buffer_bytes = 15*1024*1024 + print torrentFile + torrentFile=unquote(torrentFile) + print torrentFile + print str(xbmcvfs.exists(torrentFile)) + print str(os.path.exists(torrentFile)) + + + self.engine = Engine(uri=torrentFile) + + def __exit__(self): + log('on __exit__') + if self.engine: + self.engine.close() + log('__exit__ worked!') + + + def getContentList(self, media_types=None): + files = [] + filelist = [] + with closing(self.engine): + self.engine.start() + if media_types is None: + media_types=[MediaType.VIDEO, MediaType.AUDIO, MediaType.SUBTITLES, MediaType.UNKNOWN] + + while not files and not xbmc.abortRequested: + files = self.engine.list(media_types) + self.engine.check_torrent_error() + xbmc.sleep(200) + + for fs in files: + stringdata = {"title": fs.name, "size": fs.size, "ind": fs.index, + 'offset': fs.offset} + filelist.append(stringdata) + + + def stream(self, params): + self.params = params + self.get = self.params.get + self.contentId = int(self.get("url")) if self.get("url") else 0 + #with closing(self.engine): + self.engine.start(self.contentId) + + ready = self.buffer() + if ready: + file_status = self.engine.file_status(self.contentId) + listitem = xbmcgui.ListItem('xxxx') + playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) + playlist.clear() + playlist.add(file_status.url, listitem) + xbmc.Player().play(playlist) + while not xbmc.abortRequested and xbmc.Player().isPlaying(): + xbmc.sleep(500) + xbmc.Player().stop() + + def buffer(self): + ready = False + progressBar = xbmcgui.DialogProgress() + progressBar.create(self.localize('Please Wait'), + self.localize('Seeds searching.')) + #if self.subs_dl: + # subs = self.torrent.getSubsIds(os.path.basename(self.torrent.getFilePath(self.contentId))) + # if len(subs) > 0: + # for ind, title in subs: + # self.torrent.continueSession(ind) + + #FileStatus = namedtuple('FileStatus', "name, save_path, url, size, offset, download, progress, index, media_type") + + #SessionStatus = namedtuple('SessionStatus', "name, state, state_str, error, progress, download_rate, upload_rate, " + # "total_download, total_upload, num_peers, num_seeds, total_seeds, " + # "total_peers") + + while not xbmc.abortRequested and not ready: + xbmc.sleep(500) + status = self.engine.status() + self.engine.check_torrent_error(status) + file_status = self.engine.file_status(self.contentId) + if not file_status: + continue + log('[buffer] file_status:'+str(file_status)) + log('[buffer] status:'+str(status)) + #self.torrent.debug() + fullSize = file_status.size / 1024 / 1024 + downloadedSize = status.total_download / 1024 / 1024 + getDownloadRate = status.download_rate / 1024 * 8 + getUploadRate = status.upload_rate / 1024 * 8 + getSeeds, getPeers = status.num_seeds, status.num_peers + iterator = int(round(float(file_status.download) / self.pre_buffer_bytes, 2) * 100) + if iterator > 99: iterator = 99 + if status.state == State.QUEUED_FOR_CHECKING: + progressBar.update(iterator, self.localize('Checking preloaded files...'), ' ', ' ') + elif status.state == State.DOWNLOADING: + dialogText = self.localize('Preloaded: ') + "%d MB / %d MB" % \ + (int(downloadedSize), int(fullSize)) + peersText = ' [%s: %s; %s: %s]' % ( + self.localize('Seeds'), getSeeds, self.localize('Peers'), getPeers) + speedsText = '%s: %d Mbit/s; %s: %d Mbit/s' % ( + self.localize('Downloading'), int(getDownloadRate), + self.localize('Uploading'), int(getUploadRate)) + #if self.debug: + # peersText=peersText + ' ' + self.torrent.get_debug_info('dht_state') + # dialogText=dialogText.replace(self.localize('Preloaded: '),'') + ' ' + self.torrent.get_debug_info('trackers_sum') + progressBar.update(iterator, self.localize('Seeds searching.') + peersText, dialogText, + speedsText) + + if file_status.download >= self.pre_buffer_bytes: + ready = True + break + elif status.state in [State.FINISHED, State.SEEDING]: + ready = True + break + else: + progressBar.update(iterator, self.localize('UNKNOWN STATUS'), ' ', ' ') + if progressBar.iscanceled(): + ready = False + break + + progressBar.update(0) + progressBar.close() + return ready + + def localize(self, string): + try: + return Localization.localize(string) + except: + return string + + + def saveTorrent(self, torrentUrl): + if not xbmcvfs.exists(torrentUrl): + if re.match("^magnet\:.+$", torrentUrl): + self.magnetLink = torrentUrl + self.magnetToTorrent(torrentUrl) + self.magnetLink = None + return self.torrentFile + else: + if not xbmcvfs.exists(self.torrentFilesPath): + xbmcvfs.mkdirs(self.torrentFilesPath) + torrentFile = self.torrentFilesPath + self.md5( + torrentUrl) + '.torrent' + try: + if not re.match("^http\:.+$", torrentUrl): + content = xbmcvfs.File(torrentUrl, "rb").read() + else: + request = urllib2.Request(torrentUrl) + request.add_header('Referer', torrentUrl) + request.add_header('Accept-encoding', 'gzip') + result = urllib2.urlopen(request) + if result.info().get('Content-Encoding') == 'gzip': + buf = StringIO(result.read()) + f = gzip.GzipFile(fileobj=buf) + content = f.read() + else: + content = result.read() + + localFile = xbmcvfs.File(torrentFile, "w+b") + localFile.write(content) + localFile.close() + except Exception, e: + print 'Unable to save torrent file from "' + torrentUrl + '" to "' + torrentFile + '" in Torrent::saveTorrent' + '. Exception: ' + str( + e) + return + else: + torrentFile = torrentUrl + if xbmcvfs.exists(torrentFile): + self.torrentFile = "file:///"+torrentFile.replace('\\','//').replace('////','//') + return self.torrentFile + + def md5(self, string): + hasher = hashlib.md5() + try: + hasher.update(string) + except: + hasher.update(string.encode('utf-8', 'ignore')) + return hasher.hexdigest() + + def magnetToTorrent(self, magnet): + self.torrentFile = magnet \ No newline at end of file diff --git a/Core.py b/Core.py index a77a546..bbabdd4 100644 --- a/Core.py +++ b/Core.py @@ -45,6 +45,7 @@ class Core: def __init__(self): print '!!!!!!!!!!!!!!!!!! BORN '+self.__class__.__name__ + print str(self.ROOT) if len(self.userStorageDirectory) == 0: download_dir = get_download_dir() else: @@ -233,7 +234,7 @@ class Core: lockView('wide') def test(self, params={}): - from BTClientPlayer import BTClientPlayer + from Anteoloader import Anteoloader torrentUrl='D:\\ntest.torrent' params['url']='0' if not xbmcvfs.exists(torrentUrl): @@ -241,15 +242,13 @@ class Core: torrentUrl = action.browse(1, self.localize('Choose .torrent in video library'), 'video', '.torrent') if torrentUrl and xbmcvfs.exists(torrentUrl): if 0 != len(torrentUrl): - self.Player = BTClientPlayer(userStorageDirectory=self.userStorageDirectory, torrentUrl=torrentUrl, params=params) + self.Downloader = Anteoloader(self.userStorageDirectory, torrentUrl) else: - print self.__plugin__ + " Unexpected access to method playTorrent() without torrent content" - #path='http://127.0.0.1:5001/Inception.2010.1080p.BluRay.x264.5xRus.Eng-Otaibi.mkv' - #listitem = xbmcgui.ListItem('Inception.2010.1080p.BluRay.x264.5xRus.Eng-Otaibi.mkv', path=path) - #playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) - #playlist.clear() - #playlist.add(path, listitem) - #xbmc.Player().play(playlist) + print self.__plugin__ + " Unexpected access to method Anteoloader() without torrent content" + if self.Downloader: + self.Downloader.stream() + xbmc.sleep(1000) + self.Downloader.__exit__() def DownloadStatus(self, params={}): db = DownloadDB() @@ -345,16 +344,16 @@ class Core: progress=int(jsoninfo.get('progress')) if status=='pause': status_sign='[||]' - img = os.path.join(self.ROOT, '/icons/', 'pause-icon.png') + img = os.path.join(self.ROOT, 'icons', 'pause-icon.png') elif status=='stopped': status_sign='[X]' - img = os.path.join(self.ROOT, '/icons/', 'stop-icon.png') + img = os.path.join(self.ROOT, 'icons', 'stop-icon.png') else: status_sign='[>]' if progress==100: - img = os.path.join(self.ROOT, '/icons/', 'upload-icon.png') + img = os.path.join(self.ROOT, 'icons', 'upload-icon.png') else: - img = os.path.join(self.ROOT, '/icons/', 'download-icon.png') + img = os.path.join(self.ROOT, 'icons', 'download-icon.png') title = '[%d%%]%s %s' % (progress, status_sign, title) if jsoninfo.get('seeds')!=None and jsoninfo.get('peers')!=None and \ @@ -973,6 +972,7 @@ class Core: def drawItem(self, title, action, link='', image='', isFolder=True, contextMenu=None, replaceMenu=True, action2='', info={}): listitem = xbmcgui.ListItem(title, iconImage=image, thumbnailImage=image) + log('[drawItem]:'+str((title, action, image, isFolder, contextMenu, replaceMenu, action2, info))) if not info: info = {"Title": title, "plot": title} if isinstance(link, dict): link_url = '' @@ -1116,10 +1116,14 @@ class Core: status = TextBB(' [||] ', 'b') elif data['status'] in ('seeding', 'downloading'): status = TextBB(' [>] ', 'b') - if data['status'] == 'seed_pending': os.path.join(self.ROOT, '/icons/', 'pause-icon.png') - elif data['status'] == 'stopped': os.path.join(self.ROOT, '/icons/', 'stop-icon.png') - elif data['status'] == 'seeding': os.path.join(self.ROOT, '/icons/', 'upload-icon.png') - elif data['status'] == 'downloading': os.path.join(self.ROOT, '/icons/', 'download-icon.png') + if data['status'] == 'seed_pending': + img = os.path.join(self.ROOT, 'icons', 'pause-icon.png') + elif data['status'] == 'stopped': + img = os.path.join(self.ROOT, 'icons', 'stop-icon.png') + elif data['status'] == 'seeding': + img = os.path.join(self.ROOT, 'icons', 'upload-icon.png') + elif data['status'] == 'downloading': + img = os.path.join(self.ROOT, 'icons', 'download-icon.png') menu.append( {"title": '[' + str(data['progress']) + '%]' + status + data['name'] + ' [' + str( data['ratio']) + ']', "image":img, diff --git a/Downloader.py b/Downloader.py index ec3cd6c..e1702d8 100644 --- a/Downloader.py +++ b/Downloader.py @@ -23,6 +23,7 @@ import sys import Libtorrent import AceStream +import Anteoloader class Torrent(): @@ -36,15 +37,20 @@ class Torrent(): elif self.player == 'acestream': self.player = AceStream.AceStream(storageDirectory, torrentFile, torrentFilesDirectory) + elif self.player == 'anteo': + self.player = Anteoloader.Anteoloader(storageDirectory, torrentFile, torrentFilesDirectory) + def __exit__(self): self.player.__exit__() def get_torrent_client(self): player = self.__settings__.getSetting("torrent_player") - if player in ['0','2']: + if player == '0': self.player = 'libtorrent' elif player == '1': self.player = 'acestream' + elif player == '2': + self.player = 'anteo' def play_url_ind(self, ind, label, icon): return self.player.play_url_ind(int(ind), label, str(icon)) diff --git a/addon.xml b/addon.xml index 3a3a264..e6a4130 100644 --- a/addon.xml +++ b/addon.xml @@ -1,10 +1,12 @@  - + + + video