Getting the current song filename

1,152 views
Skip to first unread message

fubaya

unread,
Aug 23, 2011, 12:52:54 AM8/23/11
to Tasker
I know people have been wanting to get the current song title from the
Android music player. I can't offer that, but if you're rooted, you
can get the filename of the current song using the Locale Execute
Plugin. That doesn't help if your songs have funky file names, but if
you have them named with the artist and title, it works pretty well.

I made a blog post about it here:
http://a-more-common-hades.blogspot.com/2011/08/finding-current-song-playing-in-android.html

The only bug I've noticed is when switching between two apps that both
use the android music player on the backend. The first one can keep
its file open for a few minutes, making this return the wrong file.

I tested with this task:

1- execute: @! basename "$(lsof -p $(pidof mediaserver) | grep -m 1
mp3)" .mp3 > /sdcard/song

2- wait 1ms (it only needs to wait a tiny fraction of a second, just
having Tasker run the wait action is enough)

3- read line 1 from /sdcard/song to %LINE
4- go to 3 if %LINE matches EOF
5- Flash %LINE

Brivs Mekis

unread,
Aug 23, 2011, 4:07:51 AM8/23/11
to Tasker
i read your blog post about this but hadn't got around to trying it.
thanks for writing it out here with the task details. I'll give it a
try .....

On Aug 23, 5:52 am, fubaya <jdm...@gmail.com> wrote:
> I know people have been wanting to get the current song title from the
> Android music player. I can't offer that, but if you're rooted, you
> can get the filename of the current song using the Locale Execute
> Plugin. That doesn't help if your songs have funky file names, but if
> you have them named with the artist and title, it works pretty well.
>
> I made a blog post about it here:http://a-more-common-hades.blogspot.com/2011/08/finding-current-song-...

Brivs Mekis

unread,
Aug 23, 2011, 5:35:09 AM8/23/11
to Tasker
i dont seem to be getting any output from the basename command?
i have created a folder and file in this path: /sdcard/GetTrackName/
Track.txt

then run the command:

@! basename "$(lsof -p $(pidof mediaserver) | grep -m 1 > mp3)" .mp3
> /sdcard/GetTrackName/Track.txt

i run this from a task whilst I have an mp3 playing in ubermusic but
the Track.txt file is empty.

I have allowed the command in SuperUser.

Any suggestions?

On Aug 23, 5:52 am, fubaya <jdm...@gmail.com> wrote:
> I know people have been wanting to get the current song title from the
> Android music player. I can't offer that, but if you're rooted, you
> can get the filename of the current song using the Locale Execute
> Plugin. That doesn't help if your songs have funky file names, but if
> you have them named with the artist and title, it works pretty well.
>
> I made a blog post about it here:http://a-more-common-hades.blogspot.com/2011/08/finding-current-song-...

Radimus

unread,
Aug 23, 2011, 6:33:43 AM8/23/11
to Tasker
Me too:
@! basename "$(lsof -p $(pidof mediaserver) | grep -m 1 'mp3|
m4a' )" .mp3> /sdcard/song

the file 'song' appears, but it is always empty
I get the superuser flash, so I can tell that it is at least running
and I skipped the 4th step goto 3 if %line matches EOF, so I get the
EOF flash... it just seems the execute doesn't output to the file
> > 5- Flash %LINE- Hide quoted text -
>
> - Show quoted text -

Radimus

unread,
Aug 23, 2011, 7:26:55 AM8/23/11
to Tasker
I'm a newb on linux, but I'm having diffictlty in finding lsof on
android
> > - Show quoted text -- Hide quoted text -

Matthieu Berthomé

unread,
Aug 23, 2011, 8:50:47 AM8/23/11
to tas...@googlegroups.com
If you want to extract metadata from the mp3 file it's doable with a script too, if there is a ID3v1 tag available the end of the file (last 128 bytes) looks like that (see e.g. wikipedia for more infos)

Field Length
header 3 “TAG”
title 30 30 characters of the title             
artist 30 30 characters of the artist name     
album 30 30 characters of the album name 
year 4 A four-digit year                             













Then, use
tail -c 125 | head -c 30 to get the title
tail -c 95 | head -c 30 to get the artist
tail -c 65 | head -c 30 to get the album

up to the year it's easy to get the infos, afterwards it's a bit messy with the track number, but doable. If only the artist album is needed, here you have it with a script, write it in file, read it with tasker, and voilà :-)

Caveat : Works only with standard relatively old ID3v1. ID3v2 is much more complex, but doable with a much longer script I would say. ID3v2 permits longer than 30 characters field.

I'll test your script ASAP, looks great !

