예제 #1
0
 def __init__(self, callback):
     self.mgr = callback
     self.doUtils = DownloadUtils().downloadUrl
     self.xbmcplayer = Player()
     self.playqueue = self.mgr.playqueue
     Monitor.__init__(self)
     log.info("Kodi monitor started.")
예제 #2
0
 def __init__(self):
     """KodiPlayer initialisation"""
     Player.__init__(self)
     self.listen = False
     self.path = None
     self.av_started = False
     self.stream_path = None
예제 #3
0
 def __init__(self):
     """ Initialises a custom Player object """
     self.__listen = False
     self.__av_started = False
     self.__path = None
     self.__subtitle_paths = None
     Player.__init__(self)
예제 #4
0
파일: player.py 프로젝트: camster1/RTOTV
 def onControl(self, control):
     if control == self.pause:
         Player().pause()
     elif control == self.play:
         Player().pause()
     elif control == self.next:
         page = int(ADDON.getSetting('page'))
         if page < len(self.data) / config['list']['per_page']:
             ADDON.setSetting('page', str(page + 1))
             self.draw_channels()
             self.update_pagination()
             self.setFocus(self.controls['buttons'][0])
     elif control == self.prev:
         page = int(ADDON.getSetting('page'))
         if page > 0:
             ADDON.setSetting('page', str(page - 1))
             self.draw_channels()
             self.update_pagination()
             self.setFocus(
                 self.controls['buttons'][len(self.controls['buttons']) -
                                          1])
     else:
         ADDON.setSetting('channel', control.getLabel())
         ADDON.setSetting(
             'current', self.data[int(ADDON.getSetting('channel'))]['meta'])
         self.setProperty(
             'current', self.data[int(ADDON.getSetting('channel'))]['meta'])
         Player().play(self.data[int(
             ADDON.getSetting('channel'))]['stream'])
         self.update_channel()
예제 #5
0
    def __run(self):
        """
        Do the work
        """
        log.debug('Show sync info thread started')
        # cache local variables because it's faster
        total = self.total
        dialog = DialogProgressBG('dialoglogProgressBG')
        thread_stopped = self.thread_stopped
        dialog.create("%s %s: %s %s" %
                      (lang(39714), self.item_type, str(total), lang(39715)))
        player = Player()

        total = 2 * total
        totalProgress = 0
        while thread_stopped() is False and not player.isPlaying():
            with LOCK:
                get_progress = GET_METADATA_COUNT
                process_progress = PROCESS_METADATA_COUNT
                viewName = PROCESSING_VIEW_NAME
            totalProgress = get_progress + process_progress
            try:
                percentage = int(float(totalProgress) / float(total) * 100.0)
            except ZeroDivisionError:
                percentage = 0
            dialog.update(percentage,
                          message="%s %s. %s %s: %s" %
                          (get_progress, lang(39712), process_progress,
                           lang(39713), viewName))
            # Sleep for x milliseconds
            sleep(200)
        dialog.close()
        log.debug('Show sync info thread terminated')
예제 #6
0
 def __init__(self, kodi=None):
     """ Initialises a custom Player object
     :type kodi: resources.lib.kodiwrapper.KodiWrapper
     """
     self._kodi = kodi
     self.__listen = False
     self.__av_started = False
     self.__path = None
     self.__subtitle_path = None
     Player.__init__(self)
예제 #7
0
 def __init__(self):
     Player.__init__(self)
     #   self.sharedMem = SharedMemory('myfunkyname', True, 1)
     self.buttonLock = threading.Lock()
     self.preloadLock = threading.Lock()
     self.buttons = []
     self.preload = {}
     self.id2buttons = {}
     self.id2preload = {}
     _thread.start_new_thread(self.setupListener, ())
     self.providers = setupProviders()
예제 #8
0
 def __init__(self, **kwargs):
     ''' PlayerInfo initialisation '''
     self._info = kwargs['info']
     self._path = None
     self._paused = False
     self._last_pos = None
     self._total = None
     self._stop = Event()
     from random import randint
     self._id = randint(1, 10001)
     log(2, '[PlayerInfo] %d initialized' % self._id)
     Player.__init__(self)
예제 #9
0
def PLAY(url, name, sub_files=[]):
    link = get_html(url)
    match = re.compile('\'(.+?.m3u8)\'').findall(link)
    for u in match:
        listitem = xbmcgui.ListItem(name)
        listitem.setInfo('video', {'Title': name, 'Genre': 'Humor'})
        Player().play(unquote(u), listitem)
        while not Player().isPlaying():
            sleep(10)  # wait until video is being played
        for s in save_subs(path=addon.getAddonInfo('path'),
                           subs_href=sub_files,
                           url=url):
            Player().setSubtitles(s)
예제 #10
0
 def __init__(self):
     LOG.info("----===## Starting PlexCompanion ##===----")
     # Init Plex Companion queue
     # Start GDM for server/client discovery
     self.client = plexgdm.plexgdm()
     self.client.clientDetails()
     LOG.debug("Registration string is:\n%s",
               self.client.getClientDetails())
     # kodi player instance
     self.player = Player()
     self.httpd = False
     self.subscription_manager = None
     Thread.__init__(self)
예제 #11
0
def threaded_playback(kodi_playlist, startpos, offset):
    """
    Seek immediately after kicking off playback is not reliable.
    """
    player = Player()
    player.play(kodi_playlist, None, False, startpos)
    if offset and offset != '0':
        i = 0
        while not player.isPlaying():
            sleep(100)
            i += 1
            if i > 100:
                LOG.error('Could not seek to %s', offset)
                return
        js.seek_to(int(offset))
예제 #12
0
def skip_to(params):
    """
    Skip to a specific playlist position.

    Does not seem to be implemented yet by Plex!
    """
    playqueue_item_id = params.get('playQueueItemID')
    _, plex_id = GetPlexKeyNumber(params.get('key'))
    LOG.debug('Skipping to playQueueItemID %s, plex_id %s', playqueue_item_id,
              plex_id)
    found = True
    for player in js.get_players().values():
        playqueue = PQ.PLAYQUEUES[player['playerid']]
        for i, item in enumerate(playqueue.items):
            if item.id == playqueue_item_id:
                found = True
                break
        else:
            for i, item in enumerate(playqueue.items):
                if item.plex_id == plex_id:
                    found = True
                    break
        if found is True:
            Player().play(playqueue.kodi_pl, None, False, i)
        else:
            LOG.error('Item not found to skip to')
예제 #13
0
 def __init__(self):
     self.xbmcplayer = Player()
     Monitor.__init__(self)
     for playerid in state.PLAYER_STATES:
         state.PLAYER_STATES[playerid] = dict(state.PLAYSTATE)
         state.OLD_PLAYER_STATES[playerid] = dict(state.PLAYSTATE)
     LOG.info("Kodi monitor started.")
