Merge pull request #1648 from croneter/python3-beta

Bump Python 3 master
This commit is contained in:
croneter 2021-10-04 15:43:17 +02:00 committed by GitHub
commit 2d636d8e08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 122 additions and 90 deletions

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="3.5.0" provider-name="croneter"> <addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="3.5.2" provider-name="croneter">
<requires> <requires>
<import addon="xbmc.python" version="3.0.0"/> <import addon="xbmc.python" version="3.0.0"/>
<import addon="script.module.requests" version="2.22.0+matrix.1" /> <import addon="script.module.requests" version="2.22.0+matrix.1" />
@ -91,7 +91,16 @@
<summary lang="ko_KR">Plex를 Kodi에 기본 통합</summary> <summary lang="ko_KR">Plex를 Kodi에 기본 통합</summary>
<description lang="ko_KR">Kodi를 Plex Media Server에 연결합니다. 이 플러그인은 Plex로 모든 비디오를 관리하고 Kodi로는 관리하지 않는다고 가정합니다. Kodi 비디오 및 음악 데이터베이스에 이미 저장된 데이터가 손실 될 수 있습니다 (이 플러그인이 직접 변경하므로). 자신의 책임하에 사용하십시오!</description> <description lang="ko_KR">Kodi를 Plex Media Server에 연결합니다. 이 플러그인은 Plex로 모든 비디오를 관리하고 Kodi로는 관리하지 않는다고 가정합니다. Kodi 비디오 및 음악 데이터베이스에 이미 저장된 데이터가 손실 될 수 있습니다 (이 플러그인이 직접 변경하므로). 자신의 책임하에 사용하십시오!</description>
<disclaimer lang="ko_KR">자신의 책임하에 사용</disclaimer> <disclaimer lang="ko_KR">자신의 책임하에 사용</disclaimer>
<news>version 3.5.0: <news>version 3.5.2:
- version 3.5.1 for everyone
version 3.5.1 (beta only):
- Refactor stream code and fix Kodi not activating subtitle when it should
- Direct Paths: Fix TypeError: "element indices must be integers" on playback startup
- Android: Fix broken Python multiprocessing module (a Kodi 19.2 bug)
- Fix logging if fanart.tv lookup fails: be less verbose
version 3.5.0:
- versions 3.4.5-3.4.7 for everyone - versions 3.4.5-3.4.7 for everyone
version 3.4.7 (beta only): version 3.4.7 (beta only):

View file

@ -1,3 +1,12 @@
version 3.5.2:
- version 3.5.1 for everyone
version 3.5.1 (beta only):
- Refactor stream code and fix Kodi not activating subtitle when it should
- Direct Paths: Fix TypeError: "element indices must be integers" on playback startup
- Android: Fix broken Python multiprocessing module (a Kodi 19.2 bug)
- Fix logging if fanart.tv lookup fails: be less verbose
version 3.5.0: version 3.5.0:
- versions 3.4.5-3.4.7 for everyone - versions 3.4.5-3.4.7 for everyone

View file

@ -223,7 +223,11 @@ class DownloadUtils(object):
if r.status_code != 401: if r.status_code != 401:
self.count_unauthorized = 0 self.count_unauthorized = 0
if r.status_code == 204: if return_response is True:
# return the entire response object
return r
elif r.status_code == 204:
# No body in the response # No body in the response
# But read (empty) content to release connection back to pool # But read (empty) content to release connection back to pool
# (see requests: keep-alive documentation) # (see requests: keep-alive documentation)
@ -257,9 +261,6 @@ class DownloadUtils(object):
elif r.status_code in (200, 201): elif r.status_code in (200, 201):
# 200: OK # 200: OK
# 201: Created # 201: Created
if return_response is True:
# return the entire response object
return r
try: try:
# xml response # xml response
r = utils.etree.fromstring(r.content) r = utils.etree.fromstring(r.content)

View file

