#!/usr/opt/bin/tclsh
if {$argc!=1} {puts "Usage: $argv0 Dir - generates Dir/index.sqlite"; exit}
set Dir [lindex $argv 0]
if {![file isdirectory $Dir]} {puts "argument must be a directory"; exit}
set DB $Dir/index.sqlite
if {[file exists $DB]} {puts "$DB exists"; exit}
package require sqlite3
sqlite3 db $DB
db eval {PRAGMA foreign_keys = ON}
proc match {x y} {return [regexp "^$y/.*" $x]}
db function match -argcount 2 -deterministic {match}
db eval {
CREATE TABLE track(
trid INTEGER PRIMARY KEY, -- "Track ID"
nid TEXT, -- / separated two digit numbers for entering with keyboard
trp TEXT, -- real path in file system of an audio file (track)
trtxt TEXT, -- description of the audio file (track)
cdid REFERENCES cd(cdid) ON UPDATE CASCADE ON DELETE RESTRICT
);
CREATE TABLE cd(
cdid INTEGER PRIMARY KEY, -- "CD ID"
cdp TEXT UNIQUE, -- path to directory containing CD or CD collections
cdtxt TEXT -- description of audio files under cdp
);
CREATE VIEW conc AS SELECT * FROM track LEFT OUTER JOIN cd USING (cdid);
}
# cd contains the paths under 'base' containing files named 'Desc'
proc mkcd {base rpath} {
set apath [file join $base $rpath]
if {[file isfile $apath] && [file tail $apath] eq "Desc"} {
set fd [open $apath r]; set txt [read $fd]; close $fd
set rdir [file dirname $rpath]
db eval {INSERT INTO cd (cdp, cdtxt) VALUES (:rdir, :txt)}
return 1}
if {[file isdirectory $apath]} {
foreach file [lsort [glob -nocomplain -tails -directory $apath *]] {
mkcd $base [file join $rpath $file]}}}
# track contains paths trp to audiofiles (.wav, .mp3),
# cdid points to innermost path from cd containing the file below it,
# trtxt is not jet filled.
proc mktrack {base rpath nid} {
set apath [file join $base $rpath]
if {[file isfile $apath]} {
if {[regexp {.*\.wav$|.*\.mp3$} $apath]} {
set cdid [db onecolumn {SELECT max(cdid) FROM cd WHERE cdp MATCH :rpath}]
if {[string is integer -strict $cdid]} {
db eval {INSERT INTO track (nid, trp, cdid) VALUES (:nid, :rpath, :cdid)}
} else {
db eval {INSERT INTO track (nid, trp) VALUES (:nid, :rpath)}}
return 1} else {return 0}}
if {[file isdirectory $apath]} {
if {$nid eq ""} {set nid 01} else {set nid "$nid/01"}
foreach file [lsort [glob -nocomplain -tails -directory $apath *]] {
if {[mktrack $base [file join $rpath $file] $nid]} {
set nid [split $nid /]
regsub "^0*" [lindex $nid end] "" n
incr n; set n [format %02d $n]
set nid [join [lreplace $nid end end $n] /]}}
return 1}}
mkcd $Dir ""
mktrack $Dir "" ""
db close