Music

Relating to CDs, shows, etc.

Well done, Personal Radio Station

Music: 

Belly - Thief

I think my newly-weighted '90s playlist builder did a pretty decent job spitting out a super typical day in the '90s on the Good Radio Stations.

I've got some tweaks to do, but so far so good.

xrayspx's picture

Music Streaming Setup

Fixed Tags:

Step 1

- Allow Ultrasonic to send notifications






xrayspx's picture

Dammit Stupid Tarriff Antennas

Music: 

I need one of these antennas but I don't know exactly which size I should get. So rather than just buy 3 of them a month ago I've been waffling :-) If I could get it to make solid contact without opening the case on this otherwise totally pristine boombox I'd just use the wire I have there now.

It doesn't have to look great it just needs to receive FM from the other room. These are both favorites of mine among the dozen or more radios we have scattered around the house and barn. When I took this picture I hadn't even cleaned them after bringing them both home for five whole bucks.









xrayspx's picture

Quick Music Video Fact

Music: 

MTV From 1992

Or: The shit I put up with for good TV in this house.

I had two conversations today about how I basically optimize statistical analysis and data reconfiguration...blah blah. Each conversation just wound up with me wanting to tell the same story so I though I should write it down.

Some time ago I made a colossal mistake. I have a lot of music videos.. Like a lot a lot, to me anyway. And there's organization and logic to it to build different playlists and whatever.

xrayspx's picture

Have some content

Music: 

It seems like I really don't write very much, but that's kind of a massive misconception. I don't write "much", but I had a bunch of blog entries that were at least 60% written and were missing like, screenshots or links or tags or I need to make new tags for things like XScreensaver and BSDs. Haiku. Shit lots of stuff.

xrayspx's picture

That 120 Minutes Playlist

Music: 

I've just been directed toward a YouTube playlist that apparently made the rounds last August claiming to have "Every Video Played on 120 Minutes".  Well no.  Not really.  The claim is "2506 Videos".  Reality is...less.

 

I grabbed the playlist and threw it into my nightly randomizing grinder.  I already have a "120 Minutes" playlist, in which I just cram every video from every band who was ever on 120 Minutes in there.  Since it all "spiritually" counts.  I put stuff that "should" be in there too because what other slot would have played Humanwine I guess?

xrayspx's picture

Playlists

Music: 

Dr. Dre - Nuthin' But a G' Thang

I had a request to share some playlist management stuff so I thought I should explain myself. I've got a significant CD collection, and a somewhat-significant collection of TV shows. This is fine on its own, but lots of media is pretty worthless without well curated playlists that you really don't have to think about. So I built Spotify, MTV and Syndicated TV.

* NOTE: If you have a better way to do any of this let me know and I'll fix it. I particularly have the sense, which is not backed up by my testing, that "sort -R" isn't great.

Music's easier so we'll start there. I use Strawberry to manage my music. This was all running under Clementine and aside from some DB schema changes, the scripts are portable between them.

Until relatively recently I was never a big fan of "star" or "heart" ratings, but Clementine/Strawberry will store this metadata in the MP3 itself so I should be able to quickly recover if I lose my music database. In the app I have a few Smart Playlists like 3-Stars, 3 Stars + (This is 3, 4 and 5 star tracks), 4-Stars, 4-Star + and 5 Stars. To use 4 Star as an example, the rules look like this:

Match every search term (AND)
Rating - Greater than - 3.5 Stars
Rathing - Less than - 5 Stars
Ratin - Not Equals - 5 Stars
Length - Greater Than - 8 Seconds

That results in a playlist of 8423 songs with ratings between 4 and 4.99 stars. There was a bug in Clementine which I got fixed where ratings could exceed 5, so I'm a little careful to deal with weirdo cases, but it's pretty simple. I also have a bunch of manually selected playlists, so like an '80s one, '90s, and "Barn Radio". Barn Radio is our catch-all for the ubiquitous music we heard from the late '70s through late '80s. For Natalie that was largely with her dad in the dairy barn, for me it was the music of my 2 hours on the bus every day.

Anyway, I have all these .m3us stored in a folder along with my MP3s called "playlists_base". These are used by a nightly playlist generator that pulls ~200 tracks and makes daily playlists running 8 or 10 hours each. The reason for this is that streaming software such as Airsonic-Advanced kind of chokes on massive playlists. It could be Airsonic itself, it could be populating the mobile client, I don't really know or care, other than to say it works great with list sizes under about 1000 tracks or so, so I keep them shorter.

