def start_loops(self):
        spam('start_loops')
        try:
            self._t.stop()
        except:
            pass
        self._t = Thread(target=self.tick_loop_trakt, args=())
        self._t.daemon = True
        self._t.start()

        try:
            self._s.stop()
        except:
            pass
        self._s = Thread(target=self.tick_loop_shoko, args=())
        self._s.daemon = True
        self._s.start()

        try:
            self._u.stop()
        except:
            pass
        self._u = Thread(target=self.tick_loop_update_time, args=())
        self._u.daemon = True
        self._u.start()
 def onPlayBackEnded(self):
     spam('Playback Ended')
     try:
         self.handle_finished_episode()
     except:
         eh.exception(ErrorPriority.HIGH)
     self.PlaybackStatus = PlaybackStatus.ENDED
 def onPlayBackResumed(self):
     spam('Playback Resumed')
     self.PlaybackStatus = PlaybackStatus.PLAYING
     try:
         self.start_loops()
     except:
         eh.exception(ErrorPriority.HIGH)
    def __init__(self):
        spam('Player Initialized')
        xbmc.Player.__init__(self)
        self._t = None  # trakt thread
        self._s = None  # shoko thread
        self._u = None  # update thread
        self._details = None
        self.Playlist = None
        self.PlaybackStatus = PlaybackStatus.STOPPED
        # self.LoopStatus = 'None'
        # self.Shuffle = False
        self.is_transcoded = False
        self.is_movie = None
        self.file_id = 0
        self.ep_id = 0
        # we will store duration and time in kodi format here, so that calls to the player will match
        self.duration = 0
        self.time = 0
        self.path = ''
        self.scrobble = True
        self.is_external = False
        self.is_finished = False
        self.party_mode = False

        self.CanControl = True
    def onPlayBackStarted(self):
        spam('Playback Started')
        try:
            if plugin_addon.getSetting('enableEigakan') == 'true':
                log('Player is set to use Transcoding')
                self.is_transcoded = True

            # wait until the player is init'd and playing
            self.set_duration()

            self.PlaybackStatus = PlaybackStatus.PLAYING
            # we are making the player global, so if a stop is issued, then Playing will change
            while not self.isPlaying(
            ) and self.PlaybackStatus == PlaybackStatus.PLAYING:
                xbmc.sleep(250)

            # TODO get series and populate info so we know if its movie or not
            # TODO maybe we could read trakt_id from shoko,
            self.is_movie = False
            if self.duration > 0 and self.scrobble:
                scrobble_trakt(self.ep_id, 1, self.getTime(), self.duration,
                               self.is_movie)

            self.start_loops()
        except:
            eh.exception(ErrorPriority.HIGHEST)
Exemple #6
0
def kodi_rpc(method, params, limit='', json_id=0):
    json_id += 1
    jsonrpc = '{"jsonrpc":"2.0","id":%d,"method":"%s","params":{%s}%s}' % (
        json_id, method, params, limit)
    spam(' -----------> rpc (send): %s' % jsonrpc)
    rpc = xbmc.executeJSONRPC(jsonrpc)
    spam(' -----------> rpc (recv): %s' % rpc)
    rpc = json.loads(rpc)
    return rpc
 def feed(self, file_id, ep_id, duration, path, scrobble):
     spam(
         'Player feed - file_id=%s ep_id=%s duration=%s path=%s scrobble=%s'
         % (file_id, ep_id, duration, path, scrobble))
     self.file_id = file_id
     self.ep_id = ep_id
     self.duration = kodi_proxy.duration_to_kodi(duration)
     self.path = path
     self.scrobble = scrobble
