Beispiel #1
0
def queue_next_item(data=None, episode=None):
    """Function to add next episode to the UpNext queue"""

    next_item = {}
    play_url = data.get('play_url') if data else None
    episodeid = (utils.get_int(episode, 'episodeid')
                 if episode else constants.UNKNOWN_DATA)

    if play_url:
        next_item.update(file=play_url)

    elif episode and episodeid != constants.UNKNOWN_DATA:
        next_item.update(episodeid=episodeid)

    if next_item:
        log('Adding to queue: {0}'.format(next_item))
        utils.jsonrpc(method='Playlist.Add',
                      params={
                          'playlistid': get_player_id(),
                          'item': next_item
                      },
                      no_response=True)
    else:
        log('Nothing added to queue')

    return bool(next_item)
Beispiel #2
0
 def play_addon_item(self):
     if self.data.get('play_url'):
         self.log('Playing the next episode directly: %(play_url)s' % self.data, 2)
         jsonrpc(method='Player.Open', params=dict(item=dict(file=self.data.get('play_url'))))
     else:
         self.log('Sending %(encoding)s data to add-on to play: %(play_info)s' % dict(encoding=self.encoding, **self.data), 2)
         event(message=self.data.get('id'), data=self.data.get('play_info'), sender='upnextprovider', encoding=self.encoding)
Beispiel #3
0
    def get_now_playing(self):
        # Seems to work too fast loop whilst waiting for it to become active
        result = dict()
        while not result.get('result'):
            result = jsonrpc(method='Player.GetActivePlayers')
            self.log('Got active player %s' % result, 2)

        if not result.get('result'):
            return None

        playerid = result.get('result')[0].get('playerid')

        # Get details of the playing media
        self.log('Getting details of now playing media', 2)
        result = jsonrpc(method='Player.GetItem',
                         params=dict(
                             playerid=playerid,
                             properties=[
                                 'episode', 'genre', 'playcount',
                                 'plotoutline', 'season', 'showtitle',
                                 'tvshowid'
                             ],
                         ))
        self.log('Got details of now playing media %s' % result, 2)
        return result
Beispiel #4
0
def play_addon_item(data, encoding, resume=False):
    """Function to play next addon item, either using JSONRPC Player.Open or by
       passthrough back to the addon"""

    play_url = data.get('play_url')
    if play_url:
        log('Playing from addon - {0}'.format(play_url))
        utils.jsonrpc(method='Player.Open',
                      params={'item': {
                          'file': play_url
                      }},
                      options={'resume': resume},
                      no_response=True)
        return

    play_info = data.get('play_info')
    if play_info:
        log('Sending as {0} to addon - {1}'.format(encoding, play_info))
        utils.event(message=data.get('id'),
                    data=play_info,
                    sender='upnextprovider',
                    encoding=encoding)
        return

    log('Error: no addon data available for playback', utils.LOGWARNING)
Beispiel #5
0
def get_from_library(episodeid, tvshowid=None):
    """Function to get show and episode details from Kodi library"""

    result = utils.jsonrpc(method='VideoLibrary.GetEpisodeDetails',
                           params={
                               'episodeid': episodeid,
                               'properties': EPISODE_PROPERTIES
                           })
    result = result.get('result', {}).get('episodedetails')

    if not result:
        log('Error: episode info not found in library', utils.LOGWARNING)
        return None
    episode = result

    if not tvshowid:
        tvshowid = episode.get('tvshowid', constants.UNKNOWN_DATA)

    result = utils.jsonrpc(method='VideoLibrary.GetTVShowDetails',
                           params={
                               'tvshowid': tvshowid,
                               'properties': TVSHOW_PROPERTIES
                           })
    result = result.get('result', {}).get('tvshowdetails')

    if not result:
        log('Error: show info not found in library', utils.LOGWARNING)
        return None
    result.update(episode)

    log('Episode from library: {0}'.format(result))
    return result
