buffer, cron, parse torrent-file
parent
b285e05ed7
commit
d7f41a2f07
|
@ -15,7 +15,6 @@ dist/
|
||||||
downloads/
|
downloads/
|
||||||
eggs/
|
eggs/
|
||||||
.eggs/
|
.eggs/
|
||||||
lib/
|
|
||||||
lib64/
|
lib64/
|
||||||
parts/
|
parts/
|
||||||
sdist/
|
sdist/
|
||||||
|
|
|
@ -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>
|
|
@ -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)]
|
||||||
|
|
Loading…
Reference in New Issue