def finished_episode(ep_id, file_id, current_time, total_time):
    _finished = False
    spam(
        'finished_episode > ep_id = %s, file_id = %s, current_time = %s, total_time = %s'
        % (ep_id, file_id, current_time, total_time))
    mark = float(plugin_addon.getSetting('watched_mark'))
    if plugin_addon.getSetting('external_player').lower() == 'false':
        pass
    else:
        # mitigate the external player, skipping intro/outro/pv so we cut your setting in half
        mark /= 2
    mark /= 100
    spam('mark = %s * total (%s) = %s vs current = %s' %
         (mark, total_time, (total_time * mark), current_time))
    if (total_time * mark) <= current_time:
        _finished = True
        log('Video current_time (%s) has passed watch mark (%s). Marking is as watched!'
            % (current_time, (total_time * mark)))

    # TODO this got broken for addons in Leia18, until this is somehow fixed we count time by hand (in loop)
    # else:
    # external set position = 1.0 when it want to mark it as watched (based on configuration of external
    # if current_time > 0.0:
    #    _finished = True
    # else:
    #   log('Using an external player, but the settings are set to not mark as watched. Check advancedsettings.xml')
    #_finished = False
    if _finished:
        if int(ep_id) != 0 and plugin_addon.getSetting(
                'vote_always') == 'true':
            spam('vote_always, voting on episode')
            script_utils.vote_for_episode(ep_id)

        if ep_id != 0:
            from shoko_models.v2 import Episode
            ep = Episode(ep_id, build_full_object=False)
            spam('mark as watched, episode')
            ep.set_watched_status(True)

            # vote on finished series
            if plugin_addon.getSetting('vote_on_series') == 'true':
                from shoko_models.v2 import get_series_for_episode
                series = get_series_for_episode(ep_id)
                # voting should be only when you really watch full series
                spam('vote_on_series, mark: %s / %s' %
                     (series.sizes.watched_episodes,
                      series.sizes.total_episodes))
                if series.sizes.watched_episodes - series.sizes.total_episodes == 0:
                    script_utils.vote_for_series(series.id)

        elif file_id != 0:
            # file watched states
            pass

        # refresh only when we really did watch episode, this way we wait until all action after watching are executed
        script_utils.arbiter(10, 'Container.Refresh')
def add_to_queue(aid, eid, sid, rating=0):
    db_connection = database.connect(db_file)
    db_cursor = db_connection.cursor()
    db_cursor.execute('SELECT aid, eid, sid FROM queue WHERE aid=? and eid=? and sid=?', (aid, eid, sid))
    if db_cursor.fetchone() is None:
        db_cursor.execute('INSERT INTO queue (aid, eid, sid, rating) VALUES (?, ?, ?, ?)', (aid, eid, sid, rating))
        db_connection.commit()
        db_connection.close()
        spam(' ===> add_to_queue: added')
    spam(' ===> add_to_queue: %s %s %s' % (aid, eid, sid))
def get_queue():
    items = None
    try:
        db_connection = database.connect(db_file)
        db_cursor = db_connection.cursor()
        db_cursor.execute('SELECT aid, eid, sid, rating FROM queue')
        items = db_cursor.fetchall()
    except:
        pass
    spam(' ===> get_queue: %s' % (len(items),))
    return items
def add_date(date):
    db_connection = database.connect(db_file)
    db_cursor = db_connection.cursor()
    db_cursor.execute('SELECT date FROM sync_date WHERE date=?', (date,))
    if db_cursor.fetchone() is None:
        db_cursor.execute('INSERT INTO sync_date (date) VALUES (?)', (date,))
        db_connection.commit()
        db_connection.close()
        spam(' ===> add_date: %s: True' % (date,))
        return True
    spam(' ===> add_date: %s: False' % (date,))
    return False
def get_lastdate():
    items = None
    try:
        db_connection = database.connect(db_file)
        db_cursor = db_connection.cursor()
        db_cursor.execute('SELECT date FROM sync_date ORDER BY date DESC')
        items = db_cursor.fetchone()
        if items is None:
            items = ['2000-01-01']
    except:
        pass
    spam(' ===> get_latestdate: %s' % (items,))
    return items
def clear_queue(number_of_items=0):
    # as a safe-lock, check number of items before flushing, if its same then flush,
    # if different then something was added and it would be better to process it again
    if len(get_queue()) == number_of_items:
        db_connection = database.connect(db_file)
        db_cursor = db_connection.cursor()
        db_cursor.execute('DELETE FROM queue')
        db_connection.commit()
        db_connection.close()
        spam(' ===> clear_queue: True')
        return True
    spam(' ===> clear_queue: False')
    return False
