diff --git a/mp_suggest.hy b/mp_suggest.hy index b4e21a5..ee014c3 100755 --- a/mp_suggest.hy +++ b/mp_suggest.hy @@ -19,6 +19,15 @@ (print (.format "mp_suggest (hy version {})" *version*)) (sys.exit 0)) +(defn print-help [] + (print "Usage:") + (ap-each optlist (print (.format " -{} --{} {}" (get it 0) (get it 1) (get it 3)))) + (sys.exit 0)) + +; Given a set of command-line arguments, compare that to a mapped +; version of the optlist and return a canonicalized dictionary of all +; the arguments that have been set. + (defn find-opt-reducer [acc it] (let [[(, o a) it] [optmap (ap-reduce (do (assoc acc (+ "-" (. it [0])) (. it [1])) acc) optlist {})]] @@ -27,6 +36,10 @@ (assoc acc full (if hasargs a true)))) acc)) +; Assuming the directory name looked like "Artist - Album", return the +; two names separately. If only one name is here, assume a compilation +; or mixtape album and default to "VA" (Various Artists). + (defn artist-album [] (let [[aa (.split (. (.split (.getcwd os) "/") [-1]) " - ")] [sp (fn [i] (.strip i))]] @@ -34,6 +47,10 @@ (, "VA" (get aa 0)) (, (sp (get aa 0)) (sp (get aa 1)))))) +; A long list of substitutions intended to turn a filename into a +; human-readable strategy. This operation is the result of weeks +; of experimentation. Doubt it at your peril! :-) + (defn title-strategy [orig] (->> (.strip orig) (.sub re "\.[Mm][Pp]3$" "") @@ -43,33 +60,41 @@ (.sub re "^[\d\. ]+" "") (.sub re ".* \d{2} " ""))) -(defn derive-tags [mp3s] - (defn derive-tag [pos mp3] - (try - (let [[tag (.Tag eyeD3)]] - (tag.link mp3) - (, mp3 (str (.getArtist tag)) (str (.getAlbum tag)) - (str (.getGenre tag)) (str (.getTitle tag)) pos)) - (catch [err] - (, mp3 "" "" "" "")))) - (ap-map (apply derive-tag it) mp3s)) +; Given a list of mp3s, derive the list of ID3 tags. Obviously, +; filesystem access is a point of failure, but this is mostly +; reliable. -(defn print-help [] - (print "Usage:") - (ap-each optlist (print (.format " -{} --{} {}" (get it 0) (get it 1) (get it 3)))) - (sys.exit 0)) + +(defn tag-deriver [usefilenames] + (fn [mp3s] + (defn derive-tag [pos mp3] + (try + (let [[tag (.Tag eyeD3)]] + (tag.link mp3) + (, mp3 (str (.getArtist tag)) (str (.getAlbum tag)) + (str (.getGenre tag)) (str (.getTitle tag)) pos)) + (catch [err] + (, mp3 "" "" "" "")))) + (ap-map (apply derive-tag it) mp3s))) + +; For removing subgenre parentheses. This is why there's the -g option. (defn clean-paren [s] (if (not (= (.find s "(") -1)) (.sub re "\(.*?\)" "" s) s)) +; My FAT-32 based file store via Samba isn't happy with unicode, so +; this is here... + (defn is-ascii [s] (= (.decode (.encode s "ascii" "ignore") "ascii") s)) (defn ascii-or-nothing [s] (if (is-ascii s) s "")) - + +; For all the songs, analyze a consist entry (usually genre and album +; names), and return the one with the most votes. (defn find-likely [l] (let [[cts @@ -85,6 +110,9 @@ "" (get (get cts 0) 1)))) +; Auto-capitalize "found" entries like album name and title. Will not +; affect manually set entries. + (defn sfix [s] (let [[seq (.split (.strip s))]] (smart_str (string.join (ap-map (.capitalize it) seq) " ")))) @@ -95,7 +123,7 @@ (ap-filter (and (> (len it) 4) (= (slice (.lower it) -4) ".mp3"))) (sorted) (enumerate) - (derive-tags) + ((tag-deriver true)) (list))] [(, loc_artist loc_album) (artist-album)] diff --git a/mp_suggest_man.tex b/mp_suggest_man.tex index fc2899f..ba2a219 100644 --- a/mp_suggest_man.tex +++ b/mp_suggest_man.tex @@ -59,6 +59,9 @@ the details of all the MP3 files to match your specifications. The commands can be tweaked, and all of them override the techniques \Prog{mp\_suggest} uses to derive information. +This is probably completely idiosyncratic to the way I do things in my +own music archive, but as an exercise in writing Hy, it was fun. + \section{Requirements} %%%%%%%%%%%%%%%%%%%%%%