예제 #14
0
 def __init__(self, callback):
     self.mgr = callback
     self.doUtils = downloadutils.DownloadUtils().downloadUrl
     self.xbmcplayer = Player()
     self.playqueue = self.mgr.playqueue
     Monitor.__init__(self)
     log.info("Kodi monitor started.")
def play_channel(category_id, channel_id):
    """
    Plays selected song
    :param category_id: Selected category ID
    :param channel_id: Selected channel ID
    :return:
    """
    api = API()
    user = User()
    is_authenticated = user.authenticate()
    recent_tracks_url = ''
    channel = [
        item for item in api.get_channels(int(category_id))
        if item['id'] == int(channel_id)
    ][0]
    url = api.get_streaming_url(channel['streams'], user.username, user.token,
                                user.is_authenticated())

    if is_authenticated:
        recent_tracks_url = channel['recent_tracks']['vip']
    elif 'free' in channel['recent_tracks']:
        recent_tracks_url = channel['recent_tracks']['free']

    # is there a valid URL for channel?
    if url:
        url = quote(url, safe=':/?=@')
        li = ListItem(channel['title'], channel['description'],
                      channel['image'])
        li.setArt({
            'thumb':
            '{0}/{1}'.format(config['urls']['calm_arts_host'],
                             channel['image']),
            'fanart':
            '{0}{1}'.format(config['urls']['calm_blurred_arts_host'],
                            channel['image'])
        })
        li.setInfo(
            'music', {
                'Title': channel['title'].replace('CALM RADIO -', '').title(),
                'Artist': channel['description']
            })
        li.setProperty('mimetype', 'audio/mpeg')
        li.setProperty('IsPlayable', 'true')
        li.setInfo(
            'music',
            {'Title': channel['title'].replace('CALM RADIO -', '').title()})
        Player().play(item=url, listitem=li)

        log('Playing url: {0}'.format(url))
        update_artwork(channel, recent_tracks_url)
    else:
        # members only access
        dialog = Dialog()
        ret = dialog.yesno(ADDON.getLocalizedString(32200),
                           ADDON.getLocalizedString(32201))
        if ret == 1:
            ADDON.openSettings()
예제 #16
0
    def __init__(self, jsonClass, RequestMgr):
        self.serverlist = []
        self.subscribers = {}
        self.info = {}
        self.lastkey = ""
        self.containerKey = ""
        self.lastratingkey = ""
        self.volume = 0
        self.mute = '0'
        self.server = ""
        self.protocol = "http"
        self.port = ""
        self.playerprops = {}
        self.doUtils = downloadutils.DownloadUtils().downloadUrl
        self.xbmcplayer = Player()

        self.js = jsonClass
        self.RequestMgr = RequestMgr
예제 #17
0
def playback_init(plex_id, plex_type, playqueue):
    """
    Playback setup if Kodi starts playing an item for the first time.
    """
    LOG.info('Initializing PKC playback')
    xml = GetPlexMetadata(plex_id)
    try:
        xml[0].attrib
    except (IndexError, TypeError, AttributeError):
        LOG.error('Could not get a PMS xml for plex id %s', plex_id)
        # "Play error"
        dialog('notification', lang(29999), lang(30128), icon='{error}')
        return
    trailers = False
    api = API(xml[0])
    if (plex_type == v.PLEX_TYPE_MOVIE and not api.getResume()
            and settings('enableCinema') == "true"):
        if settings('askCinema') == "true":
            # "Play trailers?"
            trailers = dialog('yesno', lang(29999), lang(33016))
            trailers = True if trailers else False
        else:
            trailers = True
    LOG.debug('Playing trailers: %s', trailers)
    playqueue.clear()
    if plex_type != v.PLEX_TYPE_CLIP:
        # Post to the PMS to create a playqueue - in any case due to Companion
        xml = init_plex_playqueue(plex_id,
                                  xml.attrib.get('librarySectionUUID'),
                                  mediatype=plex_type,
                                  trailers=trailers)
        if xml is None:
            LOG.error('Could not get a playqueue xml for plex id %s, UUID %s',
                      plex_id, xml.attrib.get('librarySectionUUID'))
            # "Play error"
            dialog('notification', lang(29999), lang(30128), icon='{error}')
            return
        # Should already be empty, but just in case
        PL.get_playlist_details_from_xml(playqueue, xml)
    stack = _prep_playlist_stack(xml)
    # Sleep a bit to let setResolvedUrl do its thing - bit ugly
    sleep(200)
    _process_stack(playqueue, stack)
    # Reset some playback variables
    state.CONTEXT_MENU_PLAY = False
    state.FORCE_TRANSCODE = False
    # New thread to release this one sooner (e.g. harddisk spinning up)
    thread = Thread(target=Player().play, args=(playqueue.kodi_pl, ))
    thread.setDaemon(True)
    LOG.info('Done initializing PKC playback, starting Kodi player')
    # By design, PKC will start Kodi playback using Player().play(). Kodi
    # caches paths like our plugin://pkc. If we use Player().play() between
    # 2 consecutive startups of exactly the same Kodi library item, Kodi's
    # cache will have been flushed for some reason. Hence the 2nd call for
    # plugin://pkc will be lost; Kodi will try to startup playback for an empty
    # path: log entry is "CGUIWindowVideoBase::OnPlayMedia <missing path>"
    thread.start()
예제 #18
0
 def onClick(self, controlId):  # pylint: disable=invalid-name
     if controlId == 3012:  # Watch now
         self.set_watch_now(True)
         self.close()
     elif controlId == 3013:  # Close / Stop
         self.set_cancel(True)
         if get_setting_bool('stopAfterClose'):
             Player().stop()
         self.close()
예제 #19
0
def play_video(videoId):
    video = repository.get_video(videoId)
    streams = repository.get_video_streams(video.streamId)

    item = ListItem(path=streams[0].url)
    item.setProperty(u'IsPlayable', u'true')
    item.setInfo(
        type='Video',
        infoLabels={'Title': video.title, 'Plot': video.description}
    )

    analytics.trackVideoPlayed(video.slug)

    playlist = PlayList(PLAYLIST_VIDEO)
    playlist.clear()
    playlist.add(streams[0].url, item)

    player = Player()
    player.play(playlist)
예제 #20
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
예제 #21
0
 def __init__(self):
     self.subscribers = {}
     self.info = {}
     self.lastkey = ""
     self.containerKey = ""
     self.lastratingkey = ""
     self.volume = 0
     self.mute = '0'
     self.server = ""
     self.protocol = "http"
     self.port = ""
     self.playerprops = {}
     self.download = downloadutils.DownloadUtils()
     self.xbmcplayer = Player()
