top | item 7629177

My Quest to Build the Ultimate Music Player

370 points| AndyKelley | 12 years ago |andrewkelley.me

152 comments

order
[+] GuiA|12 years ago|reply
Congrats! This is fantastic.

If you can write code, I highly recommend taking a stab at writing yourself the tools that you use the most (whether that is a music player, chat client, text editor, etc.).

Sure, it isn't trivial - but modern languages and libraries (I'm a big fan of Python, both for the language and its ecosystem) make it a very reasonable project. You can get an MVP working in a few weeks of work (if you spend 5-10 hours a week on it), and then you can add features and tweak the thing over the months and years as you use it.

And in the end, you get a piece of software that you deeply know, to which you can add any feature you want, that is customized to fit perfectly in your workflow, etc. It's a bit of work, but it's really cool and IMO one of the neatest things you can do for yourself as a programmer. Additionally, if it's something that works well for you, chances are that other people will like it- open sourcing it and getting other people to use it is a high of its own.

I'm working on a few such apps myself (todo list, mail client, and a few others), as console applications using ncurses to make something with a responsive, smart, effective and efficient style of UI that I don't think has been done before (mostly because no one has been trying to innovate in the domain of console applications in the past 20 years- but I think interesting things can be done). When I'm at an interesting point, I'll open source it and write a few posts about it.

I hear the naysayers saying that it's a waste of time, that there are already 8000 different open source mail clients and music players and todo lists apps and that it's better to contribute to old open source projects than create your own, etc... those arguments aren't wrong, but IMO they don't outweigh the pros I outlined above.

This talk by Gary Bernhardt is relevant: https://www.destroyallsoftware.com/talks/a-whole-new-world

[+] phaylon|12 years ago|reply
If it is just for a first try to experiment with structuring those kinds of application, or if your needs aren't even that complicated, it can even be quite close to trivial sometimes. But it's hard to know what is out there, and how useful it would be. Things that I've done on the side that weren't too hard and even more fun than I imagined beforehand:

* Media Players (Video and Audio) with GStreamer (0.10 can be okay'ish, 1.0 is very nice so far)

* Text Editors (via Gtk-Source or embedded GVim)

* I've tried building a specialized browser with WebKit. Was also quite easily used, except that I gave up when trying to get the Flash plugin to run turned out to be not-fun. Others may have more motivation.

Note that I mostly try these things in Gtk2/3 with either Perl 5 or Vala. Python seems to have very good Gtk/GObject bindings as well, so that should mostly apply the same way. And I'm sure if you look at the Qt and Wx ecosystems there will also be many preexisting useful components, or ways to plug them in.

[+] spotco|12 years ago|reply
This is absolutely true. You'll come to love the tools you make (and hopefully other people will too!)

I'd love to write my own text editor, though I imagine that I'd want a whole lot more features than my "optimal" music player (probably some sort of autocomplete, syntax checking, heck just make it a full-blown multi-language IDE).

By random coincidence, I've been writing (and using for the past year) my own super minimalist ncurses music player (https://github.com/spotco/ScrapePlayerDESKTOP , one python file, powered by sox and most likely only works on OSX).

My needs were definitely very different from the OP (I just wanted the ability to play music by all folder, and all folder recursively), but it's really interesting to see other people's versions of their "optimal" player.

[+] stevekemp|12 years ago|reply
> I'm working on a few such apps myself (todo list, mail client, and a few others), as console applications using ncurses to make something with a responsive, smart, effective and efficient style of UI that I don't think has been done before

I'd love to see what you're doing there, as I've spent the past few months working on a console mail-client, and reached a point where I have to decide to leave it alone or start v2 now I've learned more about how I handle email.

[+] jfreedom|12 years ago|reply
I really like this kind of solution for android stuff. There are some very specific things that I end up doing all of the time and it's relatively easy to write the thing that solves my exact problem in the fewest number of screen taps. I'm not sure if it saves me time overall, but I also enjoy solving the problem.
[+] ecdavis|12 years ago|reply
One problem that really interests me is the "dynamic playlist." Once your music library becomes sufficiently large and diverse, simply shuffling songs ceases to be an acceptable way to listen to music. You'll randomly switch between vastly different genres, come across tracks that aren't enjoyable outside the context of an album, jump in halfway through some pieces. It's a mess.

I wrote a simple script which uses Last.fm data to generate a "path" through the artists in my music library based on their similarities. It's very far from perfect, but it suffices to build an album playlist which slowly takes me through several genres. Some day I'll improve it to work based on albums rather than artists.

Ideally, I'd like to be able to run queries on my music library and have an interesting playlist returned to me.

[+] dfc|12 years ago|reply
> Ideally, I'd like to be able to run queries on my music library and have an interesting playlist returned to me.

You want Beets.[1] Anything you could possibly want is doable with the smart playlist feature[2] and the redonkulous power of the queries and metadata (chromaprint/musicbrainz/echonest). There is a plugin for last.fm genres but I have not used it. I am not sure how you got similarities from last.fm but you can definitely use the echonest data to find similar music. There was a good discussion of beets here not so long ago.

[1]: http://beets.radbox.org/

[2]: https://beets.readthedocs.org/en/v1.3.5/plugins/smartplaylis...

[+] AndyKelley|12 years ago|reply
I'd love to read more about this idea. You might consider doing some research and writing a piece on it.
[+] splat|12 years ago|reply
This looks really cool! As a classical music fan, the one feature that I've always wanted but have never found is the ability to link several tracks together. Often times classical CDs break up a single piece into multiple tracks, so if you're listening to your library on shuffle, you will often jump into the middle of a piece, which is annoying. It would be so cool if there were a music player where you could link several tracks together as one piece so that shuffle would always start from the beginning and wouldn't shuffle away until the end.
[+] chiph|12 years ago|reply
The Redbook audio specification allows for indexes (ability to have tracks within tracks), which was intended for jumping to the next movement within classical pieces. I haven't seen the buttons for this on a CD player (real or virtual) since the late 1980s.
[+] AndyKelley|12 years ago|reply
Interesting idea. I've thought about that too, for songs that seamlessly transition into each other. The tricky part is how to incorporate that into the UI in a way that is not confusing and doesn't add a bunch of clutter.
[+] joshka|12 years ago|reply
The best way I've found to handle this for DJ sets is to use a single MP3 file and a CUE sheet with the times each subtrack starts. Then your media player has to support CUE sheets (Winamp has/had a plugin, Foobar2000 does, other than those YMMV). Matroska Audio showed promise in being the format where this would just work out of the box, but loses due to first mover advantage of mp3s and the market reach of other formats.
[+] sbtrct|12 years ago|reply
iTunes will let you do this when you're importing a cd. From memory, you right click on the tracks you want joined (before they're imported) and select the appropriate option. The only drawback is that iTunes Match (if you use it) won't match the joined file, so it'll have to upload manually.
[+] ANTSANTS|12 years ago|reply
You don't really need special support for this. Most music players have a mode for shuffling albums at a time, not individual tracks. Just make a classical playlist and select that mode.

As for shuffling your entire library, I don't understand why you'd want to do that. I get in the mood for certain genres; I don't want to jump from Rainbow to nordloef to Massive Attack randomly over the course of 10 minutes.

[+] coldtea|12 years ago|reply
iTunes can do that -- and it was added specifically for classical music. It's even called Groupping.

Another nice feature it has, is that it lets you handle albums with various artists as one entity, that is, you can set those tracks as "part of a compilation".

[+] gagege|12 years ago|reply
iTunes can (or used to) do that, believe it or not.
[+] anigbrowl|12 years ago|reply
The solution is to analyze each song before playing it to figure out how "loud" it sounds to humans. Then the music player adjusts the playback volume of each track to compensate for the perceived loudness. This way, the user does not have to adjust the volume for each track that comes on.

