Esempio n. 1
0
 def _dispatch_delete(self, objectname):
     try:
         self._objects[objectname]._shutdown()
     except Exception:
         _log.error("Error when shutting down the object %s:",
                    type(self._objects[objectname]))
         _log.debug(traceback.format_exc())
     del self._objects[objectname]
Esempio n. 2
0
    def Wait_Window_Loaded(self):
        tries = 5
        while self.Window_Is_Loading():
            if tries == 0:
                log.error("Failed to wait till window has finished loading")
                return int(False)

            tries = tries - 1
            time.sleep(0.3)

        log.debug("Finished waiting till window has finished loading")
        return int(True)
Esempio n. 3
0
    def read_and_dispatch(self, timeout=None, thread=True, condition=None):
        """
            Read one message from socket (with timeout specified by the optional
            argument *timeout*) and dispatches that message.

            Parameters:

            **timeout** = None
                Timeout in seconds of the read operation. If it is None
                (or ommitted) then the read will wait
                until new data is available.

            **(return value)**
                True, in case of the operation has suceeded and **one** message
                has been dispatched. False, if no data or malformed data has
                been received.

        """
        self.read_lock.acquire()
        self.reading_event.set()
        try:
            if condition:
                if condition() is False:
                    return False
            if thread:
                dispatch_item = self.dispatch_item_threaded
            else:
                dispatch_item = self.dispatch_item_single

            data = self.read(timeout=timeout)
            if not data:
                return False
            try:
                item = json.loads(data, self)
                if type(item) is list:  # batch call
                    for i in item:
                        dispatch_item(i)
                elif type(item) is dict:  # std call
                    if 'result' in item:
                        self.dispatch_item_single(item)
                    else:
                        dispatch_item(item)
                else:  # Unknown format :-(
                    _log.debug("Received message with unknown format type: %s",
                               type(item))
                    return False
            except Exception:
                _log.debug(traceback.format_exc())
                return False
            return True
        finally:
            self.reading_event.clear()
            self.read_lock.release()
Esempio n. 4
0
    def write_line(self, data):
        """
            Write a line *data* to socket. It appends a **newline** at
            the end of the *data* before sending it.

            The string MUST NOT contain **newline** otherwise an AssertionError will
            raise.

            Parameters:

            **data**
                String containing the data to be sent.
        """
        assert ('\n' not in data)
        self.write_lock.acquire()
        try:
            try:
                data = data.encode('utf-8')
            except AttributeError:
                pass
            if self._debug_socket:
                _log.debug("<:%d: %s", len(data), data.decode('utf-8')[:130])

            self._wbuffer += data + b'\n'
            sbytes = 0
            while self._wbuffer:
                try:
                    sbytes = self._sck.send(self._wbuffer)
                except IOError:
                    _log.debug("Read socket error: IOError (timeout: %r)",
                               self._sck.gettimeout())
                    _log.debug(traceback.format_exc(0))
                    return 0
                except socket.error:
                    _log.debug("Read socket error: socket.error (timeout: %r)",
                               self._sck.gettimeout())
                    _log.debug(traceback.format_exc(0))
                    return 0
                except:
                    raise
                if sbytes == 0:
                    break
                self._wbuffer = self._wbuffer[sbytes:]
            if self._wbuffer:
                _log.warning("%d bytes left in write buffer",
                             len(self._wbuffer))
            return len(self._wbuffer)
        finally:
            self.write_lock.release()
Esempio n. 5
0
    def Player_WatchTimes(self):
        error = ""
        watchedTime = "0"
        videoDuration = "0"
        try:
            watchedTime = str(XBMC_PLAYER.getTime())
            videoDuration = str(XBMC_PLAYER.getTotalTime())
            log.debug("Watched: %s, duration: %s" % (watchedTime, videoDuration))
        except Exception as e:
            error = "Stopped playing: %s" % repr(e)

        watchTimes = {
            "watchedTime": watchedTime,
            "videoDuration": videoDuration,
            "error": error
        }
        return watchTimes