Beispiel #6
0
def play_kodi_item(episode, resume=False):
    """Function to directly play a file from the Kodi library"""

    log('Playing from library: {0}'.format(episode))
    utils.jsonrpc(
        method='Player.Open',
        params={'item': {
            'episodeid': utils.get_int(episode, 'episodeid')
        }},
        options={'resume': resume},
        no_response=True)
Beispiel #7
0
    def queue_next_item(self, episode):
        next_item = {}
        if not self.data:
            next_item.update(episodeid=episode.get('episodeid'))
        elif self.data.get('play_url'):
            next_item.update(file=self.data.get('play_url'))

        if next_item:
            jsonrpc(method='Playlist.Add', id=0, params=dict(playlistid=1, item=next_item))

        return bool(next_item)
Beispiel #8
0
def dequeue_next_item():
    """Function to remove the 2nd item from the playlist, used by the UpNext
       queue for the next video to be played"""

    log('Removing unplayed next item from queue')
    utils.jsonrpc(method='Playlist.Remove',
                  params={
                      'playlistid': get_player_id(),
                      'position': 1
                  },
                  no_response=True)
    return False
Beispiel #9
0
def reset_queue():
    """Function to remove the 1st item from the playlist, used by the UpNext
       queue for the video that was just played"""

    log('Removing previously played item from queue')
    utils.jsonrpc(method='Playlist.Remove',
                  params={
                      'playlistid': get_player_id(),
                      'position': 0
                  },
                  no_response=True)
    return False
Beispiel #10
0
    def get_next_in_playlist(self, position):
        result = jsonrpc(method='Playlist.GetItems',
                         params=dict(
                             playlistid=1,
                             limits=dict(start=position + 1, end=position + 2),
                             properties=[
                                 'art', 'dateadded', 'episode', 'file',
                                 'firstaired', 'lastplayed', 'playcount',
                                 'plot', 'rating', 'resume', 'runtime',
                                 'season', 'showtitle', 'streamdetails',
                                 'title', 'tvshowid', 'writer'
                             ],
                         ))

        if not result:
            return None

        self.log('Got details of next playlist item %s' % result, 2)
        if result.get('result', {}).get('items') is None:
            return None

        item = result.get('result', {}).get('items', [])[0]
        if item.get('type') != 'episode':
            return None

        item['episodeid'] = item.get('id')
        item['tvshowid'] = item.get('tvshowid', item.get('id'))
        return item
Beispiel #11
0
def get_episodeid(tvshowid, season, episode):
    """Function to search Kodi library for episodeid by tvshowid, season, and
       episode"""

    filters = [{
        'field': 'season',
        'operator': 'is',
        'value': str(season)
    }, {
        'field': 'episode',
        'operator': 'is',
        'value': str(episode)
    }]
    filters = {'and': filters}

    result = utils.jsonrpc(method='VideoLibrary.GetEpisodes',
                           params={
                               'tvshowid': tvshowid,
                               'properties': EPISODE_PROPERTIES,
                               'limits': {
                                   'start': 0,
                                   'end': 1
                               },
                               'filter': filters
                           })
    result = result.get('result', {}).get('episodes')

    if not result:
        log('Error: episodeid not found in library', utils.LOGWARNING)
        return constants.UNKNOWN_DATA

    return utils.get_int(result[0], 'episodeid')
Beispiel #12
0
    def showtitle_to_id(title):
        result = jsonrpc(method='VideoLibrary.GetTVShows', id='libTvShows', params=dict(properties=['title']))

        for tvshow in result.get('result', {}).get('tvshows', []):
            if tvshow.get('label') == title:
                return tvshow.get('tvshowid')
        return '-1'
Beispiel #13
0
def get_player_id(player_type=None, player_id_cache=[None]):  # pylint: disable=dangerous-default-value
    """Function to get active player ID"""

    # We don't need to actually get playerid everytime, cache and reuse instead
    if player_id_cache[0] is not None:
        return player_id_cache[0]

    # Sometimes Kodi gets confused and uses a music playlist for video content,
    # so we use the first active player id instead.
    result = utils.jsonrpc(method='Player.GetActivePlayers')
    result = result.get('result', [{}])
    if player_type:
        result = [
            player for player in result if player.get('type') == player_type
        ]
    else:
        result = [
            player for player in result if player.get('type') in PLAYER_TYPES
        ]

    if not result:
        log('Error: no active player', utils.LOGWARNING)
        return None

    player_id = result[0].get('playerid')
    player_id_cache[0] = player_id
    return player_id