This is just going to perpetuate the arms race, because it's not hard to spoof that sort of thing by monkeying around with crest factors in transient designers, plus people seem to have quite different preferences for compression/limiting. Just tweaking gain and falling back to compression/limiting past a certain threshold is just going to lead to pumping on some program material.

There is a standard for measuring this stuff, and thanks to years of people like me complaining about jumps in volume during commercial breaks on TV and the like, a loudness-measuring standard has been formalized and is being demanded by broadcast regulators (so it will become standard in audio production software over the next year or three). It's here: http://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-3-2...

Waves, Dolby, Izotope etc. have all released plugins or free updates for 1770-3 comaptibility so it should become ubiquitous by mid-decade, as will automatic loudness normalization at the mastering stage, which wasn't previously possible in the absence of an industry-standard metric.

[+] AndyKelley|12 years ago|reply
This is exactly what the EBU R128 standard specifies. It references ITU-R BS.1770. So Groove Basin is already doing exactly what you have prescribed!
[+] daurnimator|12 years ago|reply
This article rings true with me on so many points.

I spent years searching for, and coding my dream music player/manager. Going through tens of different backends, servers, etc, not limited to: - MediaMonkey: windows only - Amarok: terrible interface, slow and hard to extend - foobar2000: closed source/windows only/columns UI stopped working - MPD: Just not enough, also poor codec support (I use wavpack) - xmms2: was a baby at the time - ExFalso

I started coding my own, dubbed lomp: https://code.google.com/p/lomp/ I solved so many interesting issues that seemed to plague other music software: I got client/server working, output redirection, even ended up coding my own library management, then tagging library. Tangentaly, tagging is HARD, no one does it correctly. The best library I found on ANY platform or in ANY language was Mutagen, part of the Quodlibet https://code.google.com/p/quodlibet/ project; but even it got a few things wrong. I eventually tried to split off my efforts as 'lamt' https://github.com/daurnimator/lamt but didn't dedicate enough time. Also worked on a wide range of front ends: console, web, etc.

But as I coded this media player, I could never settle on a decoding or output library; I went through SO many: - controling mplayer/cplay/aplay via a pipe - libvlc - gstreamer - Phonon - libavcodec But none were enough, or way too buggy... After years of failing, I decided I better just do it myself, so I started again: https://github.com/daurnimator/lomp2/ This time using LuaJIT's brand new (at the time) ffi to directly talk to libao (which I found to be the best cross platform audio output solution)

I ran out of time to work on lomp when I was at university, and now I have a job that keeps me busy. I wonder how many of my pain points you guys have solved.....

Feel free to reach out to me if you want to discuss more.

[+] AndyKelley|12 years ago|reply
I'm particularly interested in your opinions on tagging. Can you explain what most software gets wrong about tagging?

Here's the plan so far, although it's not implemented: https://github.com/andrewrk/groovebasin/issues/30

The idea is that you might edit tags for a file which doesn't even support tags, such as AAC. So it would let you do that, and the changes would then be reflected in the DB. However we would also have a UI pane for "Suggested Library Fixes" or something like that. This would be things like moving files to their canonical location, updating incorrect duration tags, duplicate file detection, etc. It would also have suggestions like this:

* These songs have tag edits that you have made but they cannot be saved. Do you accept this change? (Proposed change: wrap the file in a container format which supports tags)

[+] existencebox|12 years ago|reply
Hi darnimator,

Your statement rings VERY TRUE to me as much as the original article, and there may be an opportunity here. I've spent some time (I'm sure not nearly as much as you have) hacking on this problem, but primarily from the library management aspect, and I lean on VLC plugins for play/streaming. This seems to mesh quite nicely with the sides of this that you touch; tagging and such are exactly the sort of problems I'd find most compelling, whereas I'm quite out of my league in the media aspects of it. (my biggest "pain points" were good integration of torrenting/a programmable pipeline for dealing with torrents, library organization, and various distributed features... less pain points I guess, and more things I found compelling enough to not procrastinate on hacking on.)

