Ejemplo n.º 1
0
 def _get_ids(self, json_item):
     """
     """
     kodi_id = json_item.get('id')
     kodi_type = json_item.get('type')
     path = json_item.get('file')
     # Plex id will NOT be set with direct paths
     plex_id = state.PLEX_IDS.get(path)
     try:
         plex_type = v.PLEX_TYPE_FROM_KODI_TYPE[kodi_type]
     except KeyError:
         plex_type = None
     # No Kodi id returned by Kodi, even if there is one. Ex: Widgets
     if plex_id and not kodi_id:
         with plexdb.Get_Plex_DB() as plex_db:
             plex_dbitem = plex_db.getItem_byId(plex_id)
         try:
             kodi_id = plex_dbitem[0]
         except TypeError:
             kodi_id = None
     # If using direct paths and starting playback from a widget
     if not kodi_id and kodi_type and path and not path.startswith('http'):
         kodi_id = kodiid_from_filename(path, kodi_type)
     if not plex_id and kodi_id and kodi_type:
         with plexdb.Get_Plex_DB() as plex_db:
             plex_dbitem = plex_db.getItem_byKodiId(kodi_id, kodi_type)
         try:
             plex_id = plex_dbitem[0]
             plex_type = plex_dbitem[2]
         except TypeError:
             # No plex id, hence item not in the library. E.g. clips
             pass
     return kodi_id, kodi_type, plex_id, plex_type
Ejemplo n.º 2
0
def playlist_item_from_xml(playlist, xml_video_element, kodi_id=None,
                           kodi_type=None):
    """
    Returns a playlist element for the playqueue using the Plex xml

    xml_video_element: etree xml piece 1 level underneath <MediaContainer>
    """
    item = Playlist_Item()
    api = API(xml_video_element)
    item.plex_id = api.getRatingKey()
    item.plex_type = api.getType()
    try:
        item.id = xml_video_element.attrib['%sItemID' % playlist.kind]
    except KeyError:
        pass
    item.guid = xml_video_element.attrib.get('guid')
    if item.guid is not None:
        item.guid = escape_html(item.guid)
    if kodi_id is not None:
        item.kodi_id = kodi_id
        item.kodi_type = kodi_type
    elif item.plex_id is not None:
        with plexdb.Get_Plex_DB() as plex_db:
            db_element = plex_db.getItem_byId(item.plex_id)
        try:
            item.kodi_id, item.kodi_type = int(db_element[0]), db_element[4]
        except TypeError:
            pass
    item.xml = xml_video_element
    LOG.debug('Created new playlist item from xml: %s', item)
    return item
Ejemplo n.º 3
0
def playlist_item_from_xml(xml_video_element, kodi_id=None, kodi_type=None):
    """
    Returns a playlist element for the playqueue using the Plex xml

    xml_video_element: etree xml piece 1 level underneath <MediaContainer>
    """
    item = Playlist_Item()
    api = API(xml_video_element)
    item.plex_id = api.plex_id()
    item.plex_type = api.plex_type()
    # item.id will only be set if you passed in an xml_video_element from e.g.
    # a playQueue
    item.id = api.item_id()
    if kodi_id is not None:
        item.kodi_id = kodi_id
        item.kodi_type = kodi_type
    elif item.plex_id is not None:
        with plexdb.Get_Plex_DB() as plex_db:
            db_element = plex_db.getItem_byId(item.plex_id)
        try:
            item.kodi_id, item.kodi_type = db_element[0], db_element[4]
        except TypeError:
            pass
    item.guid = api.guid_html_escaped()
    item.playcount = api.viewcount()
    item.offset = api.resume_point()
    item.xml = xml_video_element
    LOG.debug('Created new playlist item from xml: %s', item)
    return item