Esempio n. 6
0
def register(search, search_movie, search_episode, search_season=None):
    try:
        payload = json.loads(base64.b64decode(sys.argv[1]))
    except:
        notify(getLocalizedString(30102), time=1000)
        return

    results = ()
    method = {
        "search": search,
        "search_movie": search_movie,
        "search_season": search_season,
        "search_episode": search_episode,
    }.get(payload["method"]) or (lambda *a, **kw: [])
    try:
        results = ()
        try:
            objects = method(payload["search_object"])
            if objects is not None:
                results = tuple(objects)
        except Exception as e:
            import traceback
            map(log.error, traceback.format_exc().split("\n"))
            notify("%s: %s" %
                   (getLocalizedString(30224), repr(e).encode('utf-8')))
            try:
                urllib_request.urlopen("%s/provider/%s/failure" %
                                       (da_inc_HOST, ADDON_ID))
            except:
                pass
    finally:
        try:
            req = urllib_request.Request(payload["callback_url"],
                                         data=json.dumps(results))
            with closing(urllib_request.urlopen(req)) as response:
                log.debug("callback returned: %d" % response.getcode())
        except Exception as e:
            import traceback
            map(log.error, traceback.format_exc().split("\n"))
            notify("%s: %s" %
                   (getLocalizedString(30224), repr(e).encode('utf-8')))
            try:
                urllib_request.urlopen("%s/provider/%s/failure" %
                                       (da_inc_HOST, ADDON_ID))
            except:
                pass
Esempio n. 7
0
    def _readn(self):
        """
            Internal function which reads from socket waiting for a newline
        """
        streambuffer = self._buffer
        pos = streambuffer.find(b'\n')
        # _log.debug("read...")
        # retry = 0
        while pos == -1:
            data = b''
            try:
                data = self._sck.recv(2048)
            except IOError as inst:
                _log.debug("Read socket error: IOError%r (timeout: %r)",
                           inst.args, self._sck.gettimeout())
                if inst.errno in (errno.EAGAIN, errno.EWOULDBLOCK):
                    if self._sck.gettimeout() == 0:  # if it was too fast
                        self._sck.settimeout(5)
                        continue
                        # time.sleep(0.5)
                        # retry += 1
                        # if retry < 10:
                        #     _log.debug("Retry %s", retry)
                        #     continue
                # _log.debug(traceback.format_exc(0))
                if inst.errno in self._SOCKET_COMM_ERRORS:
                    raise EofError(len(streambuffer))

                return b''
            except socket.error as inst:
                _log.error("Read socket error: socket.error%r (timeout: %r)",
                           inst.args, self._sck.gettimeout())
                # _log.debug(traceback.format_exc(0))
                return b''
            except:
                raise
            if not data:
                raise EofError(len(streambuffer))
            # _log.debug("readbuf+: %r", data)
            streambuffer += data
            pos = streambuffer.find(b'\n')

        self._buffer = streambuffer[pos + 1:]
        streambuffer = streambuffer[:pos]
        # _log.debug("read: %r", buffer)
        return streambuffer
Esempio n. 8
0
    def _format_exception(self, obj, method, args, kw, exc):
        etype, evalue, etb = exc
        funargs = ", ".join([repr(x) for x in args] +
                            ["%s=%r" % (k, kw[k]) for k in kw])
        if len(funargs) > 40:
            funargs = funargs[:37] + "..."

        _log.error("(%s) In Handler method %s.%s(%s) ",
                   obj.__class__.__module__, obj.__class__.__name__, method,
                   funargs)
        _log.debug("\n".join([
            "%s::%s:%d %s" % (filename, fnname, lineno, srcline) for filename,
            lineno, fnname, srcline in traceback.extract_tb(etb)[1:]
        ]))
        _log.error("Unhandled error: %s: %s", etype.__name__, evalue)
        del etb
        return '%s: %s' % (etype.__name__, evalue)
