示例#1
0
    def _create_arguments(self):
        if self.namedpipe:
            filename = self.namedpipe.path
            if is_win32:
                if self.player_name == "vlc":
                    filename = f"stream://\\{filename}"
                elif self.player_name == "mpv":
                    filename = f"file://{filename}"
        elif self.filename:
            filename = self.filename
        elif self.http:
            filename = self.http.url
        else:
            filename = "-"
        extra_args = []

        if self.title is not None:
            # vlc
            if self.player_name == "vlc":
                # see https://wiki.videolan.org/Documentation:Format_String/, allow escaping with \$
                self.title = self.title.replace("$", "$$").replace(r'\$$', "$")
                extra_args.extend(["--input-title-format", self.title])

            # mpv
            if self.player_name == "mpv":
                # see https://mpv.io/manual/stable/#property-expansion, allow escaping with \$, respect mpv's $>
                self.title = self._mpv_title_escape(self.title)
                extra_args.append(f"--force-media-title={self.title}")

            # potplayer
            if self.player_name == "potplayer":
                if filename != "-":
                    # PotPlayer - About - Command Line
                    # You can specify titles for URLs by separating them with a backslash (\) at the end of URLs.
                    # eg. "http://...\title of this url"
                    self.title = self.title.replace('"', '')
                    filename = filename[:-1] + '\\' + self.title + filename[-1]

        # format args via the formatter, so that invalid/unknown variables don't raise a KeyError
        argsformatter = Formatter({
            PLAYER_ARGS_INPUT_DEFAULT: lambda: filename,
            PLAYER_ARGS_INPUT_FALLBACK: lambda: filename
        })
        args = argsformatter.title(self.args)
        cmd = self.cmd

        # player command
        if is_win32:
            eargs = subprocess.list2cmdline(extra_args)
            # do not insert and extra " " when there are no extra_args
            return " ".join([cmd] + ([eargs] if eargs else []) + [args])
        return shlex.split(cmd) + extra_args + shlex.split(args)
示例#2
0
def output_stream_passthrough(stream, formatter: Formatter):
    """Prepares a filename to be passed to the player."""
    global output

    try:
        url = stream.to_url()
    except TypeError:
        console.exit("The stream specified cannot be translated to a URL")
        return False

    output = PlayerOutput(
        args.player,
        args=args.player_args,
        filename=f'"{url}"',
        call=True,
        quiet=not args.verbose_player,
        title=formatter.title(args.title, defaults=DEFAULT_STREAM_METADATA) if args.title else args.url
    )

    try:
        log.info(f"Starting player: {args.player}")
        output.open()
    except OSError as err:
        console.exit(f"Failed to start player: {args.player} ({err})")
        return False

    return True
示例#3
0
def get_formatter(plugin: Plugin):
    return Formatter(
        {
            "url": lambda: args.url,
            "author": lambda: plugin.get_author(),
            "category": lambda: plugin.get_category(),
            "game": lambda: plugin.get_category(),
            "title": lambda: plugin.get_title(),
            "time": lambda: datetime.now()
        }, {
            "time": lambda dt, fmt: dt.strftime(fmt)
        })
示例#4
0
def create_output(formatter: Formatter):
    """Decides where to write the stream.

    Depending on arguments it can be one of these:
     - The stdout pipe
     - A subprocess' stdin pipe
     - A named pipe that the subprocess reads from
     - A regular file

    """

    if (args.output or args.stdout) and (args.record or args.record_and_pipe):
        console.exit(
            "Cannot use record options with other file output options.")

    if args.output:
        if args.output == "-":
            out = FileOutput(fd=stdout)
        else:
            out = check_file_output(
                formatter.path(args.output, args.fs_safe_rules), args.force)
    elif args.stdout:
        out = FileOutput(fd=stdout)
    elif args.record_and_pipe:
        record = check_file_output(
            formatter.path(args.record_and_pipe, args.fs_safe_rules),
            args.force)
        out = FileOutput(fd=stdout, record=record)
    elif not args.player:
        console.exit("The default player (VLC) does not seem to be "
                     "installed. You must specify the path to a player "
                     "executable with --player, a file path to save the "
                     "stream with --output, or pipe the stream to "
                     "another program with --stdout.")
    else:
        http = namedpipe = record = None

        if args.player_fifo:
            try:
                namedpipe = NamedPipe()
            except OSError as err:
                console.exit(f"Failed to create pipe: {err}")
        elif args.player_http:
            http = create_http_server()

        if args.record:
            record = check_file_output(
                formatter.path(args.record, args.fs_safe_rules), args.force)

        log.info(f"Starting player: {args.player}")

        out = PlayerOutput(
            args.player,
            args=args.player_args,
            quiet=not args.verbose_player,
            kill=not args.player_no_close,
            namedpipe=namedpipe,
            http=http,
            record=record,
            title=formatter.title(args.title, defaults=DEFAULT_STREAM_METADATA)
            if args.title else args.url)

    return out
示例#5
0
def output_stream_http(plugin: Plugin,
                       initial_streams: Streams,
                       formatter: Formatter,
                       external=False,
                       port=0):
    """Continuously output the stream over HTTP."""
    global output

    if not external:
        if not args.player:
            console.exit("The default player (VLC) does not seem to be "
                         "installed. You must specify the path to a player "
                         "executable with --player.")

        server = create_http_server()
        player = output = PlayerOutput(
            args.player,
            args=args.player_args,
            filename=server.url,
            quiet=not args.verbose_player,
            title=formatter.title(args.title, defaults=DEFAULT_STREAM_METADATA)
            if args.title else args.url)

        try:
            log.info(f"Starting player: {args.player}")
            if player:
                player.open()
        except OSError as err:
            console.exit(f"Failed to start player: {args.player} ({err})")
    else:
        server = create_http_server(host=None, port=port)
        player = None

        log.info("Starting server, access with one of:")
        for url in server.urls:
            log.info(" " + url)

    for req in iter_http_requests(server, player):
        user_agent = req.headers.get("User-Agent") or "unknown player"
        log.info(f"Got HTTP request from {user_agent}")

        stream_fd = prebuffer = None
        while not stream_fd and (not player or player.running):
            try:
                streams = initial_streams or fetch_streams(plugin)
                initial_streams = None

                for stream_name in (resolve_stream_name(streams, s)
                                    for s in args.stream):
                    if stream_name in streams:
                        stream = streams[stream_name]
                        break
                else:
                    log.info(
                        "Stream not available, will re-fetch streams in 10 sec"
                    )
                    sleep(10)
                    continue
            except PluginError as err:
                log.error(f"Unable to fetch new streams: {err}")
                continue

            try:
                log.info(
                    f"Opening stream: {stream_name} ({type(stream).shortname()})"
                )
                stream_fd, prebuffer = open_stream(stream)
            except StreamError as err:
                log.error(err)

        if stream_fd and prebuffer:
            log.debug("Writing stream to player")
            read_stream(stream_fd, server, prebuffer, formatter)

        server.close(True)

    player.close()
    server.close()