I created kew, a music player for the Linux terminal.
This started when I asked myself: what if I could just type something like "play nirvana" in the terminal and have the rest taken care of automatically? That got the ball rolling and I kept adding stuff: covers in ascii and then as sixel images, a playlist view, a visualizer, a library view and finally search.
While kew can be used as a commandline tool, it has evolved into a TUI app.
Here are some example commands:
kew nirvana # Plays all of your Nirvana songs, shuffled
kew nevermind # Plays the "Nevermind" album in order
kew spirit # Plays "Smells Like Teen Spirit"
kew all # Plays all your music, shuffled
kew albums # Plays one album after the other in random order
It works best when your music library is organized like this: Artist/Album(s)/Track(s)
kew is written in C and licensed under GPLv2.
Source and screenshot: https://github.com/ravachol/kew
So much thanks for giving a good example
The aspect I like the most is using the filesystem as a database, since that's what UNIX people should like (and you can use symlinks for more complex cases). In fact, I myself made a music player with that as central philosophy, though it is much more bare/suckless compared to yours: https://git.sr.ht/~q3cpma/mus
Did you consider implementing a simple event system (maybe even IPC) for track and status change? Possibly MPRIS or something simpler. That was the main feature I kept from cmus when creating mus, so that I can easily interact with it through lemonbar and scripts.
Yes, MPRIS is supported.
Those who love this conceptually but have/had cloud music, did you act? How/why?
I ended up switching to fully-local media after realizing that my 956GB flac+mp3 would be ~159GB when converted to Opus. I now use https://github.com/nvllsvm/harmonize to maintain a 128kbps Opus version of my main library and Syncthing to synchronize it to my phone and laptop.
--- side note, Auxio is the client I'm using on Android with my synced library.
It works phenomenally.
At some point I was going to mirror it locally, but never got around to it.
It is all backed up in dropbox
Use whatever you want! Just wanted to suggest it.
sudo bash -c "curl https://raw.githubusercontent.com/ravachol/kew/main/install.sh | bash"
Might as well run unsigned binaries straight from the internet. What is this, Windows?It doesn't fit my use-case very well, though. I'm not saying it needs to, but I'm going to put my use-case out there in case someone is looking for project ideas.
We have oodles of music players on Linux, GUI and terminal. But we have very few choices that
* are optimized for the absurdly, comically large library of someone who has been diligently collecting and organizing music for decades
* collect playback statistics and allow user rating of songs
* that can be used to create smart playlists
I used amarok for years, but it keeps dying and reviving, and I don't trust it to stick around. I then used mpd for years, but while mpd excels at large libraries, the other two requirements have to be implemented client-side, and the experience was always at least a little janky. I currently use Strawberry, but 1) it chugs with a large library, 2) its smart playlists aren't expressive enough, and 3) it is also kind of janky, and I experience frequent crashes.
The only player I've found that really fits my use-case like a glove is MediaMonkey, but I walked away from Microsoft years ago, and I'm not about to go back now just to wrangle my music library.
1: https://www.navidrome.org/ 2: https://github.com/navidrome/navidrome/issues/1417
For an android client I use tempo[1] which again was one I landed on because pretty much all the other clients didn't support folder lookup either (I think dsub also does but tempo is a lot prettier).
[0] and also I think it's insane to add that much complexity to something that is single-user.
As for your other two suggestions those fall outside the scope of kew. kew is supposed to be simple with minimal bloat.
int randomNumber = getRandomNumber(1, 808);
if (randomNumber == 808)
printGlimmeringText(text, nerdFontText, lastRowColor);
Nice project!Is this a nix thing (i'm unsure what freeimage-unstable is)
error: Package ‘freeimage-unstable-2021-11-01’ in /nix/store/20yis5w6g397plssim663hqxdiiah2wr-source/pkgs/development/libraries/freeimage/default.nix:72 is marked as insecure, refusing to evaluate.
Known issues:
- CVE-2021-33367
- CVE-2021-40262
- CVE-2021-40263
- CVE-2021-40264
- CVE-2021-40265
- CVE-2021-40266
- CVE-2023-47992
- CVE-2023-47993
- CVE-2023-47994
- CVE-2023-47995
- CVE-2023-47996The version of kew packaged for Nix is very old: v1.5.2. We're at version 2.8.2. So it's more than a year old, from very early on in the project.
I don't know how relevant these vulnerabilities are to kew, which isn't run across the network in any way, it just reads your local files.
Thank you for bringing this to light. I don't know how feasible it is to use something other than freeimage though, gonna have to investigate.
Looks like a nice project, I like the terminal album art display :).
I'll have to check this out. I wonder if it can play 5.1 audio correctly?
[0] - https://musikcube.com/
And I "compiled from source" as I am using Fedora, but it was just one command.
Thank you!
This here is even better, I love the minimal approach.
Defaulting to the only result in your library is perfectly reasonable, but it the case of a collision, what does it do?
My guess is that it runs through in a loop (I haven't looked at the code) and simply goes with the first result that it finds, but that doesn't cover all possible use cases.
Unlike the -e solution, it wouldn't make the command significantly more verbose than the default option.
You could also print a list of commands for the specific options (or allow for index based selection) in cases where there were collisions.
% brew install kew
...
kew: Linux is required for this software.
Error: kew: An unsatisfied requirement failed this build.
EDIT: Added.