[patch] Song ratings

Hi all,

I've been using mocp for {4 years now, free}, and I think it's about time to give sth back to the community. So, I've tried to make moc capable of handling song ratings. Doing it right requires a few important decisions to be made; so far, I hacked together the smallest functionality that made sense to me. Ratings cannot (yet) be written to files, thus resolving the dilemma where to store them:)

Have a good one,
Adrian Lancucki

Patch (made against 2.5.0-beta1 revision 2526): http://pastebin.com/5J8LvY6J
Some eyecandy

Background

Different players handle ratings differently. They might either store the ratings in a local db (Amarok, iTunes, Banshee, Quodlibet), write it to audio files (Banshee, Windows Media Player) or pretend that they don't exist (foobar2000, Rhythmbox?, AIMP?).

Then there's the issue of how the ratings can be stored; AFAIK, some popular formats handle it differently:
- id3v1 - no ratings
- id3v2 - usually POPM frames indexed with e-mail/id (can be multiple per 1 file) with rating uint8 field 0-255, some players (foobar2k ratings plugin) use custom TXXX frames
- apev1/apev2 - no ratings
- vorbis comments - no official key for ratings, though some players (Banshee, Quodlibet) store something like "rating:quodlibet@foo.com=1.0" with ratings being 0.0-1.0 floats

Ratings patch

The good:
* it works:)
* ratings are stored in the cache