Brivs Mekis

unread,
Aug 23, 2011, 10:16:15 AM8/23/11
to Tasker
i'd be really interested if you could get the ID3v2 metadata. please
post back your task if you manage to get this working.
thanks


On Aug 23, 1:50 pm, Matthieu Berthomé <matthieu.berth...@gmail.com>
wrote:

Radimus

unread,
Aug 23, 2011, 10:19:36 AM8/23/11
to Tasker
LSOF is in cyanogen roms, but it isn't in any version of busybox I can
find
> > I'll test your script ASAP, looks great !- Hide quoted text -

Matthieu Berthomé

unread,
Aug 23, 2011, 10:49:08 AM8/23/11
to tas...@googlegroups.com
The scripts works OK, I needed to tweak it, instead of

@! basename "$(lsof -p $(pidof mediaserver) | grep -m 1 mp3)" .mp3
we need to do (not perfect but it works)
tail -c 125 "`$(lsof -F n -p $(pidof mediaserver) | sed 's/.\(.*\)/\1/' | grep -m 1 mp3)`" | head -c 30

to get the title for ID3v1. adapt it for album, artist, etc.
lsof -F n outputs only the node name (the path)
sed is there to remove the character n in front of the path (lsof does that)

Couldnt test it fully, for a weird reason the head command I have on my phone does not allow the -c modifier, I need to update my busybox. Everything works up to the point I need to trim to the 30 characters for each field.

Brivs Mekis informs that lsof is not in all android version, only CM, shit that sucks. Workaround, install the binary yourself, :-(

fubaya

unread,
Aug 23, 2011, 11:51:42 AM8/23/11
to Tasker
That stinks that lsof is only on CM. I was hoping there was a
workaround in the /proc directory but nothing looks promising.

I did notice that since this uses the android media server, I think it
may work for other players after all. I know it works for anything
using the android music player in the background but I think
everything sends the data through the mediaserver.

On Aug 23, 10:49 am, Matthieu Berthomé <matthieu.berth...@gmail.com>
wrote:

> Couldnt test it fully, for a weird reason the head command I have on my
> phone does not allow the -c modifier
Good work. Try: head -c30 and don't use the backticks

tail -c 125 "$(lsof -F n -p $(pidof mediaserver) | sed 's/.\(.*\)/\1/'
| grep -m 1 mp3)" | head -c30

Unfortunately, I have no mp3s that are tagged, I don't really listen
to music on the phone. Do you have an example of the other type of mp3
tag?

Matthieu Berthomé

unread,
Aug 23, 2011, 2:17:07 PM8/23/11
to tas...@googlegroups.com
lsof looked promising, sheesh, so bad. Anyone interested can probably upload the binary directly to its phone, more difficult but doable, not sure.
head -c30 or head -c 30 the same not working. That's on my side, Ill update and see.
get some free mp3s on www.jamendo.com if you want to try and see some tagged files ;-)
ID3v2 tag are at the start of the file instead of the end, and much more complex, but Ill see what I can do :-)

Radimus

unread,
Aug 23, 2011, 5:40:19 PM8/23/11
to Tasker
ok, I got lsof copied into my bin folder and have the task working to
some degree

@! basename "$(lsof -p $(pidof mediaserver) | grep -E -m 3 'mp3|m4a')"
> /sdcard/lsof.txt

now the issue is to make it useful... I suppose I could pipe it into
minimalistic text, but the issue would be to do it on track change...
and even so, minText only updates like every 2 minutes...


On Aug 23, 2:17 pm, Matthieu Berthomé <matthieu.berth...@gmail.com>
wrote:
> lsof looked promising, sheesh, so bad. Anyone interested can probably upload
> the binary directly to its phone, more difficult but doable, not sure.
> head -c30 or head -c 30 the same not working. That's on my side, Ill update
> and see.
> get some free mp3s onwww.jamendo.comif you want to try and see some tagged

Radimus

unread,
Aug 23, 2011, 7:38:47 PM8/23/11
to Tasker
@! basename "$(lsof -w -p $(pidof mediaserver) | grep -E -m 3
'.mp3|.m4a')" > /sdcard/lsof.txt


