private static void GetPlaylistImpl(string url, string txtpath, RunToolHelper runner)
        {
            bool isPytube = false; // use only ytdl, not pytube
            var  args     = new List <string>();

            args.Add("--ignore-config"); // don't look for global config file
            args.Add("--no-mark-watched");
            args.Add("--no-call-home");
            args.Add("-j"); // send output in json format
            args.Add("--flat-playlist");
            args.Add("-i"); // continue after errs
            args.Add(url);

            var info = new ProcessStartInfo();

            info.FileName               = CsDownloadVidFilepaths.GetYtdlPath(isPytube);
            info.Arguments              = Utils.CombineProcessArguments(args.ToArray());
            info.CreateNoWindow         = true;
            info.RedirectStandardError  = true;
            info.RedirectStandardOutput = true;
            info.UseShellExecute        = false;

            if (CsDownloadVidFilepaths.GetYtdlPath(isPytube).EndsWith(".py"))
            {
                info.FileName  = CsDownloadVidFilepaths.GetPython();
                info.Arguments = "\"" + CsDownloadVidFilepaths.GetYtdlPath(isPytube) + "\" " +
                                 Utils.CombineProcessArguments(args.ToArray());
            }

            var     stdoutGot = "";
            Process p         = new Process();

            p.StartInfo = info;
            p.Start();
            p.OutputDataReceived += (o, eparam) => { stdoutGot += eparam.Data; };
            p.BeginOutputReadLine();
            p.WaitForExit();

            if (p.ExitCode != 0)
            {
                throw new CsDownloadVidException("error - non-zero exit code of " + p.ExitCode);
            }

            stdoutGot = stdoutGot.Trim();
            if (!stdoutGot.StartsWith("{"))
            {
                throw new CsDownloadVidException("error - did not get valid json back " +
                                                 stdoutGot);
            }

            GetPlaylistImplFromJson(runner, url, stdoutGot, txtpath);
        }
        public FormGetVideo()
        {
            InitializeComponent();
            panelAdvanced.Visible               = chkShowAdvanced.Checked;
            lblEnterUrlsAdvanced.Visible        = chkShowAdvanced.Checked;
            panelChooseQuality.Visible          = false;
            panelChooseOutput.Visible           = false;
            btnNextStepIsToChooseOutput.Enabled = false;
            lblShortStatus.Text = "";
            txtStatus.Visible   = false;

            AddGenericFormatsToListbox();
            txtOutputDir.Text   = CsDownloadVidFilepaths.GetDefaultDownloadsDir();
            lblNamePattern.Text = "Filename pattern, see also" + Utils.NL +
                                  "%(upload_date)s";
            _runner = new RunToolHelper(this.txtStatus, this.lblShortStatus,
                                        (line) => (!line.Contains("[download]")));

            // pre-emptively ensure that we have paths
            var ensurePath = CsDownloadVidFilepaths.GetPython();
        }
        ProcessStartInfo GetStartInfo(string url, string format, bool listSupportedFormatsOnly)
        {
            var args = new List <string>();

            args.Add("--ignore-config"); // don't look for global config file
            args.Add("--no-mark-watched");
            args.Add("--no-call-home");
            args.Add("--no-mtime"); // don't adjust the lmt of the file, it's confusing
            args.Add("--no-playlist");

            if (listSupportedFormatsOnly)
            {
                args.Add("--list-formats");
                args.Add("--simulate");
            }
            else
            {
                args.Add("--format");
                args.Add(format);

                // post-process, otherwise the m4a won't show correctly in some media players
                if (chkDashToM4a.Checked)
                {
                    args.Add("--ffmpeg-location");
                    args.Add(CsDownloadVidFilepaths.GetFfmpeg());
                }
            }

            if (cbUsePytube.Checked)
            {
                args.Add("--outputdir=" + txtOutputDir.Text);
            }
            else
            {
                var outputTemplate = Path.Combine(txtOutputDir.Text, txtFilenamePattern.Text);
                args.Add("--output");
                args.Add(outputTemplate);
            }

            var sArgs = Utils.CombineProcessArguments(args.ToArray());

            if (!string.IsNullOrWhiteSpace(txtAdditionalArgs.Text))
            {
                sArgs += " " + txtAdditionalArgs.Text + " ";
            }

            sArgs += " " + Utils.CombineProcessArguments(new string[] { url });

            var info = new ProcessStartInfo();

            info.FileName               = CsDownloadVidFilepaths.GetYtdlPath(this.cbUsePytube.Checked);
            info.Arguments              = sArgs;
            info.CreateNoWindow         = true;
            info.RedirectStandardError  = true;
            info.RedirectStandardOutput = true;
            info.UseShellExecute        = false;

            if (CsDownloadVidFilepaths.GetYtdlPath(this.cbUsePytube.Checked).EndsWith(".py"))
            {
                info.FileName  = CsDownloadVidFilepaths.GetPython();
                info.Arguments = "\"" + CsDownloadVidFilepaths.GetYtdlPath(
                    this.cbUsePytube.Checked) + "\" " + sArgs;
            }

            return(info);
        }