Exemple #14
0
def clean_videolibrary_scan():
    log('====> VideoLibrary Scan: Start <====')
    index_start = 0
    index_stop = 10
    index_count = 100
    json_id = 0
    while index_stop < index_count:
        spam('=====> series : %s -- %s / %s' %
             (index_start, index_stop, index_count))
        results = kodi_rpc(
            'VideoLibrary.GetEpisodes',
            '"properties":["tvshowid","title","uniqueid"]',
            ',"limits":{"start":%d,"end":%d}' % (index_start, index_stop),
            json_id)

        if 'result' not in results:
            spam('====> no result found <====')
            break
        json_id = int(results['id'])
        index_start = results['result']['limits'].get('start', 0)
        index_stop = results['result']['limits'].get('end', 0)
        index_count = results['result']['limits'].get('total', 0)

        for tvshows in results['result'].get('episodes', []):
            tid = tvshows.get('tvshowid', 0)
            eid = tvshows.get('episodeid', 0)
            said = 0  # shoko_aid
            seid = 0  # shoko_eid
            aaid = 0  # anidb_aid
            aeid = 0  # anidb_eid
            if 'uniqueid' in tvshows:
                if 'shoko_aid' in tvshows[
                        'uniqueid'] and 'shoko_eid' in tvshows['uniqueid']:
                    said = tvshows['uniqueid'].get('shoko_aid', 0)
                    seid = tvshows['uniqueid'].get('shoko_eid', 0)
                    aaid = tvshows['uniqueid'].get('anidb_aid', 0)
                    aeid = tvshows['uniqueid'].get('anidb_eid', 0)
                spam(' ====> uniqueid: %s => %s => %s, %s => %s => %s' %
                     (tid, said, aaid, eid, seid, aeid))
            if tid > 0 and eid > 0 and said > 0 and seid > 0:
                if not series.check(tid=tid, aid=aaid, sid=said):
                    series.add_map(tid=tid, aid=aaid, sid=said)
                    spam(' ====> add_series: %s => %s, %s' % (tid, aaid, said))
                if not episodes.check(vlid=eid, eid=aeid, sid=seid):
                    episodes.add_map(vlid=eid, eid=aeid, sid=seid)
                    spam(' ====> add_episod: %s => %s, %s' % (eid, aeid, seid))

        index_step = index_stop - index_start
        index_start = index_stop
        index_stop += index_step
    log('====> VideoLibrary Scan: Finish')
Exemple #15
0
def is_dialog_active():
    x = -1
    try:
        x = xbmcgui.getCurrentWindowDialogId()
        x = int(x)
        log('----- > is_dialog_window_is_visible: %s' % x)
        # if there is any, wait 0.25s
        xbmc.sleep(250)
    except:
        eh.spam('----- > is_dialog_is_visible: NONE')
        pass
    # https://github.com/xbmc/xbmc/blob/master/xbmc/guilib/WindowIDs.h
    # 10138 - busy,loading
    if 10099 <= x <= 10160:
        return True
    return False
    def onAVStarted(self):
        # Will be called when Kodi has a video or audiostream, before playing file
        spam('onAVStarted')

        # isExternalPlayer() ONLY works when isPlaying(), other than that it throw 0 always
        # setting it before results in false setting
        try:
            is_external = str(kodi_proxy.external_player(self)).lower()
            plugin_addon.setSetting(id='external_player', value=is_external)
        except:
            eh.exception(ErrorPriority.HIGH)
        spam(self)

        if kodi_proxy.external_player(self):
            log('Using External Player')
            self.is_external = True
    def get_json(self, url_in, direct=False, force_cache=False, cache_time=0):
        """
        use 'get' to return json body as string
        :param url_in:
        :param direct: force to bypass cache
        :param force_cache: force to use cache even if disabled
        :param cache_time: ignore setting to set custom cache expiration time, mainly to expire data quicker to refresh watch flags
        :return:
        """

        import error_handler as eh
        from error_handler import ErrorPriority
        try:
            timeout = plugin_addon.getSetting('timeout')
            if self.api_key is None or self.api_key == '':
                apikey = plugin_addon.getSetting('apikey')
            else:
                apikey = self.api_key
            # if cache is disabled, overwrite argument and force it to direct
            if plugin_addon.getSetting('enableCache') != 'true':
                direct = True
            if direct and not force_cache:
                body = self.get_data(url_in, None, timeout, apikey)
            else:
                import cache
                eh.spam('Getting a Cached Response ---')
                eh.spam('URL:', url_in)
                db_row = cache.get_data_from_cache(url_in)
                if db_row is not None:
                    valid_until = cache_time if cache_time > 0 else int(
                        plugin_addon.getSetting('expireCache'))
                    expire_second = time.time() - float(db_row[1])
                    if expire_second > valid_until:
                        # expire, get new date
                        eh.spam('The cached data is stale.')
                        body = self.get_data(url_in, None, timeout, apikey)
                        cache.remove_cache(url_in)
                        cache.add_cache(url_in, body)
                    else:
                        body = db_row[0]
                else:
                    eh.spam('No cached data was found for the URL.')
                    body = self.get_data(url_in, None, timeout, apikey)
                    cache.add_cache(url_in, body)
        except http_error as err:
            raise err
        except Exception as ex:
            xbmc.log(' ========= ERROR JSON ============  %s' % ex,
                     xbmc.LOGNOTICE)
            eh.exception(ErrorPriority.HIGH)
            body = None
        return body