On Aug 23, 5:40 pm, Radimus <conradwheele...@gmail.com> wrote:
> ok, I got lsof copied into my bin folder and have the task working to
> some degree
>
> @! basename "$(lsof -p $(pidof mediaserver) | grep -E -m 3 'mp3|m4a')"
>
> > /sdcard/lsof.txt
>
> now the issue is to make it useful... I suppose I could pipe it into
> minimalistic text, but the issue would be to do it on track change...
> and even so, minText only updates like every 2 minutes...
>
> On Aug 23, 2:17 pm, Matthieu Berthomé <matthieu.berth...@gmail.com>
> wrote:
>
>
>
> > lsof looked promising, sheesh, so bad. Anyone interested can probably upload
> > the binary directly to its phone, more difficult but doable, not sure.
> > head -c30 or head -c 30 the same not working. That's on my side, Ill update
> > and see.
> > get some free mp3s onwww.jamendo.comifyou want to try and see some tagged
> > files ;-)
> > ID3v2 tag are at the start of the file instead of the end, and much more
> > complex, but Ill see what I can do :-)- Hide quoted text -

fubaya

unread,
Aug 23, 2011, 8:01:38 PM8/23/11
to Tasker
I was going to take a crack at the id3v2 tags but it already
frustrated me. I don't have any use for them so I can't get motivated
to do much more. These notes may get someone else motivated to
following through and tweaking to their needs.

The song title is supposed to be after the TIT2 tag, but there are
often a bunch of gibberish hex characters after TIT2 so you can't grab
the first thing after TIT2. I tried several approaches, and settled on
the least elegant:

grep -A 20 TIT2 "$(lsof -p $(pidof mediaserver) | grep -m 1 mp3 | awk
'{print substr($0, index($0,$9))}')" | grep -m 1 [a-z]

It takes 20 lines after TIT2 (half is gibberish) then greps the first
line with a lowercase letter. This actually works pretty well because
there is only gibberish between TIT2 and the title, but it assumes the
tag contains a lower case letter. Personally, I wouldn't want to see
any titles that are in all caps anyway.

The title is often followed by other tags like TYER, TALB, and TRCK.
Someone could make a list of tags and just use sed to get rid of them
all. Also, this makes grep search the whole file for "TIT2" and it
takes a couple seconds to execute. It's faster to use "head -c 2000"
then pipe to grep.

If it isn't a v2 tag, there will be no output, so you could use tail
to get the other style of tag.

On Aug 23, 5:40 pm, Radimus <conradwheele...@gmail.com> wrote:
> now the issue is to make it useful... I suppose I could pipe it into
> minimalistic text, but the issue would be to do it on track change...
> and even so, minText only updates like every 2 minutes...

What got me started on this idea was that I listen to a lot of
podcasts. I have a tasker shortcut to toggle the Beyondpod podcast app
between pause and play and change the icon accordingly. Sometimes I
pause the playback then start it later, but I don't remember what I
was listening to or whether I want to continue or start something
else.

I added a minimalistic text widget that is normally blank, but when I
tap pause (and when the headphones are removed), it gets the file name
and puts it in a MT variable and displays it. That way, when I turn
the phone on later, the podcast title is displayed on the homescreen
so I know what's going to come on when I hit play. Tapping play also
blanks out the MT widget because I don't need the filename when I'm
listening to it.

fubaya

unread,
Aug 23, 2011, 8:53:32 PM8/23/11
to Tasker
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]

Pent

unread,
Aug 24, 2011, 4:15:45 AM8/24/11
to Tasker
I'm going to let you get some ID3 data out of a file next release, if
it helps
(there's a new Test action for some other things too).

Pent

Matthieu Berthomé

unread,
Aug 24, 2011, 4:51:35 AM8/24/11
to tas...@googlegroups.com
Great ! I was going to say that Tasker-side you have access to nice APIs/libraries for ID3 tags, which are a pain to emulate in a shell script as we saw :-) Thanks for the addition Pent. what's the approx. ETA ?
fubaya, very nice work you done here ! I hope my contribution helped somewhat :-)
Instead of doing a head -c 2000 to get all the ID3, the ID3 header contains the length of the ID3 tag in it. The specification can be read here http://www.id3.org/id3v2-00 among other places.
The total length of the tag is in the ID3 header (first 10bytes of the file) That way, you can head -c the correct number of bytes to get the tag and no more.
Furthermore, each frame features the length of the frame just after the frame name, in 6 bytes after the frame name (TIT2 in that case); that way you can extract only the correct length needed. Any null character (00 or the corresponding termination character in the string encoding) are to be discarded.
I'd take a shot at doing that, but I guess I can wait for Pent's version ;-)

Pent

unread,
Aug 24, 2011, 5:16:48 AM8/24/11
to Tasker
> as we saw :-) Thanks for the addition Pent. what's the approx. ETA ?

Beta in a couple of weeks.

Pent

Brivs Mekis

unread,
Aug 24, 2011, 5:49:35 AM8/24/11
to Tasker
this works a treat thanks so much.
not sure what i'm going to do with it yet but its cool either way.

