2

Problem:
I'm trying to hook up the standard input/standard output from a unix executable file to the user interface in a MacOS application. But, I can't seem to access the values - nothing shows up.

Background:
I've implemented every solution that I could find, but none of them have worked [1][2][3][4][5][6][7][8][9]. I've completed a Python 3 course [1], so that I could customize the standard output in the python script of the executable file [1]. And, I've reviewed and implemented several working MacOS repositories that update their user interface with data from standard output [1][2][3].

Code: Full

func runExecutable() {

    let desktop = fileManager.urls(for: .desktopDirectory, in: .userDomainMask)[0]
    let url = Bundle.main.url(forResource: "youtube_dl_custom", withExtension: "")
    let arguments = [
        "--format",
        "bestvideo[ext=mp4]+bestaudio[ext=m4a]",
        "--output",
        "\(desktop)/%(title)s.%(ext)s",
        "\(videoUrlTextField.stringValue)"
    ]
    process.arguments = arguments
    process.executableURL = url
    process.standardInput = inputPipe
    process.standardOutput = outputPipe

    openConsolePipe()

    inputPipe.fileHandleForReading.readabilityHandler = {
        [weak self] fileHandle in

        let data = fileHandle.availableData
        self?.buffer.append(data)
        if let buffer = self?.buffer,
            let string = String(data: buffer, encoding: .utf8),
            string.last?.isNewline == true {

            self?.buffer.removeAll()
            print("## \(string)")
            self?.standardOutputTextView.string += string + "\n"

                self?.outputPipe.fileHandleForWriting.write(data)
            }
        }
    try? process.run()
    closeConsolePipe()
}
func openConsolePipe() {
    dup2(STDOUT_FILENO, outputPipe.fileHandleForWriting.fileDescriptor)
    dup2(inputPipe.fileHandleForWriting.fileDescriptor, STDOUT_FILENO)
    dup2(inputPipe.fileHandleForWriting.fileDescriptor, STDERR_FILENO)
}
func closeConsolePipe() {
    freopen("/dev/stdout", "a", stdout)
}

Results:
The standard output appears to automatically print to the console, but I can't seem to access the values.

Misc:
Used the youtube-dlrepository to download videos [1].
Used a custom python script for youtube-dl [1].
Converted youtube-dl to an executable file using pyinstaller [1].
Posted the project to GitHub for troubleshooting [1].

Ho1
  • 1,239
  • 1
  • 11
  • 29
  • What do you mean by "linux" here? Do you mean macOS shell? – Ho1 Aug 10 '19 at 18:03
  • Sorry, I meant unix. – david-littlefield Aug 10 '19 at 18:23
  • 1
    If you want to capture the output from the process then you should attach a readabilityHandler to the outputPipe, not to the inputPipe. – Possibly helpful: https://stackoverflow.com/q/29548811/1187415. – Martin R Aug 10 '19 at 20:21
  • Re: "but I can't seem to access the values", which values are what are you doing with them? – l'L'l Aug 10 '19 at 20:27
  • @Martin, thanks for the suggestion! I will try again with the output pipe. I forgot to mention, this code is only the most recent attempt. I've literally tried the code from nine different solutions, including the one in your suggestion. But, I'll try that one again! And, you've helped me realize I should've posted the titles instead of just the links. So, thank you! – david-littlefield Aug 10 '19 at 23:36
  • @I’L’I, I want to access the values being printed in the XCode console. Xcode automatically print the download progress while the file is running. Currently, it prints the download progress every few seconds, “Downloaded: 75.02%, Speed: 336kb/sec, Remaining: 00:31:10.” I want to access that value so that I can display it in a NSTextField in the user interface. – david-littlefield Aug 10 '19 at 23:42
  • @MartinR, the solution from the link you suggest had the same outcome as before. "nw_path_close_fd Failed to close guarded necp fd 4 [9: Bad file descriptor]" But, I do see now that after a long delay, several minutes, it does print the "str" value, in addition to the previous download progress updates. I'll post the text below. – david-littlefield Aug 11 '19 at 01:41
  • @MartinR, the solution from the link you suggest had the same outcome as before. "nw_path_close_fd Failed to close guarded necp fd 4 [9: Bad file descriptor]" But, I do see now that after a long delay, several minutes, it does print the "str" value, in addition to the previous download progress updates. But, until several minutes have passed, the console only displays the error messages. – david-littlefield Aug 11 '19 at 02:04
  • @MartinR, I figured it out! I just happened to have left the application running after it displayed the error message. And when I came back later, I noticed that the information did print but only after a long delay. So, I started looking up solutions to a delayed standard output, and I found out that the problem was in the python file. I had to call "sys.stdout.flush()" in the python file before converting it to an executable file. Apparently, that forces it to write the progress update to stdout. How do I mark your solution as correct, as well as mention the need to change the Python file? – david-littlefield Aug 11 '19 at 02:05
  • @MartinR, also, I just found out that creating and assigning a new pipe to process stdin, stdout, and stderr fixed the error message. – david-littlefield Aug 11 '19 at 02:13

0 Answers0