예제 #22
0
def skipTo(params):
    # Does not seem to be implemented yet
    playQueueItemID = params.get('playQueueItemID', 'not available')
    library, plex_id = GetPlexKeyNumber(params.get('key'))
    log.debug('Skipping to playQueueItemID %s, plex_id %s' %
              (playQueueItemID, plex_id))
    found = True
    playqueues = Playqueue()
    for (player, ID) in getPlayers().iteritems():
        playqueue = playqueues.get_playqueue_from_type(player)
        for i, item in enumerate(playqueue.items):
            if item.ID == playQueueItemID or item.plex_id == plex_id:
                break
        else:
            log.debug('Item not found to skip to')
            found = False
        if found:
            Player().play(playqueue.kodi_pl, None, False, i)
예제 #23
0
 def init_playqueue_from_plex_children(self, plex_id):
     """
     Init a new playqueue e.g. from an album. Alexa does this
     """
     xml = GetAllPlexChildren(plex_id)
     try:
         xml[0].attrib
     except (TypeError, IndexError, AttributeError):
         log.error('Could not download the PMS xml for %s' % plex_id)
         return
     playqueue = self.get_playqueue_from_type(
         v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[xml[0].attrib['type']])
     playqueue.clear()
     for i, child in enumerate(xml):
         api = API(child)
         PL.add_item_to_playlist(playqueue, i, plex_id=api.getRatingKey())
     log.debug('Firing up Kodi player')
     Player().play(playqueue.kodi_pl, None, False, 0)
예제 #24
0
    def __init__(self, jsonClass, RequestMgr):
        self.serverlist = []
        self.subscribers = {}
        self.info = {}
        self.lastkey = ""
        self.containerKey = ""
        self.lastratingkey = ""
        self.volume = 0
        self.mute = '0'
        self.server = ""
        self.protocol = "http"
        self.port = ""
        self.playerprops = {}
        self.doUtils = downloadutils.DownloadUtils().downloadUrl
        self.xbmcplayer = Player()

        self.js = jsonClass
        self.RequestMgr = RequestMgr
예제 #25
0
    def update_playqueue_from_PMS(self,
                                  playqueue,
                                  playqueue_id=None,
                                  repeat=None,
                                  offset=None):
        """
        Completely updates the Kodi playqueue with the new Plex playqueue. Pass
        in playqueue_id if we need to fetch a new playqueue

        repeat = 0, 1, 2
        offset = time offset in Plextime (milliseconds)
        """
        log.info('New playqueue %s received from Plex companion with offset '
                 '%s, repeat %s' % (playqueue_id, offset, repeat))
        with lock:
            xml = PL.get_PMS_playlist(playqueue, playqueue_id)
            playqueue.clear()
            try:
                PL.get_playlist_details_from_xml(playqueue, xml)
            except KeyError:
                log.error('Could not get playqueue ID %s' % playqueue_id)
                return
            PlaybackUtils(xml, playqueue).play_all()
            playqueue.repeat = 0 if not repeat else int(repeat)
            window('plex_customplaylist', value="true")
            if offset not in (None, "0"):
                window('plex_customplaylist.seektime',
                       str(ConvertPlexToKodiTime(offset)))
            for startpos, item in enumerate(playqueue.items):
                if item.ID == playqueue.selectedItemID:
                    break
            else:
                startpos = 0
            # Start playback. Player does not return in time
            log.debug('Playqueues after Plex Companion update are now: %s' %
                      self.playqueues)
            thread = Thread(target=Player().play,
                            args=(playqueue.kodi_pl, None, False, startpos))
            thread.setDaemon(True)
            thread.start()
예제 #26
0
    def update_progress_control(self, remaining=None, runtime=None):
        self.current_progress_percent = self.current_progress_percent - self.progress_step_size
        try:
            self.progress_control = self.getControl(3014)
        except RuntimeError:  # Occurs when skin does not include progress control
            pass
        else:
            self.progress_control.setPercent(self.current_progress_percent)  # pylint: disable=no-member,useless-suppression

        if remaining:
            self.setProperty('remaining', from_unicode('%02d' % remaining))
        if runtime:
            self.setProperty(
                'endtime',
                from_unicode(
                    localize_time(datetime.now() +
                                  timedelta(seconds=runtime))))
        if self.current_progress_percent <= 0:
            if get_setting_int('autoPlayMode') == 0:
                self.set_watch_now(True)
            else:
                Player().stop()
예제 #27
0
def init_playqueue_from_plex_children(plex_id, transient_token=None):
    """
    Init a new playqueue e.g. from an album. Alexa does this

    Returns the Playlist_Object
    """
    xml = GetAllPlexChildren(plex_id)
    try:
        xml[0].attrib
    except (TypeError, IndexError, AttributeError):
        LOG.error('Could not download the PMS xml for %s', plex_id)
        return
    playqueue = get_playqueue_from_type(
        v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[xml[0].attrib['type']])
    playqueue.clear()
    for i, child in enumerate(xml):
        api = API(child)
        PL.add_item_to_playlist(playqueue, i, plex_id=api.plex_id())
    playqueue.plex_transient_token = transient_token
    LOG.debug('Firing up Kodi player')
    Player().play(playqueue.kodi_pl, None, False, 0)
    return playqueue
def Plex_Node(url, viewOffset, plex_type, playdirectly=False):
    """
    Called only for a SINGLE element for Plex.tv watch later

    Always to return with a "setResolvedUrl"
    """
    log.info('Plex_Node called with url: %s, viewOffset: %s' %
             (url, viewOffset))
    # Plex redirect, e.g. watch later. Need to get actual URLs
    xml = downloadutils.DownloadUtils().downloadUrl(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))
    typus = v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[plex_type]
    playqueue = Playqueue().get_playqueue_from_type(typus)
    result = pbutils.PlaybackUtils(xml, playqueue).play(
        None,
        kodi_id='plexnode',
        plex_lib_UUID=xml.attrib.get('librarySectionUUID'))
    if result.listitem:
        listitem = convert_PKC_to_listitem(result.listitem)
    else:
        return
    if playdirectly:
        Player().play(listitem.getfilename(), listitem)
    else:
        xbmcplugin.setResolvedUrl(HANDLE, True, listitem)
예제 #29
0
 def __init__(self):
     self.api = Api()
     self.state = State()
     self.monitor = Monitor()
     Player.__init__(self)
예제 #30
0
addon_handle = int(sys.argv[1])
xbmcplugin.setContent(addon_handle, 'movies')

dialog = xbmcgui.Dialog()
input_data = dialog.input('Ingresar nombre, temporada y capitulo',
                         type=xbmcgui.INPUT_ALPHANUM)

input_data = input_data.split('/')
name, season, episode = input_data

args = {'name': name,
        'season': season,
        'episode': episode,
        'serve': True
        }
t = Thread(target=watch, kwargs=args)
t.start()


