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)
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 get_client_settings():
    settings = {}
    try:
        settings = json.loads(
            pyproxy.get_json(eigakan_host + '/api/clientid/%s' % clientid))
    except http_error as er:
        if er.code == 404:
            log('Client profile not found on Eigakan, sending new one...')
            kodi_utils.send_profile()
    return settings
Ejemplo n.º 4
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')
Ejemplo n.º 5
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
    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
Ejemplo n.º 7
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
Ejemplo n.º 8
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')
Ejemplo n.º 9
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)
Ejemplo n.º 10
0
 def onPlayBackSeek(self, time_to_seek, seek_offset):
     log('Playback Paused - time_to_seek=%s seek_offset=%s' %
         (time_to_seek, seek_offset))
     self.time = self.getTime()
     self.scrobble_time()
Ejemplo n.º 11
0
def process_transcoder(file_id, file_url, force_transcode_play=False):
    """

    :param file_id:
    :param file_url:
    :param force_transcode_play: force transcode
    :return:
    """

    is_transcoded = False
    m3u8_url = ''
    subs_type = ''
    is_finished = False

    if plugin_addon.getSetting(
            'enableEigakan') != 'true' and not force_transcode_play:
        return is_transcoded, m3u8_url, subs_type, is_finished

    video_url = trancode_url(file_id)
    post_data = '"file":"' + file_url + '"'

    is_dash = True
    end_url = eigakan_host + '/api/video/%s/%s/end.eigakan' % (clientid,
                                                               file_id)
    if is_dash:
        m3u8_url = eigakan_host + '/api/video/%s/%s/play.mpd' % (clientid,
                                                                 file_id)
        ts_url = eigakan_host + '/api/video/%s/%s/%s' % (clientid, file_id,
                                                         magic_chunk)
    else:
        m3u8_url = eigakan_host + '/api/video/%s/%s/play.m3u8' % (clientid,
                                                                  file_id)
        ts_url = eigakan_host + '/api/video/%s/%s/play0.ts' % (clientid,
                                                               file_id)

    try:
        kodi_utils.check_eigakan()

        # server is alive so send profile of device we didn't before
        if plugin_addon.getSetting('eigakan_handshake') == 'false':
            kodi_utils.send_profile()
        settings = get_client_settings()

        # check if file is already transcoded
        is_finished = pyproxy.head(url_in=end_url)
        if not is_finished:
            # let's probe file, maybe we already know which streams we want
            busy.create(plugin_addon.getLocalizedString(30160),
                        plugin_addon.getLocalizedString(30177))
            audio_streams, subs_streams = eigakan_utils.probe_file(
                file_id, file_url)
            busy.close()

            # pick streams that are preferred via profile on eigakan
            a_index, s_index, subs_type = eigakan_utils.pick_best_streams(
                audio_streams, subs_streams)

            # region BUSY Dialog Hell
            # please wait, Sending request to Transcode server...
            busy.create(plugin_addon.getLocalizedString(30160),
                        plugin_addon.getLocalizedString(30165))
            if a_index > -1:
                post_data += ',"audio":"%s"' % a_index
            if s_index > -1:
                post_data += ',"subtitles":"%s"' % s_index
            pyproxy.post_json(video_url, post_data,
                              custom_timeout=0.1)  # non blocking
            xbmc.sleep(1000)
            # busy.close()

            try_count = 0
            found = False
            # please wait,waiting for being queued
            busy.update(0, plugin_addon.getLocalizedString(30192))
            while True:
                if busy.iscanceled():
                    break
                if eigakan_utils.is_fileid_added_to_transcoder(file_id):
                    break

                try_count += 1
                busy.update(try_count)
                xbmc.sleep(1000)

            try_count = 0
            found = False
            # plase wait, waiting for subs to be dump
            busy.update(try_count, plugin_addon.getLocalizedString(30205))
            while True:
                if busy.iscanceled():
                    break
                ask_for_subs = json.loads(
                    pyproxy.get_json(eigakan_host + '/api/queue/%s' % file_id))
                if ask_for_subs is None:
                    ask_for_subs = {}
                y = ask_for_subs.get('queue', {"videos": {}}).get('videos', {})

                for k in y:
                    if int(k) == int(file_id):
                        found = True
                        break
                    if found:
                        break
                if found:
                    break
                try_count += 1
                if try_count >= 100:
                    try_count = 0
                    busy.update(try_count,
                                plugin_addon.getLocalizedString(30218))
                busy.update(try_count)
                xbmc.sleep(1000)

            try_count = 0
            found = False
            # please waiting, waiting for starting transcode
            busy.update(try_count, plugin_addon.getLocalizedString(30206))
            while True:
                if busy.iscanceled():
                    break
                ask_for_subs = json.loads(
                    pyproxy.get_json(eigakan_host + '/api/queue/%s' % file_id))
                if ask_for_subs is None:
                    ask_for_subs = {}
                x = ask_for_subs.get('queue', {"videos": {}}).get('videos', {})
                for k in x:
                    if int(k) == int(file_id):
                        percent = x[k].get('percent', 0)
                        if int(percent) > 0:
                            found = True
                            log('percent found of transcoding: %s' % percent)
                            break
                if found:
                    break
                try_count += 1
                if try_count >= 100:
                    try_count = 0
                    busy.update(try_count,
                                plugin_addon.getLocalizedString(30218))
                busy.update(try_count)
                xbmc.sleep(1000)

            try_count = 0
            # please wait, Waiting for response from Server...
            busy.update(try_count, plugin_addon.getLocalizedString(30164))
            while True:
                if busy.iscanceled():
                    break
                if pyproxy.head(url_in=ts_url) is False:
                    try_count += 1
                    busy.update(try_count)
                    xbmc.sleep(1000)
                else:
                    break
            busy.close()

            # endregion

        if pyproxy.head(url_in=ts_url):
            is_transcoded = True

    except:
        eh.exception(ErrorPriority.BLOCKING)
        try:
            busy.close()
        except:
            pass

    return is_transcoded, m3u8_url, subs_type, is_finished
Ejemplo n.º 12
0
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
Ejemplo n.º 13
0
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)