On Aug 24, 1:53 am, fubaya <jdm...@gmail.com> wrote:

fubaya

unread,
Aug 24, 2011, 7:17:07 AM8/24/11
to Tasker


On Aug 24, 4:51 am, Matthieu Berthomé <matthieu.berth...@gmail.com>
wrote:

> Instead of doing a head -c 2000 to get all the ID3, the ID3 header contains
> the length of the ID3 tag in it.

That seems good but the files I tried on don't follow the rules. This
is the beginning of one:

ID3.....=OWXXX..
......COMM...4..
.eng.The very ep

then there is 50 lines of text about the album

Matthieu Berthomé

unread,
Aug 24, 2011, 7:52:18 AM8/24/11
to tas...@googlegroups.com
That's the text content when using a specific encoding, am I right ? What about the binary content ? One of the files I tested on has

so ID3 is there, and the 03 00 is there for the version, in my case 03 00 for ID3v2.3 Afterwards is messy, I'm not sure how to extract the tag size from 00 02 1A 26
What's your hexadecimal content ?

Matthieu Berthomé

unread,
Aug 24, 2011, 9:01:09 AM8/24/11
to tas...@googlegroups.com
got it, to extract the size you have to discard the first bit in each byte :
(byte1 << 21) + (byte2 <<14) + (byte3 <<7) + byte4
In my case I get 36134 bytes for the tag size

fubaya

unread,
Aug 24, 2011, 12:11:21 PM8/24/11
to Tasker
Nice job. What I posted was the text from a hex dump. All the dots
were just 00 in hex. I tried a handful of files and they were all
different but didn't seem to follow any proper formatting. It's
probably just my files, but as dumb as it is, grep still found the
right title. It might make a useful backup. It should be easy now to
write a script that tries all the methods and gets the title no matter
what.
Message has been deleted

Dale Newton

unread,
Jun 5, 2015, 12:04:22 PM6/5/15
to tas...@googlegroups.com
Ok I got this working eventually using tweaks to the above, but in the end I went via a different method just using Taskers 'run shell' action under 'script'.  That way you do not need to have 'locale' app or the 'locale execute' plugin installed. 

If you wish to use the original method for some reason, these are the tweaks I made to get it to work:

1 - execute: @! basename "$(lsof | grep NAMEOFAPPLICATION | grep mp3)" .mp3 > /sdcard/song.txt

2- wait 1ms (it only needs to wait a tiny fraction of a second, just
having Tasker run the wait action is enough)

3- read line 1 from /sdcard/song to %Line
4- go to 3 if %Line matches EOF
5- Wait a few milliseconds (this action may not be necessary)
6- Flash %LINE
7-Read out loud the value of %Line, via 'call' stream.

The difference is that I used grep twice to restrict the the output to the line with the Mp3 name in it, instead of using lsof -c switch or -p switch.  I did this because those switches were not working on my device and the PID changes all the time, so that's no use. 

The value of NAMEOFAPPLICATION in the name of the application which has opened the mp3 file, as found in the 'Command' field in the output of lsof.  In my case this was 'gonemad.g', as I installed gonemad music player because it integrates with the media utilities app (see below). Incidentally the output of the command field is 9 characters by default, and was limited to 9 characters in my device (the lsof c+ switch to change this does not work with on my device. Apparently some Linux dialects restrict the length of this field).

The Media Utilities app integrates with the gonemad player, and can be used as a plugin in Tasker to trigger the profile when the song changes.  In tasker choose ''state', then Media Utilities plugin configure, then 'new metadata'.  The player you use has to be supported by MediaUtilities app and Gonemad is one such app.  There are quite a few other player apps supported at the time of writing this.   

I also added the say action, just for my own purposes.  The 'call'  stream is specified because when the filename is read out by tasker, if the 'media' or notification stream is specified it causes media utilities to send a 'metadata changed' message to Tasker, triggering the above task again (and looping endlessly).

According to the Busybox official page, lsof isn't listed as one of the 'applets' supported. For some reason I still have lsof binary on my device though. Busybox official page does list the grep and basename etc applets.

If anyone has trouble with this, you could learn how to use the lsof and basename commands from the various 'linux man' sites.  The documentation is thorough.  Start with simple uses of the commands to see if they work on your device etc and build up to the longer command which is needed to get the file data and parse it etc as above.  That way you'll also find out which switches work and don't work (the +c switch for lsof doesn't work on mine for some reason).

You need to have the binaries for the commands installed. Many basic version of these binaries come with Busybox ('applets').
Dale.
Reply all
Reply to author
Forward
0 new messages