Esempio n. 9
0
 def write_thread(self):
     abort = False
     while not abort:
         self.write_thread_semaphore.acquire()
         try:
             item = self.write_thread_queue.pop(0)
         except IndexError:  # pop from empty list?
             _log.warning("write queue was empty??")
             continue
         abort = item.get("abort", False)
         event = item.get("event")
         write_data = item.get("write_data")
         if write_data:
             item["result"] = self.write_now(write_data)
         if event:
             event.set()
     if self._debug_socket:
         _log.debug("Writing thread finished.")
Esempio n. 10
0
 def _send(self, response):
     txtResponse = None
     try:
         txtResponse = json.dumps(response, self)
     except Exception as e:
         _log.error(
             "An unexpected error ocurred when trying to create the message: %r",
             e)
         response = {
             'result': None,
             'error': "InternalServerError: " + repr(e)
         }
         txtResponse = json.dumps(response, self)
     try:
         self.write(txtResponse)
     except TypeError:
         _log.debug("response was: %r", response)
         raise
Esempio n. 11
0
    def read_line(self):
        """
            Read a line of *data* from socket. It removes the `\\n` at
            the end before returning the value.

            If the original packet contained `\\n`, the message will be decoded
            as two or more messages.

            Returns the line of *data* received from the socket.
        """

        self.read_lock.acquire()
        try:
            data = self._readn()
            if len(data) and self._debug_socket:
                _log.debug(">:%d: %s", len(data), data.decode('utf-8')[:130])
            return data.decode('utf-8')
        finally:
            self.read_lock.release()
Esempio n. 12
0
    def setresponse(self, value):
        """
            Method used by Connection instance to tell Request that a Response
            is available to this request.

            Parameters:

            **value**
                Value (JSON decoded) received from socket.
        """
        self.responses.put(value)
        for callback in self.callbacks:
            try:
                callback(self)
            except Exception as exc:
                _log.error("Error on callback: %r", exc)
                _log.debug(traceback.format_exc())

        self.event_response.set()  # helper for threads.
        if self.auto_close:
            self.close()
Esempio n. 13
0
def start_da_inc(**kwargs):
    jsonrpc_failures = 0
    while jsonrpc_enabled() is False:
        jsonrpc_failures += 1
        log.warning(
            "Unable to connect to Kodi's JSON-RPC service, retrying...")
        if jsonrpc_failures > 1:
            time.sleep(5)
            if not jsonrpc_enabled(notify=True):
                log.error(
                    "Unable to reach Kodi's JSON-RPC service, aborting...")
                return False
            else:
                break
        time.sleep(3)

    da_inc_dir, da_inc_binary = get_da_inc_binary()

    log.info("Binary dir: %s, item: %s " % (da_inc_dir, da_inc_binary))
    if da_inc_dir is False or da_inc_binary is False:
        return False

    lockfile = os.path.join(ADDON_PATH, ".lockfile")
    if os.path.exists(lockfile):
        log.warning("Existing process found from lockfile, killing...")
        try:
            with open(lockfile) as lf:
                pid = int(lf.read().rstrip(" \t\r\n\0"))
            os.kill(pid, 9)
        except OSError as e:
            if e.errno != 3:
                # Ignore:   OSError: [Errno 3] No such process
                log.error(repr(e))
        except Exception as e:
            log.error(repr(e))

        if binary_platform["os"] == "windows":
            try:
                library_lockfile = os.path.join(
                    xbmc.translatePath(
                        ADDON.getAddonInfo("profile")).decode('utf-8'),
                    "library.db.lock")
                log.warning("Removing library.db.lock file at %s ..." %
                            library_lockfile)
                os.remove(library_lockfile)
            except Exception as e:
                log.error(repr(e))

    SW_HIDE = 0
    STARTF_USESHOWWINDOW = 1

    args = [da_inc_binary]
    kwargs["cwd"] = da_inc_dir

    if binary_platform["os"] == "windows":
        args[0] = getWindowsShortPath(da_inc_binary)
        kwargs["cwd"] = getWindowsShortPath(da_inc_dir)
        si = subprocess.STARTUPINFO()
        si.dwFlags = STARTF_USESHOWWINDOW
        si.wShowWindow = SW_HIDE
        clear_fd_inherit_flags()
        kwargs["startupinfo"] = si
    else:
        env = os.environ.copy()
        env["LD_LIBRARY_PATH"] = "%s:%s" % (da_inc_dir,
                                            env.get("LD_LIBRARY_PATH", ""))
        kwargs["env"] = env
        kwargs["close_fds"] = True

    wait_counter = 1
    log.debug("Checking for visible")
    while xbmc.getCondVisibility(
            'Window.IsVisible(10140)') or xbmc.getCondVisibility(
                'Window.IsActive(10140)'):
        if wait_counter == 1:
            log.info(
                'Add-on settings currently opened, waiting before starting...')
        if wait_counter > 300:
            break
        time.sleep(1)
        wait_counter += 1

    log.info("da_inc: start args: %s, kw: %s" % (args, kwargs))

    if hasSubprocess:
        return subprocess.Popen(args, **kwargs)
    return False