dialog = xbmcgui.Dialog()
dialog.notification('touchandgo', 'touchandgo is starting waith for it.',
                      xbmcgui.NOTIFICATION_INFO, 60000)

video_url = "http://localhost:8888/"

player = Player(xbmc.PLAYER_CORE_AUTO)
player.play(video_url)


예제 #31
0
class KodiMonitor(Monitor):

    def __init__(self, callback):
        self.mgr = callback
        self.doUtils = downloadutils.DownloadUtils().downloadUrl
        self.xbmcplayer = Player()
        self.playqueue = self.mgr.playqueue
        Monitor.__init__(self)
        log.info("Kodi monitor started.")

    def onScanStarted(self, library):
        log.debug("Kodi library scan %s running." % library)
        if library == "video":
            window('plex_kodiScan', value="true")

    def onScanFinished(self, library):
        log.debug("Kodi library scan %s finished." % library)
        if library == "video":
            window('plex_kodiScan', clear=True)

    def onSettingsChanged(self):
        """
        Monitor the PKC settings for changes made by the user
        """
        # settings: window-variable
        items = {
            'logLevel': 'plex_logLevel',
            'enableContext': 'plex_context',
            'plex_restricteduser': '******',
            'dbSyncIndicator': 'dbSyncIndicator',
            'remapSMB': 'remapSMB',
            'replaceSMB': 'replaceSMB',
            'force_transcode_pix': 'plex_force_transcode_pix',
            'fetch_pms_item_number': 'fetch_pms_item_number'
        }
        # Path replacement
        for typus in REMAP_TYPE_FROM_PLEXTYPE.values():
            for arg in ('Org', 'New'):
                key = 'remapSMB%s%s' % (typus, arg)
                items[key] = key
        # Reset the window variables from the settings variables
        for settings_value, window_value in items.iteritems():
            if window(window_value) != settings(settings_value):
                log.debug('PKC settings changed: %s is now %s'
                          % (settings_value, settings(settings_value)))
                window(window_value, value=settings(settings_value))
                if settings_value == 'fetch_pms_item_number':
                    log.info('Requesting playlist/nodes refresh')
                    window('plex_runLibScan', value="views")

    @CatchExceptions(warnuser=False)
    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)
                window('plex_runLibScan', value="full")

    def PlayBackStart(self, data):
        """
        Called whenever a playback is started
        """
        # Get currently playing file - can take a while. Will be utf-8!
        try:
            currentFile = self.xbmcplayer.getPlayingFile()
        except:
            currentFile = None
            count = 0
            while currentFile is None:
                sleep(100)
                try:
                    currentFile = self.xbmcplayer.getPlayingFile()
                except:
                    pass
                if count == 50:
                    log.info("No current File, cancel OnPlayBackStart...")
                    return
                else:
                    count += 1
        # Just to be on the safe side
        currentFile = tryDecode(currentFile)
        log.debug("Currently playing file is: %s" % currentFile)

        # Get the type of media we're playing
        try:
            typus = data['item']['type']
        except (TypeError, KeyError):
            log.info("Item is invalid for PMS playstate update.")
            return
        log.debug("Playing itemtype is (or appears to be): %s" % typus)

        # Try to get a Kodi ID
        # If PKC was used - native paths, not direct paths
        plexid = window('plex_%s.itemid' % tryEncode(currentFile))
        # Get rid of the '' if the window property was not set
        plexid = None if not plexid else plexid
        kodiid = None
        if plexid is None:
            log.debug('Did not get Plex id from window properties')
            try:
                kodiid = data['item']['id']
            except (TypeError, KeyError):
                log.debug('Did not get a Kodi id from Kodi, darn')
        # For direct paths, if we're not streaming something
        # When using Widgets, Kodi doesn't tell us shit so we need this hack
        if (kodiid is None and plexid is None and typus != 'song'
                and not currentFile.startswith('http')):
            (kodiid, typus) = get_kodiid_from_filename(currentFile)
            if kodiid is None:
                return

        if plexid is None:
            # Get Plex' item id
            with plexdb.Get_Plex_DB() as plexcursor:
                plex_dbitem = plexcursor.getItem_byKodiId(kodiid, typus)
            try:
                plexid = plex_dbitem[0]
            except TypeError:
                log.info("No Plex id returned for kodiid %s. Aborting playback"
                         " report" % kodiid)
                return
        log.debug("Found Plex id %s for Kodi id %s for type %s"
                  % (plexid, kodiid, typus))

        # Set some stuff if Kodi initiated playback
        if ((settings('useDirectPaths') == "1" and not typus == "song")
                or
                (typus == "song" and settings('enableMusic') == "true")):
            if self.StartDirectPath(plexid,
                                    typus,
                                    tryEncode(currentFile)) is False:
                log.error('Could not initiate monitoring; aborting')
                return

        # Save currentFile for cleanup later and to be able to access refs
        window('plex_lastPlayedFiled', value=currentFile)
        window('plex_currently_playing_itemid', value=plexid)
        window("plex_%s.itemid" % tryEncode(currentFile), value=plexid)
        log.info('Finish playback startup')

    def StartDirectPath(self, plexid, type, currentFile):
        """
        Set some additional stuff if playback was initiated by Kodi, not PKC
        """
        xml = self.doUtils('{server}/library/metadata/%s' % plexid)
        try:
            xml[0].attrib
        except:
            log.error('Did not receive a valid XML for plexid %s.' % plexid)
            return False
        # Setup stuff, because playback was started by Kodi, not PKC
        api = API(xml[0])
        listitem = api.CreateListItemFromPlexItem()
        api.set_playback_win_props(currentFile, listitem)
        if type == "song" and settings('streamMusic') == "true":
            window('plex_%s.playmethod' % currentFile, value="DirectStream")
        else:
            window('plex_%s.playmethod' % currentFile, value="DirectPlay")
        log.debug('Window properties set for direct paths!')