Beispiel #14
0
    def handle_kodi_lookup_of_current_episode(self, tvshowid,
                                              current_episode_id):
        result = jsonrpc(method='VideoLibrary.GetEpisodes',
                         params=dict(
                             tvshowid=tvshowid,
                             properties=[
                                 'art', 'dateadded', 'episode', 'file',
                                 'firstaired', 'lastplayed', 'playcount',
                                 'plot', 'rating', 'resume', 'runtime',
                                 'season', 'showtitle', 'streamdetails',
                                 'title', 'tvshowid', 'writer'
                             ],
                             sort=dict(method='episode'),
                         ))

        if not result.get('result'):
            return None

        self.log('Find current episode called', 2)
        sleep(100)

        # Find the next unwatched and the newest added episodes
        episodes = result.get('result', {}).get('episodes', [])
        for idx, episode in enumerate(episodes):
            # Find position of current episode
            if current_episode_id == episode.get('episodeid'):
                self.log(
                    'Find current episode found episode in position: %d' % idx,
                    2)
                return episode

        # No next episode found
        self.log('No next episode found', 1)
        return None
Beispiel #15
0
def play_playlist_item(position=0, resume=False):
    """Function to play episode in playlist"""

    log('Playing from playlist position: {0}'.format(position))
    if position == 'next':
        position = get_playlist_position()

    # JSON Player.Open can be too slow but is needed if resuming is enabled
    # Unfortunately resuming from a playlist item does not seem to work...
    utils.jsonrpc(
        method='Player.Open',
        params={'item': {
            'playlistid': get_player_id(),
            'position': position
        }},
        options={'resume': resume},
        no_response=True)
Beispiel #16
0
def handle_just_watched(episodeid,
                        playcount,
                        reset_playcount=False,
                        reset_resume=True):
    """Function to update playcount and resume point of just watched video"""

    result = utils.jsonrpc(method='VideoLibrary.GetEpisodeDetails',
                           params={
                               'episodeid': episodeid,
                               'properties': ['playcount', 'resume'],
                           })
    result = result.get('result', {}).get('episodedetails')

    if result:
        actual_playcount = utils.get_int(result, 'playcount', 0)
        actual_resume = utils.get_int(result.get('resume'), 'position', 0)
    else:
        return

    params = {}

    # If Kodi has not updated playcount then UpNext will
    if reset_playcount:
        playcount = -1
    if reset_playcount or actual_playcount == playcount:
        playcount += 1
        params['playcount'] = playcount

    # If resume point has been saved then reset it
    if actual_resume and reset_resume:
        params['resume'] = {'position': 0}

    # Only update library if playcount or resume point needs to change
    if params:
        params['episodeid'] = episodeid
        utils.jsonrpc(method='VideoLibrary.SetEpisodeDetails',
                      params=params,
                      no_response=True)

    log(
        'Library update: id - {0}{1}{2}{3}'.format(
            episodeid, ', playcount - {0} to {1}'.format(
                actual_playcount, playcount) if 'playcount' in params else '',
            ', resume - {0} to 0'.format(actual_resume)
            if 'resume' in params else '', '' if params else ', no change'),
        utils.LOGDEBUG)
Beispiel #17
0
def get_player_speed():
    """Function to get speed of active player"""

    result = utils.jsonrpc(method='Player.GetProperties',
                           params={
                               'playerid': get_player_id(),
                               'properties': ['speed'],
                           })
    result = utils.get_int(result.get('result', {}), 'speed', 1)

    return result