Esempio n. 14
0
def getInfoLabels():
    id_list = [int(s) for s in sys.argv[0].split("/") if s.isdigit()]
    tmdb_id = id_list[0] if id_list else None

    # if xbmc.getInfoLabel("ListItem.DBID"):
    #     url = "%s/infolabels" % (da_inc_HOST)
    # elif not tmdb_id:
    if not tmdb_id:
        request_url = sys.argv[0] + sys.argv[2]
        parsed_url = urllib_parse.urlparse(request_url)
        query = urllib_parse.parse_qs(parsed_url.query)
        log.debug("Parsed URL: %s, Query: %s", repr(parsed_url), repr(query))
        if 'tmdb' in query and 'type' in query and query['type'][0] == 'search':
            tmdb_id = query['tmdb'][0]
            url = "%s/search/infolabels/%s" % (da_inc_HOST, tmdb_id)
        elif '/search' in parsed_url and 'tmdb' in query:
            tmdb_id = query['tmdb'][0]
            url = "%s/search/infolabels/%s" % (da_inc_HOST, tmdb_id)
        elif '/search' in parsed_url and 'q' in query:
            tmdb_id = query['q'][0]
            url = "%s/search/infolabels/%s" % (da_inc_HOST, tmdb_id)
        elif 'tmdb' in query and 'type' in query and query['type'][
                0] == 'movie':
            tmdb_id = query['tmdb'][0]
            url = "%s/movie/%s/infolabels" % (da_inc_HOST, tmdb_id)
        elif 'show' in query:
            tmdb_id = query['show'][0]
            if 'season' in query and 'episode' in query:
                url = "%s/show/%s/season/%s/episode/%s/infolabels" % (
                    da_inc_HOST, tmdb_id, query['season'][0],
                    query['episode'][0])
            else:
                url = "%s/show/%s/infolabels" % (da_inc_HOST, tmdb_id)
        else:
            url = "%s/infolabels" % (da_inc_HOST)
    elif 'movie' in sys.argv[0]:
        url = "%s/movie/%s/infolabels" % (da_inc_HOST, tmdb_id)
    elif ('episode' in sys.argv[0]
          or 'show' in sys.argv[0]) and len(id_list) > 2:
        url = "%s/show/%s/season/%s/episode/%s/infolabels" % (
            da_inc_HOST, tmdb_id, id_list[1], id_list[2])
    elif 'show' in sys.argv[0] and len(id_list) == 2:
        url = "%s/show/%s/season/%s/episode/%s/infolabels" % (
            da_inc_HOST, tmdb_id, id_list[1], 1)
    else:
        url = "%s/infolabels" % (da_inc_HOST)

    log.debug("Resolving TMDB item by calling %s for %s" %
              (url, repr(sys.argv)))

    try:
        with closing(urllib_request.urlopen(url)) as response:
            resolved = json.loads(response.read(), parse_int=str)
            if not resolved:
                return {}

            if 'info' in resolved and resolved['info']:
                resolved.update(resolved['info'])

            if 'art' in resolved and resolved['art']:
                resolved['artbanner'] = ''
                for k, v in resolved['art'].items():
                    resolved['art' + k] = v

            if 'info' in resolved:
                del resolved['info']
            if 'art' in resolved:
                del resolved['art']
            if 'stream_info' in resolved:
                del resolved['stream_info']

            if 'DBTYPE' not in resolved:
                resolved['DBTYPE'] = 'video'
            if 'mediatype' not in resolved or resolved['mediatype'] == '':
                resolved['mediatype'] = resolved['DBTYPE']

            return resolved
    except:
        log.debug("Could not resolve TMDB item: %s" % tmdb_id)
        return {}
