Android and Linux

Sunday, August 28, 2011

Part 2: Finding the current song playing in Android, still sorta.

I made a post about getting the filename from the mediaserver at the Tasker discussion group and others found that the lsof utility only comes on Cyanogen so many people don't have it. I found an alternative in "ls -l /proc/$(pidof mediaserver)/fd" and I'll show some ways to use it below.

Another poster, Matthieu, also figured out a way to get the mp3 tags from the files. The ID3v1 tags are pretty simple, but ID3v2 is a pain. Here is a post I made to that thread incorporating the lsof alternative, Matthieu's method of extracting ID3v1 from that thread, and the start of an ugly method to get ID3v2 tags. More on that in a moment.

Here's an lsof alternative. I think it could do without the grep command but it's safer with it in:
ls -l /proc/$(pidof mediaserver)/fd | sort -g -k 9 | grep mp3 | tail -n1
This will give you the long filename like /sdcard/foo.mp3:
ls -l /proc/$(pidof mediaserver)/fd | sort -g -k 9 | grep mp3 | tail -n1 | awk '{print substr($0, index($0,$11))}'
This gives the short filename like foo.mp3:
basename "$(ls -l /proc/$(pidof mediaserver)/fd | sort -g -k 9 | grep mp3 | tail -n1 | awk '{print substr($0, index($0,$11))}')" .mp3
This gives the id3v1 tag:
tail -c 125 $(ls -l /proc/$(pidof mediaserver)/fd  | sort -g -k 9 | grep mp3 | tail -n1 | awk '{print substr($0, index($0,$11))}') | head - c30
This gives the id3v2 tag but needs tweaking:
grep -A 20 TIT2 "$(ls -l /proc/$(pidof mediaserver)/fd  | sort -g -k 9 | grep mp3 | tail -n1 | awk '{print substr($0, index($0,$11))}')" | grep -m 1 [a-z]
That last one is ugly and unfinished. ID3v2 tags are variable length and the length of the tag is supposed to be encoded in the file itself but, for the life of me, I can't find a file on my system that follows that guideline. I'm obviously missing something because they display correctly when played, but most of them also have ID3v1 tags on the end as well, so maybe that's why they display properly.

I would spend time trying to find a better solution but Pent said he is going to add mp3 tag support to Tasker soon and that should work better than anything I could come up with. Plus, I'm really not interested in the tags. When something interests me, I usually get about an hour late at night to work on it, and I only want the file name.

As ugly as it is, the last one still kinda works. All the tags on my system start with TIT2, but are followed by a lot of hex gibberish before the plain text tag begins. This greps TIT2 then greps the first line below it that contains a lower case letter. On my files, it has a high success rate. One big problem it has is that the tag is often followed by another field such as TALB, so the output can be "Song TitleTALB." Someone could figure out all the possible fields in an ID3v2 tag then just use sed to chomp them off. Or someone cou otu a more reliable method, or we can just wait for Tasker to do it for us.

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.

Wednesday, August 3, 2011

Free Nexus S

If you go to google.com, there is a line of text that reads "Nexus S, a pure Google experience. Get it FREE today only"

It requires a 2 year contract or an extension of your existing contract. I wasn't impressed with the Nexus S when it came out but my Nexus One is seriously aging and I'm contemplating getting a Nexus S. I can't make up my mind because I want to wait for something better too. Oh well, in case you missed it, go to google.com and click the link.

Followers