Beispiel #18
0
def test_diagnostics(kak, mock, send):
    send('exec 7oabcdefghijklmnopqrstuvwxyz<esc>gg')

    msg = utils.jsonrpc({
        'method': 'textDocument/publishDiagnostics',
        'params': {
            'uri':
            'file://*scratch*',
            'diagnostics': [{
                'message': 'line ' + str(y),
                'range': {
                    'start': {
                        'line': y - 1,
                        'character': y * 2 - 1
                    },
                    'end': {
                        'line': y - 1,
                        'character': y * 3 - 1
                    }
                }
            } for y in [2, 4, 6]]
        }
    })
    mock.stdout.write(msg)
    time.sleep(0.1)
    first = True
    for y in [2, 4, 6, 2, 4]:
        send('lsp-diagnostics-jump next')  # 2 4 6 2 4
        if first:
            first = False
            print('listening...')
            obj = process(mock)
            pprint(obj)
            assert (obj['method'] == 'textDocument/didChange')
            assert (obj['params']['contentChanges'][0]['text'] == '\n' +
                    'abcdefghijklmnopqrstuvwxyz\n' * 7)
        time.sleep(0.1)
        call = libkak.Remote.onclient(kak.pid, 'unnamed0')
        d = call(lambda selection_desc: selection_desc)
        print('selection_desc:', d)
        assert (d == ((y, 2 * y), (y, 3 * y - 1))
                )  # end point exclusive according to protocol.md

    send('lsp-diagnostics-jump prev')  # 2
    time.sleep(0.1)
    send('lsp-diagnostics docsclient')
    time.sleep(0.3)
    send('exec x')
    time.sleep(0.3)
    call = libkak.Remote.onclient(kak.pid, 'unnamed0')
    s = call(lambda selection: selection)
    print('final selection:', s)
    assert (s == 'line 2\n')
Beispiel #19
0
def get_next_in_playlist(position, unwatched_only=False):
    """Function to get details of next episode in playlist"""

    result = utils.jsonrpc(
        method='Playlist.GetItems',
        params={
            'playlistid': get_player_id(),
            # limits are zero indexed, position is one indexed
            'limits': {
                'start': position,
                'end': -1 if unwatched_only else position + 1
            },
            'properties': EPISODE_PROPERTIES
        })
    items = result.get('result', {}).get('items')

    # Get first unwatched item in the list of remaining playlist entries
    if unwatched_only and items:
        position_offset, item = next(
            ((idx, item) for idx, item in enumerate(items)
             if utils.get_int(item, 'playcount') < 1), (0, None))
        position += position_offset
    # Or just get the first item in the list of remaining playlist entries
    else:
        item = items[0] if items else None

    # Don't check if next item is an episode, just use it if it is there
    if not item:  # item.get('type') != 'episode':
        log('Error: no next item found in playlist', utils.LOGWARNING)
        return None

    # Playlist item may not have had video info details set
    # Try and populate required details if missing
    if not item.get('title'):
        item['title'] = item.get('label', '')
    item['episodeid'] = utils.get_int(item, 'episodeid',
                                      utils.get_int(item, 'id'))
    item['tvshowid'] = utils.get_int(item, 'tvshowid')
    # If missing season/episode, change to empty string to avoid episode
    # formatting issues ("S-1E-1") in UpNext popup
    if utils.get_int(item, 'season') == constants.UNKNOWN_DATA:
        item['season'] = ''
    if utils.get_int(item, 'episode') == constants.UNKNOWN_DATA:
        item['episode'] = ''

    # Store current playlist position for later use
    item['playlist_position'] = position

    log('Next item in playlist at position {0}: {1}'.format(position, item))
    return item
Beispiel #20
0
    def get_episode_id(showid, show_season, show_episode):
        show_season = int(show_season)
        show_episode = int(show_episode)
        result = jsonrpc(method='VideoLibrary.GetEpisodes', params=dict(
            properties=['episode', 'season'],
            tvshowid=int(showid),
        ))

        episodeid = 0
        for episode in result.get('result', {}).get('episodes', []):
            if episode.get('episodeid') and episode.get('season') == show_season and episode.get('episode') == show_episode:
                episodeid = episode.get('episodeid')

        return episodeid