Exemple #18
0
def send_profile():
    eh.spam('Trying to send_profile(). Wish me luck!')
    log_setsuzoku(Category.EIGAKAN, Action.PROFILE, Event.SEND)
    # setup client on server
    settings = {}

    # tweak-ninja
    settings['manual_mode'] = plugin_addon.getSetting('eigakan_manual_mode')
    settings['h_resolution'] = plugin_addon.getSetting('eigakan_h_resolution')
    settings['h_bitrate'] = plugin_addon.getSetting('eigakan_h_bitrate')
    settings['l_resolution'] = plugin_addon.getSetting('eigakan_l_resolution')
    settings['l_bitrate'] = plugin_addon.getSetting('eigakan_l_bitrate')
    settings['x264_preset'] = plugin_addon.getSetting('eigakan_x264_preset')
    settings['burn_subs'] = plugin_addon.getSetting('burnEigakan')
    # lang-master
    settings['pref_audio'] = plugin_addon.getSetting('audiolangEigakan')
    settings['pref_subs'] = plugin_addon.getSetting('subEigakan')

    settings = json.dumps(settings)

    eh.spam('send_profile() data = %s' % settings)

    try:
        pyproxy.post_data(eigakan_host + '/api/clientid/%s' % get_device_id(), settings)
        # if no error, lets mark that we did full handshake with eigakan
        plugin_addon.setSetting('eigakan_handshake', 'true')
    except Exception as ex:
        plugin_addon.setSetting('eigakan_handshake', 'false')
        eh.spam('error while send_profile(): %s' % ex)
Exemple #19
0
def process_queue_of_watched_episodes():
    s_watch = True if xbmcaddon.Addon('service.nakamori').getSetting(
        'sv-watch') == 'true' else False
    s_rate = True if xbmcaddon.Addon('service.nakamori').getSetting(
        'sv-rate') == 'true' else False
    if s_watch or s_rate:
        log('===> process_queue_of_watched_episodes()')
        queue = sync.get_queue()
        for q in queue:
            a_aid = q[0]
            a_eid = q[1]
            shoko_eid = q[2]
            rating = q[3]
            vl_ep_id = episodes.get(eid=a_eid, sid=shoko_eid)
            if vl_ep_id is not None:
                vl_ep_id = vl_ep_id[0]
                # we found mapping
                spam('===> process_queue_of_watched_episodes vl_ep_id: %s' %
                     vl_ep_id)
                r = kodi_rpc(
                    'VideoLibrary.GetEpisodeDetails',
                    '"episodeid": %s,"properties":["playcount","rating"]' %
                    vl_ep_id)
                if 'result' in r and 'episodedetails' in r['result']:
                    if s_watch:
                        if r['result']['episodedetails']['playcount'] == 0:
                            m = kodi_rpc(
                                'VideoLibrary.SetEpisodeDetails',
                                '"episodeid":%s,"playcount": 1' % vl_ep_id)
                            if m.get('result', '') == "OK":
                                spam('===> mark watched %s - OK' % vl_ep_id)
                    if s_rate:
                        if rating > 0:
                            # maybe add force to re-rate it ?
                            if r['result']['episodedetails']['rating'] == 0:
                                m = kodi_rpc(
                                    'VideoLibrary.SetEpisodeDetails',
                                    '"episodeid":%s,"rating": %d' %
                                    (vl_ep_id, rating))
                                if m.get('result', '') == "OK":
                                    spam('===> rating %s - %s' %
                                         (vl_ep_id, rating))
            else:
                spam('----> missing mapping ! %s %s %s <----' %
                     (a_aid, a_eid, shoko_eid))
        # try to clear queue
        return sync.clear_queue(len(queue))
    else:
        log('===> process_queue_of_watched_episodes() - DISABLED')
        return False
