Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch from add-on playback to new playback method using a webservice #792

Open
wants to merge 74 commits into
base: python2-beta
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
9b4584e
Switch to stream playback, part I
croneter Mar 25, 2019
7c6fdad
Fixup
croneter Mar 30, 2019
059ed7a
Switch to stream playback, part II
croneter Apr 6, 2019
16423e1
Ignore suspends for webservice
croneter Apr 6, 2019
4a3b38f
Increase logging
croneter Apr 6, 2019
c0035c8
Fix monitor's playlist.onadd
croneter Apr 6, 2019
875d704
Don't store filename in Kodi db
croneter Apr 6, 2019
20c1c6e
Add missing default.py option
croneter Apr 6, 2019
dfcfa0e
Better detect videos playing for playback cleanup
croneter Apr 6, 2019
d7541b7
TO BE CHECKED: better method to delete obsolete fileIds
croneter Apr 7, 2019
20bffc1
Enable webservice playback for shows
croneter Apr 7, 2019
12befec
Rewire video resume info
croneter Apr 7, 2019
439857a
Rewire autoplay flag
croneter Apr 7, 2019
797a58a
Rewire plex.playlist.audio
croneter Apr 7, 2019
484b034
Fix resume flags for ListItems
croneter Apr 7, 2019
4ed17f1
Fix widgets not updating
croneter Apr 7, 2019
5428daf
Simplify code
croneter Apr 7, 2019
f4c3674
Increase logging
croneter Apr 11, 2019
0d36a2a
Simplify code
croneter Apr 11, 2019
8c614f3
Don't automatically look up kodi_id from Plex DB
croneter Apr 11, 2019
fe52efd
Less playlist logging
croneter Apr 11, 2019
b11ca48
Enable playqueue elements comparison
croneter Apr 13, 2019
ad6c160
Don't sleep
croneter Apr 13, 2019
643e617
Revamp monitor
croneter Apr 13, 2019
9a9bc9f
Optimize code
croneter Apr 13, 2019
0acf470
Optimize logging
croneter Apr 13, 2019
61ff2b7
Increase logging
croneter Apr 13, 2019
ac28546
Fix main movie being added as trailer
croneter Apr 13, 2019
885e8dd
Fix PKC wanting to initiate playback when it should not
croneter Apr 13, 2019
d380aa8
Drop filename for url arg, but add kodi_type
croneter Apr 13, 2019
95b37b5
Fix resume
croneter Apr 13, 2019
c63d9ad
Some more switches to webservice, away from plugin playback
croneter Apr 14, 2019
3aa5c87
Skip force close connection error messages
croneter Apr 14, 2019
2dac26f
Fix force transcoding
croneter Apr 14, 2019
130ec67
Fix companion playback crashing
croneter Apr 14, 2019
4fa1f48
Improve logging
croneter Apr 17, 2019
7753903
Be more resiliant when manipulating Plex playqueues
croneter Apr 19, 2019
bbd8e18
Increase timeout
croneter Apr 19, 2019
8660b12
Fix position
croneter Apr 19, 2019
0d8b3b3
Remove arg
croneter Apr 19, 2019
578ced7
Fix arg
croneter Apr 19, 2019
1218cde
Big update
croneter Apr 28, 2019
6bd98fc
Cleanup
croneter May 4, 2019
48cda46
Move method
croneter May 4, 2019
353cb04
New functions
croneter May 4, 2019
45fc9fa
Better way to detect video widget playback
croneter May 4, 2019
8ad6d1b
Clear playqueue on playback startup
croneter May 5, 2019
1123a2e
Fix widget playback not starting up
croneter May 5, 2019
dc56c2a
Improve code
croneter May 5, 2019
b586ac0
Fix moving of items in Plex playqueue
croneter May 5, 2019
7616d6d
Fixup
croneter May 5, 2019
cef07c3
Set kodi_type for PlaylistItem automatically from plex_type
croneter May 5, 2019
1d01f47
Fixup
croneter May 5, 2019
a1f4960
Revert "Set kodi_type for PlaylistItem automatically from plex_type"
croneter May 5, 2019
ea4a062
Big update
croneter May 12, 2019
0ce29dc
Fix Plex Companion telling the wrong item is playing
croneter May 19, 2019
7725af5
Fix resume from Plex Companion
croneter May 21, 2019
9d79f78
Fix TypeError
croneter May 21, 2019
f7237d7
Cleanup
croneter May 25, 2019
d397fb5
Cleanup
croneter May 25, 2019
9d517c2
Refactoring
croneter May 25, 2019
3d4bde8
Cleanup
croneter May 25, 2019
d3752e1
Rename to PlayqueueError
croneter May 26, 2019
fb21bc7
Cleanup
croneter May 26, 2019
6e692d2
Fix resume when user chose to not resume
croneter May 26, 2019
7254167
Revert "Fix resume when user chose to not resume"
croneter May 26, 2019
bb2fff5
Fix resume when user chose to not resume
croneter May 26, 2019
0f9e754
Cleanup
croneter May 26, 2019
a650c42
Lock playqueue activities
croneter May 26, 2019
7e676eb
Fix playback startup
croneter May 26, 2019
e204ef9
Replace window var plex.playlist.ready with app.PLAYSTATE var
croneter May 26, 2019
27c4c6a
Replace window var plex.playlist.start with app.PLAYSTATE var
croneter May 26, 2019
48d288a
Remove some logging
croneter May 26, 2019
6cba4a1
Fix playback startup for Plex Companion
croneter May 26, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion default.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,21 @@ def __init__(self):
mode = params.get('mode', '')
itemid = params.get('id', '')