Beispiel #21
0
def get_now_playing():
    """Function to get detail of currently playing item"""

    result = utils.jsonrpc(method='Player.GetItem',
                           params={
                               'playerid': get_player_id(),
                               'properties': EPISODE_PROPERTIES,
                           })
    result = result.get('result', {}).get('item')

    if not result:
        log('Error: now playing item info not found', utils.LOGWARNING)
        return None

    log('Now playing: {0}'.format(result))
    return result
Beispiel #22
0
    def handle_kodi_lookup_of_episode(self, tvshowid, current_file, include_watched, current_episode_id):
        result = jsonrpc(method='VideoLibrary.GetEpisodes', params=dict(
            tvshowid=tvshowid,
            properties=['art', 'dateadded', 'episode', 'file', 'firstaired', 'lastplayed',
                        'playcount', 'plot', 'rating', 'resume', 'runtime', 'season',
                        'showtitle', 'streamdetails', 'title', 'tvshowid', 'writer'],
            sort=dict(method='episode'),
        ))

        if not result.get('result'):
            return None

        self.log('Got details of next up episode %s' % result, 2)
        sleep(100)

        # Find the next unwatched and the newest added episodes
        return self.find_next_episode(result, current_file, include_watched, current_episode_id)
Beispiel #23
0
    def get_playlistid(playlistid_cache=[None]):  # pylint: disable=dangerous-default-value
        """Function to get playlistid of active player"""

        # We don't need to actually get playlistid everytime, cache and reuse instead
        if playlistid_cache[0] is not None:
            return playlistid_cache[0]

        result = jsonrpc(method='Player.GetProperties',
                         params={
                             'playerid':
                             Api._get_playerid(playerid_cache=[None]),
                             'properties': ['playlistid'],
                         })
        result = get_int(result.get('result', {}), 'playlistid',
                         Api.PLAYER_PLAYLIST['video'])

        return result
Beispiel #24
0
    def _get_playerid(playerid_cache=[None]):  # pylint: disable=dangerous-default-value
        """Function to get active player playerid"""

        # We don't need to actually get playerid everytime, cache and reuse instead
        if playerid_cache[0] is not None:
            return playerid_cache[0]

        # Sometimes Kodi gets confused and uses a music playlist for video content,
        # so get the first active player instead, default to video player.
        result = jsonrpc(method='Player.GetActivePlayers')
        result = [
            player for player in result.get('result', [{}])
            if player.get('type', 'video') in Api.PLAYER_PLAYLIST
        ]

        playerid = get_int(result[0], 'playerid') if result else -1

        if playerid == -1:
            return None

        playerid_cache[0] = playerid
        return playerid
Beispiel #25
0
    def get_next_in_playlist(self, position):
        result = jsonrpc(
            method='Playlist.GetItems',
            params=dict(
                playlistid=Api.get_playlistid(),
                # limits are zero indexed, position is one indexed
                limits=dict(start=position, end=position + 1),
                properties=[
                    'art', 'dateadded', 'episode', 'file', 'firstaired',
                    'lastplayed', 'playcount', 'plot', 'rating', 'resume',
                    'runtime', 'season', 'showtitle', 'streamdetails', 'title',
                    'tvshowid', 'writer'
                ],
            ))

        item = result.get('result', {}).get('items')

        # Don't check if next item is an episode, just use it if it is there
        if not item:  # item.get('type') != 'episode':
            self.log('Error: no next item found in playlist', 1)
            return None
        item = item[0]

        # Playlist item may not have had video info details set
        # Try and populate required details if missing
        if not item.get('title'):
            item['title'] = item.get('label', '')
        item['episodeid'] = get_int(item, 'id')
        item['tvshowid'] = get_int(item, 'tvshowid')
        # If missing season/episode, change to empty string to avoid episode
        # formatting issues ("S-1E-1") in UpNext popup
        if get_int(item, 'season') == -1:
            item['season'] = ''
        if get_int(item, 'episode') == -1:
            item['episode'] = ''

        self.log('Next item in playlist: %s' % item, 2)
        return item