Exemple #20
0
def check_eigakan():
    try:
        eigakan_data = pyproxy.get_json(eigakan_host + '/api/version')

        if eigakan_data is None:
            return False
        elif 'eigakan' not in eigakan_data:
            # raise RuntimeError('Invalid response from Eigakan')
            return False
        else:
            if plugin_addon.getSetting('eigakan_handshake') == 'false':
                eh.spam('We did not find Eigakan handshake')
                try:
                    pyproxy.get_json(eigakan_host + '/api/clientid/%s' % get_device_id())
                except http_err as err:
                    if int(err.code) == 404:
                        eh.spam('We did not find device profile on Eigakan, sending new one...')
                        plugin_addon.setSetting('eigakan_handshake', 'false')
                        send_profile()
                    else:
                        return False
            return True
    except:
        return False
Exemple #21
0
def query_last_watched_episodes():
    s_watch = True if xbmcaddon.Addon('service.nakamori').getSetting(
        'sv-watch') == 'true' else False
    s_rate = True if xbmcaddon.Addon('service.nakamori').getSetting(
        'sv-rate') == 'true' else False
    if s_watch or s_rate:
        log('====> query_last_watched_episodes')
        from nakamori_utils.globalvars import server
        # [{"type":"ep","view":1,"view_date":"2019-09-03T13:42:36.9194063+02:00","eptype":"Episode","epnumber":10,"aid":14662,"eid":219322,"id":74,"name":"Episode 10","summary":"Episode Overview not Available","year":"2019","air":"2019-09-02","rating":"2.80","votes":"1","art":{}}]
        today = date.today().strftime("%Y-%m-%d")
        offset = 0
        limit = 100  # setting without limit results in loop
        url = server + '/api/ep/last_watched?query=%s&limit=%s&offset=%s' % (
            today, limit, offset)
        spam('====> url: %s' % url)
        x = pyproxy.get_json(url, True)
        if x is not None and len(x) > 2:  # []
            x = json.loads(x)
            while len(x) > 0:
                for y in x:
                    if isinstance(y, dict):
                        spam('====> query_last_watched_episodes x: %s %s' %
                             (type(y), y))
                        watch_date = y.get('view_date', '')
                        aid = y.get('aid', 0)
                        eid = y.get('eid', 0)
                        shoko_eid = y.get('id', 0)
                        user_rating = 0
                        if s_rate:
                            user_rating = y.get('userrating', 0)
                        sync.add_to_queue(aid, eid, shoko_eid, user_rating)

                offset = offset + limit
                url = server + '/api/ep/last_watched?query=%s&limit=%s&offset=%s' % (
                    today, limit, offset)
                spam('====> url: %s' % url)
                x = pyproxy.get_json(url, True)
                if x is None:
                    break
                if x == '[]':
                    break

        # finish checking
        sync.add_date(today)
    else:
        log('====> query_last_watched_episodes - DISABLED')
Exemple #22
0
def debug_init():
    """
    start debugger if it's enabled
    also dump argv if spamLog
    :return:
    """
    if plugin_addon.getSetting('remote_debug') == 'true':
        # try pycharm first
        try:
            import pydevd
            # try to connect multiple times...in case we forgot to start it
            # TODO Show a message to the user that we are waiting on the debugger
            connected = False
            tries = 0
            while not connected and tries < 60:
                try:
                    pydevd.settrace(host=plugin_addon.getSetting('remote_ip'),
                                    stdoutToServer=True,
                                    stderrToServer=True,
                                    port=5678,
                                    suspend=False)
                    eh.spam('Connected to debugger')
                    connected = True
                except:
                    tries += 1
                    # we keep this message the same, as kodi will merge them into Previous line repeats...
                    eh.spam('Failed to connect to debugger')
                    xbmc.sleep(1000)
        except (ImportError, NameError):
            eh.log(
                'unable to import pycharm debugger, falling back on the web-pdb'
            )
            try:
                import web_pdb
                web_pdb.set_trace()
            except Exception:
                eh.exception(ErrorPriority.NORMAL,
                             'Unable to start debugger, disabling it')
                plugin_addon.setSetting('remote_debug', 'false')
        except:
            eh.exception(ErrorPriority.HIGHEST, 'Unable to start debugger')

    eh.spam('argv:', sys.argv)
