0

I'm creating a program that sends a command on the terminal:

cmus-remote -Q

The output:

status stopped
set aaa_mode album
set continue false
set play_library true
set play_sorted false
set replaygain disabled
set replaygain_limit true
set replaygain_preamp 6.000000
set repeat false
set repeat_current false
set shuffle false
set softvol false
set vol_left 0
set vol_right 0

This command returns the status of my music player (cmus), but sometimes the player is closed and doesn't answer my command.

My objective is to identify when I got no answer and close the program and open it again (in C++). I know how to kill it and start again. I tried to something with popen() function but I don't know how to use it. How can I do that?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Welcome to Stack Overflow. Please read the [About] page soon. When you start your `cmus` service, do you run the `cmus` command? Is that what you want to do from your script? Or do you want to run the `cmus-remote -Q` command and read the output, and if it starts with `status stopped` then run the `cmus` command? If the latter, what is the problem with `FILE *fp = popen("cmus-remote -Q", "r"):` to give you a file stream you can read from if the command was executed? – Jonathan Leffler Sep 10 '13 at 19:20
  • Thx for the fast answer.I'll explain with more details.My cmus is running in another computer and i control it from my computor,they are connected with a link, when the link is broken, i got no answer from cmus-remote -Q.I want to send "cmus-remote -Q" command and detect if it was not answered, so i can reboot the cmus program. – user2766207 Sep 10 '13 at 19:29

2 Answers2

0

In terms of a C function that could be compiled with C++ (with suitable changes to headers and the addition of using namespace std; if appropriate). You'll need to review what the status message from cmus-remote -Q is when the player is running — I've assumed 'status ready' but if there are multiple responses ('status playing', 'status paused', ...) then you'll need to modify the code appropriately. I'm also assuming you only need the first line of the response. Again, if that's wrong, you'll have to make consequential changes to the code.

bool is_cmus_running(void)
{
    char buffer[4096];
    FILE *fp = popen("cmus-remote -Q", "r");
    if (fp == 0)
        return false;
    char *rv = fgets(buffer, sizeof(buffer), fp);
    pclose(fp);
    if (rv == 0 || strncmp(buffer, "status ready", sizeof("status ready") - 1) != 0)
        return false;
    return true;
}

For C99, you'd need:

#include <stdbool.h>
#include <stdio.h>
#include <string.h>

For C++, I think you could use the same headers, but you might also use:

#include <cstdio>
#include <cstring>
using namespace std;

(You don't need a header for bool since that is built into C++ in a way that it isn't in C.)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

(1) I would do it in a simpler way unless there is a specific reason to stick with C++. A basic shell script will do the job perfectly, something like the cplay script (https://wiki.archlinux.org/index.php/Cmus#Remote_Control):

$ ps h -C cmus || cmus

Since Cmus is not a real background service, – eg. you cannot start it without the ncurses GUI – the best if you are running it in a screen session.

$ screen -rD cmus || screen -dmS 'cmus' /usr/bin/cmus

With this command, you always have a running cmus session within a screen session. You can even close the terminal, the service will be keep running in the backround. Just put this command to your .bashrc as an alias and you'll always have an easy access to the player

$ alias mycmus='screen -rD cmus || screen -dmS 'cmus' /usr/bin/cmus'

Will start a cmus+screen session if it's not running, otherwise it opens the session. "Ctrl+a d" detaches the window.

Putting them together and answering your question (in shell script):

Add the following lines to a file, eg.: "mycplayer.sh" (don't forget the chmod +x mycplayer.sh, then add it to the the PATH)

#!/bin/sh

cmus-remote -Q > /dev/null || screen -dmS 'cmus' /usr/bin/cmus

cmus-remote $1

The first line will make sure there is a running cmus instance (in the background, using screen), the second line will execute the remote command.

Usage:

$ mycplayer.sh -u   start/stop the player
$ mycplayer.sh -n   next in the playlist
etc.

(2) In C++

(3) If cmus is a network service, so it was started with --listen host[:port], then you'll need an ssh to start the service on the remote box. See the screen command above how to do it.

Hope this helps.

Community
  • 1
  • 1