if mode == 'play':
if mode == 'playstrm':
while not utils.window('plex.playlist.play'):
xbmc.sleep(25)
if utils.window('plex.playlist.aborted'):
LOG.info("playback aborted")
break
else:
LOG.info("Playback started")
xbmcplugin.setResolvedUrl(int(argv[1]),
False,
xbmcgui.ListItem())
utils.window('plex.playlist.play', clear=True)
utils.window('plex.playlist.aborted', clear=True)

elif mode == 'play':
self.play()

elif mode == 'plex_node':
Expand Down
25 changes: 19 additions & 6 deletions resources/lib/app/playstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,25 @@ def __init__(self):
}
self.played_info = {}

# Set by SpecialMonitor - did user choose to resume playback or start from the
# beginning?
self.resume_playback = False
# Set by SpecialMonitor - did user choose to resume playback or start
# from the beginning?
# Do set to None if NO resume dialog is displayed! True/False otherwise
self.resume_playback = None
# Don't ask user whether to resume but immediatly resume
self.autoplay = False
# Was the playback initiated by the user using the Kodi context menu?
self.context_menu_play = False
# Set by context menu - shall we force-transcode the next playing item?
self.force_transcode = False
# Which Kodi player is/has been active? (either int 1, 2 or 3)
# Which Kodi player is/has been active? (either int 0, 1, 2)
self.active_players = set()
# Have we initiated playback via Plex Companion or Alexa - so from the
# Plex side of things?
self.initiated_by_plex = False
# PKC adds/replaces items in the playqueue. We need to use
# xbmcplugin.setResolvedUrl() AFTER an item has successfully been added
# This flag is set by Kodimonitor/xbmc.Monitor() and the Playlist.OnAdd
# signal only when the currently playing item that called the
# webservice has successfully been processed
self.playlist_ready = False
# Flag for Kodimonitor to check when the correct item has been
# processed and the Playlist.OnAdd signal has been received
self.playlist_start_pos = None
25 changes: 14 additions & 11 deletions resources/lib/context_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from .plex_api import API
from .plex_db import PlexDB
from . import context, plex_functions as PF, playqueue as PQ
from . import context, plex_functions as PF
from . import utils, variables as v, app

###############################################################################
Expand Down Expand Up @@ -112,8 +112,7 @@ def _action_menu(self):
"""
selected = self._selected_option
if selected == OPTIONS['Transcode']:
app.PLAYSTATE.force_transcode = True
self._PMS_play()
self._PMS_play(transcode=True)
elif selected == OPTIONS['PMS_Play']:
self._PMS_play()
elif selected == OPTIONS['Extras']:
Expand All @@ -139,17 +138,21 @@ def _delete_item(self):
if PF.delete_item_from_pms(self.plex_id) is False:
utils.dialog("ok", heading="{plex}", line1=utils.lang(30414))

def _PMS_play(self):
def _PMS_play(self, transcode=False):
"""
For using direct paths: Initiates playback using the PMS
"""
playqueue = PQ.get_playqueue_from_type(
v.KODI_PLAYLIST_TYPE_FROM_KODI_TYPE[self.kodi_type])
playqueue.clear()
app.PLAYSTATE.context_menu_play = True
handle = self.api.path(force_first_media=False, force_addon=True)
handle = 'RunPlugin(%s)' % handle
xbmc.executebuiltin(handle.encode('utf-8'))
path = ('http://127.0.0.1:%s/plex/play/file.strm?plex_id=%s'
% (v.WEBSERVICE_PORT, self.plex_id))
if self.plex_type:
path += '&plex_type=%s' % self.plex_type
if self.kodi_id:
path += '&kodi_id=%s' % self.kodi_id
if self.kodi_type:
path += '&kodi_type=%s' % self.kodi_type
if transcode:
path += '&transcode=true'
xbmc.executebuiltin(('PlayMedia(%s)' % path).encode('utf-8'))

def _extras(self):
"""
Expand Down
3 changes: 2 additions & 1 deletion resources/lib/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ def show_listing(xml, plex_type=None, section_id=None, synched=True, key=None,
# Need to chain keys for navigation
widgets.KEY = key
# Process all items to show
widgets.attach_kodi_ids(xml)
if synched:
widgets.attach_kodi_ids(xml)
all_items = widgets.process_method_on_list(widgets.generate_item, xml)
all_items = widgets.process_method_on_list(widgets.prepare_listitem,
all_items)
Expand Down
10 changes: 6 additions & 4 deletions resources/lib/itemtypes/movies.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,12 @@ def add_update(self, xml, section, children=None):
scraper='metadata.local')
if do_indirect:
# Set plugin path and media flags using real filename
filename = api.file_name(force_first_media=True)
path = 'plugin://%s.movies/' % v.ADDON_ID
filename = ('%s?plex_id=%s&plex_type=%s&mode=play&filename=%s'
% (path, plex_id, v.PLEX_TYPE_MOVIE, filename))
path = 'http://127.0.0.1:%s/plex/kodi/movies/' % v.WEBSERVICE_PORT
filename = '{0}/file.strm?kodi_id={1}&kodi_type={2}&plex_id={0}&plex_type={3}'
filename = filename.format(plex_id,
kodi_id,
v.KODI_TYPE_MOVIE,
v.PLEX_TYPE_MOVIE)
playurl = filename
kodi_pathid = self.kodidb.get_path(path)

