def check_inputstream_addon(): try: addon_enabled = control.addon_details('inputstream.adaptive').get('enabled') except KeyError: addon_enabled = False leia_plus = control.kodi_version() >= 18.0 first_time_file = control.join(control.dataPath, 'first_time') if not addon_enabled and not file_exists(first_time_file) and leia_plus: try: yes = control.yesnoDialog(control.lang(30014)) if yes: control.enable_addon('inputstream.adaptive') control.infoDialog(control.lang(30402)) with open(first_time_file, 'a'): pass except Exception: pass
def play(self, url, query=None, resolved_mode=True): if url in [self.live_link_cy, self.live_link_gr]: title = 'Alpha' icon = control.icon() elif query: title = query icon = control.addonmedia('news.png') else: title = None icon = None stream = self.resolve(url) meta = {'title': title} dash = 'm3u8' in stream and control.kodi_version() >= 18.0 directory.resolve( url=stream, meta=meta, dash=dash, icon=icon, mimetype='application/vnd.apple.mpegurl' if '.m3u8' in stream else None, manifest_type='hls' if '.m3u8' in stream else None, resolved_mode=resolved_mode )
def play(url): try: addon_enabled = control.addon_details('inputstream.adaptive').get( 'enabled') except KeyError: addon_enabled = False mimetype = None manifest_type = None leia_plus = control.kodi_version() >= 18.0 stream = resolve(url) if '.m3u8' in stream: manifest_type = 'hls' mimetype = 'application/vnd.apple.mpegurl' elif '.mpd' in stream: manifest_type = 'mpd' dash = addon_enabled and ('.m3u8' in stream or '.mpd' in stream) directory.resolve(stream, dash=dash and leia_plus, mimetype=mimetype, manifest_type=manifest_type)
def install(): if control.conditional_visibility('System.Platform.Linux') and not ( path.exists(control.transPath(xbmc_path)) or path.exists(control.transPath(home_path))): control.okDialog(heading='AliveGR', line1=control.lang(30323)) return False elif path.exists(control.transPath(xbmc_path)) or path.exists( control.transPath(home_path)): return True elif control.kodi_version() >= 18.0 and not control.condVisibility( 'System.HasAddon(pvr.iptvsimple)'): control.execute('InstallAddon(pvr.iptvsimple)') return True elif control.condVisibility('System.HasAddon(pvr.iptvsimple)'): return 'enabled' else: return False
def set_controls(self): # Username label self.username_label = pyxbmct.Label(control.lang(30152)) self.placeControl(self.username_label, 0, 0) # Username input self.user_input = pyxbmct.Edit(control.lang(30152)) self.placeControl(self.user_input, 1, 0) # Password label self.password_label = pyxbmct.Label(control.lang(30153)) self.placeControl(self.password_label, 2, 0) # Password input if control.kodi_version() >= 18.0: self.pass_input = pyxbmct.Edit(control.lang(30153)) self.placeControl(self.pass_input, 3, 0) self.pass_input.setType(6, control.lang(30153)) else: self.pass_input = pyxbmct.Edit(control.lang(30153), isPassword=True) self.placeControl(self.pass_input, 3, 0) # Submit button self.submit_button = pyxbmct.Button(control.lang(30154)) self.placeControl(self.submit_button, 4, 0) self.connect(self.submit_button, lambda: self.submit(True)) # Cancel button self.cancel_button = pyxbmct.Button(control.lang(30064)) self.placeControl(self.cancel_button, 5, 0) self.connect(self.cancel_button, self.close)
def stations(self): self.list = self.get_stations() if self.list is None: return self.list = sorted(self.list, key=lambda k: k['album'].lower()) for item in self.list: refresh = {'title': 30015, 'query': {'action': 'refresh'}} cache_clear = {'title': 30002, 'query': {'action': 'cache_clear'}} info_cm = {'title': 30020, 'query': {'action': 'info_cm'}} station_info = { 'title': 30016, 'query': { 'action': 'description', 'text': item['comment'] } } history = { 'title': 30017, 'query': { 'action': 'history', 'url': item['history'] } } if control.kodi_version() < 17.0: item.update({ 'cm': [refresh, cache_clear, history], 'action': 'play', 'isFolder': 'False' }) else: item.update({ 'cm': [refresh, cache_clear, history, station_info, info_cm], 'action': 'play', 'isFolder': 'False' }) for count, item in list(enumerate(self.list, start=1)): item.setdefault('tracknumber', count) control.sortmethods() control.sortmethods('album') control.sortmethods('genre') control.sortmethods('listeners') directory.add(self.list, infotype='music')
def play(url): if not any(['.m3u8' in url, '.mpd' in url, 'radiostreaming' in url]): url = resolve(url) dash = ('.m3u8' in url or '.mpd' in url) and control.kodi_version() >= 18.0 directory.resolve( url, dash=dash, mimetype='application/vnd.apple.mpegurl' if 'm3u8' in url else None, manifest_type='hls' if 'm3u8' in url else None)
def rtmp_enable(): if control.kodi_version() < 17.0: control.infoDialog(control.lang(30322)) return try: enabled = control.addon_details('inputstream.rtmp').get('enabled') except Exception: enabled = False try: if enabled: control.infoDialog(control.lang(30276)) return else: xbmc_path = control.join('special://xbmc', 'addons', 'inputstream.rtmp') home_path = control.join('special://home', 'addons', 'inputstream.rtmp') if path.exists(control.transPath(xbmc_path)) or path.exists( control.transPath(home_path)): yes = control.yesnoDialog(control.lang(30277)) if yes: control.enable_addon('inputstream.rtmp') control.infoDialog(control.lang(30402)) else: try: control.execute('InstallAddon(inputstream.rtmp)') except Exception: control.okDialog(heading='AliveGR', line1=control.lang(30323)) except Exception: control.infoDialog(control.lang(30279))
def play(self, url): if control.setting('debug') == 'false': stream = cache.get(self.resolve, 96, url) else: stream = self.resolve(url) if stream is None: return m3u8_dash = 'm3u8' in stream and control.kodi_version() >= 18.0 directory.resolve( stream, dash=any(['.mpd' in stream, m3u8_dash]), mimetype='application/vnd.apple.mpegurl' if m3u8_dash else None, manifest_type='hls' if m3u8_dash else None )
def play(url): if '.m3u8' not in url: url = resolve(url) dash = ('.m3u8' in url or '.mpd' in url) and control.kodi_version() >= 18.0 meta = None if url == LIVE_LINK: meta = {'title': 'ANT1'} directory.resolve( url, dash=dash, meta=meta, mimetype='application/vnd.apple.mpegurl' if 'm3u8' in url else None, manifest_type='hls' if 'm3u8' in url else None )
def play(self, url): resolved = self.resolve(url) if 'youtu' in resolved: resolved = self.yt_session(resolved) if isinstance(resolved, tuple): stream, plot = resolved meta = {'plot': plot} else: stream = resolved meta = None icon = None if url == self.radio_link: meta = {'title': 'Skai Radio 100.3FM'} elif url == self.live_link: meta = {'title': 'Skai Live TV'} icon = control.icon() dash = ('dash' in stream or '.mpd' in stream or 'm3u8' in stream) and control.kodi_version() >= 18.0 directory.resolve(url=stream, meta=meta, dash=dash, icon=icon, mimetype='application/vnd.apple.mpegurl' if 'm3u8' in stream else None, manifest_type='hls' if '.m3u8' in stream else None)
def play(self, url): if '.mp4' in url or '.m3u8' in url: stream = url else: html = client.request(url) stream = re.search("video/mp4.+?'(.+?)'", html, re.S).group(1) try: addon_enabled = control.addon_details('inputstream.adaptive').get('enabled') except KeyError: addon_enabled = False dash = '.m3u8' in url and control.kodi_version() >= 18.0 and addon_enabled and control.setting('hls_dash') == 'true' if dash: directory.resolve(stream, dash=dash, mimetype='application/vnd.apple.mpegurl', manifest_type='hls') else: directory.resolve(stream)
def play(self, url): resolved = self.resolve(url) if 'youtu' in resolved: resolved = self.yt_session(resolved) if isinstance(resolved, tuple): stream, plot = resolved meta = {'plot': plot} else: stream = resolved meta = None icon = None if url == self.live_link: icon = { 'poster': control.icon(), 'icon': control.icon(), 'thumb': control.icon() } dash = ('dash' in stream or '.mpd' in stream or 'm3u8' in stream) and control.kodi_version() >= 18.0 directory.resolve(url=stream, meta=meta, dash=dash, icon=icon, mimetype='application/vnd.apple.mpegurl' if 'm3u8' in stream else None, manifest_type='hls' if '.m3u8' in stream else None)
def live(self): lang = 'www' if self.lang == 'en' else self.lang stream = self.resolve_live(lang=lang) if control.setting( 'quality_live') == '2' and control.kodi_version() >= 18.0: dash = True manifest_type = 'hls' mimetype = 'application/vnd.apple.mpegurl' else: dash = False manifest_type = None mimetype = None directory.resolve(stream, meta={'title': 'Euronews'}, dash=dash, manifest_type=manifest_type, mimetype=mimetype)
def resolve(url, meta=None, icon=None, dash=False, manifest_type=None, inputstream_type='adaptive', headers=None, mimetype=None, resolved_mode=True, live=False, verify=True): """ Prepares a resolved url into a listitem for playback :param url: Requires a string or unicode, append required urlencoded headers with pipe | :param meta: a dictionary with listitem keys: values :param icon: String :param dash: Boolean :param manifest_type: String :param inputstream_type: String 99.9% of the time it is adaptive :param headers: dictionary or urlencoded string :param mimetype: String :return: None """ from tulip.init import syshandle # Fail gracefully instead of making Kodi complain. if not url: from kodi_six.xbmc import log log('URL was not provided, failure to resolve stream') return if not headers and '|' in url: url, sep, headers = url.rpartition('|') elif headers: if isinstance(headers, basestring): if headers.startswith('|'): headers = headers[1:] elif isinstance(headers, dict): headers = urlencode(headers) if not verify and 'verifypeer' not in headers: if headers: headers += '&verifypeer=false' else: headers = 'verifypeer=false' if not dash and headers: url = '|'.join([url, headers]) item = control.item(path=url) if icon is not None: item.setArt({'icon': icon, 'thumb': icon}) if meta is not None: item.setInfo(type='Video', infoLabels=meta) krypton_plus = control.kodi_version() >= 17.0 try: isa_enabled = control.addon_details('inputstream.adaptive').get( 'enabled') except KeyError: isa_enabled = False if dash and krypton_plus and isa_enabled: if not manifest_type: manifest_type = 'mpd' if not mimetype: mimetype = 'application/xml+dash' item.setContentLookup(False) item.setMimeType('{0}'.format(mimetype)) item.setProperty('inputstreamaddon', 'inputstream.{}'.format(inputstream_type)) item.setProperty( 'inputstream.{0}.manifest_type'.format(inputstream_type), manifest_type) if headers: item.setProperty( "inputstream.{0}.stream_headers".format(inputstream_type), headers) elif mimetype: item.setContentLookup(False) item.setMimeType('{0}'.format(mimetype)) if dash and live: item.setProperty( 'inputstream.{}.manifest_update_parameter'.format( inputstream_type), '&start_seq=$START_NUMBER$') if resolved_mode: control.resolve(syshandle, True, item) else: control.player().play(url, item)
def run(self, query=None): if 'Greek' not in str(self.langs).split(','): control.directory(self.syshandle) control.infoDialog(control.lang(30002)) return if not control.conditional_visibility( 'System.HasAddon(script.module.futures)') and is_py2: if 17.0 <= control.kodi_version() <= 18.9: control.execute('InstallAddon(script.module.futures)') control.sleep(1500) elif 16.0 <= control.kodi_version() <= 16.2: control.okDialog('Subtitles.gr', control.lang(30229)) return dup_removal = False if not query: with concurrent.futures.ThreadPoolExecutor(5) as executor: if control.condVisibility('Player.HasVideo'): infolabel_prefix = 'VideoPlayer' else: infolabel_prefix = 'ListItem' title = control.infoLabel('{0}.Title'.format(infolabel_prefix)) if re.search(r'[^\x00-\x7F]+', title) is not None: title = control.infoLabel( '{0}.OriginalTitle'.format(infolabel_prefix)) title = unicodedata.normalize('NFKD', title).encode('ascii', 'ignore') title = py3_dec(title) year = control.infoLabel('{0}.Year'.format(infolabel_prefix)) tvshowtitle = control.infoLabel( '{0}.TVshowtitle'.format(infolabel_prefix)) season = control.infoLabel( '{0}.Season'.format(infolabel_prefix)) if len(season) == 1: season = '0' + season episode = control.infoLabel( '{0}.Episode'.format(infolabel_prefix)) if len(episode) == 1: episode = '0' + episode if 's' in episode.lower(): season, episode = '0', episode[-1:] if tvshowtitle != '': # episode title_query = '{0} {1}'.format(tvshowtitle, title) season_episode_query = '{0} S{1} E{2}'.format( tvshowtitle, season, episode) season_episode_query_nospace = '{0} S{1}E{2}'.format( tvshowtitle, season, episode) threads = [ executor.submit(self.subtitlesgr, season_episode_query_nospace), executor.submit(self.xsubstv, season_episode_query), executor.submit(self.podnapisi, season_episode_query), executor.submit(self.vipsubs, season_episode_query) ] dup_removal = True log_debug('Dual query used for subtitles search: ' + title_query + ' / ' + season_episode_query) if control.setting('queries') == 'true': threads.extend([ executor.submit(self.subtitlesgr, title_query), executor.submit(self.vipsubs, title_query), executor.submit(self.podnapisi, title_query), executor.submit(self.subtitlesgr, season_episode_query) ]) elif year != '': # movie query = '{0} ({1})'.format(title, year) threads = [ executor.submit(self.subtitlesgr, query), executor.submit(self.xsubstv, query), executor.submit(self.vipsubs, query), executor.submit(self.podnapisi, query) ] else: # file query, year = control.cleanmovietitle(title) if year != '': query = '{0} ({1})'.format(query, year) threads = [ executor.submit(self.subtitlesgr, query), executor.submit(self.xsubstv, query), executor.submit(self.vipsubs, query), executor.submit(self.podnapisi, query) ] for future in concurrent.futures.as_completed(threads): item = future.result() if not item: continue self.list.extend(item) if not dup_removal: log_debug('Query used for subtitles search: ' + query) self.query = query self.query = py3_dec(self.query) else: with concurrent.futures.ThreadPoolExecutor(5) as executor: query = py3_dec(query) threads = [ executor.submit(self.subtitlesgr, query), executor.submit(self.xsubstv, query), executor.submit(self.vipsubs, query), executor.submit(self.podnapisi, query) ] for future in concurrent.futures.as_completed(threads): item = future.result() if not item: continue self.list.extend(item) if len(self.list) == 0: control.directory(self.syshandle) return f = [] # noinspection PyUnresolvedReferences f += [i for i in self.list if i['source'] == 'xsubstv'] f += [i for i in self.list if i['source'] == 'subtitlesgr'] f += [i for i in self.list if i['source'] == 'podnapisi'] f += [i for i in self.list if i['source'] == 'vipsubs'] self.list = f if dup_removal: self.list = [ dict(t) for t in {tuple(d.items()) for d in self.list} ] for i in self.list: try: if i['source'] == 'xsubstv': i['name'] = u'[xsubstv] {0}'.format(i['name']) elif i['source'] == 'podnapisi': i['name'] = u'[podnapisi] {0}'.format(i['name']) elif i['source'] == 'vipsubs': i['name'] = u'[vipsubs] {0}'.format(i['name']) except Exception: pass if control.setting('sorting') == '1': key = 'source' elif control.setting('sorting') == '2': key = 'downloads' elif control.setting('sorting') == '3': key = 'rating' else: key = 'title' self.list = sorted(self.list, key=lambda k: k[key].lower(), reverse=control.setting('sorting') in ['1', '2', '3']) for i in self.list: u = {'action': 'download', 'url': i['url'], 'source': i['source']} u = '{0}?{1}'.format(self.sysaddon, urlencode(u)) item = control.item(label='Greek', label2=i['name']) item.setArt({'icon': str(i['rating'])[:1], 'thumb': 'el'}) item.setProperty('sync', 'false') item.setProperty('hearing_imp', 'false') control.addItem(handle=self.syshandle, url=u, listitem=item, isFolder=False) control.directory(self.syshandle)
def info(self): separator = '[CR]' if control.setting('wrap_labels') == '0' else ' ' try: disclaimer = control.addonInfo('disclaimer').decode('utf-8') except (UnicodeEncodeError, UnicodeDecodeError, AttributeError): disclaimer = control.addonInfo('disclaimer') self.list = [ { 'title': control.lang(30331), 'action': 'welcome', 'icon': control.addonInfo('icon'), 'isFolder': 'False', 'isPlayable': 'False' } , { 'title': control.lang(30105), 'action': 'dmca', 'plot': disclaimer, 'icon': control.addonmedia( addonid=ART_ID, theme='icons', icon='dmca.png', media_subfolder=False ), 'isFolder': 'False', 'isPlayable': 'False' } , { 'title': control.lang(30290), 'action': 'pp', 'isFolder': 'False', 'isPlayable': 'False' } , { 'title': control.lang(30295), 'action': 'toggle_debug', 'isFolder': 'False', 'isPlayable': 'False' } , { 'title': control.lang(30341), 'action': 'kodi_log_upload', 'isFolder': 'False', 'isPlayable': 'False' } , { 'title': control.lang(30296), 'action': 'force', 'isFolder': 'False', 'isPlayable': 'False' } , { 'title': control.lang(30260).format(separator), 'action': 'open_link', 'url': SUPPORT, 'plot': 'Git repo', 'icon': control.addonmedia( addonid=ART_ID, theme='icons', icon='bitbucket.png', media_subfolder=False ), 'isFolder': 'False', 'isPlayable': 'False' } , { 'title': control.lang(30141) + ': [COLOR cyan]' + PAYPAL + '[/COLOR]', 'action': 'open_link', 'url': PAYPAL, 'isFolder': 'False', 'isPlayable': 'False' } , { 'title': control.lang(30142) + ': [COLOR cyan]' + PATREON + '[/COLOR]', 'action': 'open_link', 'url': PATREON, 'isFolder': 'False', 'isPlayable': 'False' } , { 'title': control.lang(30256).format(separator, control.addonInfo('version')), 'action': 'force', 'plot': control.lang(30265), 'icon': control.addonInfo('icon'), 'isFolder': 'False', 'isPlayable': 'False' } , { 'title': control.lang(30257).format(separator, control.addon('script.module.tulip').getAddonInfo('version')), 'action': 'force', 'plot': control.lang(30265), 'icon': control.addon('script.module.tulip').getAddonInfo('icon'), 'isFolder': 'False', 'isPlayable': 'False' } # , # { # 'title': control.lang(30294).format(separator, control.addon('script.module.streamlink.base').getAddonInfo('version')), # 'action': 'force', # 'image': control.addon('script.module.streamlink.base').getAddonInfo('icon'), # 'plot': control.lang(30265), # 'isFolder': 'False', # 'isPlayable': 'False' # } , { 'title': control.lang(30258).format(separator, control.kodi_version()), 'action': 'system_info', 'plot': control.lang(30263), 'icon': control.addonmedia(addonid=ART_ID, theme='icons', icon='kodi.png', media_subfolder=False), 'isFolder': 'False', 'isPlayable': 'False' } ] try: rurl_enabled = control.addon_details('script.module.resolveurl').get('enabled') except Exception: rurl_enabled = False if rurl_enabled: resolveurl = { 'title': control.lang(30264).format(separator, control.addon('script.module.resolveurl').getAddonInfo('version')), 'action': 'other_addon_settings', 'query': 'script.module.resolveurl', 'plot': control.lang(30265), 'icon': control.addon('script.module.resolveurl').getAddonInfo('icon'), 'isFolder': 'False', 'isPlayable': 'False' } self.list.insert(-2, resolveurl) directory.add(self.list, content='movies')
def info(self): separator = '[CR]' if control.setting('wrap_labels') == '0' else ' ' try: disclaimer = control.addonInfo('disclaimer').decode('utf-8') except (UnicodeEncodeError, UnicodeDecodeError, AttributeError): disclaimer = control.addonInfo('disclaimer') self.list = [ { 'title': control.lang(30331), 'action': 'welcome', 'icon': control.addonInfo('icon'), 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': control.lang(30105), 'action': 'dmca', 'plot': disclaimer, 'icon': control.addonmedia(addonid=ART_ID, theme='icons', icon='dmca.png', media_subfolder=False), 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': control.lang(30290), 'action': 'pp', 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': '[B]' + control.lang(30110) + '[/B]', 'action': 'changelog', 'icon': control.addonInfo('icon'), 'plot': changelog(get_text=True), 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': control.lang(30295), 'action': 'toggle_debug', 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': control.lang(30341), 'action': 'kodi_log_upload', 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': control.lang(30296), 'action': 'force', 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': control.lang(30260).format(separator), 'action': 'open_link', 'url': SUPPORT, 'plot': 'Git repo', 'icon': control.addonmedia(addonid=ART_ID, theme='icons', icon='bitbucket.png', media_subfolder=False), 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': control.lang(30141) + ': [COLOR cyan]' + PAYPAL + '[/COLOR]', 'action': 'open_link', 'url': PAYPAL, 'isFolder': 'False', 'isPlayable': 'False' } # , # { # 'title': control.lang(30142) + ': [COLOR cyan]' + PATREON + '[/COLOR]', # 'action': 'open_link', # 'url': PATREON, # 'isFolder': 'False', # 'isPlayable': 'False' # } , { 'title': control.lang(30256).format(separator, control.addonInfo('version')), 'action': 'force', 'plot': control.lang(30265), 'icon': control.addonInfo('icon'), 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': control.lang(30257).format( separator, control.addon('script.module.tulip').getAddonInfo( 'version')), 'action': 'force', 'plot': control.lang(30265), 'icon': control.addon('script.module.tulip').getAddonInfo('icon'), 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': control.lang(30264).format( separator, control.addon('script.module.resolveurl').getAddonInfo( 'version')), 'action': 'other_addon_settings', 'query': 'script.module.resolveurl', 'plot': control.lang(30265), 'icon': control.addon('script.module.resolveurl').getAddonInfo('icon'), 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': control.lang(30258).format(separator, control.kodi_version()), 'action': 'system_info', 'plot': control.lang(30263), 'icon': control.addonmedia(addonid=ART_ID, theme='icons', icon='kodi.png', media_subfolder=False), 'isFolder': 'False', 'isPlayable': 'False' }, { 'title': control.lang(30303).format( separator, '.'.join([ str(sys.version_info[0]), str(sys.version_info[1]), str(sys.version_info[2]) ])), 'action': 'system_info', 'plot': control.lang(30263), 'image': 'https://www.python.org/static/opengraph-icon-200x200.png', 'isFolder': 'False', 'isPlayable': 'False' } ] directory.add(self.list, content='movies')