buffer, cron, parse torrent-file

master
Бородин Роман 2019-05-06 23:40:24 +03:00
parent b285e05ed7
commit d7f41a2f07
3 changed files with 106 additions and 1 deletions

1
.gitignore vendored
View File

@ -15,7 +15,6 @@ dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/

17
addon.xml 100644
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.module.pyrrent" name="pyrrent" version="0.0.1" provider-name="inpos">
<requires>
<import addon="xbmc.python" version="2.25.0"/>
<import addon="script.module.torrent_parser" version="0.3.0"/>
</requires>
<extension point="xbmc.python.module" library="lib"/>
<extension point="xbmc.addon.metadata">
<platform>all</platform>
<language>en_GB ru_RU</language>
<summary lang="en_GB">Pure python torrent video stream engine for KODI</summary>
<summary lang="ru_RU">Движок потокового видео из сети torrent на чистом Python</summary>
<description lang="ru">Движок потокового видео из сети torrent на чистом Python</description>
<description lang="en">Pure python torrent video stream engine for KODI</description>
<email>roman@ukamnya.ru</email>
<source>https://git.ukamnya.ru/roman/script.module.pyrrent</source></extension>
</addon>

89
lib/pyrrent.py 100644
View File

@ -0,0 +1,89 @@
import torrent_parser as tp
import threading
from math import ceil
BUFFER_SIZE = 10 * 1024 * 1024
class Cron(object):
alive = False
def __init__(self, interval, func, *a, **kw):
self.interval = interval
self.func = func
self.a = a
self.kw = kw
self.ticker = threading.Event()
def start(self):
self.t = threading.Thread(target=self.run)
self.alive = True
self.t.start()
def run(self):
while self.alive and not self.ticker.wait(self.interval):
self.func(*self.a, **self.kw)
def stop(self):
self.alive = False
class Buffer(object):
def __init__(self, piece_size):
self.buf_reset_pending = False
self.buf_changed = threading.Event()
self.size = ceil(BUFFER_SIZE / piece_size)
self.buf = []
def buf_changed_event(self):
self.buf_changed.set()
self.buf_changed.clear()
def put(self, piece):
if not self.buf_reset_pending:
self.buf.append(piece)
self.buf_changed_event()
return True
else:
return False
def get(self):
if not self.buf_reset_pending:
if len(self.buf):
return self.buf.pop(0)
return None
def reset(self):
self.buf_reset_pending = True
self.buf = []
self.buf_reset_pending = False
self.buf_changed_event()
def pieces(self):
if not self.buf_reset_pending:
return list(map(lambda x: (x.index, x.hash), self.buf))
else:
return []
class Piece(object):
def __init__(self, p_index, p_hash, payload):
self.index = p_index
self.hash = p_hash
self.payload = payload
class Pyrrent(object):
multifile = False
def __init__(self, filepath):
self.data = tp.parse_torrent_file(filepath)
self.piece_length = self.data['info']['piece length']
self.buffer = Buffer(self.piece_length)
self.pieces = self.data['info']['pieces']
if 'files' in self.data['info'].keys():
self.multifile = True
if not self.multifile:
self.file_addresses = [(0, self.piece_length)]
else:
self.file_addresses = []
addr_ptr = 0
for length in map(lambda x: x['length'], self.data['info']['files']):
next_at = addr_ptr + length
self.file_addresses.append((addr_ptr, next_at))
addr_ptr += length
def piece_range(self, f_index):
start, next_at = self.file_addresses[f_index]
start_piece = start // self.piece_length
start_byte = start % self.piece_length
tail = next_at % self.piece_length
end_piece = next_at // self.piece_length - int(not bool(tail))
end_byte = self.piece_length if not tail else tail
return [(start_piece, start_byte),(end_piece, end_byte)]