Question

So I have been attempting to read and write from the Pianobar (console Pandora player) STDIN and STDOUT to control it from within another application.

However, for some when reading from STDOUT it completely blocks at the last line (where it displays the time of the song).

I thought I was doing something wrong (probably still am) but I downloaded the demo project for sending/receiving input to another applications STDIN/STDOUT via a couple handles.

So I dove into the Pianobar code, and put in printf commands all over the place to trace where the block was occurring (is block the right word for this?) Anyways I finally get to a section of code that appears to loop extremely quickly when created as a child process, and also blocks STDOUT.

From Pianobar, ui_readline.c BarReadline replacement

/*  readline replacement
 *  @param buffer
 *  @param buffer size
 *  @param accept these characters
 *  @param input fds
 *  @param flags
 *  @param timeout (seconds) or -1 (no timeout)
 *  @return number of bytes read from stdin
 */
size_t BarReadline (char *buf, const size_t bufSize, const char *mask,
        BarReadlineFds_t *input, const BarReadlineFlags_t flags, int timeout)
{
// took out some extra code from here ...
printf("In BarReadline 005\n");
fflush(stdout);
while (true) {
    Sleep(400); // added this to stop it from doing 100% on a core
    printf("In BarReadline 006\n");
    fflush(stdout);
    if (timeout != INFINITE) {
        DWORD now = GetTickCount ();
        printf("In BarReadline 007\n");
        fflush(stdout);
        if ((int)(now - timeStamp) < timeout) {
            timeout -= (int)(now - timeStamp);
            timeStamp = now;
        }
        else
            timeout = 150; // KYLE changed from 0
    }
    printf("Current timeout: %d\n",timeout);
    printf("In BarReadline 008\n");
    fflush(stdout);
    waitResult = WaitForSingleObject (handle, timeout);

    printf("In BarReadline 009\n");
    fflush(stdout);
    if (WAIT_OBJECT_0 == waitResult) {
        INPUT_RECORD inputRecords[8];
        INPUT_RECORD* record;
        DWORD recordsRead, i;

        printf("In BarReadline 010\n");
        fflush(stdout);
        successConsole = ReadConsoleInput (handle, inputRecords, sizeof(inputRecords) / sizeof(*inputRecords), &recordsRead);
        if(successConsole != 0) {
            printf("We read from console\n");
        }

        printf("In BarReadline 011\n");
        fflush(stdout);
        for (i = 0, record = inputRecords; i < recordsRead; ++i, ++record) {
            int codePoint, keyCode;

            printf("In BarReadline 012\n");
            fflush(stdout);

And the code above prints out:

In BarReadLine 005
In BarReadline 006
In BarReadline 007
Current timeout: 150
In BarReadline 008
In BarReadline 009
In BarReadline 010
In BarReadline 011
In BarReadline 006
In BarReadline 007
Current timeout: 150
In BarReadline 008
In BarReadline 009
In BarReadline 010
In BarReadline 011 

Anyways, I can bash the "input" key on the Redirect Demo app with a known key that doesn't require anything special and it just keeps spinning through that loop and doesn't seem to catch it, which to me sounds like one of two things; We don't have access to the INPUT function as it is being blocked by the reading of STDOUT, or ReadConsoleInput isn't recognizing the things we send from the Redirect Demo.

Is this something I would need to send with some type of Async I/O process? And why does using "cmd" and opening a regular command prompt not cause the blocking, but this does?

Update 1: I managed to build an INPUT_RECORD to send to the ReadConsoleInput within Pianobar (child console). However, what I'm finding is that my parent application is returning an "invalid handle" when I try to send WriteConsoleInput(m_hStdinWrite, inputRecords, sizeof(inputRecords) / sizeof(*inputRecords), &dwWritten);

Are there different types of handles for a child's console STDIN? Using WriteFile works, but I cannot send INPUT_RECORDs that way.

Redirect Demo App

Pianobar Windows Binaries

Pianobar Windows Build Environment

Helped, but not sure what's causing the invalid handle: Low Level Console Input and Redirection

Was it helpful?

Solution

I believe it is because the program is using ReadConsoleInput instead of ReadFile. ReadConsoleInput requires a console handle.

You would need to create a console and pass its handle. Then you'd need to write console input events into it.

It'd be better if you could change the other program to just use ReadFile, if you could make that work.

This seems to be the MSDN reference for consoles.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top