From d7f41a2f07ba0e89b9af4083415d827883c5a03a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D1=80=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=A0=D0=BE?= =?UTF-8?q?=D0=BC=D0=B0=D0=BD?= Date: Mon, 6 May 2019 23:40:24 +0300 Subject: [PATCH] buffer, cron, parse torrent-file --- .gitignore | 1 - addon.xml | 17 ++++++++++ lib/pyrrent.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 addon.xml create mode 100644 lib/pyrrent.py diff --git a/.gitignore b/.gitignore index 8f9852c..e13ae64 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,6 @@ dist/ downloads/ eggs/ .eggs/ -lib/ lib64/ parts/ sdist/ diff --git a/addon.xml b/addon.xml new file mode 100644 index 0000000..578547d --- /dev/null +++ b/addon.xml @@ -0,0 +1,17 @@ + + + + + + + + + all + en_GB ru_RU + Pure python torrent video stream engine for KODI + Движок потокового видео из сети torrent на чистом Python + Движок потокового видео из сети torrent на чистом Python + Pure python torrent video stream engine for KODI + roman@ukamnya.ru + https://git.ukamnya.ru/roman/script.module.pyrrent + diff --git a/lib/pyrrent.py b/lib/pyrrent.py new file mode 100644 index 0000000..eb8866b --- /dev/null +++ b/lib/pyrrent.py @@ -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)] +