예제 #32
0
class SubscriptionManager:
    def __init__(self, jsonClass, RequestMgr):
        self.serverlist = []
        self.subscribers = {}
        self.info = {}
        self.lastkey = ""
        self.containerKey = ""
        self.lastratingkey = ""
        self.volume = 0
        self.mute = '0'
        self.server = ""
        self.protocol = "http"
        self.port = ""
        self.playerprops = {}
        self.doUtils = downloadutils.DownloadUtils().downloadUrl
        self.xbmcplayer = Player()

        self.js = jsonClass
        self.RequestMgr = RequestMgr

    def getServerByHost(self, host):
        if len(self.serverlist) == 1:
            return self.serverlist[0]
        for server in self.serverlist:
            if (server.get('serverName') in host or
                    server.get('server') in host):
                return server
        return {}

    def getVolume(self):
        self.volume, self.mute = self.js.getVolume()

    def msg(self, players):
        msg = getXMLHeader()
        msg += '<MediaContainer commandID="INSERTCOMMANDID"'
        if players:
            self.getVolume()
            maintype = plex_audio()
            for p in players.values():
                if p.get('type') == xbmc_video():
                    maintype = plex_video()
                elif p.get('type') == xbmc_photo():
                    maintype = plex_photo()
            self.mainlocation = "fullScreen" + maintype[0:1].upper() + maintype[1:].lower()
        else:
            self.mainlocation = "navigation"
        msg += ' location="%s">' % self.mainlocation
        msg += self.getTimelineXML(self.js.getAudioPlayerId(players), plex_audio())
        msg += self.getTimelineXML(self.js.getPhotoPlayerId(players), plex_photo())
        msg += self.getTimelineXML(self.js.getVideoPlayerId(players), plex_video())
        msg += "\r\n</MediaContainer>"
        return msg
        
    def getTimelineXML(self, playerid, ptype):
        if playerid is not None:
            info = self.getPlayerProperties(playerid)
            # save this info off so the server update can use it too
            self.playerprops[playerid] = info;
            state = info['state']
            time = info['time']
        else:
            state = "stopped"
            time = 0
        ret = "\r\n"+'  <Timeline state="%s" time="%s" type="%s"' % (state, time, ptype)
        if playerid is None:
            ret += ' seekRange="0-0"'
            ret += ' />'
            return ret

        # pbmc_server = str(WINDOW.getProperty('plexbmc.nowplaying.server'))
        # userId = str(WINDOW.getProperty('currUserId'))
        pbmc_server = window('pms_server')
        if pbmc_server:
            (self.protocol, self.server, self.port) = \
                pbmc_server.split(':')
            self.server = self.server.replace('/', '')
        keyid = None
        count = 0
        while not keyid:
            if count > 300:
                break
            keyid = window('Plex_currently_playing_itemid')
            xbmc.sleep(100)
            count += 1
        if keyid:
            self.lastkey = "/library/metadata/%s"%keyid
            self.lastratingkey = keyid
            ret += ' location="%s"' % (self.mainlocation)
            ret += ' key="%s"' % (self.lastkey)
            ret += ' ratingKey="%s"' % (self.lastratingkey)
        serv = self.getServerByHost(self.server)
        if info.get('playQueueID'):
            self.containerKey = "/playQueues/%s" % info.get('playQueueID')
            ret += ' playQueueID="%s"' % info.get('playQueueID')
            ret += ' playQueueVersion="%s"' % info.get('playQueueVersion')
            ret += ' playQueueItemID="%s"' % (info.get('playQueueItemID'))
            ret += ' containerKey="%s"' % self.containerKey
        elif keyid:
            self.containerKey = self.lastkey
            ret += ' containerKey="%s"' % (self.containerKey)

        ret += ' duration="%s"' % info['duration']
        ret += ' seekRange="0-%s"' % info['duration']
        ret += ' controllable="%s"' % self.controllable()
        ret += ' machineIdentifier="%s"' % serv.get('uuid', "")
        ret += ' protocol="%s"' % serv.get('protocol', "http")
        ret += ' address="%s"' % serv.get('server', self.server)
        ret += ' port="%s"' % serv.get('port', self.port)
        ret += ' guid="%s"' % info['guid']
        ret += ' volume="%s"' % info['volume']
        ret += ' shuffle="%s"' % info['shuffle']
        ret += ' mute="%s"' % self.mute
        ret += ' repeat="%s"' % info['repeat']
        # Might need an update in the future
        ret += ' subtitleStreamID="-1"'
        ret += ' audioStreamID="-1"'

        ret += ' />'
        return ret

    def updateCommandID(self, uuid, commandID):
        if commandID and self.subscribers.get(uuid, False):
            self.subscribers[uuid].commandID = int(commandID)            
        
    def notify(self, event = False):
        self.cleanup()
        # Don't tell anyone if we don't know a Plex ID and are still playing
        # (e.g. no stop called). Used for e.g. PVR/TV without PKC usage
        if not window('Plex_currently_playing_itemid'):
            return True
        players = self.js.getPlayers()
        # fetch the message, subscribers or not, since the server
        # will need the info anyway
        msg = self.msg(players)
        if self.subscribers:
            with threading.RLock():
                for sub in self.subscribers.values():
                    sub.send_update(msg, len(players)==0)
        self.notifyServer(players)
        return True
    
    def notifyServer(self, players):
        if not players:
            return True
        for p in players.values():
            info = self.playerprops[p.get('playerid')]
            params = {'state': 'stopped'}
            params['containerKey'] = (self.containerKey or "/library/metadata/900000")
            if info.get('playQueueID'):
                params['containerKey'] = '/playQueues/' + info['playQueueID']
                params['playQueueVersion'] = info['playQueueVersion']
                params['playQueueItemID'] = info['playQueueItemID']
            params['key'] = (self.lastkey or "/library/metadata/900000")
            params['ratingKey'] = (self.lastratingkey or "900000")
            params['state'] = info['state']
            params['time'] = info['time']
            params['duration'] = info['duration']

            serv = self.getServerByHost(self.server)
            url = serv.get('protocol', 'http') + '://' \
                + serv.get('server', 'localhost') + ':' \
                + serv.get('port', '32400') + "/:/timeline"
            self.doUtils(url, type="GET", parameters=params)
            # requests.getwithparams(serv.get('server', 'localhost'), serv.get('port', 32400), "/:/timeline", params, getPlexHeaders(), serv.get('protocol', 'http'))
            self.logMsg("sent server notification with state = %s"
                        % params['state'], 2)

    def controllable(self):
        return "volume,shuffle,repeat,audioStream,videoStream,subtitleStream,skipPrevious,skipNext,seekTo,stepBack,stepForward,stop,playPause"

    def addSubscriber(self, protocol, host, port, uuid, commandID):
        sub = Subscriber(protocol,
                         host,
                         port,
                         uuid,
                         commandID,
                         self,
                         self.RequestMgr)
        with threading.RLock():
            self.subscribers[sub.uuid] = sub
        return sub

    def removeSubscriber(self, uuid):
        with threading.RLock():
            for sub in self.subscribers.values():
                if sub.uuid == uuid or sub.host == uuid:
                    sub.cleanup()
                    del self.subscribers[sub.uuid]

    def cleanup(self):
        with threading.RLock():
            for sub in self.subscribers.values():
                if sub.age > 30:
                    sub.cleanup()
                    del self.subscribers[sub.uuid]
            
    def getPlayerProperties(self, playerid):
        info = {}
        try:
            # get info from the player
            props = self.js.jsonrpc("Player.GetProperties", {"playerid": playerid, "properties": ["time", "totaltime", "speed", "shuffled", "repeat"]})
            self.logMsg(self.js.jsonrpc("Player.GetItem", {"playerid": playerid, "properties": ["file", "showlink", "episode", "season"]}), 2)
            info['time'] = timeToMillis(props['time'])
            info['duration'] = timeToMillis(props['totaltime'])
            info['state'] = ("paused", "playing")[int(props['speed'])]
            info['shuffle'] = ("0","1")[props.get('shuffled', False)]
            info['repeat'] = pf.getPlexRepeat(props.get('repeat'))
            # New PMS playQueue attributes
            cf = self.xbmcplayer.getPlayingFile()
            info['playQueueID'] = window('playQueueID')
            info['playQueueVersion'] = window('playQueueVersion')
            info['playQueueItemID'] = window('plex_%s.playQueueItemID' % cf)
            info['guid'] = window('plex_%s.guid' % cf)

        except:
            info['time'] = 0
            info['duration'] = 0
            info['state'] = "stopped"
            info['shuffle'] = False
        # get the volume from the application
        info['volume'] = self.volume
        info['mute'] = self.mute

        return info