Ejemplo n.º 4
0
 def process_plex_node(self, url, viewOffset, directplay=False,
                       node=True):
     """
     Called for Plex directories or redirect for playback (e.g. trailers,
     clips, watchlater)
     """
     log.info('process_plex_node called with url: %s, viewOffset: %s'
              % (url, viewOffset))
     # Plex redirect, e.g. watch later. Need to get actual URLs
     if url.startswith('http') or url.startswith('{server}'):
         xml = DownloadUtils().downloadUrl(url)
     else:
         xml = DownloadUtils().downloadUrl('{server}%s' % url)
     try:
         xml[0].attrib
     except:
         log.error('Could not download PMS metadata')
         return
     if viewOffset != '0':
         try:
             viewOffset = int(v.PLEX_TO_KODI_TIMEFACTOR * float(viewOffset))
         except:
             pass
         else:
             window('plex_customplaylist.seektime', value=str(viewOffset))
             log.info('Set resume point to %s' % str(viewOffset))
     api = API(xml[0])
     typus = v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[api.getType()]
     if node is True:
         plex_id = None
         kodi_id = 'plexnode'
     else:
         plex_id = api.getRatingKey()
         kodi_id = None
         with plexdb.Get_Plex_DB() as plex_db:
             plexdb_item = plex_db.getItem_byId(plex_id)
             try:
                 kodi_id = plexdb_item[0]
             except TypeError:
                 log.info('Couldnt find item %s in Kodi db'
                          % api.getRatingKey())
     playqueue = self.playqueue.get_playqueue_from_type(typus)
     with lock:
         result = PlaybackUtils(xml, playqueue).play(
             plex_id,
             kodi_id=kodi_id,
             plex_lib_UUID=xml.attrib.get('librarySectionUUID'))
     if directplay:
         if result.listitem:
             listitem = convert_PKC_to_listitem(result.listitem)
             Player().play(listitem.getfilename(), listitem)
         return Playback_Successful()
     else:
         return result
Ejemplo n.º 5
0
def _record_playstate(status, ended):
    with kodidb.GetKodiDB('video') as kodi_db:
        # Hack - remove any obsolete file entries Kodi made
        kodi_db.clean_file_table()
    if not status['plex_id']:
        LOG.debug('No Plex id found to record playstate for status %s', status)
        return
    with plexdb.Get_Plex_DB() as plex_db:
        kodi_db_item = plex_db.getItem_byId(status['plex_id'])
    if kodi_db_item is None:
        # Item not (yet) in Kodi library
        LOG.debug('No playstate update due to Plex id not found: %s', status)
        return
    totaltime = float(kodi_time_to_millis(status['totaltime'])) / 1000
    if ended:
        progress = 0.99
        time = v.IGNORE_SECONDS_AT_START + 1
    else:
        time = float(kodi_time_to_millis(status['time'])) / 1000
        try:
            progress = time / totaltime
        except ZeroDivisionError:
            progress = 0.0
        LOG.debug('Playback progress %s (%s of %s seconds)', progress, time,
                  totaltime)
    playcount = status['playcount']
    last_played = unix_date_to_kodi(unix_timestamp())
    if playcount is None:
        LOG.info('playcount not found, looking it up in the Kodi DB')
        with kodidb.GetKodiDB('video') as kodi_db:
            playcount = kodi_db.get_playcount(kodi_db_item[1])
        playcount = 0 if playcount is None else playcount
    if time < v.IGNORE_SECONDS_AT_START:
        LOG.debug('Ignoring playback less than %s seconds',
                  v.IGNORE_SECONDS_AT_START)
        # Annoying Plex bug - it'll reset an already watched video to unwatched
        playcount = 0
        last_played = None
        time = 0
    elif progress >= v.MARK_PLAYED_AT:
        LOG.debug('Recording entirely played video since progress > %s',
                  v.MARK_PLAYED_AT)
        playcount += 1
        time = 0
    with kodidb.GetKodiDB('video') as kodi_db:
        kodi_db.addPlaystate(kodi_db_item[1], time, totaltime, playcount,
                             last_played)
    # Hack to force "in progress" widget to appear if it wasn't visible before
    if (state.FORCE_RELOAD_SKIN
            and xbmc.getCondVisibility('Window.IsVisible(Home.xml)')):
        LOG.debug('Refreshing skin to update widgets')
        xbmc.executebuiltin('ReloadSkin()')
Ejemplo n.º 6
0
 def skipTo(self, plexId, typus):
     # playlistId = self.getPlaylistId(tryDecode(xbmc_type(typus)))
     # playerId = self.
     with plexdb.Get_Plex_DB() as plex_db:
         plexdb_item = plex_db.getItem_byId(plexId)
         try:
             dbid = plexdb_item[0]
             mediatype = plexdb_item[4]
         except TypeError:
             log.info('Couldnt find item %s in Kodi db' % plexId)
             return
     log.debug('plexid: %s, kodi id: %s, type: %s' %
               (plexId, dbid, mediatype))