Beispiel #26
0
def get_tvshowid(title):
    """Function to search Kodi library for tshowid by title"""

    result = utils.jsonrpc(method='VideoLibrary.GetTVShows',
                           params={
                               'properties': ['title'],
                               'limits': {
                                   'start': 0,
                                   'end': 1
                               },
                               'filter': {
                                   'field': 'title',
                                   'operator': 'is',
                                   'value': title
                               }
                           })
    result = result.get('result', {}).get('tvshows')

    if not result:
        log('Error: tvshowid not found in library', utils.LOGWARNING)
        return constants.UNKNOWN_DATA

    return utils.get_int(result[0], 'tvshowid')
Beispiel #27
0
 def play_kodi_item(episode):
     jsonrpc(method='Player.Open',
             id=0,
             params=dict(item=dict(episodeid=episode.get('episodeid'))))
Beispiel #28
0
 def reset_queue():
     """Remove previously played item from video playlist"""
     jsonrpc(method='Playlist.Remove',
             id=0,
             params=dict(playlistid=Api.get_playlistid(), position=0))
Beispiel #29
0
 def dequeue_next_item():
     """Remove unplayed next item from video playlist"""
     jsonrpc(method='Playlist.Remove',
             id=0,
             params=dict(playlistid=Api.get_playlistid(), position=1))
     return False
Beispiel #30
0
def get_next_from_library(episodeid=constants.UNKNOWN_DATA,
                          tvshowid=None,
                          unwatched_only=False,
                          next_season=True,
                          random=False,
                          episode=None):
    """Function to get show and next episode details from Kodi library"""

    episode = episode.copy() if episode else get_from_library(episodeid)

    if not episode:
        log('Error: no next episode found, current episode not in library',
            utils.LOGWARNING)
        episode = None
        new_season = False
        return episode, new_season

    (path, filename) = os.path.split(episode['file'])
    filters = [
        # Check that both next filename and path are different to current
        # to deal with different file naming schemes e.g.
        # Season 1/Episode 1.mkv
        # Season 1/Episode 1/video.mkv
        # Season 1/Episode 1-2-3.mkv
        {
            'or': [{
                'field': 'filename',
                'operator': 'isnot',
                'value': filename
            }, {
                'field': 'path',
                'operator': 'isnot',
                'value': path
            }]
        }
    ]

    if unwatched_only:
        # Exclude watched episodes
        filters.append({
            'field': 'playcount',
            'operator': 'lessthan',
            'value': '1'
        })

    if not random:
        # Next episode in current season
        episode_filter = {
            'and': [{
                'field': 'season',
                'operator': 'is',
                'value': str(episode['season'])
            }, {
                'field': 'episode',
                'operator': 'greaterthan',
                'value': str(episode['episode'])
            }]
        }
        # Next episode in next season
        if next_season:
            episode_filter = [
                episode_filter, {
                    'field': 'season',
                    'operator': 'greaterthan',
                    'value': str(episode['season'])
                }
            ]
            episode_filter = {'or': episode_filter}
        filters.append(episode_filter)

    filters = {'and': filters}

    if not tvshowid:
        tvshowid = episode.get('tvshowid', constants.UNKNOWN_DATA)

    result = utils.jsonrpc(method='VideoLibrary.GetEpisodes',
                           params={
                               'tvshowid':
                               tvshowid,
                               'properties':
                               EPISODE_PROPERTIES,
                               'sort': ({
                                   'method': 'random'
                               } if random else {
                                   'order': 'ascending',
                                   'method': 'episode'
                               }),
                               'limits': {
                                   'start': 0,
                                   'end': 1
                               },
                               'filter':
                               filters
                           })
    result = result.get('result', {}).get('episodes')

    if not result:
        log('No next episode found in library')
        episode = None
        new_season = False
        return episode, new_season

    log('Next episode from library: {0}'.format(result[0]))
    new_season = not random and episode['season'] != result[0]['season']
    episode.update(result[0])
    return episode, new_season