为什么不与pog123进行通信?

时间:2015-11-12 18:14:52

标签: c linux popen

我为我的树莓派写了一个媒体服务器。我能够创建一个程序,使用popen通过遥控器控制omxplayer。

我现在想控制音乐的mpg123。我使用与popen一起在omxplayer程序中使用的相同代码并将其应用于mpg123,但它不起作用。它启动,但不会确认发送给它的任何输入。我不知道为什么一个人会工作而另一个人不会。

这是我的代码:

void play_music (char *list, int random)
{
    FILE *pp;
    char c;
    char command[501];
    struct stat buf;

    if(access(list, R_OK) == -1)
    {
        fprintf(stderr, "%s: play_music: access failed (%s) (%s)\n", program_name, strerror(errno), list);
        exit(EXIT_FAILURE);
    }

    if(stat(list, &buf) == -1)
    {
        fprintf(stderr, "%s: play_music: stat failed (%s) (%s)\n", program_name, strerror(errno), list);
        exit(EXIT_FAILURE);
    }

    strcpy(command, "/usr/bin/mpg123 -C ");

    if(random == 1)
        strcat(command, "-z ");

    if(S_ISREG(buf.st_mode) == 1)
    {
        strcat(command, "-@ ");
        strcat(command, list);
    }
    else if(S_ISDIR(buf.st_mode) == 1)
    {
        strcat(command, list);

        if(list[strlen(list) - 1] != '*')
        {
            if(list[strlen(list) - 1] != '/')
                strcat(command, "/");

            strcat(command, "*");
        }
    }
    else
    {
        fprintf(stderr, "%s: play_music: stat reported unknown (%s)\n", program_name, list);
        exit(EXIT_FAILURE);
    }

    strcat(command, " > /dev/null 2>&1");

    if((pp = popen(command, "w")) == NULL)
    {
        fprintf(stderr, "%s: play_music popen failed (%s)\n", program_name, strerror(errno));
        exit(EXIT_FAILURE);
    }

    while((c = get_code()))
    {
        if(system("pidof mpg123 > /dev/null") != 0)
            return;

        switch(c)
        {
            case 31:
                fputc('f', pp);
                break;
            case 32:
                fputc('d', pp);
                break;
            case 33:
                fputc('s', pp);
                break;
            case 34:
                fputc('q', pp);
        }

        if(fflush(pp) == EOF)
        {
            fprintf(stderr, "%s: play_music fflush failed (%s)\n", program_name, strerror(errno));
            exit(EXIT_FAILURE);
        }
    }
}

我一直试图解决这个问题太长时间了,有人可以帮忙!

注意:

  • get_code()是一个工作函数,它根据按下的遥控器按钮返回一个int。

  • 变量'列表'是目录路径还是播放列表文件名。

  • 变量' random'是一个int标志(1表示随机播放)。

1 个答案:

答案 0 :(得分:1)

正如J.F. Sebastian在评论中所说的那样,“自己提供一个假tty”结果证明是我需要做的。创建一个伪终端,就像来自键盘的输入一样,是需要工作的。

以下是修订后的代码:

void play_music (char *playlist, int random)
{
    char c;
    int fdm;
    int fds = 0;
    int x = 0;
    pid_t pid;
    char *flag1 = "/usr/bin/mpg123";
    char *flag2 = "-C";
    char *flag3 = "-z";
    char *flag4 = "-@";
    char *flag5 = TEMP_FILE; // /tmp/temp_playlist.pls
    char *slave_name;
    char *argv[6];
    struct stat buf;

    if(stat(playlist, &buf) == -1)
    {
        fprintf(stderr, "%s: play_music: stat failed (%s) (%s)\n", program_name, strerror(errno), playlist);
        exit(EXIT_FAILURE);
    }

    if((fdm = posix_openpt(O_RDWR)) == -1)
    {
        fprintf(stderr, "%s: posix_openpt failed (%s)\n", program_name, strerror(errno));
        exit(EXIT_FAILURE);
    }

    if(grantpt(fdm) == -1)
    {
        fprintf(stderr, "%s: grantpt failed (%s)\n", program_name, strerror(errno));
        close(fdm);
        exit(EXIT_FAILURE);
    }

    if(unlockpt(fdm) == -1)
    {
        fprintf(stderr, "%s: unlockpt failed (%s)\n", program_name, strerror(errno));
        close(fdm);
        exit(EXIT_FAILURE);
    }

    if((slave_name = ptsname(fdm)) == NULL)
    {
        fprintf(stderr, "%s: ptsname failed\n", program_name);
        close(fdm);
        exit(EXIT_FAILURE);
    }

    if((pid = fork()) == -1)
    {
        fprintf(stderr, "%s: fork failed (%s)\n", program_name, strerror(errno));
        close(fdm);
        exit(EXIT_FAILURE);
    }

    if(pid == 0) // Child
    {
        if(setsid() == -1)
        {
            fprintf(stderr, "%s: setsid failed (%s)\n", program_name, strerror(errno));
            close(fdm);
            exit(EXIT_FAILURE);
        }

        if((fds = open(slave_name, O_RDWR)) == -1)
        {
            fprintf(stderr, "%s: open failed (%s)\n", program_name, strerror(errno));
            close(fdm);
            exit(EXIT_FAILURE);
        }

        if(dup2(fds, STDIN_FILENO) == -1)
        {
            fprintf(stderr, "%s: dup2(1) failed (%s)\n", program_name, strerror(errno));
            close(fdm);
            close(fds);
            exit(EXIT_FAILURE);
        }

        if(dup2(fds, STDOUT_FILENO) == -1)
        {
            fprintf(stderr, "%s: dup2(2) failed (%s)\n", program_name, strerror(errno));
            close(fdm);
            close(fds);
            exit(EXIT_FAILURE);
        }

        if(dup2(fds, STDERR_FILENO) == -1)
        {
            fprintf(stderr, "%s: dup2(3) failed (%s)\n", program_name, strerror(errno));
            close(fdm);
            close(fds);
            exit(EXIT_FAILURE);
        }

        argv[x++] = flag1;
        argv[x++] = flag2;

        if(random == 1)
            argv[x++] = flag3;

        argv[x++] = flag4;

        if(S_ISREG(buf.st_mode) == 1)
            argv[x++] = playlist;
        else if(S_ISDIR(buf.st_mode) == 1)
        {
            if(make_playlist(playlist) == RETURN_FAILURE)
            {
                fprintf(stderr, "%s: play_music: make_playlist failed (%s)\n", program_name, playlist);
                close(fdm);
                close(fds);
                exit(EXIT_FAILURE);
            }

            argv[x++] = flag5;
        }
        else
        {
            fprintf(stderr, "%s: play_music: stat reported unknown (%s)\n", program_name, playlist);
            close(fdm);
            close(fds);
            exit(EXIT_FAILURE);
        }

        argv[x++] = NULL;

        if(execv("/usr/bin/mpg123", argv) == -1)
        {
            fprintf(stderr, "%s: execv failed (%s)\n", program_name, strerror(errno));
            close(fdm);
            close(fds);
            exit(EXIT_FAILURE);
        }
    }
    else // Parent
    {
        while((c = get_code()) != 31)
        {
            switch(c)
            {
                case 30:
                case 19:
                    write(fdm, " ", 1);
                    break;
                case 20: // Up
                    write(fdm, "+", 1);
                    break;
                case 22: // Down
                    write(fdm, "-", 1);
                    break;
                case 21: // Right
                    write(fdm, "f", 1);
                    break;
                case 23: // Left
                    write(fdm, "d", 1);
                    break;
            }
        }

        write(fdm, "q", 1);
        wait(&pid);
        close(fdm);

        if(fds != 0)
            close(fds);
    }

}