Ejemplo n.º 7
0
def conclude_playback(playqueue, pos):
    """
    ONLY if actually being played (e.g. at 5th position of a playqueue).

        Decide on direct play, direct stream, transcoding
        path to
            direct paths: file itself
            PMS URL
            Web URL
        audiostream (e.g. let user choose)
        subtitle stream (e.g. let user choose)
        Init Kodi Playback (depending on situation):
            start playback
            return PKC listitem attached to result
    """
    LOG.info('Concluding playback for playqueue position %s', pos)
    result = Playback_Successful()
    listitem = PKC_ListItem()
    item = playqueue.items[pos]
    if item.xml is not None:
        # Got a Plex element
        api = API(item.xml)
        api.setPartNumber(item.part)
        api.CreateListItemFromPlexItem(listitem)
        playutils = PlayUtils(api, item)
        playurl = playutils.getPlayUrl()
    else:
        playurl = item.file
    listitem.setPath(tryEncode(playurl))
    if item.playmethod in ('DirectStream', 'DirectPlay'):
        listitem.setSubtitles(api.externalSubs())
    else:
        playutils.audio_subtitle_prefs(listitem)
    if state.RESUME_PLAYBACK is True:
        state.RESUME_PLAYBACK = False
        if (item.offset is None and item.plex_type
                not in (v.PLEX_TYPE_SONG, v.PLEX_TYPE_CLIP)):
            with plexdb.Get_Plex_DB() as plex_db:
                plex_dbitem = plex_db.getItem_byId(item.plex_id)
                file_id = plex_dbitem[1] if plex_dbitem else None
            with kodidb.GetKodiDB('video') as kodi_db:
                item.offset = kodi_db.get_resume(file_id)
        LOG.info('Resuming playback at %s', item.offset)
        listitem.setProperty('StartOffset', str(item.offset))
        listitem.setProperty('resumetime', str(item.offset))
    # Reset the resumable flag
    state.RESUMABLE = False
    result.listitem = listitem
    pickle_me(result)
    LOG.info('Done concluding playback')
Ejemplo n.º 8
0
def playlist_item_from_plex(plex_id):
    """
    Returns a playlist element providing the plex_id ("ratingKey")

    Returns a Playlist_Item
    """
    item = Playlist_Item()
    item.plex_id = plex_id
    with plexdb.Get_Plex_DB() as plex_db:
        plex_dbitem = plex_db.getItem_byId(plex_id)
    try:
        item.kodi_id = plex_dbitem[0]
        item.kodi_type = plex_dbitem[4]
    except:
        raise KeyError('Could not find plex_id %s in database' % plex_id)
    return item
Ejemplo n.º 9
0
def _prep_playlist_stack(xml):
    stack = []
    for item in xml:
        api = API(item)
        if (state.CONTEXT_MENU_PLAY is False
                and api.plex_type() != v.PLEX_TYPE_CLIP):
            # If user chose to play via PMS or force transcode, do not
            # use the item path stored in the Kodi DB
            with plexdb.Get_Plex_DB() as plex_db:
                plex_dbitem = plex_db.getItem_byId(api.plex_id())
            kodi_id = plex_dbitem[0] if plex_dbitem else None
            kodi_type = plex_dbitem[4] if plex_dbitem else None
        else:
            # We will never store clips (trailers) in the Kodi DB.
            # Also set kodi_id to None for playback via PMS, so that we're
            # using add-on paths.
            kodi_id = None
            kodi_type = None
        for part, _ in enumerate(item[0]):
            api.set_part_number(part)
            if kodi_id is None:
                # Need to redirect again to PKC to conclude playback
                params = {
                    'mode': 'play',
                    'plex_id': api.plex_id(),
                    'plex_type': api.plex_type()
                }
                path = ('plugin://%s/?%s' %
                        (v.ADDON_TYPE[api.plex_type()], urlencode(params)))
                listitem = api.create_listitem()
                listitem.setPath(try_encode(path))
            else:
                # Will add directly via the Kodi DB
                path = None
                listitem = None
            stack.append({
                'kodi_id': kodi_id,
                'kodi_type': kodi_type,
                'file': path,
                'xml_video_element': item,
                'listitem': listitem,
                'part': part,
                'playcount': api.viewcount(),
                'offset': api.resume_point(),
                'id': api.item_id()
            })
    return stack