The x-Star playlists are all built from the database like this 4 Star + playlist below. You can see it do a couple of different Star Rating DB queries, dump out the tracks to $playlist_tmp.m3u, then cat that file and do a random sort to generate the final version. It's pretty easy to adjust the mix based on ratings, so if I wanted to weight high-rated tracks I could do that by adjusting how many tracks of the 200 are returned by each search:

#!/bin/bash

rm /Volumes/Filestore/CDs/playlists/4\ Stars\ +.m3u

i=1

while [ $i -le 100 ]
do

### Switching from Clementine to Strawberry ###
#       file=$(sqlite3 /var/tmp/clementine.db "select filename from songs where rating > "0.9" order by random() limit 1;" | awk -F "file://" '{print $2}')
        file=$(sqlite3 /var/tmp/strawberry.db "select url from songs where rating > "0.9" order by random() limit 1;" | awk -F "file://" '{print $2}')
       
        ### Clementine data encodes special characters and accent marks and stuff so I'm using
        ### Joel Parker Henderson's urldecode.sh to undo that: https://gist.github.com/cdown/1163649
       
        data=$(/home/xrayspx/bin/urldecode.sh "$file")
        if [ -f "$data" ]
        then
                ### Have to escape leading brackets because grep treated it as a range and would allow duplicates ###
                ### Can't do that in "data" because \[ isn't in the filename so they'll fail ###
               
                escaped=$(echo "$data" | sed 's/\[/\\[/g')
                #echo "$escaped"
               
                ### Avoid duplicates
                match=$(grep -i "$escaped" /var/tmp/4-star-tmp.m3u)
                if [ -z "$match" ]
                then
                        echo "$data" >> /var/tmp/4-star-tmp.m3u
                        ((i++))
                fi
        fi
done

i=1