Exemple #23
0
def perform_server_action(command,
                          object_id=None,
                          refresh='refresh10',
                          post=False,
                          post_body=''):
    """
    Performs an action on the server
    Args:
        object_id: the object_id or None
        command: string representing api/command?object_id=...
        refresh: whether to refresh
        post: is it a POST endpoint
        post_body: the body to post, minus the {}
    """
    key_url = server + '/api/' + command
    if object_id is not None and object_id != 0 and object_id != '':
        key_url = pyproxy.set_parameter(key_url, 'id', object_id)

    eh.spam('url:', key_url, 'id:', object_id)
    eh.spam('post:', post, 'body:', post_body)

    if post:
        response = pyproxy.post_json(key_url, post_body)
    else:
        response = pyproxy.get_json(key_url)

    eh.spam(response)

    refresh_message = localization_refresh_map.get(refresh, '')
    xbmc.executebuiltin('XBMC.Notification(%s, %s, 2000, %s)' %
                        (localization_notification_map.get(command, command),
                         refresh_message, plugin_addon.getAddonInfo('icon')))

    # there's a better way to do this, but I don't feel like trying to make it work in Python
    if refresh != '' and refresh != 'awhile':
        xbmc.sleep(10000)
        kodi_utils.refresh()
def play_video(file_id,
               ep_id=0,
               mark_as_watched=True,
               resume=False,
               force_direct_play=False,
               force_transcode_play=False,
               party_mode=False):
    """
    Plays a file
    :param file_id: file ID. It is needed to look up the file
    :param ep_id: episode ID, not needed, but it fills in a lot of info
    :param mark_as_watched: should we mark it after playback
    :param resume: should we auto-resume
    :param force_direct_play: force direct play
    :param force_transcode_play: force transcoding file
    :return: True if successfully playing
    """

    eh.spam('Processing play_video %s %s %s %s %s %s' %
            (file_id, ep_id, mark_as_watched, resume, force_direct_play,
             force_transcode_play))

    from shoko_models.v2 import Episode, File, get_series_for_episode

    # check if we're already playing something
    player = xbmc.Player()
    if player.isPlayingVideo():
        playing_item = player.getPlayingFile()
        log('Player is currently playing %s' % playing_item)
        log('Player Stopping')
        player.stop()

    # wait for it to stop
    while True:
        try:
            if not player.isPlayingVideo():
                break
            xbmc.sleep(500)
            continue
        except:
            pass

    # now continue
    file_url = ''

    if int(ep_id) != 0:
        ep = Episode(ep_id, build_full_object=True)
        series = get_series_for_episode(ep_id)
        ep.series_id = series.id
        ep.series_name = series.name
        item = ep.get_listitem()
        f = ep.get_file_with_id(file_id)
    else:
        f = File(file_id, build_full_object=True)
        item = f.get_listitem()

    if item is not None:
        if resume:
            # TODO looks like this does nothing...
            item.resume()
        else:
            item.setProperty('ResumeTime', '0')
        file_url = f.url_for_player if f is not None else None

    if file_url is not None:
        is_transcoded = False
        m3u8_url = ''
        subs_extension = ''
        is_finished = False
        if not force_direct_play:
            if 'smb://' in file_url:
                file_url = f.remote_url_for_player
            is_transcoded, m3u8_url, subs_extension, is_finished = process_transcoder(
                file_id, file_url, force_transcode_play)

        player = Player()
        player.feed(file_id, ep_id, f.duration,
                    m3u8_url if is_transcoded else file_url, mark_as_watched)

        try:
            item.setProperty('IsPlayable', 'true')

            if is_transcoded:
                #player.play(item=m3u8_url)
                url_for_player = m3u8_url
                item.setPath(url_for_player)
                item.setProperty('inputstreamaddon', 'inputstream.adaptive')
                item.setProperty('inputstream.adaptive.manifest_type', 'mpd')
                item.setMimeType('application/dash+xml')
                item.setContentLookup(False)

                # TODO maybe extract all subs and include them ?
                subs_url = eigakan_host + '/api/video/%s/%s/subs.%s' % (
                    clientid, file_id, subs_extension)
                if pyproxy.head(url_in=subs_url):
                    item.setSubtitles([
                        subs_url,
                    ])
                    item.addStreamInfo('subtitle', {
                        'language': 'Default',
                    })

            else:
                #file_url = f.remote_url_for_player
                #player.play(item=file_url, listitem=item)
                url_for_player = f.url_for_player  # file_url
                item.setPath(url_for_player)

            handle = int(sys.argv[1])

            if handle == -1:
                player.play(item=url_for_player, listitem=item)
            else:
                # thanks to anxdpanic for pointing in right direction
                xbmcplugin.setResolvedUrl(handle, True, item)
        except:
            eh.exception(ErrorPriority.BLOCKING)

        # leave player alive so we can handle onPlayBackStopped/onPlayBackEnded
        # TODO Move the instance to Service, so that it is never disposed
        xbmc.sleep(int(plugin_addon.getSetting('player_sleep')))
        return player_loop(player, is_transcoded, is_finished, ep_id,
                           party_mode)
