Question

Problem: I can't find any way to reliably get the current playing file in an MPlayer playlist.

Here is how far I have gotten. This working ash script monitors a text file with the path to the current playlist. When I update the file, the script closes the old instance of MPlayer and opens a new one with the new playlist:

# POLL PLAYLIST FILE FOR CHANGES
CURRENTPLAYLISTPATH=/home/tc/currentplaylist
INFIFO=/tmp/mplayer-in

CURRENTPLAYLIST="NEVERMATCHAPLAYLIST"
FIRSTRUN=1

while [ 1 ];
do
    # CHECK FOR NEW PLAYLIST
    NEWPLAYLIST=$(head -n 1 $CURRENTPLAYLISTPATH)
    if [[ "$NEWPLAYLIST" != "$CURRENTPLAYLIST" ]]; then
        if [ "$FIRSTRUN" == 0 ]; then
            echo "quit" > "$INFIFO"
        fi

        # CREATE NAMED PIPE, IF NEEDED
        trap "rm -f $INFIFO" EXIT
        if [ ! -p $INFIFO ]; then
            mkfifo $INFIFO
        fi

        # START MPLAYER
        mplayer -fixed-vo -nolirc -vc ffmpeg12vdpau,ffh264vdpau, -playlist $NEWPLAYLIST -loop 0 -geometry 1696x954 -slave -idle -input file=$INFIFO -quiet -msglevel all=0 -identify | tee -a /home/tc/mplayer.log &

        CURRENTPLAYLIST=$NEWPLAYLIST
        FIRSTRUN=0
    fi

    sleep 5;
done

My original plan was just to use the "-identify" flag and parse the log file. This actually works really well up until I need to truncate the log file to keep it from getting too large. As soon as my truncating script is run, MPlayer stops writing to the log file:

FILENAME=/home/tc/mplayer.log
MAXCOUNT=100
if [ -f "$FILENAME" ]; then
    LINECOUNT=`wc -l "$FILENAME" | awk '{print $1}'`

    if [ "$LINECOUNT" -gt "$MAXCOUNT" ]; then
        REMOVECOUNT=`expr $LINECOUNT - $MAXCOUNT`
        sed -i 1,"$REMOVECOUNT"d "$FILENAME"
    fi
fi

I have searched and searched but have been unable to find any other way of getting the current playing file that works.

I have tried piping the output to another named pipe and then monitoring it, but only works for a few seconds, then MPlayer completely freezes.

I have also tried using bash (instead of ash) and piping the output to a function like the following, but get the same freezing problem:

function parseOutput()
{
    while read LINE
    do
        echo "get_file_name" > /tmp/mplayer-in
        if [[ "$LINE" == *ANS_FILENAME* ]]
        then
          echo ${LINE##ANS_FILENAME=} > "$CURRENTFILEPATH"
        fi
        sleep 1
    done

}

# START MPLAYER
mplayer -fixed-vo -nolirc -vc ffmpeg12vdpau,ffh264vdpau, -playlist $NEWPLAYLIST -loop 0 -geometry 1696x954 -slave -idle -input file=/tmp/mplayer-in -quiet | parseOutput &

I suspect I am missing something very obvious here, so any help, ideas, points in the right direction would be greatly appreciated.

fodder

Was it helpful?

Solution 2

Well, I gave up on getting the track from MPlayer itself.

My 'solution' is probably too hackish, but works for my needs since I know my machine will only ever have one instance of MPlayer running:

lsof -p $(pidof mplayer) | grep -o "/path/to/my/assets/.*"

If anyone has a better option I'm certainly still interested in doing this the right way, I just couldn't make any of the methods work.

fodder

OTHER TIPS

Alright then, so I'll post mine too.

Give this one a try (assuming there is only one instance running, like on fodder's machine):

basename "$(readlink /proc/$(pidof mplayer)/fd/* | grep -v '\(/dev/\|pipe:\|socket:\)')"

This is probably the safer way, since the file descriptors might not always be in the same order on all systems. However, this can be shortened, with a little risk:

basename "$(readlink /proc/$(pidof mplayer)/fd/*)" | head -1

You might probably like to install this, too: http://mplayer-tools.sourceforge.net/

You can use the run command.

Put this in ~/.mplayer/input.conf:

DEL run "echo ${filename} ${stream_pos} >> /home/knarf/out"

Now if you press the delete key while playing a file it will do what you expect i.e. append the current file playing and the position in the stream to the ~/out file. You can replace echo with your program.

See slave mod docs for more info (Ctrl-F somevar).

About getting properties from MPlayer

I have used a non-elegant solution, but it is working for me.

stdbuf -oL mplayer --slave --input=file=$FIFO awesome_awesome.mp3 |
{
while IFS= read -r line 
    do
    if [[ "${line}" == ANS_* ]]; then
        echo "${line#*=}" > ${line%=*}  # echo property_value > property_name
    fi
    done
} & 
mplayer_pid=&!

read filename < ./ANS_FILENAME
read timeLength < ./ANS_LENGTH

echo ($timeLength) $filename

and so on..

It is in another proccess, that's why I've used files to bring properties

'stdbuf' is for not to miss anything

I started putting together a bash library to handle tasks like this. Basically, you can accomplish this by dumping the mplayer output to a file. Then you grep that dump for "Playing " and take the last result with tail. This should give you the name of the file that's currently playing or that last finished playing.

Take a look at my bash code. You'll want to modify the playMediaFile function to your needs, but the getMediaFileName function should do exactly what you're asking. You'll find the code on my github.

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