while [ $i -le 100 ]
do
### Switching from Clementine to Strawberry ###
#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file=$(sqlite3&nbsp;/var/tmp/clementine.db&nbsp;"select&nbsp;filename&nbsp;from&nbsp;songs&nbsp;where&nbsp;rating&nbsp;>=&nbsp;"0.8"&nbsp;and&nbsp;rating&nbsp;<&nbsp;"1"&nbsp;order&nbsp;by&nbsp;random()&nbsp;limit&nbsp;1;"&nbsp;|&nbsp;awk&nbsp;-F&nbsp;"file://"&nbsp;'{print&nbsp;$2}')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file=$(sqlite3&nbsp;/var/tmp/strawberry.db&nbsp;"select&nbsp;url&nbsp;from&nbsp;songs&nbsp;where&nbsp;rating&nbsp;>=&nbsp;"0.8"&nbsp;and&nbsp;rating&nbsp;<&nbsp;"1"&nbsp;&nbsp;order&nbsp;by&nbsp;random()&nbsp;limit&nbsp;1;"&nbsp;|&nbsp;awk&nbsp;-F&nbsp;"file://"&nbsp;'{print&nbsp;$2}')
       
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;###&nbsp;Clementine&nbsp;data&nbsp;encodes&nbsp;special&nbsp;characters&nbsp;and&nbsp;accent&nbsp;marks&nbsp;and&nbsp;stuff&nbsp;so&nbsp;I'm&nbsp;using
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;###&nbsp;Joel&nbsp;Parker&nbsp;Henderson's&nbsp;urldecode.sh&nbsp;to&nbsp;undo&nbsp;that:&nbsp;https://gist.github.com/cdown/1163649

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data=$(/home/xrayspx/bin/urldecode.sh&nbsp;"$file")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;[&nbsp;-f&nbsp;"$data"&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;###&nbsp;Have&nbsp;to&nbsp;escape&nbsp;leading&nbsp;brackets&nbsp;because&nbsp;grep&nbsp;treated&nbsp;it&nbsp;as&nbsp;a&nbsp;range&nbsp;and&nbsp;would&nbsp;allow&nbsp;duplicates&nbsp;###
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;###&nbsp;Can't&nbsp;do&nbsp;that&nbsp;in&nbsp;"data"&nbsp;because&nbsp;\[&nbsp;isn't&nbsp;in&nbsp;the&nbsp;filename&nbsp;so&nbsp;they'll&nbsp;fail&nbsp;###
                       
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;escaped=$(echo&nbsp;"$data"&nbsp;|&nbsp;sed&nbsp;'s/\[/\\[/g')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#echo&nbsp;"$escaped"
       
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;###&nbsp;Avoid&nbsp;duplicates
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;match=$(grep&nbsp;-i&nbsp;"$escaped"&nbsp;/var/tmp/4-star-tmp.m3u)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;[&nbsp;-z&nbsp;"$match"&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;"$data"&nbsp;>>&nbsp;/var/tmp/4-star-tmp.m3u
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((i++))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi
done

cat&nbsp;/var/tmp/4-star-tmp.m3u&nbsp;|&nbsp;sort&nbsp;-R&nbsp;>&nbsp;/Volumes/Filestore/CDs/playlists/4\&nbsp;Stars\&nbsp;+.m3u

rm&nbsp;/var/tmp/4-star-tmp.m3u

Those Star Rating lists are called at the beginning of my overall static playlist script, but the Barn playlist and other manually selected ones are built from the "playlists_base" directory. I basically just edit those .m3us in place with Strawberry as we add CDs. They just the files, do a random sort and pull the top 200. This will use any .m3u in .../playlists_base/ and make a daily file from it:

#!/bin/bash

#scp&nbsp;xrayspx@pro:~/.config/Clementine/clementine.db&nbsp;/var/tmp/

###&nbsp;Switching&nbsp;between&nbsp;Clementine&nbsp;and&nbsp;Strawberry&nbsp;###
#cp&nbsp;/Volumes/Filestore/CDs/playlists_base/clementine.db&nbsp;/var/tmp/

cp&nbsp;/Volumes/Filestore/CDs/playlists_base/strawberry.db&nbsp;/var/tmp/

/home/xrayspx/bin/3-star-playlist.sh
/home/xrayspx/bin/4-star-playlist.sh
/home/xrayspx/bin/5-star-playlist.sh
/home/xrayspx/bin/get-the-led-out.sh

ls&nbsp;/Volumes/Filestore/CDs/playlists_base/*.m3u&nbsp;>&nbsp;/Volumes/Filestore/CDs/playlists_base/m3us.txt

while&nbsp;IFS=&nbsp;read&nbsp;-r&nbsp;file
do

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filename=$(echo&nbsp;$file&nbsp;|&nbsp;awk&nbsp;-F&nbsp;"/Volumes/Filestore/CDs/playlists_base/"&nbsp;'{print&nbsp;$2}')

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;Filename:&nbsp;$file

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;"$file.full"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;"$file.scratch"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;"/Volumes/Filestore/CDs/playlists/$filename"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;###Testing&nbsp;a&nbsp;change&nbsp;since&nbsp;Strawberry&nbsp;creates&nbsp;playlists&nbsp;without&nbsp;EXTINF&nbsp;lines&nbsp;###
#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array=`grep&nbsp;EXTINF&nbsp;"$file"&nbsp;|&nbsp;sort&nbsp;|&nbsp;uniq`
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;array=`grep&nbsp;-v&nbsp;EXTINF&nbsp;"$file"&nbsp;|&nbsp;sort&nbsp;|&nbsp;uniq`

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf&nbsp;'%s\n'&nbsp;"${array[@]}"&nbsp;|&nbsp;sort&nbsp;-R&nbsp;>&nbsp;"$file.full"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;head&nbsp;-n&nbsp;200&nbsp;"$file.full"&nbsp;>&nbsp;"/Volumes/Filestore/CDs/playlists_base/$filename.scratch"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n=0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;IFS=&nbsp;read&nbsp;-r&nbsp;extinfo
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do
#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;$extinfo
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;term=`echo&nbsp;$extinfo`&nbsp;#&nbsp;|&nbsp;cut&nbsp;-d&nbsp;","&nbsp;-f&nbsp;2-`
#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;$term

&nbsp;###Testing&nbsp;a&nbsp;change&nbsp;since&nbsp;Strawberry&nbsp;creates&nbsp;playlists&nbsp;without&nbsp;EXTINF&nbsp;lines&nbsp;###
&nbsp;#&nbsp;grep&nbsp;-A&nbsp;1&nbsp;-m&nbsp;1&nbsp;"$term"&nbsp;"$file"&nbsp;>>&nbsp;"/Volumes/Filestore/CDs/playlists/$filename"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;grep&nbsp;-m&nbsp;1&nbsp;"$term"&nbsp;"$file"&nbsp;>>&nbsp;"/Volumes/Filestore/CDs/playlists/$filename"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;done&nbsp;<&nbsp;"$file.scratch"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;"$file.full"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rm&nbsp;"$file.scratch"

done&nbsp;<&nbsp;/Volumes/Filestore/CDs/playlists_base/m3us.txt

rm&nbsp;/var/tmp/clementine.db
rm&nbsp;/var/tmp/strawberry.db

For TV shows it's a bit more complicated. I've got individual scripts for things like Sitcoms, Saturday Morning Cartoons, Buddy-Cop shows, Nick-at-Nite, etc. Each script uses a text file which just lists the relative path to the directories I want to randomize. I just read in that text file then scan each directory and build an array that again I sort -R and dump in an m3u. You'll see a couple of my conventions here, like the "dvd_extras" folders I use for any extras that I want to keep but don't want to have show up in the mix, as well as a bunch of other crap I grep out.

This script references "./.sitcoms.txt", which looks like this:

./Archer (2009)
./30 Rock
./Absolutely Fabulous
./Alexei Sayle's Stuff
#!&nbsp;/bin/bash

array=$(
while&nbsp;read&nbsp;line
do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;find&nbsp;"$line"&nbsp;-type&nbsp;f;
done&nbsp;&lt;&nbsp;.sitcoms.txt
)

printf&nbsp;'%s\n'&nbsp;"${array[@]}"&nbsp;|&nbsp;sort&nbsp;-R&nbsp;|&nbsp;grep&nbsp;-v&nbsp;-w&nbsp;"batch"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;dvd_extras&nbsp;|&nbsp;grep&nbsp;-v&nbsp;"./$"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;"\.m3u"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;-i&nbsp;ds_store&nbsp;|
&nbsp;grep&nbsp;-v&nbsp;"\.nzb"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;"\.nfo"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;"\.sub"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;"\.sfv"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;"\.srt"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;-i&nbsp;"\.ifo"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;-i&nbsp;"\.idx"&nbsp;|
&nbsp;sed&nbsp;'s/^/..\//'&nbsp;>&nbsp;./1\&nbsp;-\&nbsp;Playlists/Sitcoms.m3u

This dumps out to a folder called "1 - Playlists" inside my TV Shows directory, just so it shows up first. There's a folder in there for Blocks as well, in which I create blocks of 10 random episodes of a bunch of shows. This is built to replicate like TBS/TNT/USA in the evening where you just sit and watch a block of whatever is on. In practice I do this wrong and tend to be too picky about these and just watch blocks until I've worked my way through a whole series and wind up tired of it forever.

One thing I do for things like Nick at Nite and overall Sitcom lists and stuff is that I mix in commercials. I don't do this very well though, I just treat my directory of commercials like any other TV show. I'd rather do "pull a TV show, toss in two commercials, repeat", but I'm not there yet I guess.

The last type of lists I build are for music videos. I break this into a few different playlists, one overall catchall that pulls in all videos, a playlist for MTV 120 Minutes, and one for "Arcade / Pizzeria" music. Basically the ubiquitous music you'd hear in a pizza shop or arcade in the '80s or '90s. I do the same commercial thing here as well.

Example:

#!&nbsp;/bin/bash

array=`find&nbsp;../120\&nbsp;Minutes&nbsp;-type&nbsp;f;
find&nbsp;../../../Commercials&nbsp;-type&nbsp;f`

printf&nbsp;'%s\n'&nbsp;"${array[@]}"&nbsp;|&nbsp;sort&nbsp;-R&nbsp;|&nbsp;grep&nbsp;-v&nbsp;dvd_extras&nbsp;|&nbsp;grep&nbsp;-v&nbsp;"./$"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;"ERRORS$"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;"\.sh"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;"\.m3u"&nbsp;|
&nbsp;grep&nbsp;-v&nbsp;-i&nbsp;ds_store&nbsp;|&nbsp;grep&nbsp;-v&nbsp;".nzb"&nbsp;|&nbsp;grep&nbsp;-v&nbsp;".srt"&nbsp;>&nbsp;120\&nbsp;Minutes.m3u

xrayspx's picture

Community? What's that?

Music: 

Jack Burton and the Lo Pans

I've had a bunch of people suggest that I post "content" and be a "YouTuber" and join the Retro Community and whatever.

I have never been interested in any community aspect to the Internet which doesn't involve face to face hacking on cool shit and putting it on the Internet. I can do that here and I really don't care about "engagement", "views", other people's opinions, or any of the rest. This is because I have no interest in dealing with the noise generated by other humans.

xrayspx's picture

Lattice of Convenience - MP3 Playlists

Music: 

Underworld - Kittens

Hopefully everyone can live in the future someday.

We do a lot with MP3 playlists. I run Airsonic for streaming around the house and in the car, and we have a playlist-based FM transmitter setup, etc. So I have scripts which run every night and generate playlists based on star ratings and other things (GET THE LED OUT ANYONE?).

Previously what I've done is dump the contents of a bunch of Smart Playlists in Clementine to a file and use those files to generate the randomized 200 track daily playlists. The downside to that is that every time I add music or change star ratings, I'd have to refresh these "base" files like some kind of animal. I had base playlists for "3+ stars", "4+ Stars" and "5 Stars", among others.

Today I decided to fix all that. Clementine uses a SQLite3 database, so now I'm just querying it instead, and it seems to be working well. For example, my "5 star" playlist in Clementine results in 10800 or so tracks. The same one built from the DB ends up with a couple hundred more tracks, but is pretty close. I'm not entirely sure what the difference there is just yet, but "close enough". What it looks like to me is I probably need to enable Samba case sensitivity.

The DB records ratings as decimal numbers from 0.0 (Zero stars) through 1.0 (5 Stars). So to build a "4-Star +" playlist, searching for rating >= "0.8", you get ratings like this:

1
1.10000002384186
0.800000011920929
0.800000011920929
0.800000011920929
1.10000002384186
1.10000002384186
0.800000011920929
0.800000011920929
1
1
1
1

! Caveat: Prior to Clementine 1.4.0rc1-533-gf4e70face there was a bug where it was possible to give a song a higher than 5 star rating (higher than 1.0 in the DB) as you can see above, so know that if you have Clementine from the repositories, it's likely you have that bug. For instance in the UI, if you want to show all 5 star songs, use "Rating is Greater Than 4.5 Stars" rather than "Rating is Equal to 5 Stars".

Now I can just have a cron job to copy the master Clementine DB once a day to my server and drop it in next to the playlist generation scripts.

The downside to all this is speed. When using the Clementine-Generated base playlists, I could be sure all the files actually exist on disk. However while Clementine will only show you files that exist in the UI, it doesn't seem to do a very good job of cleaning the database of stale files which no longer exist. So if you move or rename files, the old DB entries stick around unless you purge it completely and start over from scratch. That means I have to test every single file as I add it to the playlist, which takes time. It takes about 5-8 seconds to generate my 200 track 5-Star M3U file.

The 5-Star.sh script is below if you'd like to play along at home:

  

#!/bin/bash

rm /Volumes/Filestore/CDs/playlists/5\ Stars.m3u

i=1

while [ $i -le 200 ]
do
&nbsp;file=$(sqlite3 ./clementine.db "select filename from songs where rating > "0.9" order by random() limit 1;" | awk -F "file://" '{print $2}')

&nbsp;### Clementine data encodes special characters and accent marks and stuff so I'm using
&nbsp;### Joel Parker Henderson's urldecode.sh to undo that: https://gist.github.com/cdown/1163649
&nbsp;
&nbsp;data=$(urldecode.sh "$file")
&nbsp;if [ -f "$data" ]
&nbsp;then
&nbsp;&nbsp;### Have to escape leading brackets because grep treated it as a range and would allow duplicates ###
&nbsp;&nbsp;### Can't do that in "data" because \[ isn't in the filename so they'll fail ###

&nbsp;&nbsp;escaped=$(echo "$data" | sed 's/\[/\\[/g')
&nbsp;&nbsp;#echo "$escaped"

&nbsp;&nbsp;### Avoid duplicates
&nbsp;&nbsp;match=$(grep -i "$escaped" /Volumes/Filestore/CDs/playlists/5\ Stars.m3u)
&nbsp;&nbsp;if [ -z "$match" ]
&nbsp;&nbsp;then
&nbsp;&nbsp;&nbsp;echo "$data" >> /Volumes/Filestore/CDs/playlists/5\ Stars.m3u
&nbsp;&nbsp;&nbsp;((i++))
&nbsp;&nbsp;fi
&nbsp;fi
done

For the 3+ and 4+ lists, I repeat this main block, but instead each rating dumps into a text file that I randomize into an .m3u at the end. So for the 3-Star + script below, I collect 130 5-star tracks, 45 4-star, and 25 3-star, push them out to a temp file and then cat temp.m3u | sort -R > "./3 Star +.m3u". I could do all this by creating a new table in the database and stuffing tracks into that, but this was faster for me to write and it works well enough:

#!/bin/bash

rm /Volumes/Filestore/CDs/playlists/3\ Stars\ +.m3u

i=1

while [ $i -le 130 ]
do
&nbsp;file=$(sqlite3 ./clementine.db "select filename from songs where rating > "0.9" order by random() limit 1;" | awk -F "file://" '{print $2}')

&nbsp;### Clementine data encodes special characters and accent marks and stuff so I'm using
&nbsp;### Joel Parker Henderson's urldecode.sh to undo that: https://gist.github.com/cdown/1163649
&nbsp;
&nbsp;data=$(urldecode.sh "$file")
&nbsp;if [ -f "$data" ]
&nbsp;then
&nbsp;&nbsp;### Have to escape leading brackets because grep treated it as a range and would allow duplicates ###
&nbsp;&nbsp;### Can't do that in "data" because \[ isn't in the filename so they'll fail ###

&nbsp;&nbsp;escaped=$(echo "$data" | sed 's/\[/\\[/g')
&nbsp;&nbsp;#echo "$escaped"

&nbsp;&nbsp;### Avoid duplicates
&nbsp;&nbsp;match=$(grep -i "$escaped" ./3-star-tmp.m3u)
&nbsp;&nbsp;if [ -z "$match" ]
&nbsp;&nbsp;then
&nbsp;&nbsp;&nbsp;echo "$data" >> ./3-star-tmp.m3u
&nbsp;&nbsp;&nbsp;((i++))
&nbsp;&nbsp;fi
&nbsp;fi
done

i=1

while [ $i -le 45 ]
do
&nbsp; file=$(sqlite3 ./clementine.db "select filename from songs where rating >= "0.8" and rating < "1" order by random() limit 1;" | awk -F "file://" '{print $2}')

&nbsp; ### Clementine data encodes special characters and accent marks and stuff so I'm using
&nbsp; ### Joel Parker Henderson's urldecode.sh to undo that: https://gist.github.com/cdown/1163649

&nbsp; data=$(urldecode.sh "$file")
&nbsp; if [ -f "$data" ]
&nbsp; then
&nbsp;&nbsp;  ### Have to escape leading brackets because grep treated it as a range and would allow duplicates ###
&nbsp;&nbsp;  ### Can't do that in "data" because \[ isn't in the filename so they'll fail ###

&nbsp;&nbsp;  escaped=$(echo "$data" | sed 's/\[/\\[/g')
&nbsp;&nbsp;  #echo "$escaped"

&nbsp;&nbsp;  ### Avoid duplicates
&nbsp;&nbsp;  match=$(grep -i "$escaped" ./3-star-tmp.m3u)
&nbsp;&nbsp;  if [ -z "$match" ]
&nbsp;&nbsp;  then
&nbsp;&nbsp;&nbsp;   echo "$data" >> ./3-star-tmp.m3u
&nbsp;&nbsp;&nbsp;   ((i++))
&nbsp;&nbsp;  fi
&nbsp; fi
done

i=1

while [ $i -le 25 ]
do
&nbsp; file=$(sqlite3 ./clementine.db "select filename from songs where rating >= "0.6" and rating < "0.8" order by random() limit 1;" | awk -F "file://" '{print $2}')

&nbsp; ### Clementine data encodes special characters and accent marks and stuff so I'm using
&nbsp; ### Joel Parker Henderson's urldecode.sh to undo that: https://gist.github.com/cdown/1163649

&nbsp; data=$(urldecode.sh "$file")
&nbsp; if [ -f "$data" ]
&nbsp; then
&nbsp;&nbsp;  ### Have to escape leading brackets because grep treated it as a range and would allow duplicates ###
&nbsp;&nbsp;  ### Can't do that in "data" because \[ isn't in the filename so they'll fail ###

&nbsp;&nbsp;  escaped=$(echo "$data" | sed 's/\[/\\[/g')
&nbsp;&nbsp;  #echo "$escaped"

&nbsp;&nbsp;  ### Avoid duplicates
&nbsp;&nbsp;  match=$(grep -i "$escaped" ./3-star-tmp.m3u)
&nbsp;&nbsp;  if [ -z "$match" ]
&nbsp;&nbsp;  then
&nbsp;&nbsp;&nbsp;   echo "$data" >> ./3-star-tmp.m3u
&nbsp;&nbsp;&nbsp;   ((i++))
&nbsp;&nbsp;  fi
&nbsp; fi
done

cat ./3-star-tmp.m3u | sort -R > /Volumes/Filestore/CDs/playlists/3\ Stars\ +.m3u

rm ./3-star-tmp.m3u

xrayspx's picture

Sharp Boombox Repair

Music: 

Tom Petty - Freefallin'

Pages

Subscribe to RSS - Music