Exemple #25
0
def pick_best_streams(audio_streams, subs_streams):
    a_index = -1
    s_index = -1
    subs_type = ''
    eh.spam('Processing streams a: %s; s: %s' % (audio_streams, subs_streams))
    if plugin_addon.getSetting('eigakan_manual_mode') == 'false':
        if len(audio_streams.split('\r')) == 1:
            a_index = audio_streams.split('|')[0]
        else:
            for a in audio_streams.split('\r'):
                a = a.split('|')
                for x in a:
                    if x == "*":
                        if a_index == -1:
                            a_index = a[0]
                        else:
                            a_index = -1
                            break

        if len(subs_streams.split('\r')) == 1:
            s_index = subs_streams.split('|')[0]
        else:
            for s in subs_streams.split('\r'):
                s = s.split('|')
                for x in s:
                    if x == "*":
                        if s_index == -1:
                            s_index = s[0]
                        else:
                            s_index = -1
                            break

    if not isinstance(a_index, int):
        a_index = -1

    if not isinstance(s_index, int):
        s_index = -1

    eh.spam('Pick_Best_Streams (after preference): "%s" "%s" "%s"' %
            (a_index, s_index, subs_type))
    # we use manual mode or we didn't have your preferred streams
    if a_index == -1 or s_index == -1:
        if a_index == -1:
            if audio_streams != '':  # less likely but check anyway
                a_option = audio_streams.split('\r')
                if len(a_option) == 1:
                    a_index = a_option[0].split('|')[0]
                else:
                    a_idx = xbmcgui.Dialog().select(
                        plugin_addon.getLocalizedString(30178), a_option)
                    if a_idx > -1:
                        a_index = a_option[a_idx].split('|')[0]
                        if a_index == '':
                            a_index = -1
        if s_index == -1:
            if subs_streams != '':  # check for no data
                s_option = subs_streams.split('\r')
                if len(s_option) == 1:
                    s_index = s_option[0].split('|')[0]
                    subs_type = s_option[0].split('|')[1]
                else:
                    s_idx = xbmcgui.Dialog().select(
                        plugin_addon.getLocalizedString(30179), s_option)
                    if s_idx > -1:
                        s_index = s_option[s_idx].split('|')[0]
                        if s_index == '':
                            s_index = -1
                        else:
                            subs_type = s_option[s_idx].split('|')[1]
                            if subs_type not in ['ass', 'aas', 'srt']:
                                subs_type = ''
            else:
                # TODO try to get external subtitles
                pass
    eh.spam('Pick_Best_Streams results: "%s" "%s" "%s"' %
            (a_index, s_index, subs_type))
    return a_index, s_index, subs_type
 def onPlayBackPaused(self):
     spam('Playback Paused')
     self.PlaybackStatus = PlaybackStatus.PAUSED
     self.scrobble_time()
    def get_data(self, url, referer, timeout, apikey):
        try:
            import error_handler as eh
            headers = {
                'Accept': 'application/json',
                'apikey': apikey,
            }

            if referer is not None:
                referer = quote(self.encode(referer)).replace('%3A', ':')
                if len(referer) > 1:
                    headers['Referer'] = referer

            if '127.0.0.1' not in url and 'localhost' not in url:
                headers['Accept-Encoding'] = 'gzip'
            if '/Stream/' in url:
                headers['api-version'] = '1.0'

            # self.encode(url) # py3 fix
            req = Request(url, headers=headers)
            data = None

            eh.spam('Getting Data ---')
            eh.spam('URL: ', url)
            eh.spam('Headers:', headers)
            response = urlopen(req, timeout=int(timeout))

            if response.info().get('Content-Encoding') == 'gzip':
                eh.spam('Got gzipped response. Decompressing')
                try:
                    buf = BytesIO(response.read())
                    f = gzip.GzipFile(fileobj=buf)
                    data = f.read()
                except Exception as e:
                    eh.spam('Failed to decompress.', e.message)
            else:
                data = response.read()
            response.close()

            eh.spam('Response Body:', data)
            eh.spam('Checking Response for a text error.\n')

            if data is not None and data != '':
                self.parse_possible_error(req, data)

            return data
        except Exception as ex:
            xbmc.log(' === get_data error === %s' % ex, xbmc.LOGNOTICE)
