From: Clinton Ebadi Date: Thu, 12 Dec 2013 18:52:27 +0000 (-0500) Subject: Merge remote-tracking branch 'trunk' X-Git-Url: https://git.hcoop.net/clinton/abcde.git/commitdiff_plain/e1b59b02e02ef1b397d3c09c633f83c5a83af5fb?hp=fbedbd330d97561b6ea2d0534ffa0163ce0a2a48 Merge remote-tracking branch 'trunk' --- diff --git a/abcddb-tool b/abcddb-tool new file mode 100755 index 0000000..218e75a --- /dev/null +++ b/abcddb-tool @@ -0,0 +1,138 @@ +#!/usr/bin/guile -s +!# + +;;; -*- scheme -*- + +;;; Parse for enhanced XMCD. Original format: http://ftp.freedb.org/pub/freedb/latest/DBFORMAT + +(use-modules (ice-9 format) + (ice-9 rdelim) + (ice-9 streams) + (ice-9 regex) + (ice-9 vlist) + + (srfi srfi-1)) + +;;; VList/VHash utility functions + +(define (vhash-cat key new-value vhash) + "Add NEW-VALUE to the VList stored under VHASH.KEY" + (vhash-set key (vlist-append (let ((lst (vhash-assoc key vhash))) + (if lst (cdr lst) vlist-null)) + (vlist-cons new-value vlist-null)) + vhash)) + +(define (vhash-set key new-value vhash) + (vhash-cons key new-value (vhash-delete key vhash))) + + +;;; Simple key/value database for cddb and toc info + +;;; DO NOT RELY ON THE IMPLEMENTATION, it sucks. Always use the query +;;; functions. The disc query functions return the list of values, the +;;; track query functions return an alist of (track-num +;;; . values). Values are always plural, just grab the car if you want +;;; a single value. It's not the best interface, but it sure beats +;;; grepping the xmcd file! + +(define (make-initial-db . toplevel-keys) + (fold (lambda (key db) (vhash-cons key vlist-null db)) vlist-null toplevel-keys)) + +(define (cddb-query-disc db tag) + "Query the database for a disc attribute" + (let ((result (vhash-assoc tag (cdr (vhash-assoc 'disc db))))) + (if result (vlist->list (cdr result)) #f))) + +(define (cddb-query-tracks db tag) + "Query the database for a track attribute and return alist +of (disc-number . tag-value)" + (let ((r (vlist->list (vhash-fold (lambda (key vh results) + (let ((result (vhash-assoc tag vh))) + (if result + (vhash-cons key (vlist->list (cdr result)) results) + results))) + vlist-null + (cdr (vhash-assoc 'tracks db)))))) + (if (null? r) #f r))) + +(define (read-cddb cddb-port) + (define (parse-cddb-line line db) + (define (line-match regex) (string-match regex line)) + + (cond + ((line-match "^#(.*)$") => (lambda (x) (vhash-cat 'comment (match:substring x 1) db))) + ((line-match "^DISCID=([[:graph:]]+)$") => (lambda (x) (let ((disc-db (cdr (vhash-assoc 'disc db)))) + (vhash-set 'disc (vhash-cat 'DISCID (match:substring x 1) disc-db) + db)))) + ((line-match "^D([[:alpha:]]+)=([[:graph:][:space:]]+)$") => (lambda (x) + (let ((disc-db (cdr (vhash-assoc 'disc db))) + (key (string->symbol (match:substring x 1)))) + (vhash-set 'disc (vhash-cat key (match:substring x 2) disc-db) + db)))) + + ((line-match "^T([[:alpha:]]+)([[:digit:]]+)=([[:graph:][:space:]]+)$") + => (lambda (x) + (let* ((tracks-db (cdr (vhash-assoc 'tracks db))) + (tracknum (string->number (match:substring x 2))) + (tracknum-db ((lambda (vh) (if vh (cdr vh) vlist-null)) (vhash-assoc tracknum tracks-db))) + (key (string->symbol (match:substring x 1))) + (tag-value (match:substring x 3))) + (vhash-set 'tracks (vhash-set tracknum (vhash-cat key tag-value tracknum-db) + tracks-db) + db)))) + + ;; Also match EXTD? Might just punt if abcde handles it separately + (else db))) + + (stream-fold parse-cddb-line + (make-initial-db 'comment 'disc 'tracks) + (port->stream cddb-port read-line))) + +;;; Commands + +;; string-tokenize is weird, might want to just use regexeps instead +(define cddb-dtitle-char-set (char-set-difference char-set:printing + (char-set #\/))) + +(define* (cddb->export cddb #:optional (out (current-output-port))) + "Convert database to shell expression for abcde" + ;; Using single quoting instead of "" to make life easier + (letrec* ((escape-for-shell + (lambda (x) (regexp-substitute/global #f "['\\\\]" x + 'pre + (lambda (m) (string-append "\\" (match:substring m))) + 'post))) + (disc-query (lambda* (key #:optional (default '(""))) + (cond ((cddb-query-disc cddb key) => identity) + (else default)))) + + (artist ((lambda (s) (substring s 0 (- (string-index s #\/) 1))) (car (disc-query 'TITLE))) + + #;(string-trim-right (car (string-tokenize (car (disc-query 'TITLE)) cddb-dtitle-char-set)))) + + (album ((lambda (s) (substring s (+ (string-index s #\/) 2))) (car (disc-query 'TITLE))) + #;(string-trim (string-join (cdr (string-tokenize (car (disc-query 'TITLE)) cddb-dtitle-char-set)) + "/")))) + + + (newline out) + + ;; Not exported CDDBGENRE intentionally, since it appears unused + (format out "DISCID=$'~A'~%DALBUM=$'~A'~%DARTIST=$'~A'~%CDYEAR=$'~A'~%" + (escape-for-shell (car (disc-query 'DISCID))) + (escape-for-shell artist) + (escape-for-shell album) + (escape-for-shell (car (disc-query 'YEAR)))) + + ;; Store genre(s) in a bash array. mp3s will just have to live with + ;; using the first, but Vorbis/FLAC can handle an arbitrary set of + ;; genres + (format out "DGENRE=(~{$'~A' ~})~%" (map escape-for-shell (disc-query 'GENRE))) + + (format out "~:{TRACK~A=$'~A'~%~}" + (map (lambda (ttitle) (list (1+ (first ttitle)) (escape-for-shell (second ttitle)))) + (cddb-query-tracks cddb 'TITLE))))) + + + + diff --git a/abcde-musicbrainz-tool b/abcde-musicbrainz-tool index 4f2021b..a0a08ae 100644 --- a/abcde-musicbrainz-tool +++ b/abcde-musicbrainz-tool @@ -77,7 +77,9 @@ if ($command =~ m/^id/) { my @sums; foreach my $release (@releases) { + #print Dumper( $release->release_event_list() ); my $a_artist = $release->artist()->name(); + my $a_date = substr (@{$release->release_event_list()->events()}[0]->date(), 0, 4); my $va = 0; if ($a_artist =~ /Various Artists/) { $va = 1; @@ -104,7 +106,7 @@ if ($command =~ m/^id/) { print OUT "#CATEGORY=none\n"; print OUT "DISCID=" . $discid . "\n"; print OUT "DTITLE=" . $a_artist. " / " . $release->title() . "\n"; - print OUT "DYEAR=\n"; + print OUT "DYEAR=" . $a_date . "\n"; print OUT "DGENRE=\n"; my @tracks = @{$release->track_list()->tracks()}; @@ -119,7 +121,8 @@ if ($command =~ m/^id/) { } } - print OUT "EXTD=\n"; + print OUT "EXTD=barcode=" . @{$release->release_event_list()->events()}[0]->barcode() + . " catalognumber=" . @{$release->release_event_list()->events()}[0]->catalog_number() . "\n"; for (my $i = 0; $i < scalar(@tracks); $i++) { printf OUT "EXTT%d=\n", $i; }