The bad:
* ratings are read-only
* they don't work with the ffmpeg plugin (I had a look at the sources and I'm pretty sure that libavformat can't handle POPM frames)
* the pretty star symbol I have used is utf8 and comes out garbled and breaks the layout on non-utf8 terminals
* ratings are not being stored in the playlist (.m3u doesn't handle ratings as #EXTINF)

I have patched the following plugins: aac, mp3, flac and vorbis. aac and mp3 both use libid3tag, so I'm using the first POPM frame available, mapping the values 0-255 to 0-5 stars the same way Banshee does
As for flac and vorbis, again similarly to Banshee, the pseudo-key "rating:banshee@foo=1.0" is being leveraged, mapping 0.0-1.0 to 0-255 (by multiplying by 255).

How to use it

1. Apply the patch.
2. Set "ShowRating = yes" in the config.
3. rm .moc/cache/tags.db
4. Make sure that ffmpeg is not the default plugin (by setting something like mp3(mp3):flac(flac):ogg(vorbis):" in the config file.

Having mocp store the ratings in db does a little sense to me, since it's not a portable solution. For now, I would suggest rating the songs elsewhere (Banshee or cmdline tools).

TODO
I'm not really sure how to check if the terminal supports utf8; if it's not, then the pretty star should be replaced with ugly "*".
Also, it would look nice if there was a new set of "theme" attributes for the rating stars only.
Make the ffmpeg plugin read the tags with libid3tag ?

Forums:

Hi Andrek14.

Your patch seems to have some hitch; can you resolve them in order to use the patch on Linux ?

+ /usr/bin/patch -p1 -b --suffix moc-r2506+fsf_addr.patch --fuzz=0
patching file decoder_plugins/mp3/xing.c
patching file decoder_plugins/mp3/xing.h
+ patch -p1
(Stripping trailing CRs from patch.)
patching file common.c
(Stripping trailing CRs from patch.)
patching file common.h
(Stripping trailing CRs from patch.)
patching file decoder_plugins/aac/aac.c
(Stripping trailing CRs from patch.)
patching file decoder_plugins/flac/flac.c
(Stripping trailing CRs from patch.)
patching file decoder_plugins/mp3/mp3.c
(Stripping trailing CRs from patch.)
patching file decoder_plugins/vorbis/vorbis.c
(Stripping trailing CRs from patch.)
patching file interface.c
(Stripping trailing CRs from patch.)
patching file interface_elements.c
(Stripping trailing CRs from patch.)
patching file menu.c
(Stripping trailing CRs from patch.)
patching file menu.h
(Stripping trailing CRs from patch.)
patching file options.c
(Stripping trailing CRs from patch.)
patching file playlist.c
(Stripping trailing CRs from patch.)
patching file playlist_file.c
(Stripping trailing CRs from patch.)
patching file playlist.h
(Stripping trailing CRs from patch.)
patching file protocol.c
(Stripping trailing CRs from patch.)
patching file server.c
(Stripping trailing CRs from patch.)
patching file tags_cache.c
+ exit 0

get_tag_rating() in aac.c requires additional return statement.

@sagitter: Seems I have had a little mix-up with patches, for the patch I posted did not work for me either. Updated the patch, seems ok now. I have succesfully applied it with

patch -p1 -b --suffix moc-r2526+fsf_addr.patch --fuzz=0 -i moc-2.5.0-beta1-ratings.patch

Make sure it's r2526 though.

@jcf Fixed (and frankly, it was already fixed in the correct version of the patch).

Not yet. Maybe you should manage them separately.

Patch #1 (moc_2.5.0-beta1_rev_2526_ratings_patch):
+ /usr/bin/cat /home/sagitter/rpmbuild/SOURCES/moc_2.5.0-beta1_rev_2526_ratings_patch
+ /usr/bin/patch -p1 --fuzz=0
(Stripping trailing CRs from patch.)
patching file common.c
(Stripping trailing CRs from patch.)
patching file common.h
(Stripping trailing CRs from patch.)
patching file decoder_plugins/aac/aac.c
(Stripping trailing CRs from patch.)
patching file decoder_plugins/flac/flac.c
Hunk #1 succeeded at 426 (offset 3 lines).
Hunk #2 succeeded at 460 (offset 3 lines).
Hunk #3 succeeded at 504 (offset 3 lines).
Hunk #4 succeeded at 529 (offset 3 lines).
(Stripping trailing CRs from patch.)
patching file decoder_plugins/mp3/mp3.c
(Stripping trailing CRs from patch.)
patching file decoder_plugins/vorbis/vorbis.c
Hunk #3 FAILED at 174.
Hunk #4 FAILED at 260.
Hunk #5 succeeded at 367 (offset -3 lines).
2 out of 5 hunks FAILED -- saving rejects to file decoder_plugins/vorbis/vorbis.c.rej
(Stripping trailing CRs from patch.)
patching file interface.c
(Stripping trailing CRs from patch.)
patching file interface_elements.c
(Stripping trailing CRs from patch.)
patching file menu.c
Hunk #1 succeeded at 120 (offset -5 lines).
Hunk #2 succeeded at 178 (offset -5 lines).
Hunk #3 succeeded at 194 (offset -5 lines).
Hunk #4 succeeded at 277 (offset -5 lines).
Hunk #5 succeeded at 312 (offset -5 lines).
Hunk #6 succeeded at 353 (offset -5 lines).
Hunk #7 succeeded at 608 (offset -5 lines).
Hunk #8 succeeded at 673 (offset -5 lines).
Hunk #9 succeeded at 703 (offset -5 lines).
(Stripping trailing CRs from patch.)
patching file menu.h
(Stripping trailing CRs from patch.)
patching file options.c
(Stripping trailing CRs from patch.)
patching file playlist.c
(Stripping trailing CRs from patch.)
patching file playlist_file.c
(Stripping trailing CRs from patch.)
patching file playlist.h
(Stripping trailing CRs from patch.)
patching file protocol.c
(Stripping trailing CRs from patch.)
patching file server.c
(Stripping trailing CRs from patch.)
patching file tags_cache.c
error: Bad exit status from /var/tmp/rpm-tmp.QZL3Js (%prep)

Managing patchsets can be frustrating. If you're using GIT then I'd suggest TopGit as a solution which works well for me (and I juggle dozens of uncommitted patches on MOC).

Using git svn you can track the current MOC SVN HEAD and then use TopGit to layer patches for each concern into a single and maintainable patchset which can be easily exported in Quilt format.

I have just set up TopGit, it's a nice solution indeed! Might have saved my career as a MOC contributor.

@sagitter: You can get a Quilt patch here. I have zero experience with quilt; however, for me it sufficed to put the patch directory into the trunk and run quilt push -a. Let me know if this time it works.

Thank you. Your patch is ok.

If someone want test this new feature by adrek14, I built new RPMs for Fedora 18 specifically: moc-2.5.0-0.1.svn2526.*

adrek14, if I have understood correctly, currently

- I cannot rate my songs in MOC directly
- Currently MOC is just able to read rating from others audio players

?

Yes, that's correct. I'm glad the patch worked.