예제 #33
0
 def __new__(cls, lights=[]):
     obj = Player.__new__(cls)
     obj.lights = dict((light, None) for light in lights)
     obj.lights_lock = RLock()
     
     return obj
예제 #34
0
 def __init__(self):
     Player.__init__(self)
     self.ended = False
     self.started = False
예제 #35
0
    def play(self, plex_id, kodi_id=None, plex_lib_UUID=None):
        """
        plex_lib_UUID: xml attribute 'librarySectionUUID', needed for posting
        to the PMS
        """
        log.info("Playbackutils called")
        item = self.xml[0]
        api = API(item)
        playqueue = self.playqueue
        xml = None
        result = Playback_Successful()
        listitem = ListItem()
        playutils = putils.PlayUtils(item)
        playurl = playutils.getPlayUrl()
        if not playurl:
            log.error('No playurl found, aborting')
            return

        if kodi_id in (None, 'plextrailer', 'plexnode'):
            # Item is not in Kodi database, is a trailer/clip or plex redirect
            # e.g. plex.tv watch later
            api.CreateListItemFromPlexItem(listitem)
            api.set_listitem_artwork(listitem)
            if kodi_id == 'plexnode':
                # Need to get yet another xml to get final url
                window('plex_%s.playmethod' % playurl, clear=True)
                xml = downloadutils.DownloadUtils().downloadUrl(
                    '{server}%s' % item[0][0].attrib.get('key'))
                try:
                    xml[0].attrib
                except (TypeError, AttributeError):
                    log.error('Could not download %s' %
                              item[0][0].attrib.get('key'))
                    return
                playurl = tryEncode(xml[0].attrib.get('key'))
                window('plex_%s.playmethod' % playurl, value='DirectStream')

            playmethod = window('plex_%s.playmethod' % playurl)
            if playmethod == "Transcode":
                playutils.audioSubsPref(listitem, tryDecode(playurl))
            listitem.setPath(playurl)
            api.set_playback_win_props(playurl, listitem)
            result.listitem = listitem
            return result

        kodi_type = v.KODITYPE_FROM_PLEXTYPE[api.getType()]
        kodi_id = int(kodi_id)

        # ORGANIZE CURRENT PLAYLIST ################
        contextmenu_play = window('plex_contextplay') == 'true'
        window('plex_contextplay', clear=True)
        homeScreen = getCondVisibility('Window.IsActive(home)')
        sizePlaylist = len(playqueue.items)
        if contextmenu_play:
            # Need to start with the items we're inserting here
            startPos = sizePlaylist
        else:
            # Can return -1
            startPos = max(playqueue.kodi_pl.getposition(), 0)
        self.currentPosition = startPos

        propertiesPlayback = window('plex_playbackProps') == "true"
        introsPlaylist = False
        dummyPlaylist = False

        log.info("Playing from contextmenu: %s" % contextmenu_play)
        log.info("Playlist start position: %s" % startPos)
        log.info("Playlist plugin position: %s" % self.currentPosition)
        log.info("Playlist size: %s" % sizePlaylist)

        # RESUME POINT ################
        seektime, runtime = api.getRuntime()
        if window('plex_customplaylist.seektime'):
            # Already got seektime, e.g. from playqueue & Plex companion
            seektime = int(window('plex_customplaylist.seektime'))

        # We need to ensure we add the intro and additional parts only once.
        # Otherwise we get a loop.
        if not propertiesPlayback:
            window('plex_playbackProps', value="true")
            log.info("Setting up properties in playlist.")
            # Where will the player need to start?
            # Do we need to get trailers?
            trailers = False
            if (api.getType() == v.PLEX_TYPE_MOVIE and not seektime
                    and sizePlaylist < 2
                    and settings('enableCinema') == "true"):
                if settings('askCinema') == "true":
                    trailers = xbmcgui.Dialog().yesno(lang(29999),
                                                      "Play trailers?")
                else:
                    trailers = True
            # Post to the PMS. REUSE THE PLAYQUEUE!
            xml = init_plex_playqueue(plex_id,
                                      plex_lib_UUID,
                                      mediatype=api.getType(),
                                      trailers=trailers)
            try:
                get_playlist_details_from_xml(playqueue, xml=xml)
            except KeyError:
                return

            if (not homeScreen and not seektime and sizePlaylist < 2
                    and window('plex_customplaylist') != "true"
                    and not contextmenu_play):
                # Need to add a dummy file because the first item will fail
                log.debug("Adding dummy file to playlist.")
                dummyPlaylist = True
                add_listitem_to_Kodi_playlist(playqueue, startPos,
                                              xbmcgui.ListItem(), playurl,
                                              xml[0])
                # Remove the original item from playlist
                remove_from_Kodi_playlist(playqueue, startPos + 1)
                # Readd the original item to playlist - via jsonrpc so we have
                # full metadata
                add_item_to_kodi_playlist(playqueue,
                                          self.currentPosition + 1,
                                          kodi_id=kodi_id,
                                          kodi_type=kodi_type,
                                          file=playurl)
                self.currentPosition += 1

            # -- ADD TRAILERS ################
            if trailers:
                for i, item in enumerate(xml):
                    if i == len(xml) - 1:
                        # Don't add the main movie itself
                        break
                    self.add_trailer(item)
                    introsPlaylist = True

            # -- ADD MAIN ITEM ONLY FOR HOMESCREEN ##############
            if homeScreen and not seektime and not sizePlaylist:
                # Extend our current playlist with the actual item to play
                # only if there's no playlist first
                log.info("Adding main item to playlist.")
                add_item_to_kodi_playlist(playqueue, self.currentPosition,
                                          kodi_id, kodi_type)

            elif contextmenu_play:
                if state.DIRECT_PATHS:
                    # Cannot add via JSON with full metadata because then we
                    # Would be using the direct path
                    log.debug("Adding contextmenu item for direct paths")
                    if window('plex_%s.playmethod' % playurl) == "Transcode":
                        playutils.audioSubsPref(listitem, tryDecode(playurl))
                    api.CreateListItemFromPlexItem(listitem)
                    api.set_playback_win_props(playurl, listitem)
                    api.set_listitem_artwork(listitem)
                    add_listitem_to_Kodi_playlist(
                        playqueue,
                        self.currentPosition + 1,
                        convert_PKC_to_listitem(listitem),
                        file=playurl,
                        kodi_item={
                            'id': kodi_id,
                            'type': kodi_type
                        })
                else:
                    # Full metadata$
                    add_item_to_kodi_playlist(playqueue,
                                              self.currentPosition + 1,
                                              kodi_id, kodi_type)
                self.currentPosition += 1
                if seektime:
                    window('plex_customplaylist.seektime', value=str(seektime))

            # Ensure that additional parts are played after the main item
            self.currentPosition += 1

            # -- CHECK FOR ADDITIONAL PARTS ################
            if len(item[0]) > 1:
                self.add_part(item, api, kodi_id, kodi_type)

            if dummyPlaylist:
                # Added a dummy file to the playlist,
                # because the first item is going to fail automatically.
                log.info("Processed as a playlist. First item is skipped.")
                # Delete the item that's gonna fail!
                del playqueue.items[startPos]
                # Don't attach listitem
                return result

        # We just skipped adding properties. Reset flag for next time.
        elif propertiesPlayback:
            log.debug("Resetting properties playback flag.")
            window('plex_playbackProps', clear=True)

        # SETUP MAIN ITEM ##########
        # For transcoding only, ask for audio/subs pref
        if (window('plex_%s.playmethod' % playurl) == "Transcode"
                and not contextmenu_play):
            playutils.audioSubsPref(listitem, tryDecode(playurl))

        listitem.setPath(playurl)
        api.set_playback_win_props(playurl, listitem)
        api.set_listitem_artwork(listitem)

        # PLAYBACK ################
        if (homeScreen and seektime and window('plex_customplaylist') != "true"
                and not contextmenu_play):
            log.info("Play as a widget item")
            api.CreateListItemFromPlexItem(listitem)
            result.listitem = listitem
            return result

        elif ((introsPlaylist and window('plex_customplaylist') == "true")
              or (homeScreen and not sizePlaylist) or contextmenu_play):
            # Playlist was created just now, play it.
            # Contextmenu plays always need this
            log.info("Play playlist from starting position %s" % startPos)
            # Need a separate thread because Player won't return in time
            thread = Thread(target=Player().play,
                            args=(playqueue.kodi_pl, None, False, startPos))
            thread.setDaemon(True)
            thread.start()
            # Don't attach listitem
            return result
        else:
            log.info("Play as a regular item")
            result.listitem = listitem
            return result
