Skip to content

Commit

Permalink
Merge pull request #128 from guidosarducci/add-spmc-dash
Browse files Browse the repository at this point in the history
Add support for both addon-based (Kodi 17) and built-in (SPMC 16) MPEG-DASH
  • Loading branch information
jdf76 committed Dec 11, 2016
2 parents da0072c + 31ad48c commit 19c1374
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 53 deletions.
3 changes: 2 additions & 1 deletion addon.xml
Expand Up @@ -6,9 +6,10 @@
<extension point="xbmc.python.pluginsource" library="default.py">
<provides>video</provides>
</extension>
<extension point="xbmc.service" library="startup.py" start="startup" />
<extension point="xbmc.addon.metadata">
<news>
[add] MPEG-DASH support for Kodi 17 w/ inputstream.adaptive Add-on
[add] MPEG-DASH support for Kodi 17 w/ inputstream.adaptive add-on or SPMC 16 w/ builtin-in
[add] optional History and Watch Later custom playlist to Settings -> Folders, or (My)Playlists context menu to set/remove
[add] Maintenance section to Settings
[add] 'Subtitle language(s) to download' selection to Settings -> General
Expand Down
2 changes: 2 additions & 0 deletions resources/lib/kodion/constants/const_settings.py
Expand Up @@ -6,6 +6,8 @@
CACHE_SIZE = 'kodion.cache.size' # (int)
VIDEO_QUALITY = 'kodion.video.quality' # (int)
VIDEO_QUALITY_ASK = 'kodion.video.quality.ask' # (bool)
DASH_SUPPORT_BUILTIN = 'kodion.video.support.mpd.builtin' # (bool)
DASH_SUPPORT_ADDON = 'kodion.video.support.mpd.addon' # (bool)
USE_DASH = 'kodion.video.quality.mpd' # (bool)
SUBTITLE_LANGUAGES = 'kodion.subtitle.languages' # (int)
SETUP_WIZARD = 'kodion.setup_wizard' # (bool)
Expand Down
6 changes: 6 additions & 0 deletions resources/lib/kodion/impl/abstract_settings.py
Expand Up @@ -93,6 +93,12 @@ def is_support_alternative_player_enabled(self):
def use_dash(self):
return self.get_bool(constants.setting.USE_DASH, False)

def dash_support_builtin(self):
return self.get_bool(constants.setting.DASH_SUPPORT_BUILTIN, False)

def dash_support_addon(self):
return self.get_bool(constants.setting.DASH_SUPPORT_ADDON, False)

def subtitle_languages(self):
return self.get_int(constants.setting.SUBTITLE_LANGUAGES, 0)

Expand Down
23 changes: 16 additions & 7 deletions resources/lib/kodion/impl/abstract_system_version.py
Expand Up @@ -2,31 +2,40 @@


class AbstractSystemVersion(object):
def __init__(self, version, name):
def __init__(self, version, releasename, appname):
if not isinstance(version, tuple):
self._version = (0, 0, 0, 0)
else:
self._version = version
pass

if not name or not isinstance(name, basestring):
self._name = 'UNKNOWN'
if not releasename or not isinstance(releasename, basestring):
self._releasename = 'UNKNOWN'
else:
self._name = name
self._releasename = releasename
pass

if not appname or not isinstance(appname, basestring):
self._appname = 'UNKNOWN'
else:
self._appname = appname
pass
pass

def __str__(self):
return unicode(self).encode('utf-8')

def __unicode__(self):
obj_str = "%s (%s)" % (self._name, '.'.join(map(str, self._version)))
obj_str = "%s (%s-%s)" % (self._releasename, self._appname, '.'.join(map(str, self._version)))
return obj_str

def get_name(self):
return self._name
def get_release_name(self):
return self._releasename

def get_version(self):
return self._version

def get_app_name(self):
return self._appname

pass
2 changes: 1 addition & 1 deletion resources/lib/kodion/impl/mock/mock_context.py
Expand Up @@ -21,7 +21,7 @@ def __init__(self, path=u'/', params=None, plugin_name='MOCK Plugin', plugin_id=
5001: u'MOCK Plugin'}

self._ui = None
self._system_version = MockSystemVersion(1, 3, 'Kodion Test System')
self._system_version = MockSystemVersion(1, 3, 'Kodion Test System', 'MOCK App')
self._language = 'en-US'
self._version = '1.9'
pass
Expand Down
4 changes: 2 additions & 2 deletions resources/lib/kodion/impl/mock/mock_system_version.py
Expand Up @@ -4,7 +4,7 @@