I also have a job that eats my time, but if you would like to trade contact info, I'd be more than happy for a chance to pick the brain of someone who's been attacking this longer than I have, as well as potentially see what could come of it.

[+] asgard1024|12 years ago|reply
I also had a quest to build the ultimate music player. My motivation was that most music players got complicated to the point I was unable to use them.

My player is 200 lines of Python, utilizing MPD and Qt (for Docker icon), and has about 3 features. It plays all the mp3 in a directory (including subdirs) randomly, and you can "like" or "dislike" song, which modifies the probability of it being played (and these data are remembered in MPD database). Also has "pause" and "next song" buttons (from the tray menu) and that's it, literally.

To each his own, but that's my personal definition of "ultimate".

[+] JTon|12 years ago|reply
Sounds good to me too. I'd like to set a "mood" as well. The probabilities for each track adjust based on the mood selected (aside: in the future the mood selection will be automatically and accurately determined via bio-sensors :)
[+] aaronem|12 years ago|reply
I'd try something like that, but most of what I listen to is from the common-practice era, so the quantum of content is not an individual file, but a playlist. "Shuffle" therefore doesn't work for me; what I really need is a player whose playlists can contain either individual files or other playlists.

I wouldn't have thought this would be all that outré a desire, but apparently everyone who's ever implemented a music player disagrees with me...

[+] fragmede|12 years ago|reply
> utilizing MPD

Yeah, that's a non-starter for reasons that are well described in the post. (But to each their own.)

[+] Touche|12 years ago|reply
This post makes me feel bad about myself. How many "passion projects" have I started and gave up on the first time something difficult came up? Too many to count.

There are several lessons to be learned from this post. Perseverance. Starting small. Not sacrificing your vision. Willingness to go as low-level as needed. Patience. This is an inspiring post. I think I'm going to dust off one of my old projects now and get back to work.

[+] AndyKelley|12 years ago|reply
> How many "passion projects" have I started and gave up on the first time something difficult came up?

Probably not as many as I have. This is the one project that I keep coming back to and the only reason it has survived so long is that I dogfood it.

[+] endgame|12 years ago|reply
Really good article, but if you're going to bundle libraries, PLEASE provide a way to make configuration fail if you can't get to the system copy.

A lot of projects (libgroove included) will try the system copy and then fall back to the bundled copy if the system one wasn't found. That's nice for users (maybe), but it's a pain for packagers. If the packager just happens to have one of the dependencies installed, the package will automagically find it but it will have incorrect deps.

Further reading: https://blog.flameeyes.eu/2009/01/bundling-libraries-for-des...

[+] ammmir|12 years ago|reply
That's funny, seems like a lot of us have built music players because none have seemed adequate :)