예제 #36
0
class PlexCompanion(Thread):
    """
    Plex Companion monitoring class. Invoke only once
    """
    def __init__(self):
        LOG.info("----===## Starting PlexCompanion ##===----")
        # Init Plex Companion queue
        # Start GDM for server/client discovery
        self.client = plexgdm.plexgdm()
        self.client.clientDetails()
        LOG.debug("Registration string is:\n%s",
                  self.client.getClientDetails())
        # kodi player instance
        self.player = Player()
        self.httpd = False
        self.subscription_manager = None
        Thread.__init__(self)

    def _process_alexa(self, data):
        xml = PF.GetPlexMetadata(data['key'])
        try:
            xml[0].attrib
        except (AttributeError, IndexError, TypeError):
            LOG.error('Could not download Plex metadata for: %s', data)
            return
        api = API(xml[0])
        if api.plex_type() == v.PLEX_TYPE_ALBUM:
            LOG.debug('Plex music album detected')
            PQ.init_playqueue_from_plex_children(
                api.plex_id(), transient_token=data.get('token'))
        elif data['containerKey'].startswith('/playQueues/'):
            _, container_key, _ = PF.ParseContainerKey(data['containerKey'])
            xml = PF.DownloadChunks('{server}/playQueues/%s?' % container_key)
            if xml is None:
                # "Play error"
                utils.dialog('notification',
                             utils.lang(29999),
                             utils.lang(30128),
                             icon='{error}')
                return
            playqueue = PQ.get_playqueue_from_type(
                v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[api.plex_type()])
            playqueue.clear()
            PL.get_playlist_details_from_xml(playqueue, xml)
            playqueue.plex_transient_token = data.get('token')
            if data.get('offset') != '0':
                offset = float(data['offset']) / 1000.0
            else:
                offset = None
            playback.play_xml(playqueue, xml, offset)
        else:
            state.PLEX_TRANSIENT_TOKEN = data.get('token')
            if data.get('offset') != '0':
                state.RESUMABLE = True
                state.RESUME_PLAYBACK = True
            playback.playback_triage(api.plex_id(),
                                     api.plex_type(),
                                     resolve=False)

    @staticmethod
    def _process_node(data):
        """
        E.g. watch later initiated by Companion. Basically navigating Plex
        """
        state.PLEX_TRANSIENT_TOKEN = data.get('key')
        params = {
            'mode': 'plex_node',
            'key': '{server}%s' % data.get('key'),
            'offset': data.get('offset')
        }
        executebuiltin('RunPlugin(plugin://%s?%s)' %
                       (v.ADDON_ID, urlencode(params)))

    def _process_playlist(self, data):
        # Get the playqueue ID
        _, container_key, query = PF.ParseContainerKey(data['containerKey'])
        try:
            playqueue = PQ.get_playqueue_from_type(
                v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[data['type']])
        except KeyError:
            # E.g. Plex web does not supply the media type
            # Still need to figure out the type (video vs. music vs. pix)
            xml = PF.GetPlexMetadata(data['key'])
            try:
                xml[0].attrib
            except (AttributeError, IndexError, TypeError):
                LOG.error('Could not download Plex metadata')
                return
            api = API(xml[0])
            playqueue = PQ.get_playqueue_from_type(
                v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[api.plex_type()])
        update_playqueue_from_PMS(playqueue,
                                  playqueue_id=container_key,
                                  repeat=query.get('repeat'),
                                  offset=data.get('offset'),
                                  transient_token=data.get('token'))

    def _process_streams(self, data):
        """
        Plex Companion client adjusted audio or subtitle stream
        """
        playqueue = PQ.get_playqueue_from_type(
            v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[data['type']])
        pos = js.get_position(playqueue.playlistid)
        if 'audioStreamID' in data:
            index = playqueue.items[pos].kodi_stream_index(
                data['audioStreamID'], 'audio')
            self.player.setAudioStream(index)
        elif 'subtitleStreamID' in data:
            if data['subtitleStreamID'] == '0':
                self.player.showSubtitles(False)
            else:
                index = playqueue.items[pos].kodi_stream_index(
                    data['subtitleStreamID'], 'subtitle')
                self.player.setSubtitleStream(index)
        else:
            LOG.error('Unknown setStreams command: %s', data)

    def _process_refresh(self, data):
        """
        example data: {'playQueueID': '8475', 'commandID': '11'}
        """
        xml = PL.get_pms_playqueue(data['playQueueID'])
        if xml is None:
            return
        if len(xml) == 0:
            LOG.debug('Empty playqueue received - clearing playqueue')
            plex_type = PL.get_plextype_from_xml(xml)
            if plex_type is None:
                return
            playqueue = PQ.get_playqueue_from_type(
                v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[plex_type])
            playqueue.clear()
            return
        playqueue = PQ.get_playqueue_from_type(
            v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[xml[0].attrib['type']])
        update_playqueue_from_PMS(playqueue, data['playQueueID'])

    def _process_tasks(self, task):
        """
        Processes tasks picked up e.g. by Companion listener, e.g.
        {'action': 'playlist',
         'data': {'address': 'xyz.plex.direct',
                  'commandID': '7',
                  'containerKey': '/playQueues/6669?own=1&repeat=0&window=200',
                  'key': '/library/metadata/220493',
                  'machineIdentifier': 'xyz',
                  'offset': '0',
                  'port': '32400',
                  'protocol': 'https',
                  'token': 'transient-cd2527d1-0484-48e0-a5f7-f5caa7d591bd',
                  'type': 'video'}}
        """
        LOG.debug('Processing: %s', task)
        data = task['data']
        if task['action'] == 'alexa':
            with state.LOCK_PLAYQUEUES:
                self._process_alexa(data)
        elif (task['action'] == 'playlist'
              and data.get('address') == 'node.plexapp.com'):
            self._process_node(data)
        elif task['action'] == 'playlist':
            with state.LOCK_PLAYQUEUES:
                self._process_playlist(data)
        elif task['action'] == 'refreshPlayQueue':
            with state.LOCK_PLAYQUEUES:
                self._process_refresh(data)
        elif task['action'] == 'setStreams':
            try:
                self._process_streams(data)
            except KeyError:
                pass

    def run(self):
        """
        Ensure that sockets will be closed no matter what
        """
        try:
            self._run()
        finally:
            try:
                self.httpd.socket.shutdown(SHUT_RDWR)
            except AttributeError:
                pass
            finally:
                try:
                    self.httpd.socket.close()
                except AttributeError:
                    pass
        LOG.info("----===## Plex Companion stopped ##===----")

    def _run(self):
        httpd = self.httpd
        # Cache for quicker while loops
        client = self.client
        stopped = self.stopped
        suspended = self.suspended

        # Start up instances
        request_mgr = httppersist.RequestMgr()
        subscription_manager = subscribers.SubscriptionMgr(
            request_mgr, self.player)
        self.subscription_manager = subscription_manager

        if utils.settings('plexCompanion') == 'true':
            # Start up httpd
            start_count = 0
            while True:
                try:
                    httpd = listener.ThreadedHTTPServer(
                        client, subscription_manager, ('', v.COMPANION_PORT),
                        listener.MyHandler)
                    httpd.timeout = 0.95
                    break
                except:
                    LOG.error("Unable to start PlexCompanion. Traceback:")
                    import traceback
                    LOG.error(traceback.print_exc())
                sleep(3000)
                if start_count == 3:
                    LOG.error("Error: Unable to start web helper.")
                    httpd = False
                    break
                start_count += 1
        else:
            LOG.info('User deactivated Plex Companion')
        client.start_all()
        message_count = 0
        if httpd:
            thread = Thread(target=httpd.handle_request)

        while not stopped():
            # If we are not authorized, sleep
            # Otherwise, we trigger a download which leads to a
            # re-authorizations
            while suspended():
                if stopped():
                    break
                sleep(1000)
            try:
                message_count += 1
                if httpd:
                    if not thread.isAlive():
                        # Use threads cause the method will stall
                        thread = Thread(target=httpd.handle_request)
                        thread.start()

                    if message_count == 3000:
                        message_count = 0
                        if client.check_client_registration():
                            LOG.debug('Client is still registered')
                        else:
                            LOG.debug(
                                'Client is no longer registered. Plex '
                                'Companion still running on port %s',
                                v.COMPANION_PORT)
                            client.register_as_client()
                # Get and set servers
                if message_count % 30 == 0:
                    subscription_manager.serverlist = client.getServerList()
                    subscription_manager.notify()
                    if not httpd:
                        message_count = 0
            except:
                LOG.warn("Error in loop, continuing anyway. Traceback:")
                import traceback
                LOG.warn(traceback.format_exc())
            # See if there's anything we need to process
            try:
                task = state.COMPANION_QUEUE.get(block=False)
            except Empty:
                pass
            else:
                # Got instructions, process them
                self._process_tasks(task)
                state.COMPANION_QUEUE.task_done()
                # Don't sleep
                continue
            sleep(50)
        subscription_manager.signal_stop()
        client.stop_all()