@ -382,72 +382,17 @@ class KodiMonitor(xbmc.Monitor):
if not playerid == v.KODI_VIDEO_PLAYER_ID: if not playerid == v.KODI_VIDEO_PLAYER_ID:
# We're just messing with Kodi's videoplayer # We're just messing with Kodi's videoplayer
return return
if not self._switched_to_plex_streams:
# We need to switch to the Plex streams ONCE upon playback start
# after onavchange has been fired
self.switch_to_plex_streams()
self._switched_to_plex_streams = True
else:
item = app.PLAYSTATE.item
if item is None:
# Player might've quit
return
kodi_audio_stream = js.get_current_audio_stream_index(playerid)
sub_enabled = js.get_subtitle_enabled(playerid)
kodi_sub_stream = js.get_current_subtitle_stream_index(playerid)
# Audio
if kodi_audio_stream != item.current_kodi_audio_stream:
item.on_kodi_audio_stream_change(kodi_audio_stream)
# Subtitles - CURRENTLY BROKEN ON THE KODI SIDE!
# current_kodi_sub_stream may also be zero
subs_off = (None, False)
if ((sub_enabled and item.current_kodi_sub_stream in subs_off)
or (not sub_enabled and item.current_kodi_sub_stream not in subs_off)
or (kodi_sub_stream is not None
and kodi_sub_stream != item.current_kodi_sub_stream)):
item.on_kodi_subtitle_stream_change(kodi_sub_stream,
sub_enabled)
@staticmethod
def switch_to_plex_streams():
"""
Override Kodi audio and subtitle streams with Plex PMS' selection
"""
item = app.PLAYSTATE.item item = app.PLAYSTATE.item
if item is None: if item is None:
# Player might've quit # Player might've quit
return return
for typus in ('audio', 'subtitle'): if not self._switched_to_plex_streams:
try: # We need to switch to the Plex streams ONCE upon playback start
plex_index, language_tag = item.active_plex_stream_index(typus) # after onavchange has been fired
except TypeError: item.switch_to_plex_streams()
LOG.debug('Deactivating Kodi subtitles because the PMS ' self._switched_to_plex_streams = True
'told us to not show any subtitles') else:
app.APP.player.showSubtitles(False) item.on_av_change(playerid)
item.current_kodi_sub_stream = False
continue
LOG.debug('The PMS wants to display %s stream with Plex id %s and '
'languageTag %s',
typus, plex_index, language_tag)
kodi_index = item.kodi_stream_index(plex_index, typus)
if kodi_index is None:
LOG.debug('Leaving Kodi %s stream settings untouched since we '
'could not parse Plex %s stream with id %s to a Kodi'
' index', typus, typus, plex_index)
else:
LOG.debug('Switching to Kodi %s stream number %s because the '
'PMS told us to show stream with Plex id %s',
typus, kodi_index, plex_index)
# If we're choosing an "illegal" index, this function does
# need seem to fail nor log any errors
if typus == 'audio':
app.APP.player.setAudioStream(kodi_index)
else:
app.APP.player.setSubtitleStream(kodi_index)
if typus == 'audio':
item.current_kodi_audio_stream = kodi_index
else:
item.current_kodi_sub_stream = kodi_index
def _playback_cleanup(ended=False): def _playback_cleanup(ended=False):

View file

@ -324,6 +324,58 @@ class PlaylistItem(object):
PF.change_audio_stream(plex_stream_index, self.api.part_id()) PF.change_audio_stream(plex_stream_index, self.api.part_id())
self.current_kodi_audio_stream = kodi_stream_index self.current_kodi_audio_stream = kodi_stream_index
def switch_to_plex_streams(self):
self.switch_to_plex_stream('audio')
self.switch_to_plex_stream('subtitle')
def switch_to_plex_stream(self, typus):
try:
plex_index, language_tag = self.active_plex_stream_index(typus)
except TypeError:
LOG.debug('Deactivating Kodi subtitles because the PMS '
'told us to not show any subtitles')
app.APP.player.showSubtitles(False)
self.current_kodi_sub_stream = False
return
LOG.debug('The PMS wants to display %s stream with Plex id %s and '
'languageTag %s', typus, plex_index, language_tag)
kodi_index = self.kodi_stream_index(plex_index, typus)
if kodi_index is None:
LOG.debug('Leaving Kodi %s stream settings untouched since we '
'could not parse Plex %s stream with id %s to a Kodi'
' index', typus, typus, plex_index)
else:
LOG.debug('Switching to Kodi %s stream number %s because the '
'PMS told us to show stream with Plex id %s',
typus, kodi_index, plex_index)
# If we're choosing an "illegal" index, this function does
# need seem to fail nor log any errors
if typus == 'audio':
app.APP.player.setAudioStream(kodi_index)
else:
app.APP.player.setSubtitleStream(kodi_index)
app.APP.player.showSubtitles(True)
if typus == 'audio':
self.current_kodi_audio_stream = kodi_index
else:
self.current_kodi_sub_stream = kodi_index
def on_av_change(self, playerid):
kodi_audio_stream = js.get_current_audio_stream_index(playerid)
sub_enabled = js.get_subtitle_enabled(playerid)
kodi_sub_stream = js.get_current_subtitle_stream_index(playerid)
# Audio
if kodi_audio_stream != self.current_kodi_audio_stream:
self.on_kodi_audio_stream_change(kodi_audio_stream)
# Subtitles - CURRENTLY BROKEN ON THE KODI SIDE!
# current_kodi_sub_stream may also be zero
subs_off = (None, False)
if ((sub_enabled and self.current_kodi_sub_stream in subs_off)
or (not sub_enabled and self.current_kodi_sub_stream not in subs_off)
or (kodi_sub_stream is not None
and kodi_sub_stream != self.current_kodi_sub_stream)):
self.on_kodi_subtitle_stream_change(kodi_sub_stream, sub_enabled)
def playlist_item_from_kodi(kodi_item): def playlist_item_from_kodi(kodi_item):
""" """