I built CloudPlay (http://cloudplay.fm) because I wasn't satisfied with Mac music players and none supported streaming from YouTube or SoundCloud. At the time, I had also been itching to build my first Mac app, so what better opportunity to learn Objective-C/Cocoa and improve my music listening experience?

It turned out to be a longer journey than it should have. I got most of it working in a month or two, but I spent too much time with unnecessary detours like:

- writing a low-level audio streaming framework that I scrapped once I discovered a higher-level API

- building a basic search index and deciding to use LuaJIT (!) to implement it, thereby requiring me to build my own Objective-C/Lua bridge, only to discover that the OS already provided a full-text search framework

Yes, I could've read the documentation more carefully, but it's also easy to get sucked down a rabbit hole building stuff from scratch for the sake of exploration. Sometimes building at a lower level helps you appreciate and understand the higher level and why you shouldn't always reinvent the wheel :)

[+] jfb|12 years ago|reply
Yes, I could've read the documentation more carefully, but it's also easy to get sucked down a rabbit hole building stuff from scratch for the sake of exploration. Sometimes building at a lower level helps you appreciate and understand the higher level and why you shouldn't always reinvent the wheel :)

But that's what's fun about what we do.

[+] sandGorgon|12 years ago|reply
Quick question - are people listening to a lot of music through their laptops ?

do note I wrote "through" not "on" - which means that you may still have your music on your laptop, but you could be listening through your mobile (streaming through plex, dlna,etc)

I find the audio quality of listening through mobile phones to be far better than my laptop (and I have a latitude - the highest end of its generation). In general the music player is of far better quality as well (Poweramp, etc.).

The only drawback I can think of is battery consumption, which is easily solvable via a USB cable. It also works great because an incoming call will pause the music and resume when done - as opposed to manually pausing and resuming on the laptop.

And if you are on earphones with a mic, then you understand the true meaning of "gapless" - or do you prefer taking off your foam-covered in-ear 'phones every time you get a call ?

[+] baddox|12 years ago|reply
The thing about loudness compensation is that it only further reduces the dynamic range of your music collection (unless you have programmatic control over the analog gain of your amplifier, which you probably don't), so the arguments for it shouldn't really appeal to dynamic range.
[+] AndyKelley|12 years ago|reply
The end result is that the music comes out sounding quieter, so the user ends up increasing the analog gain of their amplifier. This increases dynamic range because the alternative is having the highly compressed music sound very loud resulting in users keeping their amplifier gain low.
[+] eqbridges|12 years ago|reply
Great idea for a project! I too was a big fan of Amarok, and have been disappointed by music players since having used it.

One thing I haven't seen mentioned, which Amarok, excelled at but other players haven't, was dealing with large (>100gb) collections hosted over a network. Hopefully you'll include this in your testing. As well Amarok allowed you to store metadata in arbitrary databases (which QT had support for) hosted on a network, thus allowing for metadata to be shared by computers for a given account. Quite common nowadays is to use SQLite locally; however SQLite does not support working over a network :-/

Anyway, kudos and fare-thee-well!

[+] aaronem|12 years ago|reply
A general observation, which the comments in this thread have brought to the point of perceptibility:

Perhaps only in the field of music management and playback is it considered so reasonable to suggest that an acceptable solution to lousy user interface design is to modify the otherwise well-formed data presented by that interface, rather than just to fix the interface and be done with it.

I'm not sure why this is, and I don't mean by it to denigrate people who develop music player software, but it does seem awfully odd to me by comparison with pretty much any other specialization of software design.

[+] AndyKelley|12 years ago|reply
What about the whole "everybody is doing loudness compensation wrong" issue I pointed out? That's an example of something that is not merely a user interface design issue.
[+] lawn|12 years ago|reply
What a great effort you've done! I'm certainly tempted to try it out on a raspberry. I would appreciate a tutorial article on how to get it running.
[+] mrweasel|12 years ago|reply
It may just be me being old fashion, but I haven't seen or used a good music player since XMMS. Every single new media player seems want to take up a huge amount of screen space or have a ton of useless feature.

XMMS was great, simple and pretty interface, just add the files you want to play and you could queue up tracks (A feature that seem to elude iTunes ).

[+] johnchristopher|12 years ago|reply
> At some point I plan to write a tutorial article detailing exactly how to get this application running on a Raspberry Pi. It's mostly straightforward but there are enough "gotchas" here and there that I think it could be a useful article.

I'd be really interested in reading that.

[+] romainvv|12 years ago|reply
I was wondering what is the differences (pro/cons) between DLNA/UPNP protocols and your solution ? With a XBMC server, you can play song over network from any sources thanks to UPNP
[+] ubercow13|12 years ago|reply
UPnP doesn't work well over the internet
[+] jxn|12 years ago|reply
xmms2 seems like it fits the required bill the best, though the project is pretty stagnant and there's never been a real release. It does seem to get all the big issues right.
[+] FranOntanaya|12 years ago|reply
As simple as Audacious is, I've stuck to it for the LADSPA and Sample Rate conversion filters. I wouldn't take UI improvements over sound itself.
[+] callesgg|12 years ago|reply
Really really nice work thought the loudness videos was very interesting.

Personally I have moved on to spotify and more or less abandoned my old music collection.