def player_loop(player, is_transcoded, is_transcode_finished, ep_id,
                party_mode):
    try:
        monitor = xbmc.Monitor()

        # seek to beginning of stream :hack: https://github.com/peak3d/inputstream.adaptive/issues/94
        if is_transcoded:
            while not xbmc.Player().isPlayingVideo():
                monitor.waitForAbort(0.25)

            if not is_transcode_finished:
                if xbmc.Player().isPlayingVideo():
                    log('Seek back - so the stream is from beginning')
                    # TODO part1: hack is temporary and not working in 100%
                    # TODO part2: (with small segments + fast cpu, you wont start from 1st segment)
                    #xbmc.executebuiltin('Seek(-60)')
                    xbmc.executeJSONRPC(
                        '{"jsonrpc":"2.0","method":"Player.Seek","params":{"playerid":1,"value":{"seconds":0}},"id":1}'
                    )

        while player.PlaybackStatus != PlaybackStatus.STOPPED and player.PlaybackStatus != PlaybackStatus.ENDED:
            xbmc.sleep(500)

        if player.PlaybackStatus == PlaybackStatus.STOPPED or player.PlaybackStatus == PlaybackStatus.ENDED:
            log('Playback Ended - Shutting Down: ', monitor.abortRequested())

            if player.is_finished:
                log('post-finish: start events')

                if ep_id != 0:
                    from shoko_models.v2 import Episode
                    ep = Episode(ep_id, build_full_object=False)
                    spam('mark as watched, episode')
                    ep.set_watched_status(True)

                # wait till directory is loaded
                while kodi_utils.is_dialog_active():
                    xbmc.sleep(500)
                # refresh it, so it moves onto next item and the mark watched is refreshed
                kodi_utils.refresh()

                # wait till it load again
                while kodi_utils.is_dialog_active():
                    xbmc.sleep(500)

                if int(ep_id) != 0 and plugin_addon.getSetting(
                        'vote_always') == 'true' and not party_mode:
                    spam('vote_always, voting on episode')
                    script_utils.vote_for_episode(ep_id)

                if int(ep_id) != 0 and plugin_addon.getSetting(
                        'vote_on_series') == 'true' and not party_mode:
                    from shoko_models.v2 import get_series_for_episode
                    series = get_series_for_episode(ep_id)
                    # voting should be only when you really watch full series
                    spam('vote_on_series, mark: %s / %s' %
                         (series.sizes.watched_episodes,
                          series.sizes.total_episodes))
                    if series.sizes.watched_episodes - series.sizes.total_episodes == 0:
                        script_utils.vote_for_series(series.id)

            return -1
        else:
            log(
                'Playback Ended - Playback status was not "Stopped" or "Ended". It was ',
                player.PlaybackStatus)
        return 0
    except:
        eh.exception(ErrorPriority.HIGHEST)
        return -1
 def reset(self):
     spam('Player reset')
     self.__init__()
 def onAVChange(self):
     # Will be called when Kodi has a video, audio or subtitle stream. Also happens when the stream changes.
     spam('onAVChange')