Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge commit '7321effd4c4a979edfc01f40c1d1a6573db3dd2d' as 'plugin.vi…
…deo.douyutv2'
- Loading branch information
Showing
14 changed files
with
1,032 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
*.zip | ||
*.pyc | ||
*.pyo | ||
*.swp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
# -*- coding: utf-8 -*- | ||
import xbmc | ||
import xbmcgui | ||
import os | ||
import threading | ||
import logging | ||
|
||
#Initialize logging | ||
logging.getLogger().setLevel(logging.INFO) | ||
logging.basicConfig(format='[%(module)s][%(funcName)s] %(message)s') | ||
|
||
WINDOW_FULLSCREEN_VIDEO = 12005 | ||
class BulletLabel(object): | ||
def __init__(self, text, label, timeout, line): | ||
self.label = label | ||
self.timeout = timeout | ||
self.line = line | ||
self.delay = self.showtime(text, timeout) | ||
|
||
def showtime(self, text, timeout): | ||
length = self.strlen(text) | ||
delay = int(length * timeout / 200) | ||
if delay > timeout: | ||
delay = timeout | ||
return delay | ||
|
||
def strlen(self, text): | ||
length = len(text) | ||
utf8_length = len(text.encode('utf-8')) | ||
return (utf8_length - length) / 2 + length | ||
|
||
|
||
class BulletScreen(object): | ||
def __init__(self, *args, **kwargs): | ||
self.window = xbmcgui.Window(WINDOW_FULLSCREEN_VIDEO) | ||
viewport_w, viewport_h = self._get_skin_resolution() | ||
self.running = False | ||
self.thread = threading.Thread(target = self.run) | ||
self.texts = [] | ||
self.labels = [] | ||
self.textColor = kwargs.get("textColor", "0xFFFFFFFF") | ||
fontSize = kwargs.get("fontSize", "normal") | ||
position = kwargs.get("position", "up") | ||
self.left =int(viewport_w) | ||
self.width = int(viewport_w) | ||
self.speed = kwargs.get("speed", 10000) | ||
if fontSize == "normal": | ||
self.fontSize = "font13" | ||
self.fontHeight = int(viewport_h * 0.03) | ||
else: | ||
self.fontSize = "font16" | ||
self.fontHeight = int(viewport_h * 0.04) | ||
if position == "up": | ||
self.direction = 1 | ||
self.top = int(viewport_h * 0.01) | ||
else: | ||
self.direction = -1 | ||
self.top = int(viewport_h * 0.99 - self.fontHeight) | ||
|
||
self.available_line = [] | ||
self.lines = 0 | ||
|
||
def run(self): | ||
interval = 100 | ||
while self.running: | ||
while len(self.texts) >= (2 << self.lines): | ||
self.available_line.append(self.lines) | ||
self.lines += 1 | ||
|
||
while ((len(self.available_line) > 0) and (len(self.texts) > 0)): | ||
#Add texts | ||
text = self.texts.pop(0) | ||
line = self.available_line.pop(0) | ||
top = self.top + self.direction * self.fontHeight * line | ||
label = xbmcgui.ControlLabel(self.left, top, self.width, self.fontHeight, text, | ||
self.fontSize, self.textColor) | ||
self.labels.append(BulletLabel(text, label, self.speed, line)) | ||
self.window.addControl(label) | ||
label.setAnimations([('conditional', 'condition=true effect=slide start=%d,0 end=%d,0 time=%d' % | ||
(0, -(self.width * 2), self.speed))]) | ||
logging.debug('Add label: ' + text) | ||
|
||
for label in self.labels: | ||
#Check for available line | ||
if label.delay != 0: | ||
if label.delay > interval: | ||
label.delay -= interval | ||
else: | ||
self.available_line.append(label.line) | ||
while (self.lines > 0) and (len(self.texts) < (2 << (self.lines - 1))) and ((self.lines - 1) in self.available_line): | ||
self.lines -= 1 | ||
self.available_line.remove((self.lines)) | ||
label.delay = 0 | ||
|
||
#Remove label that is timeout | ||
if label.timeout > interval: | ||
label.timeout -= interval | ||
else: | ||
logging.debug('Remove text: ' + label.label.getLabel()) | ||
self.window.removeControl(label.label) | ||
self.labels.remove(label) | ||
|
||
xbmc.sleep(interval) | ||
|
||
logging.info('BulletScreen thread exit') | ||
|
||
#Remove labels | ||
for label in self.labels: | ||
self.window.removeControl(label.label) | ||
|
||
|
||
def addText(self, text): | ||
logging.debug('Add text: ' + text) | ||
self.texts.append(text) #pending | ||
|
||
if self.running == False: | ||
self.running = True | ||
self.thread.start() | ||
|
||
def exit(self): | ||
if self.running == True: | ||
self.running = False | ||
self.thread.join() | ||
|
||
|
||
# This is so hackish it hurts. | ||
def _get_skin_resolution(self): | ||
import xml.etree.ElementTree as ET | ||
skin_path = xbmc.translatePath("special://skin/") | ||
tree = ET.parse(os.path.join(skin_path, "addon.xml")) | ||
res = tree.findall("./extension/res")[0] | ||
return int(res.attrib["width"]), int(res.attrib["height"]) | ||
|
||
|
||
if __name__ == '__main__': | ||
import xbmcgui | ||
import xbmcplugin | ||
import sys | ||
from urlparse import parse_qsl | ||
from douyudanmu import douyudanmu | ||
if 0: | ||
from addon import router | ||
router(sys.argv[2][1:]) | ||
else: | ||
__handle__ = int(sys.argv[1]) | ||
params = dict(parse_qsl(sys.argv[2][1:])) | ||
if 'test' in params: | ||
xbmcplugin.setResolvedUrl(__handle__, True, xbmcgui.ListItem(path='d:\empty.mpeg')) | ||
player = xbmc.Player() | ||
bs = BulletScreen() | ||
#danmu=douyudanmu('138286') | ||
danmu=douyudanmu('321358') | ||
while not player.isPlaying(): | ||
xbmc.sleep(1000) | ||
while not xbmc.abortRequested and player.isPlaying(): | ||
s=danmu.get_danmu() | ||
if len(s)!=0: | ||
bs.addText(s) | ||
bs.exit() | ||
else: | ||
item = xbmcgui.ListItem(label='Play') | ||
item.setProperty('IsPlayable', 'true') | ||
xbmcplugin.addDirectoryItem(__handle__, sys.argv[0]+'?test=1', item) | ||
xbmcplugin.endOfDirectory(__handle__) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
#!/usr/bin/env python2 | ||
import thread | ||
import urllib2 | ||
import SocketServer | ||
import time | ||
import threading | ||
from SimpleHTTPServer import SimpleHTTPRequestHandler | ||
import logging | ||
|
||
#Initialize logging | ||
logging.getLogger().setLevel(logging.INFO) | ||
logging.basicConfig(format='[%(levelname)s][%(funcName)s] %(message)s') | ||
|
||
#Global variables | ||
douyu_proxy_handler = None | ||
douyu_http_server_idle_event = threading.Event() | ||
|
||
class Douyu_Proxy_Handler(object): | ||
response = None | ||
headers = '' | ||
data_buffer = '' | ||
buffer_max = 1024 * 1024 | ||
read_size = 10 * 1024 | ||
|
||
def start(self, url): | ||
if ((self.response is None) or | ||
(self.headers == '')): | ||
try: | ||
self.response = urllib2.urlopen(urllib2.Request(url, headers={'User-Agent': 'kodi'})) | ||
self.headers = 'HTTP/1.1 200 OK\r\n' + ''.join(self.response.info().headers) + '\r\n' | ||
logging.debug('Connected to %s' % (url)) | ||
return True | ||
except: | ||
self.response = None | ||
self.headers = '' | ||
logging.debug('Unable to connect to %s' %(url)) | ||
return False | ||
else: | ||
logging.debug('Already connected to %s' %(url)) | ||
return True | ||
|
||
def send_header(self, request_handler): | ||
if (self.headers == ''): | ||
logging.debug('No header') | ||
request_handler.send_error(404) | ||
return False | ||
else: | ||
request_handler.wfile.write(self.headers) | ||
return True | ||
|
||
def do_head(self, request_handler, url): | ||
if (self.start(url) == False): | ||
return | ||
|
||
self.send_header(request_handler) | ||
|
||
|
||
def do_get(self, request_handler, url): | ||
if (self.start(url) == False): | ||
return | ||
|
||
if (self.send_header(request_handler) == False): | ||
return | ||
|
||
offset = 0 | ||
try: | ||
while True: | ||
self.data_buffer += self.response.read(self.read_size) | ||
request_handler.wfile.write(self.data_buffer[offset:]) | ||
|
||
if (len(self.data_buffer) > self.buffer_max): | ||
logging.debug('Reset buffer') | ||
self.data_buffer = '' | ||
self.headers = '' | ||
offset = 0 | ||
else: | ||
offset = len(self.data_buffer) | ||
|
||
except: | ||
logging.debug('Done') | ||
|
||
|
||
class HTTP_Handler(SimpleHTTPRequestHandler): | ||
def do_GET(self): | ||
global douyu_proxy_handler | ||
global douyu_http_server_idle_event | ||
douyu_http_server_idle_event.set() | ||
if (douyu_proxy_handler is None): | ||
douyu_proxy_handler = Douyu_Proxy_Handler() | ||
douyu_proxy_handler.do_get(self, self.path[1:]) | ||
douyu_http_server_idle_event.clear() | ||
|
||
def do_HEAD(self): | ||
global douyu_proxy_handler | ||
global douyu_http_server_idle_event | ||
douyu_http_server_idle_event.set() | ||
if (douyu_proxy_handler is None): | ||
douyu_proxy_handler = Douyu_Proxy_Handler() | ||
douyu_proxy_handler.do_head(self, self.path[1:]) | ||
douyu_http_server_idle_event.clear() | ||
|
||
class Douyu_HTTP_Server(object): | ||
def thread_entry(self): | ||
self.httpd.serve_forever() | ||
|
||
def proxy(self, douyu_url, address = 'localhost', start_port = 10000): | ||
while True: | ||
try: | ||
self.httpd = SocketServer.TCPServer(('', start_port), HTTP_Handler) | ||
break | ||
except: | ||
logging.debug('Unable to bind to %d' % (start_port)) | ||
start_port += 1 | ||
if (start_port > 65535): | ||
logging.error('No available port') | ||
return '' | ||
thread.start_new_thread(self.thread_entry, ()) | ||
url = 'http://%s:%d/%s' % (address, start_port, douyu_url) | ||
logging.info('Douyu URL: %s' % (url)) | ||
return url | ||
|
||
def wait_for_idle(self, wait_option): | ||
global douyu_http_server_idle_event | ||
while (douyu_http_server_idle_event.wait(wait_option) == True): | ||
time.sleep(wait_option) | ||
self.exit() | ||
|
||
def exit(self): | ||
self.httpd.shutdown() | ||
logging.info('Proxy exit') |
Oops, something went wrong.