Esempio n. 15
0
 def http_error_302(self, req, fp, code, msg, headers):
     infourl = urllib_response.addinfourl(fp, headers, headers["Location"])
     infourl.status = code
     infourl.code = code
     log.debug("Redirecting to: %s", headers["Location"])
     return infourl
Esempio n. 16
0
def run(url_suffix="", retry=0):
    try:
        buffer_timeout = int(ADDON.getSetting("buffer_timeout"))
        if buffer_timeout < 60:
            buffer_timeout = 60
    except:
        buffer_timeout = 60
    buffer_timeout = buffer_timeout * 2

    try:
        preload_timeout = int(ADDON.getSetting("preload_timeout"))
        if preload_timeout < 1:
            preload_timeout = 1
    except:
        preload_timeout = 1

    socket.setdefaulttimeout(buffer_timeout)
    urllib_request.install_opener(
        urllib_request.build_opener(NoRedirectHandler()))

    # Pause currently playing da_inc file to avoid doubling requests
    try:
        if xbmc.Player().isPlaying() and ADDON_ID in xbmc.Player(
        ).getPlayingFile():
            xbmc.Player().pause()
    except:
        pass

    url = sys.argv[0].replace("plugin://%s" % ADDON_ID,
                              da_inc_HOST + url_suffix) + sys.argv[2]
    query_add = ""

    if len(sys.argv) > 3:
        app = sys.argv[3].replace(":", "=")

        # Replacing resume=false with resume=true if item is launched from main window
        title = xbmc.getInfoLabel('ListItem.Title')
        label = xbmc.getInfoLabel('ListItem.Label')
        # if "resume" in app and not title and not label:
        #     app = app.replace("resume=false", "resume=true")
        # if "resume" not in app and not title and not label:
        if not title and not label:
            if app:
                app = app.replace("resume=false", "")
                app += "&"
            if app and "resume" not in app:
                app += "resume=true"
        query_add = app
    elif "play" in url or "links" in url:
        query_add = "resume=true"

    if query_add and "resume" not in url:
        query_add = query_add.replace("resume=", "doresume=")
        if "?" in url:
            url += "&" + query_add
        else:
            url += "?" + query_add

    log.debug("Requesting %s from %s" % (url, repr(sys.argv)))

    try:
        data = _json(url)
    except PlayerException as e:
        redirect_url = e.__str__()
        log.debug("Launching player with %s" % (redirect_url))
        xbmcplugin.endOfDirectory(HANDLE, succeeded=True)
        xbmc.sleep(500)
        xbmc.executeJSONRPC(
            '{"jsonrpc":"2.0","method":"Player.Open","params":{"item":{"file":"%s"}},"id":"1"}'
            % (redirect_url))
        return
    except RedirectException as e:
        redirect_url = e.__str__()
        log.debug("Redirecting Kodi with %s" % (redirect_url))
        xbmcplugin.endOfDirectory(HANDLE, succeeded=True)
        xbmc.sleep(500)
        if "keyboard=1" in sys.argv[0]:
            xbmc.executebuiltin('Container.Update(%s,replace)' %
                                (redirect_url))
        else:
            xbmc.executebuiltin('Container.Update(%s)' % (redirect_url))
        return
    except urllib_error.URLError as e:
        # We can retry the request if connection is refused.
        # For example when plugin has not yet started but is requested by someone.
        if retry <= 2:
            time.sleep(preload_timeout)
            return run(retry=retry + 1)

        if isinstance(e.reason, IOError) or isinstance(
                e.reason, OSError) or 'Connection refused' in e.reason:
            notify(getLocalizedString(30116), time=7000)
        else:
            import traceback
            map(log.error, traceback.format_exc().split("\n"))
            notify(e.reason, time=7000)
        return
    except Exception as e:
        import traceback
        map(log.error, traceback.format_exc().split("\n"))
        try:
            msg = six.ensure_text(e.__str__(), errors='ignore')
        except:
            try:
                msg = six.ensure_binary(e.__str__(), errors='ignore')
            except:
                msg = repr(e)
        notify(getLocalizedLabel(msg), time=7000)
        return

    if not data:
        return

    if data["content_type"]:
        content_type = data["content_type"]
        if data["content_type"].startswith("menus"):
            content_type = data["content_type"].split("_")[1]

        xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_UNSORTED)
        if content_type != "tvshows":
            xbmcplugin.addSortMethod(HANDLE,
                                     xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE)
        else:
            xbmcplugin.addSortMethod(HANDLE,
                                     xbmcplugin.SORT_METHOD_TITLE_IGNORE_THE)
        xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_DATE)
        xbmcplugin.addSortMethod(HANDLE, xbmcplugin.SORT_METHOD_GENRE)
        xbmcplugin.setContent(HANDLE, content_type)

    listitems = list(range(len(data["items"])))
    for i, item in enumerate(data["items"]):
        # Translate labels
        if item["label"][0:8] == "LOCALIZE":
            item["label"] = getLocalizedLabel(item["label"])
            if isinstance(item["label"], str):
                item["label"] = six.ensure_text(item["label"], 'utf-8')
        if item["label2"][0:8] == "LOCALIZE":
            item["label2"] = getLocalizedLabel(item["label2"])

        listItem = xbmcgui.ListItem(label=item["label"],
                                    label2=item["label2"],
                                    iconImage=item["icon"],
                                    thumbnailImage=item["thumbnail"])
        if item.get("info"):
            listItem.setInfo("video", item["info"])
        if item.get("stream_info"):
            for type_, values in item["stream_info"].items():
                listItem.addStreamInfo(type_, values)
        if item.get("art"):
            listItem.setArt(item["art"])
        elif ADDON.getSetting('default_fanart'
                              ) == 'true' and item["label"] != six.ensure_text(
                                  getLocalizedString(30218), 'utf-8'):
            fanart = os.path.join(ADDON_PATH, "fanart.png")
            listItem.setArt({'fanart': fanart})
        if item.get("context_menu"):
            # Translate context menus
            for m, menu in enumerate(item["context_menu"]):
                if menu[0][0:8] == "LOCALIZE":
                    menu[0] = getLocalizedLabel(menu[0])
            listItem.addContextMenuItems(item["context_menu"])
        listItem.setProperty("isPlayable", item["is_playable"] and "true"
                             or "false")
        if item.get("properties"):
            for k, v in item["properties"].items():
                listItem.setProperty(k, v)
        listitems[i] = (item["path"], listItem, not item["is_playable"])

    xbmcplugin.addDirectoryItems(HANDLE, listitems, totalItems=len(listitems))

    # Set ViewMode
    if data["content_type"]:
        viewMode = ADDON.getSetting("viewmode_%s" % data["content_type"])
        if viewMode:
            try:
                xbmc.executebuiltin('Container.SetViewMode(%s)' % viewMode)
            except Exception as e:
                log.warning("Unable to SetViewMode(%s): %s" %
                            (viewMode, repr(e)))

    xbmcplugin.endOfDirectory(HANDLE,
                              succeeded=True,
                              updateListing=False,
                              cacheToDisc=False)