Android and Linux

Saturday, August 20, 2011

Finding the current song playing in Android, sorta.

I've seen people wanting to use Tasker to get the title of the currently playing song before, but it's not really possible because Android doesn't have an API for it. There is a semi-workable solution using the Locale Execute Plugin. We can find which files the media server has open with the lsof command. Assuming the only files you're interested in are mp3s, we can just grep the mp3s from the list and print the filename:
lsof -p $(pidof mediaserver) | grep -m 1 mp3 | awk '{print substr($0, index($0,$9))}'
As luck would have it, the current song seems to always be at the top of the list, so using grep -m 1 we can just get the first line of output.

Output: /mnt/sdcard/download/AloeBlacc-YouMakeMeSmile.mp3

It can be cleaned up a little with the basename command:
basename "$(lsof -p $(pidof mediaserver) | grep -m 1 mp3 | awk '{print substr($0, index($0,$9))}')" .mp3
Output: AloeBlacc-YouMakeMeSmile

If you're interested in files other than mp3, you can add them to the grep command:
grep -E -m 1 'mp3|wav|other1|other2'
The downside is that this just gets the file name and doesn't display any metadata or anything like that. If your file is Track10.mp3, it may show information about the artist and song in the media player, but with this trick it will only show Track10.

This trick also works to display the file being played in BeyondPod, the podcatcher app, but podcasts often don't follow naming schemes meant for humans so the output for the Jordan Jesse Go! podcast ends up being jjgo110814_ep187. If your goal was to display the file in Tasker or Zoom, you could set up replacement titles for your podcasts, like if the title matches jjgo*, display "Jordan Jesse Go!"

Aug 23: I edited the awk command to handle filenames with spaces, then I realized the awk command isn't needed. There's no need to pick out the field with the filename with awk. You can use the entire line, the basename command will only output whatever is to the right of the last "/" anyway. I'll leave the original up since it's been there for a couple of days and people have already seen it, but this simpler command would be better to use:
basename "$(lsof -p $(pidof mediaserver) | grep -m 1 mp3)" .mp3
Use that one instead, and I'll try to notice the obvious sooner next time.