class MockSystemVersion(AbstractSystemVersion):
def __init__(self, major, minor, name):
AbstractSystemVersion.__init__(self, (major, minor), name)
def __init__(self, major, minor, releasename, appname):
AbstractSystemVersion.__init__(self, (major, minor), releasename, appname)

pass
27 changes: 14 additions & 13 deletions resources/lib/kodion/impl/xbmc/xbmc_context.py
Expand Up @@ -43,25 +43,26 @@ def __init__(self, path='/', params=None, plugin_name=u'', plugin_id=u'', overri
self._path = urllib.unquote(comps.path).decode('utf-8')

# after that try to get the params
params = sys.argv[2][1:]
if len(params) > 0:
self._uri = self._uri + '?' + params

self._params = {}
params = dict(urlparse.parse_qsl(params))
for _param in params:
item = params[_param]
self._params[_param] = item.decode('utf-8')
if len(sys.argv) > 2:
params = sys.argv[2][1:]
if len(params) > 0:
self._uri = self._uri + '?' + params

self._params = {}
params = dict(urlparse.parse_qsl(params))
for _param in params:
item = params[_param]
self._params[_param] = item.decode('utf-8')
pass
pass
pass
pass

self._ui = None
self._video_playlist = None
self._audio_playlist = None
self._video_player = None
self._audio_player = None
self._plugin_handle = int(sys.argv[1])
self._plugin_handle = int(sys.argv[1]) if len(sys.argv) > 1 else None
self._plugin_id = plugin_id or self._addon.getAddonInfo('id')
self._plugin_name = plugin_name or self._addon.getAddonInfo('name')
self._version = self._addon.getAddonInfo('version')
Expand Down Expand Up @@ -105,7 +106,7 @@ def get_language(self):
return 'en-US'

"""
if self.get_system_version().get_name() == 'Frodo':
if self.get_system_version().get_release_name() == 'Frodo':
return 'en-US'
try:
Expand All @@ -121,7 +122,7 @@ def get_language(self):

def get_system_version(self):
if not self._system_version:
self._system_version = XbmcSystemVersion(version='', name='')
self._system_version = XbmcSystemVersion(version='', releasename='', appname='')
pass

return self._system_version
Expand Down
2 changes: 1 addition & 1 deletion resources/lib/kodion/impl/xbmc/xbmc_items.py
Expand Up @@ -26,7 +26,7 @@ def to_video_item(context, video_item):
item.addContextMenuItems(video_item.get_context_menu(), replaceItems=video_item.replace_context_menu())
pass

if video_item.use_dash():
if video_item.use_dash() and settings.dash_support_addon():
item.setProperty('inputstreamaddon', 'inputstream.adaptive')
item.setProperty('inputstream.adaptive.manifest_type', 'mpd')

Expand Down
27 changes: 14 additions & 13 deletions resources/lib/kodion/impl/xbmc/xbmc_system_version.py
Expand Up @@ -6,39 +6,40 @@


class XbmcSystemVersion(AbstractSystemVersion):
def __init__(self, version, name):
super(XbmcSystemVersion, self).__init__(version, name)
def __init__(self, version, releasename, appname):
super(XbmcSystemVersion, self).__init__(version, releasename, appname)
try:
json_query = xbmc.executeJSONRPC(
'{ "jsonrpc": "2.0", "method": "Application.GetProperties", "params": {"properties": ["version", "name"]}, "id": 1 }')
json_query = unicode(json_query, 'utf-8', errors='ignore')
json_query = json.loads(json_query)
version_installed = []
if 'result' in json_query and 'version' in json_query['result']:
version_installed = json_query['result']['version']
self._version = (version_installed.get('major', 1), version_installed.get('minor', 0))
pass
version_installed = json_query['result']['version']
self._version = (version_installed.get('major', 1), version_installed.get('minor', 0))
self._appname = json_query['result']['name']
pass
except:
self._version = (1, 0) # Frodo
self._appname = 'Unknown Application'
pass
self._name = 'Unknown XBMC System'
self._releasename = 'Unknown XBMC Release'
if self._version >= (12, 0):
self._name = 'Frodo'
self._releasename = 'Frodo'
pass
if self._version >= (13, 0):
self._name = 'Gotham'
self._releasename = 'Gotham'
pass
if self._version >= (14, 0):
self._name = 'Helix'
self._releasename = 'Helix'
pass
if self._version >= (15, 0):
self._name = 'Isengard'
self._releasename = 'Isengard'
pass
if self._version >= (16, 0):
self._name = 'Jarvis'
self._releasename = 'Jarvis'
pass
if self._version >= (17, 0):
self._name = 'Krypton'
self._releasename = 'Krypton'
pass

pass
22 changes: 9 additions & 13 deletions resources/lib/youtube/helper/video_info.py
Expand Up @@ -595,17 +595,15 @@ def _method_get_video_info(self, video_id):
pass
"""

if self._context.get_settings().use_dash():
major_version = self._context.get_system_version().get_version()[0]
if major_version > 16:
use_dash = True
if not self._context.addon_enabled('inputstream.adaptive'):
if self._context.get_ui().on_yes_no_input(self._context.get_name(), self._context.localize(30579)):
use_dash = self._context.set_addon_enabled('inputstream.adaptive')
else:
use_dash = False
else:
use_dash = False
settings = self._context.get_settings()
use_dash = settings.use_dash()

if use_dash:
if settings.dash_support_addon() and not self._context.addon_enabled('inputstream.adaptive'):
if self._context.get_ui().on_yes_no_input(self._context.get_name(), self._context.localize(30579)):
use_dash = self._context.set_addon_enabled('inputstream.adaptive')
else:
use_dash = False

if use_dash:
mpd_url = params.get('dashmpd', None)
Expand All @@ -623,8 +621,6 @@ def _method_get_video_info(self, video_id):
video_stream.update(self.FORMAT.get('9999'))
stream_list.append(video_stream)
return stream_list
else:
self._context.get_settings().set_bool('kodion.video.quality.mpd', False)

added_subs = False # avoid repeat calls from loop or cipher signature
# extract streams from map
Expand Down
6 changes: 4 additions & 2 deletions resources/settings.xml
Expand Up @@ -6,8 +6,10 @@
<!-- kodion Visual -->
<setting id="kodion.video.quality" type="enum" label="30010" enable="eq(1,false)" lvalues="30016|30017|30011|30012|30018" default="3"/>
<setting id="kodion.video.quality.ask" type="bool" label="30009" default="false"/>
<setting id="kodion.video.quality.mpd" type="bool" label="30007" default="false" enable="System.HasAddon(inputstream.adaptive)"/>
<setting id="kodion.video.quality.mpd.configure" type="action" label="30008" enable="eq(-1,true)" visible="eq(-1,true)" option="close" action="RunPlugin(plugin://plugin.video.youtube/config/mpd/)"/>
<setting id="kodion.video.support.mpd.builtin" type="bool" label="" visible="false" enable="true" default="false"/>
<setting id="kodion.video.support.mpd.addon" type="bool" label="" visible="false" enable="true" default="false"/>
<setting id="kodion.video.quality.mpd" type="bool" label="30007" default="false" enable="eq(-1,true)|eq(-2,true)"/>
<setting id="kodion.video.quality.mpd.configure" type="action" label="30008" enable="eq(-1,true)+eq(-2,true)" visible="eq(-1,true)+eq(-2,true)" option="close" action="RunPlugin(plugin://plugin.video.youtube/config/mpd/)"/>
<setting id="kodion.subtitle.languages" type="enum" label="30560" lvalues="30561|30562|30563|30564|30565|30566" default="0"/>
<setting id="youtube.playlist.watchlater.autoremove" type="bool" label="30515" default="true" />
<setting type="sep" />
Expand Down
27 changes: 27 additions & 0 deletions startup.py
@@ -0,0 +1,27 @@
__author__ = 'bromix'

from resources.lib.kodion.impl import Context
from resources.lib.kodion.constants import setting

if __name__ == '__main__':
context = Context()

context.log_debug('YouTube settings startup initialization...')
version = context.get_system_version().get_version()
application = context.get_system_version().get_app_name()
settings = context.get_settings()

mpd_addon = False
mpd_builtin = False

if version >= (17, 0):
mpd_addon = True
elif version >= (16, 5) and application == 'SPMC':
mpd_builtin = True
else:
settings.set_bool(setting.USE_DASH, False)

settings.set_bool(setting.DASH_SUPPORT_BUILTIN, mpd_builtin)
settings.set_bool(setting.DASH_SUPPORT_ADDON, mpd_addon)
context.log_notice('Startup: detected %s, setting DASH_SUPPORT_BUILTIN = %s, DASH_SUPPORT_ADDON = %s' %
(context.get_system_version(), mpd_builtin, mpd_addon))

0 comments on commit 19c1374

Please sign in to comment.