largely works; annoying problems remain
This commit is contained in:
parent
03f0b12ea9
commit
cc28c85b38
1 changed files with 108 additions and 24 deletions
128
hsmusic.lisp
128
hsmusic.lisp
|
@ -1,29 +1,69 @@
|
||||||
(ql:quickload '(:cl-yaml :alexandria :cl-ppcre))
|
(ql:quickload '(:alexandria :cl-yaml :cl-json :yason))
|
||||||
(defpackage :hsmusic
|
(defpackage :hsmusic
|
||||||
(:use :common-lisp :alexandria))
|
(:use :common-lisp :alexandria))
|
||||||
(in-package :hsmusic)
|
(in-package :hsmusic)
|
||||||
|
|
||||||
|
(defpackage :track)
|
||||||
|
|
||||||
(defparameter tracks
|
(defparameter tracks
|
||||||
(loop for path in (directory #p"hsmusic-data/album/*.yaml")
|
(loop for path in (directory #p"hsmusic-data/album/*.yaml")
|
||||||
appending (loop for entry in (yaml:parse path :multi-document-p t)
|
appending
|
||||||
|
(let* ((parsed (yaml:parse path :multi-document-p t))
|
||||||
|
(album (gethash "Album" (cadr parsed))))
|
||||||
|
(loop for entry in parsed
|
||||||
when (and (not (symbolp entry)) (gethash "Track" entry))
|
when (and (not (symbolp entry)) (gethash "Track" entry))
|
||||||
collect entry)))
|
collect (progn (setf (gethash "Album" entry) album)
|
||||||
|
entry)))))
|
||||||
|
|
||||||
|
(defun tracks-with-name (name)
|
||||||
|
(loop for track in tracks
|
||||||
|
when (equal name (gethash "Track" track))
|
||||||
|
collect track))
|
||||||
|
|
||||||
|
; does a macro really make sense like come on
|
||||||
|
; w/e
|
||||||
|
(defmacro apply-regices (target &body regices)
|
||||||
|
(with-gensyms (new)
|
||||||
|
`(let ((,new (copy-array ,target)))
|
||||||
|
,@(loop for (from to) in regices
|
||||||
|
collecting `(setf ,new (ppcre:regex-replace-all ,from ,new ,to)))
|
||||||
|
,new)))
|
||||||
|
|
||||||
|
(defun default-href (name)
|
||||||
|
(apply-regices (string-downcase name)
|
||||||
|
(" " "-")
|
||||||
|
|
||||||
|
("&" "-and-")
|
||||||
|
("\\+" "-plus-")
|
||||||
|
("%" "-percent-")
|
||||||
|
|
||||||
|
("(\\b[^\\s-.]{2,})\\." "\\1-")
|
||||||
|
("/\\.([^\\s-.]{2,})\\b" "-\\1")
|
||||||
|
|
||||||
|
("[/@#$%*()_=,[\\]{}|\\\\;:<>?`~]" "-")
|
||||||
|
|
||||||
|
("[áâäàå]" "a")
|
||||||
|
("[çč]" "c")
|
||||||
|
("[éêëè]" "e")
|
||||||
|
("[íîïì]" "i")
|
||||||
|
("[óôöò]" "o")
|
||||||
|
("[úûüù]" "u")
|
||||||
|
|
||||||
|
("[^a-z0-9-]" "")
|
||||||
|
|
||||||
|
("-{2,}" "-")
|
||||||
|
|
||||||
|
("^-+|-+$" "")))
|
||||||
|
|
||||||
; terrible, idc
|
|
||||||
; lossy! (not surprising)
|
|
||||||
; upcase for nice interning
|
|
||||||
(defun track->href (track)
|
(defun track->href (track)
|
||||||
(or (gethash "Directory" track)
|
(or (gethash "Directory" track)
|
||||||
(let ((r (copy-array (gethash "Track" track))))
|
(default-href (gethash "Track" track))))
|
||||||
(setf r (ppcre:regex-replace-all " " r "-"))
|
|
||||||
(setf r (ppcre:regex-replace-all "&" r "and"))
|
(defun href->url (href)
|
||||||
(setf r (ppcre:regex-replace-all "[^a-zA-Z0-9-]" r ""))
|
(format nil "https://hsmusic.wiki/track/~a" href))
|
||||||
(setf r (ppcre:regex-replace-all "-{2,}" r ""))
|
|
||||||
(setf r (ppcre:regex-replace-all "^-+|-+$" r ""))
|
|
||||||
(nstring-downcase r))))
|
|
||||||
|
|
||||||
(defun track->url (track)
|
(defun track->url (track)
|
||||||
(format nil "https://hsmusic.wiki/track/~a" (track->href track)))
|
(href->url (track->href track)))
|
||||||
|
|
||||||
; let's just store the href because that's unambiguous and links are desirable anyway
|
; let's just store the href because that's unambiguous and links are desirable anyway
|
||||||
|
|
||||||
|
@ -32,8 +72,26 @@
|
||||||
; there's ambiguity here! so consult only when not given a track:!
|
; there's ambiguity here! so consult only when not given a track:!
|
||||||
(defparameter hrefs (make-hash-table :test 'equal))
|
(defparameter hrefs (make-hash-table :test 'equal))
|
||||||
|
|
||||||
|
; TODO: logically flawed
|
||||||
|
(defparameter href->track-table (make-hash-table))
|
||||||
|
|
||||||
(loop for track in tracks
|
(loop for track in tracks
|
||||||
do (setf (gethash (gethash "Track" track) hrefs) (track->href track)))
|
; works? no. e.g. Buy NAK Sell DOOF has a Directory but is referred to without track:
|
||||||
|
; track: is a disambiguator
|
||||||
|
; how do we decide which one is "canon" then? idk! no clue. help
|
||||||
|
; tomorrow problem
|
||||||
|
unless (gethash "Directory" track)
|
||||||
|
do (let ((href (intern (track->href track) :track)))
|
||||||
|
(setf (gethash (gethash "Track" track) hrefs) href)
|
||||||
|
(setf (gethash href href->track-table) track)))
|
||||||
|
|
||||||
|
(defun track-name->href (name)
|
||||||
|
(if (string= (ignore-errors (subseq name 0 6)) "track:")
|
||||||
|
(intern (subseq name 6) :track)
|
||||||
|
(gethash name hrefs)))
|
||||||
|
|
||||||
|
(defun href->track (href)
|
||||||
|
(gethash href href->track-table))
|
||||||
|
|
||||||
; a -> b <-> a references b
|
; a -> b <-> a references b
|
||||||
; screw it! let's use symbols. why not? (LKFDSJKFDJ)
|
; screw it! let's use symbols. why not? (LKFDSJKFDJ)
|
||||||
|
@ -42,13 +100,15 @@
|
||||||
(defparameter <- (make-hash-table))
|
(defparameter <- (make-hash-table))
|
||||||
|
|
||||||
(loop for track in tracks
|
(loop for track in tracks
|
||||||
do (let ((from-name (intern (track-normalized-name track) :keyword)))
|
do (let ((from-name (intern (track->href track) :track)))
|
||||||
(loop for ref in (append (gethash "Referenced Tracks" track) (gethash "Sampled Tracks" track))
|
(loop for ref in (append (gethash "Referenced Tracks" track) (gethash "Sampled Tracks" track))
|
||||||
do (let ((to-name (intern (normalize-name ref) :keyword)))
|
do (let ((to-name (track-name->href ref)))
|
||||||
; bodge
|
(when (not to-name) (print ref))
|
||||||
(unless (eq from-name to-name)
|
(if (eq from-name to-name)
|
||||||
|
(format t "https://hsmusic.wiki/track/~a~%" from-name)
|
||||||
|
(progn
|
||||||
(unionf (gethash from-name ->) (list to-name))
|
(unionf (gethash from-name ->) (list to-name))
|
||||||
(unionf (gethash to-name <-) (list from-name)))))))
|
(unionf (gethash to-name <-) (list from-name))))))))
|
||||||
|
|
||||||
(defun tree (src from depth)
|
(defun tree (src from depth)
|
||||||
(let ((succs (gethash from src)))
|
(let ((succs (gethash from src)))
|
||||||
|
@ -57,10 +117,10 @@
|
||||||
from)))
|
from)))
|
||||||
|
|
||||||
(defun ->tree (from depth)
|
(defun ->tree (from depth)
|
||||||
(tree -> from depth))
|
(tree -> (track-name->href from) depth))
|
||||||
|
|
||||||
(defun <-tree (from depth)
|
(defun <-tree (from depth)
|
||||||
(tree <- from depth))
|
(tree <- (track-name->href from) depth))
|
||||||
|
|
||||||
(defun pp-tree (tree &key (stream t) (indent 0) (indent-increment 2))
|
(defun pp-tree (tree &key (stream t) (indent 0) (indent-increment 2))
|
||||||
(let ((ind (make-string indent :initial-element #\ )))
|
(let ((ind (make-string indent :initial-element #\ )))
|
||||||
|
@ -72,3 +132,27 @@
|
||||||
do (pp-tree to :stream stream
|
do (pp-tree to :stream stream
|
||||||
:indent (+ indent indent-increment)
|
:indent (+ indent indent-increment)
|
||||||
:indent-increment indent-increment))))))
|
:indent-increment indent-increment))))))
|
||||||
|
|
||||||
|
(defun archive (url)
|
||||||
|
(sb-ext:run-program
|
||||||
|
"/usr/bin/env"
|
||||||
|
(list "curl" "--insecure" "-F" (format nil "url=~a" "url=") "-F" "capture_all=on" url)))
|
||||||
|
|
||||||
|
(defparameter exif (yason:parse #p"/home/mbk/Music/exif-data.json"))
|
||||||
|
|
||||||
|
(defun track->path (track)
|
||||||
|
(loop for e in exif
|
||||||
|
when (and (equal (gethash "Title" e) (gethash "Track" track))
|
||||||
|
(equal (gethash "Album" e) (gethash "Album" track)))
|
||||||
|
do (return-from track->path (pathname (gethash "SourceFile" e)))))
|
||||||
|
|
||||||
|
; TODO: <- & higher-order
|
||||||
|
; reversed bc personal preference :]
|
||||||
|
(defun ->m3u (from &optional (depth 413) (stream t))
|
||||||
|
(dolist (href (reverse (flatten (->tree from depth))))
|
||||||
|
(let ((path (track->path (href->track href))))
|
||||||
|
(when path (format stream "~a~%" path)))))
|
||||||
|
|
||||||
|
(defun ->link-list (from &optional (depth 413) (stream t))
|
||||||
|
(dolist (href (reverse (flatten (->tree from depth))))
|
||||||
|
(format stream "~a~%" (href->url href))))
|
||||||
|
|
Loading…
Reference in a new issue