Expand Down
34 changes: 19 additions & 15 deletions resources/lib/itemtypes/tvshows.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ def add_update(self, xml, section, children=None):
scraper='metadata.local')
else:
# Set plugin path
toplevelpath = "plugin://%s.tvshows/" % v.ADDON_ID
toplevelpath = ('http://127.0.0.1:%s/plex/kodi/shows/'
% v.WEBSERVICE_PORT)
path = "%s%s/" % (toplevelpath, plex_id)
# Do NOT set a parent id because addon-path cannot be "stacked"
toppathid = None
Expand Down Expand Up @@ -448,22 +449,25 @@ def add_update(self, xml, section, children=None):
if do_indirect:
# Set plugin path - do NOT use "intermediate" paths for the show
# as with direct paths!
filename = api.file_name(force_first_media=True)
path = 'plugin://%s.tvshows/%s/' % (v.ADDON_ID, show_id)
filename = ('%s?plex_id=%s&plex_type=%s&mode=play&filename=%s'
% (path, plex_id, v.PLEX_TYPE_EPISODE, filename))
# Set plugin path and media flags using real filename
path = ('http://127.0.0.1:%s/plex/kodi/shows/%s/'
% (v.WEBSERVICE_PORT, show_id))
filename = '{0}/file.strm?kodi_id={1}&kodi_type={2}&plex_id={0}&plex_type={3}'
filename = filename.format(plex_id,
kodi_id,
v.KODI_TYPE_EPISODE,
v.PLEX_TYPE_EPISODE)
playurl = filename
# Root path tvshows/ already saved in Kodi DB
kodi_pathid = self.kodidb.add_path(path)
if not app.SYNC.direct_paths:
# need to set a 2nd file entry for a path without plex show id
# This fixes e.g. context menu and widgets working as they
# should
# A dirty hack, really
path_2 = 'plugin://%s.tvshows/' % v.ADDON_ID
# filename_2 is exactly the same as filename
# so WITH plex show id!
kodi_pathid_2 = self.kodidb.add_path(path_2)
kodi_pathid = self.kodidb.get_path(path)
# HACK
# need to set a 2nd file entry for a path without plex show id
# This fixes e.g. context menu and widgets working as they
# should
path_2 = 'http://127.0.0.1:%s/plex/kodi/shows/' % v.WEBSERVICE_PORT
# filename_2 is exactly the same as filename
# so WITH plex show id!
kodi_pathid_2 = self.kodidb.add_path(path_2)

# UPDATE THE EPISODE #####
if update_item:
Expand Down
26 changes: 14 additions & 12 deletions resources/lib/kodi_db/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
from sqlite3 import IntegrityError

from . import common
from .. import path_ops, timing, variables as v, app
from .. import path_ops, timing, variables as v

LOG = getLogger('PLEX.kodi_db.video')

MOVIE_PATH = 'plugin://%s.movies/' % v.ADDON_ID
SHOW_PATH = 'plugin://%s.tvshows/' % v.ADDON_ID
MOVIE_PATH = 'http://127.0.0.1:%s/plex/kodi/movies/' % v.WEBSERVICE_PORT
SHOW_PATH = 'http://127.0.0.1:%s/plex/kodi/shows/' % v.WEBSERVICE_PORT


class KodiVideoDB(common.KodiDBBase):
Expand Down Expand Up @@ -174,15 +174,17 @@ def modify_file(self, filename, path_id, date_added):
def obsolete_file_ids(self):
"""
Returns a generator for idFile of all Kodi file ids that do not have a
dateAdded set (dateAdded NULL) and the filename start with
'plugin://plugin.video.plexkodiconnect'
These entries should be deleted as they're created falsely by Kodi.
"""
return (x[0] for x in self.cursor.execute('''
SELECT idFile FROM files
WHERE dateAdded IS NULL
AND strFilename LIKE \'plugin://plugin.video.plexkodiconnect%\'
'''))
dateAdded set (dateAdded NULL) and the associated path entry has
a field noUpdate of NULL as well as dateAdded of NULL
"""
return (x[0] for x in self.cursor.execute("""
SELECT files.idFile
FROM files
LEFT JOIN path ON path.idPath = files.idPath
WHERE files.dateAdded IS NULL
AND path.noUpdate IS NULL
AND path.dateAdded IS NULL
"""))

def show_id_from_path(self, path):
"""
Expand Down
Loading