Ejemplo n.º 10
0
def _prep_playlist_stack(xml):
    stack = []
    for item in xml:
        api = API(item)
        if (state.CONTEXT_MENU_PLAY is False
                and api.getType() != v.PLEX_TYPE_CLIP):
            # If user chose to play via PMS or force transcode, do not
            # use the item path stored in the Kodi DB
            with plexdb.Get_Plex_DB() as plex_db:
                plex_dbitem = plex_db.getItem_byId(api.getRatingKey())
            kodi_id = plex_dbitem[0] if plex_dbitem else None
            kodi_type = plex_dbitem[4] if plex_dbitem else None
        else:
            # We will never store clips (trailers) in the Kodi DB
            kodi_id = None
            kodi_type = None
        for part, _ in enumerate(item[0]):
            api.setPartNumber(part)
            if kodi_id is None:
                # Need to redirect again to PKC to conclude playback
                params = {
                    'mode': 'play',
                    'plex_id': api.getRatingKey(),
                    'plex_type': api.getType()
                }
                path = ('plugin://plugin.video.plexkodiconnect?%s' %
                        urlencode(params))
                listitem = api.CreateListItemFromPlexItem()
                listitem.setPath(tryEncode(path))
            else:
                # Will add directly via the Kodi DB
                path = None
                listitem = None
            stack.append({
                'kodi_id': kodi_id,
                'kodi_type': kodi_type,
                'file': path,
                'xml_video_element': item,
                'listitem': listitem,
                'part': part,
                'playcount': api.getViewCount(),
                'offset': api.getResume(),
                'id': api.getItemId()
            })
    return stack
Ejemplo n.º 11
0
def playlist_item_from_xml(playlist, xml_video_element):
    """
    Returns a playlist element for the playqueue using the Plex xml
    """
    item = Playlist_Item()
    api = API(xml_video_element)
    item.plex_id = api.getRatingKey()
    item.ID = xml_video_element.attrib['%sItemID' % playlist.kind]
    item.guid = xml_video_element.attrib.get('guid')
    if item.plex_id:
        with plexdb.Get_Plex_DB() as plex_db:
            db_element = plex_db.getItem_byId(item.plex_id)
        try:
            item.kodi_id, item.kodi_type = int(db_element[0]), db_element[4]
        except TypeError:
            pass
    log.debug('Created new playlist item from xml: %s' % item)
    return item
Ejemplo n.º 12
0
def playlist_item_from_plex(plex_id):
    """
    Returns a playlist element providing the plex_id ("ratingKey")

    Returns a Playlist_Item
    """
    item = Playlist_Item()
    item.plex_id = plex_id
    with plexdb.Get_Plex_DB() as plex_db:
        plex_dbitem = plex_db.getItem_byId(plex_id)
    try:
        item.kodi_id = plex_dbitem[0]
        item.kodi_type = plex_dbitem[4]
    except:
        raise KeyError('Could not find plex_id %s in database' % plex_id)
    item.plex_UUID = plex_id
    item.uri = ('library://%s/item/library%%2Fmetadata%%2F%s' %
                (item.plex_UUID, plex_id))
    log.debug('Made playlist item from plex: %s' % item)
    return item
Ejemplo n.º 13
0
    def onNotification(self, sender, method, data):

        if data:
            data = loads(data, 'utf-8')
            log.debug("Method: %s Data: %s" % (method, data))

        if method == "Player.OnPlay":
            self.PlayBackStart(data)

        elif method == "Player.OnStop":
            # Should refresh our video nodes, e.g. on deck
            # xbmc.executebuiltin('ReloadSkin()')
            pass

        elif method == "VideoLibrary.OnUpdate":
            # Manually marking as watched/unwatched
            playcount = data.get('playcount')
            item = data.get('item')

            try:
                kodiid = item['id']
                item_type = item['type']
            except (KeyError, TypeError):
                log.info("Item is invalid for playstate update.")
            else:
                # Send notification to the server.
                with plexdb.Get_Plex_DB() as plexcur:
                    plex_dbitem = plexcur.getItem_byKodiId(kodiid, item_type)
                try:
                    itemid = plex_dbitem[0]
                except TypeError:
                    log.error("Could not find itemid in plex database for a "
                              "video library update")
                else:
                    # Stop from manually marking as watched unwatched, with
                    # actual playback.
                    if window('plex_skipWatched%s' % itemid) == "true":
                        # property is set in player.py
                        window('plex_skipWatched%s' % itemid, clear=True)
                    else:
                        # notify the server
                        if playcount > 0:
                            scrobble(itemid, 'watched')
                        else:
                            scrobble(itemid, 'unwatched')

        elif method == "VideoLibrary.OnRemove":
            pass

        elif method == "System.OnSleep":
            # Connection is going to sleep
            log.info("Marking the server as offline. SystemOnSleep activated.")
            window('plex_online', value="sleep")

        elif method == "System.OnWake":
            # Allow network to wake up
            sleep(10000)
            window('plex_onWake', value="true")
            window('plex_online', value="false")

        elif method == "GUI.OnScreensaverDeactivated":
            if settings('dbSyncScreensaver') == "true":
                sleep(5000)
                plex_command('RUN_LIB_SCAN', 'full')

        elif method == "System.OnQuit":
            log.info('Kodi OnQuit detected - shutting down')
            state.STOP_PKC = True