View file

@ -220,12 +220,14 @@ class Artwork(object):
else: else:
# Not supported artwork # Not supported artwork
return artworks return artworks
data = DU().downloadUrl(url, authenticate=False, timeout=15) data = DU().downloadUrl(url,
try: authenticate=False,
data.get('test') timeout=15,
except AttributeError: return_response=True)
LOG.error('Could not download data from FanartTV') if not data.ok:
LOG.debug('Could not download data from FanartTV')
return artworks return artworks
data = data.json()
fanart_tv_types = list(v.FANART_TV_TO_KODI_TYPE) fanart_tv_types = list(v.FANART_TV_TO_KODI_TYPE)

View file

@ -16,12 +16,15 @@ METADATA_PROVIDERS = (('imdb', utils.REGEX_IMDB),
('tvdb', utils.REGEX_TVDB), ('tvdb', utils.REGEX_TVDB),
('tmdb', utils.REGEX_TMDB), ('tmdb', utils.REGEX_TMDB),
('anidb', utils.REGEX_ANIDB)) ('anidb', utils.REGEX_ANIDB))
class Base(object): class Base(object):
""" """
Processes a Plex media server's XML response Processes a Plex media server's XML response
xml: xml.etree.ElementTree element xml: xml.etree.ElementTree element
""" """
def __init__(self, xml): def __init__(self, xml):
self.xml = xml self.xml = xml
# which media part in the XML response shall we look at if several # which media part in the XML response shall we look at if several
@ -260,13 +263,21 @@ class Base(object):
Returns the media streams directly from the PMS xml. Returns the media streams directly from the PMS xml.
Mind to set self.mediastream and self.part before calling this method! Mind to set self.mediastream and self.part before calling this method!
""" """
return self.xml[self.mediastream][self.part] try:
return self.xml[self.mediastream][self.part]
except TypeError:
# Direct Paths when we don't set mediastream and part
return self.xml[0][0]
def part_id(self): def part_id(self):
""" """
Returns the unique id of the currently active part [int] Returns the unique id of the currently active part [int]
""" """
return int(self.xml[self.mediastream][self.part].attrib['id']) try:
return int(self.xml[self.mediastream][self.part].attrib['id'])
except TypeError:
# Direct Paths when we don't set mediastream and part
return int(self.xml[0][0].attrib['id'])
def plot(self): def plot(self):
""" """

View file

@ -357,16 +357,15 @@ class Media(object):
filename, filename,
extension) extension)
response = DU().downloadUrl(url, return_response=True) response = DU().downloadUrl(url, return_response=True)
try: if not response.ok:
response.status_code
except AttributeError:
LOG.error('Could not temporarily download subtitle %s', url) LOG.error('Could not temporarily download subtitle %s', url)
LOG.error('HTTP status: %s, message: %s',
response.status_code, response.text)
return return
else: LOG.debug('Writing temp subtitle to %s', path)
LOG.debug('Writing temp subtitle to %s', path) with open(path, 'wb') as f:
with open(path, 'wb') as f: f.write(response.content)
f.write(response.content) return path
return path
def validate_playurl(self, path, typus, force_check=False, folder=False, def validate_playurl(self, path, typus, force_check=False, folder=False,
omit_check=False): omit_check=False):

View file

@ -23,6 +23,11 @@ import re
import gc import gc
try: try:
from multiprocessing.pool import ThreadPool from multiprocessing.pool import ThreadPool
# Annyoing Kodi bug on Android, introduced with
# https://github.com/xbmc/xbmc/pull/20034
# See https://github.com/croneter/PlexKodiConnect/issues/1641
with ThreadPool():
pass
SUPPORTS_POOL = True SUPPORTS_POOL = True
except Exception: except Exception:
SUPPORTS_POOL = False SUPPORTS_POOL = False
@ -867,13 +872,12 @@ def process_method_on_list(method_to_run, items):
all_items = [] all_items = []
if SUPPORTS_POOL: if SUPPORTS_POOL:
pool = ThreadPool() pool = ThreadPool()
try: with ThreadPool() as pool:
all_items = pool.map(method_to_run, items) try:
except Exception: all_items = pool.map(method_to_run, items)
# catch exception to prevent threadpool running forever except Exception:
ERROR(notify=True) # catch exception to prevent threadpool running forever
pool.close() ERROR(notify=True)
pool.join()
else: else:
all_items = [method_to_run(item) for item in items] all_items = [method_to_run(item) for item in items]
all_items = [_f for _f in all_items if _f] all_items = [_f for _f in all_items if _f]