예제 #37
0
    
    # authenticate with leafs TV
    ltv = authenticate()
    if ltv == None:
        return
    
    # get the archived game URL
    try:
        url = ltv.getArchivedGame(game_id)
    except LeafsTVError, ltvErr:
        dialog = xbmcgui.Dialog()
        dialog.ok(__language__(30008),__language__(30010))
        return

    # play the archived game
    player = Player(xbmc.PLAYER_CORE_AUTO)
    player.play(url)
    
    return


# if the second argument is empty this is the main menu
if (len(sys.argv[2]) == 0):
    createMainMenu()
elif sys.argv[2] == "?url=archived":
    createArchivedMenu()
elif sys.argv[2] == '?url=live':
    createLiveMenu()
else:
    match = re.match('\?archive\=(.*)', sys.argv[2])
    if match != None:
예제 #38
0
if not exists(MyTmp):
    mkdirs(MyTmp)

action = None
if len(sys.argv) >= 2:
    params = getParams(sys.argv[2])
    action = getParam("action", params)

MyLog("Version:%s" % MyVersion)
MyLog("Action:%s" % action)

if action == 'search':
    item = {}

    MyLog("isPlaying:%s" % Player().isPlaying())
    if Player().isPlaying():
        item['year'] = getInfoLabel("VideoPlayer.Year")  # Year

        item['season'] = str(getInfoLabel("VideoPlayer.Season"))  # Season
        if item['season'] == '' or item['season'] < 1:
            item['season'] = 0
        item['episode'] = str(getInfoLabel("VideoPlayer.Episode"))  # Episode
        if item['episode'] == '' or item['episode'] < 1:
            item['episode'] = 0

        if item['episode'] == 0:
            item['title'] = lowercase_with_underscores(
                getInfoLabel(
                    "VideoPlayer.Title"))  # no original title, get just Title
        else: