712 lines
32 KiB
Python
712 lines
32 KiB
Python
# -*- coding: utf-8 -*-
|
||
|
||
# script.module.python.koding.aio
|
||
# Python Koding AIO (c) by TOTALREVOLUTION LTD (support@trmc.freshdesk.com)
|
||
|
||
# Python Koding AIO is licensed under a
|
||
# Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
|
||
|
||
# You should have received a copy of the license along with this
|
||
# work. If not, see http://creativecommons.org/licenses/by-nc-nd/4.0.
|
||
|
||
# Please make sure you've read and understood the license, this code can NOT be used commercially
|
||
# and it can NOT be modified and redistributed. If you're found to be in breach of this license
|
||
# then any affected add-ons will be blacklisted and will not be able to work on the same system
|
||
# as any other add-ons which use this code. Thank you for your cooperation.
|
||
|
||
import os
|
||
import requests
|
||
import shutil
|
||
import xbmc
|
||
import xbmcgui
|
||
|
||
from guitools import Show_Busy
|
||
from systemtools import Last_Error
|
||
|
||
dp = xbmcgui.DialogProgress()
|
||
check_started = xbmc.translatePath('special://profile/addon_data/script.module.python.koding.aio/temp/playback_in_progress')
|
||
#----------------------------------------------------------------
|
||
# TUTORIAL #
|
||
def Check_Playback(ignore_dp=False,timeout=10):
|
||
"""
|
||
This function will return true or false based on video playback. Simply start a stream
|
||
(whether via an add-on, direct link to URL or local storage doesn't matter), the code will
|
||
then work out if playback is successful. This uses a number of checks and should take into
|
||
account all potential glitches which can occur during playback. The return should happen
|
||
within a second or two of playback being successful (or not).
|
||
|
||
CODE: Check_Playback()
|
||
|
||
AVAILABLE PARAMS:
|
||
|
||
ignore_dp - By default this is set to True but if set to False
|
||
this will ignore the DialogProgress window. If you use a DP while
|
||
waiting for the stream to start then you'll want to set this True.
|
||
Please bare in mind the reason this check is in place and enabled
|
||
by default is because some streams do bring up a DialogProgress
|
||
when initiated (such as f4m proxy links) and disabling this check
|
||
in those circumstances can cause false positives.
|
||
|
||
timeout - This is the amount of time you want to allow for playback
|
||
to start before sending back a response of False. Please note if
|
||
ignore_dp is set to True then it will also add a potential 10s extra
|
||
to this amount if a DialogProgress window is open. The default setting
|
||
for this is 10s.
|
||
|
||
EXAMPLE CODE:
|
||
xbmc.Player().play('http://totalrevolution.tv/videos/python_koding/Browse_To_Folder.mov')
|
||
isplaying = koding.Check_Playback()
|
||
if isplaying:
|
||
dialog.ok('PLAYBACK SUCCESSFUL','Congratulations, playback was successful')
|
||
xbmc.Player().stop()
|
||
else:
|
||
dialog.ok('PLAYBACK FAILED','Sorry, playback failed :(')
|
||
~"""
|
||
if not ignore_dp:
|
||
isdialog = True
|
||
counter = 1
|
||
|
||
# Check if the progress window is active and wait for playback
|
||
while isdialog and counter < 60:
|
||
if xbmc.getCondVisibility('Window.IsActive(progressdialog)'):
|
||
try:
|
||
if dp.iscanceled():
|
||
dp.close()
|
||
break
|
||
except:
|
||
pass
|
||
xbmc.log('### Current Window: %s' % xbmc.getInfoLabel('System.CurrentWindow'))
|
||
xbmc.log('### Current XML: %s' % xbmc.getInfoLabel('Window.Property(xmlfile)'))
|
||
xbmc.log('### Progress Dialog active, sleeping for %s seconds' % counter)
|
||
xbmc.sleep(1000)
|
||
if xbmc.getCondVisibility('Window.IsActive(progressdialog)') or (xbmc.getInfoLabel('Window.Property(xmlfile)') == 'DialogProgress.xml'):
|
||
isdialog = True
|
||
else:
|
||
isdialog = False
|
||
counter += 1
|
||
xbmc.log('counter: %s' % counter)
|
||
|
||
# Given the DialogProgress 10 seconds to finish and it's still up - time to close it
|
||
if counter >= 10:
|
||
try:
|
||
xbmc.log('attempting to send click to close dp')
|
||
xbmc.executebuiltin('SendClick()')
|
||
if dp.iscanceled():
|
||
dp.close()
|
||
try:
|
||
dp.close()
|
||
except:
|
||
pass
|
||
except:
|
||
xbmc.log('### FAILED TO CLOSE DP')
|
||
try:
|
||
dp.close()
|
||
except:
|
||
pass
|
||
|
||
isplaying = xbmc.Player().isPlaying()
|
||
counter = 1
|
||
if xbmc.Player().isPlayingAudio():
|
||
return True
|
||
# If xbmc player is not yet active give it some time to initialise
|
||
while not isplaying and counter < timeout:
|
||
xbmc.sleep(1000)
|
||
isplaying = xbmc.Player().isPlaying()
|
||
xbmc.log('### XBMC Player not yet active, sleeping for %s seconds' % counter)
|
||
counter += 1
|
||
|
||
success = 0
|
||
counter = 0
|
||
|
||
# If it's playing give it time to physically start streaming then attempt to pull some info
|
||
if isplaying:
|
||
xbmc.sleep(1000)
|
||
while not success and counter < 5:
|
||
try:
|
||
if xbmc.Player().isPlayingVideo():
|
||
infotag = xbmc.Player().getVideoInfoTag()
|
||
vidtime = xbmc.Player().getTime()
|
||
if vidtime > 0:
|
||
success = 1
|
||
|
||
# If playback doesn't start automatically (buffering) we force it to play
|
||
else:
|
||
xbmc.log('### Playback active but time at zero, trying to unpause')
|
||
xbmc.executebuiltin('PlayerControl(Play)')
|
||
xbmc.sleep(2000)
|
||
vidtime = xbmc.Player().getTime()
|
||
if vidtime > 0:
|
||
success = 1
|
||
|
||
# If no infotag or time could be pulled then we assume playback failed, try and stop the xbmc.player
|
||
except:
|
||
counter += 1
|
||
xbmc.sleep(1000)
|
||
|
||
# Check if the busy dialog is still active from previous locked up playback attempt
|
||
isbusy = xbmc.getCondVisibility('Window.IsActive(busydialog)')
|
||
counter = 1
|
||
while isbusy:
|
||
xbmc.log('### Busy dialog active, sleeping for %ss' % counter)
|
||
xbmc.sleep(1000)
|
||
isbusy = xbmc.getCondVisibility('Window.IsActive(busydialog)')
|
||
counter += 1
|
||
if counter >= 5:
|
||
xbmc.executebuiltin('Dialog.Close(busydialog)')
|
||
|
||
if not success:
|
||
xbmc.executebuiltin('PlayerControl(Stop)')
|
||
xbmc.log('### Failed playback, stopped stream')
|
||
return False
|
||
else:
|
||
return True
|
||
#----------------------------------------------------------------
|
||
# TUTORIAL #
|
||
def Last_Played():
|
||
"""
|
||
Return the link of the last played (or currently playing) video.
|
||
This differs to the built in getPlayingFile command as that only shows details
|
||
of the current playing file, these details can differ to the url which was
|
||
originally sent through to initiate the stream. This Last_Played function
|
||
directly accesses the database to get the REAL link which was initiated and
|
||
will even return the plugin path if it's been played through an external add-on.
|
||
|
||
CODE: Last_Played()
|
||
|
||
EXAMPLE CODE:
|
||
if koding.Play_Video('http://totalrevolution.tv/videos/python_koding/Browse_To_Folder.mov'):
|
||
xbmc.sleep(3000)
|
||
xbmc.Player().stop()
|
||
last_vid = Last_Played()
|
||
dialog.ok('VIDEO LINK','The link we just played is:\n\n%s'%last_vid)
|
||
else:
|
||
dialog.ok('PLAYBACK FAILED','Sorry this video is no longer available, please try using a different video link.')
|
||
~"""
|
||
from database import DB_Query
|
||
from filetools import DB_Path_Check
|
||
from vartools import Decode_String
|
||
db_path = DB_Path_Check('MyVideos')
|
||
sql = "SELECT files.strFilename as mystring, path.strPath as mybase FROM files JOIN path ON files.idPath=path.idPath ORDER BY files.lastPlayed DESC LIMIT 1"
|
||
results = DB_Query(db_path, sql)
|
||
try:
|
||
if Decode_String(results[0]['mybase']).startswith('plugin://'):
|
||
return Decode_String(results[0]['mystring'])
|
||
else:
|
||
return Decode_String(results[0]['mybase']+results[0]['mystring'])
|
||
except:
|
||
return False
|
||
#----------------------------------------------------------------
|
||
# TUTORIAL #
|
||
def Link_Tester(video='', local_check=True, proxy_list=None, proxy_url='https://free-proxy-list.net/', ip_col=0, port_col=1, table=0):
|
||
"""
|
||
Send through a link and test whether or not it's playable on other devices.
|
||
Many links include items in the query string which lock the content down to your
|
||
IP only so what may open fine for you may not open for anyone else!
|
||
|
||
This function will attempt to load the page using a proxy. If when trying to access
|
||
the link via a proxy the header size and content-type match then we assume the
|
||
link will play on any device. This is not fool proof and could potentially return
|
||
false positives depending on the security used on the website being accessed.
|
||
|
||
The return you'll get is a dictionary of the following items:
|
||
|
||
'plugin_path' - This will have the path for a plugin, it means the stream was
|
||
originally passed through an add-on to get the final link. If this is not set
|
||
to None then it "should" work on any device so long as that add-on is installed
|
||
(e.g. YouTube).
|
||
|
||
'url' - This is the final resolved url which Kodi was playing, you need to check
|
||
the status though to find out whether or not that link is locked to your IP only.
|
||
|
||
'status' - This will return one of the following status codes:
|
||
good - The link should work on all IPs.
|
||
|
||
bad_link - The link was not valid, won't even play on your current Kodi setup.
|
||
|
||
proxy_fail - None of the proxies sent through worked.
|
||
|
||
locked - The url only works on this device, if this is the case consider using
|
||
the plugin_path which should generally work on all devices (although this does
|
||
depend on how the developer of that add-on coded up their add-on).
|
||
|
||
CODE: Link_Tester([proxy_list, url, ip_col, port_col, table])
|
||
|
||
AVAILABLE PARAMS:
|
||
|
||
video - This is the url of the video you want to check
|
||
|
||
local_check - By default this is set to True and this function will first of
|
||
all attempt to play the video locally with no proxy just to make sure the
|
||
link is valid in the first place. If you want to skip this step then set
|
||
this to False.
|
||
|
||
proxy_list - If you already have a list of proxies you want to test with
|
||
send them through in the form of a list of dictionaries. Use the following
|
||
format: [{"ip":"0.0.0.0","port":"80"},{"ip":"127.0.0.1","port":"8080"}]
|
||
|
||
proxy_url - If you want to scrape for online proxies and loop through until a
|
||
working one has been found you can set the url here. If using this then
|
||
proxy_list can be left as the default (None). If you open this Link_Tester
|
||
function with no params the defaults are setup to grab from:
|
||
free-proxy-list.net but there is no guarantee this will always
|
||
work, the website may well change it's layout/security over time.
|
||
|
||
ip_col - If you've sent through a proxy_url then you'll need to set a column number
|
||
for where in the table the IP address is stored. The default is 0
|
||
|
||
port_col - If you've sent through a proxy_url then you'll need to set a column number
|
||
for where in the table the port details are stored. The default is 1
|
||
|
||
table - If you've sent through a proxy_url then you'll need to set a table number.
|
||
The default is 0 - this presumes we need to use the first html table found on the
|
||
page, if you require a different table then alter accordingly - remember zero is the
|
||
first instance so if you want the 3rd table on the page you would set to 2.
|
||
|
||
EXAMPLE CODE:
|
||
vid_test = Link_Tester(video='http://totalrevolution.tv/videos/python_koding/Browse_To_Folder.mov')
|
||
if vid_test['status'] == 'bad_link':
|
||
dialog.ok('BAD LINK','The link you sent through cannot even be played on this device let alone another one!')
|
||
elif vid_test['status'] == 'proxy_fail':
|
||
dialog.ok('PROXIES EXHAUSTED','It was not possible to get any working proxies as a result it\'s not possible to fully test whether this link will work on other devices.')
|
||
elif vid_test['status'] == 'locked':
|
||
dialog.ok('NOT PLAYABLE','Although you can play this link locally the tester was unable to play it when using a proxy so this is no good.')
|
||
if vid_test['plugin_path']:
|
||
dialog.ok('THERE IS SOME GOOD NEWS!','Although the direct link for this video won\'t work on other IPs it "should" be possible to open this using the following path:\n[COLOR dodgerblue]%s[/COLOR]'%vid_test['plugin_path'])
|
||
else:
|
||
dialog.ok('WORKING!!!','Congratulations this link can be resolved and added to your playlist.')
|
||
~"""
|
||
import random
|
||
import urllib
|
||
from guitools import Notify
|
||
from vartools import Table_Convert
|
||
from systemtools import System
|
||
# xbmc.executebuiltin('RunScript(special://home/addons/script.module.python.koding.aio/lib/koding/localproxy.py)')
|
||
Notify('PLEASE WAIT','Checking Link - Step 1','5000','Video.png')
|
||
isplaying = xbmc.Player().isPlaying()
|
||
|
||
# If video not yet playing try playing it
|
||
if not isplaying:
|
||
xbmc.Player().play(video)
|
||
|
||
if Check_Playback(True):
|
||
xbmclink = xbmc.Player().getPlayingFile()
|
||
active_plugin = System(command='addonid')
|
||
plugin_path = System(command='currentpath')
|
||
vid_title = ''
|
||
title_count = 0
|
||
|
||
while vid_title == '' and title_count < 10:
|
||
vid_title = xbmc.getInfoLabel('Player.Title')
|
||
xbmc.sleep(100)
|
||
title_count += 1
|
||
|
||
xbmc.Player().stop()
|
||
video_orig = Last_Played()
|
||
xbmc.log('VIDEO: %s'%video_orig,2)
|
||
if video_orig.startswith('plugin://'):
|
||
video = xbmclink
|
||
xbmc.log('NEW VIDEO: %s'%video,2)
|
||
else:
|
||
video = video_orig
|
||
r = requests.head(url=video, timeout=5)
|
||
orig_header = r.headers
|
||
try:
|
||
orig_size = orig_header['Content-Length']
|
||
except:
|
||
orig_size = 0
|
||
try:
|
||
orig_type = orig_header['Content-Type']
|
||
except:
|
||
orig_type = ''
|
||
proxies = Table_Convert(url=proxy_url, contents={"ip":ip_col,"port":port_col}, table=table)
|
||
myproxies = []
|
||
used_proxies = []
|
||
for item in proxies:
|
||
myproxies.append({'http':'http://%s:%s'%(item['ip'],item['port']),'https':'https://%s:%s'%(item['ip'],item['port'])})
|
||
success = False
|
||
if video_orig.startswith('plugin://'):
|
||
dp.create('[COLOR gold]CHECKING PROXIES[/COLOR]','This video is being parsed through another add-on so using the plugin path should work. Now checking the final resolved link...','')
|
||
else:
|
||
dp.create('[COLOR gold]CHECKING PROXIES[/COLOR]','Please wait...','')
|
||
|
||
counter = 1
|
||
while (not success) and (len(myproxies) > 0):
|
||
dp.update(counter/len(myproxies),'Checking proxy %s'%counter)
|
||
counter += 1
|
||
proxychoice = random.choice( range(0,len(myproxies)) )
|
||
currentproxy = myproxies[proxychoice]
|
||
|
||
# Find a working proxy and play the video through it
|
||
try:
|
||
xbmc.log(repr(currentproxy),2)
|
||
r = requests.head(url=video, proxies=currentproxy, timeout=5)
|
||
headers = r.headers
|
||
try:
|
||
new_size = headers['Content-Length']
|
||
except:
|
||
new_size = 0
|
||
try:
|
||
new_type = headers['Content-Type']
|
||
except:
|
||
new_type = ''
|
||
xbmc.log('orig size: %s'%orig_size,2)
|
||
xbmc.log('new size: %s'%new_size,2)
|
||
xbmc.log('orig type: %s'%orig_type,2)
|
||
xbmc.log('new type: %s'%new_type,2)
|
||
xbmc.log('VIDEO: %s'%video,2)
|
||
if orig_size != 0 and (orig_size==new_size) and (orig_type==new_type):
|
||
dp.close()
|
||
success = True
|
||
except:
|
||
xbmc.log('failed with proxy: %s'%currentproxy,2)
|
||
|
||
myproxies.pop(proxychoice)
|
||
if dp.iscanceled():
|
||
dp.close()
|
||
break
|
||
plugin_path = None
|
||
if video_orig.startswith('plugin://'):
|
||
plugin_path = video_orig
|
||
if len(myproxies)==0 and not success:
|
||
return {"plugin_path":plugin_path, "url":video, "status":"proxy_fail"}
|
||
elif not success:
|
||
return {"plugin_path":plugin_path, "url":video, "status":"locked"}
|
||
else:
|
||
return {"plugin_path":plugin_path, "url":video, "status":"good"}
|
||
else:
|
||
return {"plugin_path":None, "url":video, "status":"bad_link"}
|
||
#----------------------------------------------------------------
|
||
# TUTORIAL #
|
||
def M3U_Selector(url,post_type='get',header='Stream Selection'):
|
||
"""
|
||
Send through an m3u/m3u8 playlist and have the contents displayed via a dialog select.
|
||
The return will be a dictionary of 'name' and 'url'. You can send through either
|
||
a locally stored filepath or an online URL.
|
||
|
||
This function will try it's best to pull out the relevant playlist details even if the
|
||
web page isn't a correctly formatted m3u playlist (e.g. an m3u playlist embedded into
|
||
a blog page).
|
||
|
||
CODE: M3U_Selector(url, [post_type, header])
|
||
|
||
AVAILABLE PARAMS:
|
||
(*) url - The location of your m3u file, this can be local or online
|
||
|
||
post_type - If you need to use POST rather than a standard query string
|
||
in your url set this to 'post', by default it's set to 'get'.
|
||
|
||
header - This is the header you want to appear at the top of your dialog
|
||
selection window, by default it's set to "Stream Selection"
|
||
|
||
EXAMPLE CODE:
|
||
dialog.ok('M3U SELECTOR','We will now call this function using the following url:','','[COLOR dodgerblue]http://totalrevolution.tv/videos/playlists/youtube.m3u[/COLOR]')
|
||
|
||
# This example uses YouTube plugin paths but any playable paths will work
|
||
vid = koding.M3U_Selector(url='http://totalrevolution.tv/videos/playlists/youtube.m3u')
|
||
|
||
|
||
# Make sure there is a valid link returned
|
||
if vid:
|
||
playback = koding.Play_Video(video=vid['url'], showbusy=False)
|
||
if playback:
|
||
dialog.ok('SUCCESS!','Congratulations the playback was successful!')
|
||
xbmc.Player().stop()
|
||
else:
|
||
dialog.ok('OOPS!','Looks like something went wrong there, the playback failed. Check the links are still valid.')
|
||
~"""
|
||
from web import Open_URL
|
||
from vartools import Cleanup_String, Find_In_Text
|
||
from filetools import Text_File
|
||
success = False
|
||
if url.startswith('http'):
|
||
content = Open_URL(url=url, post_type=post_type, timeout=10)
|
||
else:
|
||
try:
|
||
url = xbmc.translatePath(url)
|
||
except:
|
||
pass
|
||
content = Text_File(url,'r')
|
||
if content:
|
||
newcontent = content.splitlines()
|
||
name_array = []
|
||
url_array = []
|
||
name = ''
|
||
for line in newcontent:
|
||
line = line.strip()
|
||
# Grab the name of the stream
|
||
if line.startswith('#EXT'):
|
||
name = line.split(',')
|
||
name.pop(0)
|
||
name = ''.join(name)
|
||
# Grab the url(s) of the stream
|
||
if name != '' and line != '' and not line.startswith('#EXT'):
|
||
name_array.append(Cleanup_String(name))
|
||
line = line.replace('<br>','').replace('<br />','').replace('<br/>','')
|
||
line = line.replace('</p>','').replace('</div>','').replace('</class>','')
|
||
xbmc.log('line: %s'%line)
|
||
if 'm3u' in line or 'm3u8' in line:
|
||
line = 'LIST~'+line
|
||
if 'src="' in line:
|
||
line = Find_In_Text(content=line, start='src="', end='"')[0]
|
||
url_array.append(line)
|
||
name = ''
|
||
line = ''
|
||
# If there is only one entry with no names/comments just return as unknown with the link
|
||
if not '#EXT' in content:
|
||
return {'name' : 'Unknown', 'url' : line}
|
||
|
||
# If there's a list we show a dialog select of the available links
|
||
if len(name_array) > 0:
|
||
choice = xbmcgui.Dialog().select(header, name_array)
|
||
if choice >= 0:
|
||
|
||
# If the selection is a final url and not a list of multiple links
|
||
if not url_array[choice].startswith('LIST~'):
|
||
success = True
|
||
return {'name' : name_array[choice], 'url' : url_array[choice]}
|
||
|
||
# List of multiple links detected, give option of which link to play
|
||
else:
|
||
clean_link = url_array[choice].replace('LIST~','')
|
||
content = Open_URL(url=clean_link, timeout=10)
|
||
if content:
|
||
newcontent = content.splitlines()
|
||
name_array = []
|
||
url_array = []
|
||
name = ''
|
||
counter = 1
|
||
for line in newcontent:
|
||
# Show name as link 1,2,3,4 etc.
|
||
if line.startswith('#EXT'):
|
||
name = 'LINK '+str(counter)
|
||
# Grab the link(s) to the video
|
||
if name != '' and line != '' and not line.startswith('#EXT'):
|
||
name_array.append(name)
|
||
line = line.replace('<br>','').replace('<br />','').replace('<br/>','')
|
||
line = line.replace('</p>','').replace('</div>','').replace('</class>','')
|
||
url_array.append(line)
|
||
name = ''
|
||
line = ''
|
||
counter += 1
|
||
# If there is only one entry with no names/comments just return as unknown with the link
|
||
if not '#EXT' in content:
|
||
return {'name' : 'Unknown', 'url' : line}
|
||
|
||
# Give option of which link to play in case of multiple links available
|
||
if len(name_array) > 0:
|
||
choice = xbmcgui.Dialog().select(header, name_array)
|
||
if choice >= 0:
|
||
success = True
|
||
return {'name' : name_array[choice], 'url' : url_array[choice]}
|
||
if not success:
|
||
xbmcgui.Dialog().ok('NO LINKS FOUND','Sorry no valid links could be found for this stream.')
|
||
return False
|
||
#----------------------------------------------------------------
|
||
# TUTORIAL #
|
||
def Play_Video(video,showbusy=True,content='video',ignore_dp=False,timeout=10, item=None, player=xbmc.Player(), resolver=None):
|
||
"""
|
||
This will attempt to play a video and return True or False on
|
||
whether or not playback was successful. This function is similar
|
||
to Check_Playback but this actually tries a number of methods to
|
||
play the video whereas Check_Playback does not actually try to
|
||
play a video - it will just return True/False on whether or not
|
||
a video is currently playing.
|
||
|
||
If you have m3u or m3u8 playlist links please use the M3U_Selector
|
||
function to get the final resolved url.
|
||
|
||
CODE: Play_Video(video, [showbusy, content, ignore_dp, timeout, item])
|
||
|
||
AVAILABLE PARAMS:
|
||
|
||
(*) video - This is the path to the video, this can be a local
|
||
path, online path or a channel number from the PVR.
|
||
|
||
showbusy - By default this is set to True which means while the
|
||
function is attempting to playback the video the user will see the
|
||
busy dialog. Set to False if you prefer this not to appear but do
|
||
bare in mind a user may navigate to another section and try playing
|
||
something else if they think this isn't doing anything.
|
||
|
||
content - By default this is set to 'video', however if you're
|
||
passing through audio you may want to set this to 'music' so the
|
||
system can correctly set the tags for artist, song etc.
|
||
|
||
ignore_dp - By default this is set to True but if set to False
|
||
this will ignore the DialogProgress window. If you use a DP while
|
||
waiting for the stream to start then you'll want to set this True.
|
||
Please bare in mind the reason this check is in place and enabled
|
||
by default is because some streams do bring up a DialogProgress
|
||
when initiated (such as f4m proxy links) and disabling this check
|
||
in those circumstances can cause false positives.
|
||
|
||
timeout - This is the amount of time you want to allow for playback
|
||
to start before sending back a response of False. Please note if
|
||
ignore_dp is set to True then it will also add a potential 10s extra
|
||
to this amount if a DialogProgress window is open. The default setting
|
||
for this is 10s.
|
||
|
||
item - By default this is set to None and in this case the metadata
|
||
will be auto-populated from the previous Add_Dir so you'll just get the
|
||
basics like title, thumb and description. If you want to send through your
|
||
own metadata in the form of a dictionary you can do so and it will override
|
||
the auto-generation. If anything else sent through no metadata will be set,
|
||
you would use this option if you've already set metadata in a previous function.
|
||
|
||
player - By default this is set to xbmc.Player() but you can send through
|
||
a different class/function if required.
|
||
|
||
resolver - By default this is set to urlresolver but if you prefer to use
|
||
your own custom resolver then just send through that class when calling this
|
||
function and the link sent through will be resolved by your custom resolver.
|
||
|
||
EXAMPLE CODE:
|
||
isplaying = koding.Play_Video('http://totalrevolution.tv/videos/python_koding/Browse_To_Folder.mov')
|
||
if isplaying:
|
||
dialog.ok('PLAYBACK SUCCESSFUL','Congratulations, playback was successful')
|
||
xbmc.Player().stop()
|
||
else:
|
||
dialog.ok('PLAYBACK FAILED','Sorry, playback failed :(')
|
||
~"""
|
||
|
||
xbmc.log('### ORIGINAL VIDEO: %s'%video)
|
||
if not resolver:
|
||
import urlresolver
|
||
resolver = urlresolver
|
||
try: import simplejson as json
|
||
except: import json
|
||
|
||
if not item:
|
||
meta = {}
|
||
for i in ['title', 'originaltitle', 'tvshowtitle', 'year', 'season', 'episode', 'genre', 'rating', 'votes',
|
||
'director', 'writer', 'plot', 'tagline']:
|
||
try:
|
||
meta[i] = xbmc.getInfoLabel('listitem.%s' % i)
|
||
except:
|
||
pass
|
||
meta = dict((k, v) for k, v in meta.iteritems() if not v == '')
|
||
if 'title' not in meta:
|
||
meta['title'] = xbmc.getInfoLabel('listitem.label')
|
||
icon = xbmc.getInfoLabel('listitem.icon')
|
||
item = xbmcgui.ListItem(path=video, iconImage =icon, thumbnailImage=icon)
|
||
if content == "music":
|
||
try:
|
||
meta['artist'] = xbmc.getInfoLabel('listitem.artist')
|
||
item.setInfo(type='Music', infoLabels={'title': meta['title'], 'artist': meta['artist']})
|
||
except:
|
||
item.setInfo(type='Video', infoLabels=meta)
|
||
else:
|
||
item.setInfo(type='Video', infoLabels=meta)
|
||
|
||
elif type(item).__name__ == 'dict':
|
||
item.setInfo(type='Video', infoLabels=meta)
|
||
|
||
else:
|
||
pass
|
||
|
||
playback = False
|
||
if showbusy:
|
||
Show_Busy()
|
||
|
||
|
||
# if a plugin path is sent we try activate window
|
||
if video.startswith('plugin://'):
|
||
try:
|
||
xbmc.log('Attempting to play via xbmc.Player().play() method')
|
||
player.play(video)
|
||
playback = Check_Playback(ignore_dp,timeout)
|
||
except:
|
||
xbmc.log(Last_Error())
|
||
|
||
# If an XBMC action has been sent through we do an executebuiltin command
|
||
elif video.startswith('ActivateWindow') or video.startswith('RunAddon') or video.startswith('RunScript') or video.startswith('PlayMedia'):
|
||
try:
|
||
xbmc.log('Attempting to play via xbmc.executebuiltin method')
|
||
xbmc.executebuiltin('%s'%video)
|
||
playback = Check_Playback(ignore_dp,timeout)
|
||
except:
|
||
xbmc.log(Last_Error())
|
||
|
||
elif ',' in video:
|
||
# Standard xbmc.player method (a comma in url seems to throw urlresolver off)
|
||
try:
|
||
xbmc.log('Attempting to play via xbmc.Player.play() method')
|
||
player.play('%s'%video, item)
|
||
playback = Check_Playback(ignore_dp,timeout)
|
||
|
||
# Attempt to resolve via urlresolver
|
||
except:
|
||
try:
|
||
xbmc.log('Attempting to resolve via urlresolver module')
|
||
xbmc.log('video = %s'%video)
|
||
hmf = resolver.HostedMediaFile(url=video, include_disabled=False, include_universal=True)
|
||
if hmf.valid_url() == True:
|
||
video = hmf.resolve()
|
||
xbmc.log('### VALID URL, RESOLVED: %s'%video)
|
||
player.play('%s' % video, item)
|
||
playback = Check_Playback(ignore_dp,timeout)
|
||
except:
|
||
xbmc.log(Last_Error())
|
||
|
||
# Play from a db entry - untested
|
||
elif video.isdigit():
|
||
xbmc.log('### Video is digit, presuming it\'s a db item')
|
||
command = ('{"jsonrpc": "2.0", "id":"1", "method": "Player.Open","params":{"item":{"channelid":%s}}}' % url)
|
||
xbmc.executeJSONRPC(command)
|
||
playback = Check_Playback(ignore_dp,timeout)
|
||
|
||
else:
|
||
# Attempt to resolve via urlresolver
|
||
try:
|
||
xbmc.log('Attempting to resolve via urlresolver module')
|
||
xbmc.log('video = %s'%video)
|
||
hmf = resolver.HostedMediaFile(url=video, include_disabled=False, include_universal=True)
|
||
if hmf.valid_url() == True:
|
||
video = hmf.resolve()
|
||
xbmc.log('### VALID URL, RESOLVED: %s'%video)
|
||
player.play('%s' % video, item)
|
||
playback = Check_Playback(ignore_dp,timeout)
|
||
|
||
# Standard xbmc.player method
|
||
except:
|
||
try:
|
||
xbmc.log('Attempting to play via xbmc.Player.play() method')
|
||
player.play('%s' % video, item)
|
||
playback = Check_Playback(ignore_dp,timeout)
|
||
except:
|
||
xbmc.log(Last_Error())
|
||
|
||
xbmc.log('Playback status: %s' % playback)
|
||
Show_Busy(False)
|
||
counter = 1
|
||
dialogprogress = xbmc.getCondVisibility('Window.IsActive(progressdialog)')
|
||
if not ignore_dp:
|
||
while dialogprogress:
|
||
dp.create('Playback Good','Closing dialog...')
|
||
xbmc.log('Attempting to close dp #%s'%counter)
|
||
dp.close()
|
||
xbmc.sleep(1000)
|
||
counter += 1
|
||
dialogprogress = xbmc.getCondVisibility('Window.IsActive(progressdialog)')
|
||
|
||
return playback
|
||
#----------------------------------------------------------------
|
||
# TUTORIAL #
|
||
def Sleep_If_Playback_Active():
|
||
"""
|
||
This will allow you to pause code while kodi is playing audio or video
|
||
|
||
CODE: Sleep_If_Playback_Active()
|
||
|
||
EXAMPLE CODE:
|
||
dialog.ok('PLAY A VIDEO','We will now attempt to play a video, once you stop this video you should see a dialog.ok message.')
|
||
xbmc.Player().play('http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_720p_stereo.avi')
|
||
xbmc.sleep(3000) # Give kodi enough time to load up the video
|
||
koding.Sleep_If_Playback_Active()
|
||
dialog.ok('PLAYBACK FINISHED','The playback has now been finished so this dialog code has now been initiated')
|
||
~"""
|
||
isplaying = xbmc.Player().isPlaying()
|
||
while isplaying:
|
||
xbmc.sleep(500)
|
||
isplaying = xbmc.Player().isPlaying()
|