Skip to content

Commit

Permalink
Merge commit '7321effd4c4a979edfc01f40c1d1a6573db3dd2d' as 'plugin.vi…
Browse files Browse the repository at this point in the history
…deo.douyutv2'
  • Loading branch information
catro committed Apr 9, 2017
2 parents 5eb4374 + 7321eff commit 45e7901
Show file tree
Hide file tree
Showing 14 changed files with 1,032 additions and 0 deletions.
4 changes: 4 additions & 0 deletions plugin.video.douyutv2/.gitignore
@@ -0,0 +1,4 @@
*.zip
*.pyc
*.pyo
*.swp
164 changes: 164 additions & 0 deletions plugin.video.douyutv2/BulletScreen.py
@@ -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__)
130 changes: 130 additions & 0 deletions plugin.video.douyutv2/Douyu.py
@@ -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')

0 comments on commit 45e7901

Please sign in to comment.