# HG changeset patch # User darius # Date 965787527 0 # Node ID 74031379d3cb32a2e87bc734b36b9d5bbdef3adc # Parent 5cead4da1db9deacf9315a8579af8e7e3b7417df Initial revision diff -r 5cead4da1db9 -r 74031379d3cb cddb-id.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cddb-id.c Wed Aug 09 02:18:47 2000 +0000 @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int cddb_sum(int n); +unsigned long cddb_discid(int tot_trks, struct cd_toc_entry *cdtoc); +void usage(void); + +int +main(int argc, char **argv) +{ + int cd_fd, tot_tracks, i, machine, disc_length, tracknums; + unsigned long disc_id; + struct ioc_toc_header toc_head; + struct ioc_read_toc_entry toc_entries_head; + struct cd_toc_entry *toc_entries; + char cd_path[256], ch; + + /* Default CD path */ + strcpy(cd_path, "/dev/cd0c"); + + /* Default to human readable */ + machine = 0; + + /* Default to no track number stuff */ + tracknums = 0; + + while ((ch = getopt(argc, argv, "f:mhn")) != -1) { + switch(ch) { + case 'f': + if (strlen(optarg) > 255) { + warnx("Filename too long"); + exit(EX_USAGE); + } + + strcpy(cd_path, optarg); + break; + + case 'm': + machine = 1; + break; + + case 'n': + tracknums = 1; + break; + + case '?': + case 'h': + default: + usage(); + break; + } + } + + if ((cd_fd = open(cd_path, O_RDWR)) == -1) { + warnx("Failed to open %s, reason: %s", cd_path, strerror(errno)); + exit(EX_IOERR); + } + + if (ioctl(cd_fd, CDIOREADTOCHEADER, &toc_head) == -1) { + warnx("Failed to get TOC header, reason: %s", strerror(errno)); + exit(EX_UNAVAILABLE); + } + + tot_tracks = toc_head.ending_track - toc_head.starting_track + 1; + + toc_entries = (struct cd_toc_entry *)malloc(sizeof(struct cd_toc_entry) * (tot_tracks + 1)); + if (toc_entries == NULL) { + warnx("Couldn't allocate memeory for TOC entries"); + exit(EX_UNAVAILABLE); + } + + toc_entries_head.data = toc_entries; + toc_entries_head.data_len = sizeof(struct cd_toc_entry) * (tot_tracks + 1); + toc_entries_head.starting_track = 0; + toc_entries_head.address_format = CD_MSF_FORMAT; + + if (ioctl(cd_fd, CDIOREADTOCENTRYS, &toc_entries_head) == -1) { + warnx("Failed to get TOC entries, reason: %s\n", strerror(errno)); + exit(EX_UNAVAILABLE); + } + + if (tracknums) { + for (i = 1; i <= tot_tracks; i++) + if (!(toc_entries[i].control & 4)) + printf("%d ", i); + + printf("\n"); + + exit(0); + } + + disc_id = cddb_discid(tot_tracks, toc_entries); + disc_length = (toc_entries[tot_tracks].addr.msf.minute * 60) + + (toc_entries[tot_tracks].addr.msf.second); + + if (machine == 0) { + printf("Start track = %d, end track = %d, length = %d\n", toc_head.starting_track, + toc_head.ending_track, toc_head.len); + printf("Disc ID is %08x\n", disc_id); + printf("Length is %d seconds\n", disc_length); + } else { + printf("%08x", disc_id); + } + + for (i = 0; i < tot_tracks; i++) { + if (machine == 0) { + printf("Track %d, Minute = %d, Second = %d, Frame = %d, Type = %s, Offset = %d\n", + toc_entries[i].track, toc_entries[i].addr.msf.minute, + toc_entries[i].addr.msf.second, toc_entries[i].addr.msf.frame, + (toc_entries[i].control & 4) ? "data" : "audio", + (toc_entries[i].addr.msf.minute * 60 * 75) + + (toc_entries[i].addr.msf.second * 75) + + toc_entries[i].addr.msf.frame); + } else { + printf(" %d", (toc_entries[i].addr.msf.minute * 60 * 75) + + (toc_entries[i].addr.msf.second * 75) + + toc_entries[i].addr.msf.frame); + } + + } + + if (machine == 1) { + printf(" %d\n", disc_length); + } +} + +int +cddb_sum(int n) +{ + int ret; + + /* For backward compatibility this algorithm must not change */ + + ret = 0; + + while (n > 0) { + ret = ret + (n % 10); + n = n / 10; + } + + return (ret); +} + +unsigned long +cddb_discid(int tot_trks, struct cd_toc_entry *cdtoc) +{ + int i, + t = 0, + n = 0; + + /* For backward compatibility this algorithm must not change */ + + i = 0; + + while (i < tot_trks) { + n = n + cddb_sum((cdtoc[i].addr.msf.minute * 60) + + cdtoc[i].addr.msf.second); + i++; + } + t = ((cdtoc[tot_trks].addr.msf.minute * 60) + + cdtoc[tot_trks].addr.msf.second) - + ((cdtoc[0].addr.msf.minute * 60) + + cdtoc[0].addr.msf.second); + + return ((n % 0xff) << 24 | t << 8 | tot_trks); +} + +void +usage(void) +{ + printf("Usage:\n"); + printf("cddb-id [-f ] [-m]\n"); + printf(" is the cd device to use (Default: /dev/cd0c)\n"); + printf("-m causes machine readable output\n"); + exit(EX_USAGE); +} diff -r 5cead4da1db9 -r 74031379d3cb get_cdinfo.tcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/get_cdinfo.tcl Wed Aug 09 02:18:47 2000 +0000 @@ -0,0 +1,169 @@ +#!/bin/sh +# tcl magic \ +exec tclsh8.0 $0 $* + +# +# This software is copyright Daniel O'Connor (darius@dons.net.au) 1998, 1999 +# +# This software is release under the GNU Public License Version 2. +# A copy of this licence must be distributed with this software. +# + +proc main {} { + global argv0 argv tracks auto_path; + + lappend auto_path "."; + + if { [ llength $argv ] < 4 } { + puts stderr "Bad usage"; + puts stderr "$argv0 \[ ... \] "; + exit 1; + } + set outfile [ lindex $argv 0 ]; + set discid [ lindex $argv 1 ]; + set trackoffs [ lrange $argv 2 [ expr [ llength $argv ] - 2 ] ]; + set disclen [ lindex $argv end ]; + + if { $outfile == "-" } { + set wfh stdout; + } else { + set wfh [ open $outfile "w" ]; + } + + set fh [ socket cddb.cddb.com 8880 ]; + + # Greeting from server + #puts [ gets $fh ]; + gets $fh; + + puts $fh "CDDB HELLO [ exec id -u -n ] [ exec hostname ] TclMangler 0.1"; + flush $fh + + # Hello message + #puts [ gets $fh ]; + gets $fh; + + puts $fh "CDDB QUERY $discid [ llength $trackoffs ] $trackoffs $disclen" + flush $fh + + set line [ gets $fh ]; + if { [ regexp {([0-9][0-9][0-9]) (.*)} $line a rtn rest ] } { + switch -- $rtn { + "200" { + if { [ regexp {([a-z]*) ([0-9a-f]*) (.*)} $rest a cat discid name ] } { + puts stderr "Matched CD called $name in category $cat"; + } else { + puts stderr "Couldn't parse line with code 200 '$rest'"; + exit 1; + } + } + + "202" { + puts stderr "No such CD found.. generating dummy file"; + puts $wfh "# xmcd CD database file +# Copyright (C) 1993-1999 CDDB, Inc. +# +# Track frame offsets:"; + foreach t $trackoffs { + puts $wfh "#\t$t"; + } + puts $wfh "# +# Disc length: $disclen seconds +# +# Revision: 1 +# Submitted via: Tcl Mangler 0.1 - Copyright (c) 1999 Daniel O'Connor +# +DISCID=$discid +DTITLE="; + set i 0; + foreach t $trackoffs { + puts $wfh "TTITLE$i="; + incr i + } + + exit; + } + + "211" { + set tot 0; + set matches ""; + + while { 1 } { + set line [ gets $fh ]; + if { $line == "." } { + break; + } + + if { [ regexp {^([a-z]*) ([0-9a-f]*) (.*)} $line a cat discid name ] } { + puts stderr "[ expr $tot + 1 ]) Matched CD called $name in category $cat"; + lappend matches [ list $cat $discid $name ]; + incr tot; + } else { + puts stderr "Couldn't parse line after code 210 - '$line'"; + exit 1; + } + } + + if { $tot == 0 } { + puts stderr "No matches found for 210?"; + exit 1; + } + + if { $tot == 1 } { + set num 0; + } else { + puts stderr "Please enter the number which corresponds to the correct entry"; + while { 1 } { + set num [ gets stdin ]; + if { ($num >= 1) && ($num <= $tot ) } { + break; + } + puts stderr "Sorry, that number is invalid, please try again"; + } + + set cat [ lindex [ lindex $matches [ expr $num - 1 ] ] 0 ]; + set discid [ lindex [ lindex $matches [ expr $num - 1 ] ] 1 ]; + set name [ lindex [ lindex $matches [ expr $num - 1 ] ] 2 ]; + } + } + + "501" { + puts stderr"Invalid disc ID $discid"; + exit 1; + } + + default { + puts stderr "Couldn't parse '$line'"; + exit 1; + } + } + } + + puts $fh "CDDB READ $cat $discid" + flush $fh + + gets $fh line; + + if { [ regexp {([0-9][0-9][0-9]) (.*)} $line a rtn rest ] } { + if { $rtn != "210" } { + puts stderr "Bad error from CDDB READ command ($line)" + exit 1; + } + } else { + puts stderr "Couldn't parse $line"; + exit 1; + } + + while { 1 } { + set line [ gets $fh ]; + if { $line == "." } { + break; + } + + puts $wfh $line; + } + + close $fh; +} + +main; \ No newline at end of file diff -r 5cead4da1db9 -r 74031379d3cb gettracks.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gettracks.sh Wed Aug 09 02:18:47 2000 +0000 @@ -0,0 +1,27 @@ +#!/bin/sh + +cddev=/dev/acd0c +root=`dirname $0` +if [ $# -eq 0 ]; then + tracks=`$root/cddb-id -f $cddev -n` +else + tracks=$* +fi + +echo Ripping tracks $tracks + +ripper="cdd -t \$num -" +comp="lame -x -b 192 - -" +#comp="gogo -silent -offset 0 -b 192 stdin" + +for t in $tracks ; do + num=`printf %02d $t` + name=`printf track_%s.mp3 $num` + echo Ripping $num to $name + eval $ripper 2>> rip.log | sox -t cdr - -t wav - | $comp > $name + if [ $? -ne 0 ]; then + echo "Failed!" + exit 1 + fi +done + diff -r 5cead4da1db9 -r 74031379d3cb tracknamer.tcl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tracknamer.tcl Wed Aug 09 02:18:47 2000 +0000 @@ -0,0 +1,305 @@ +#!/bin/sh +# tcl magic \ +exec tclsh8.0 $0 $* + +# +# This software is copyright Daniel O'Connor (darius@dons.net.au) 1998, 1999 +# +# This software is release under the GNU Public License Version 2. +# A copy of this licence must be distributed with this software. +# + +proc edit_tracks {} { + global tracks state; + +# if { [ catch {loadlibs [ list "X11" "tk80" ]} msg] } { +# log "Failed to load library files - $msg"; +# exit 1; +# } + + set tracks(tmp:albumartist) $tracks(albumartist); + set tracks(tmp:albumname) $tracks(albumname); + for { set i 1 } { $i <= $tracks(number) } { incr i } { + set tracks(tmp:artist:$i) $tracks(artist:$i); + set tracks(tmp:title:$i) $tracks(title:$i); + } + + # create the toplevel + eval destroy [winfo child .]; + wm title . "Track Edit" + + # Let's have a menubar + frame .menubar -relief raised -bd 2 + pack .menubar -side top -fill x + + # Add the File menu + menubutton .menubar.file -text "File" -menu .menubar.file.m -underline 0; + menu .menubar.file.m -tearoff 0; + .menubar.file.m add command -label " Fill Down" -command "fill_down" \ + -underline 2 -accelerator "Ctrl-d"; + .menubar.file.m add command -label " Revert " -command "revert" \ + -underline 2 -accelerator "Ctrl-r"; + .menubar.file.m add command -label " Swap " -command "swap" \ + -underline 2 + .menubar.file.m add separator; + .menubar.file.m add command -label " Save " -command "save_names" \ + -underline 2 -accelerator "Ctrl-s"; + .menubar.file.m add command -label " Exit " -command "namer_exit" \ + -underline 2 -accelerator "Ctrl-q"; + + pack .menubar.file -side left; + + # Top frame for entry widgets + frame .top -relief raised -bd 1 + pack .top -side top -fill both + # Bottom frame for button + frame .bot -relief raised -bd 1 + pack .bot -side top -fill both + + frame .top.disctitle; + pack .top.disctitle; + label .top.disctitle.label -text "Disc Title"; + entry .top.disctitle.entry -width 80 -relief sunken -textvariable tracks(tmp:albumname); + pack .top.disctitle.label .top.disctitle.entry -side left; + frame .top.discartist; + pack .top.discartist; + label .top.discartist.label -text "Disc Artist"; + entry .top.discartist.entry -width 80 -relief sunken -textvariable tracks(tmp:albumartist); + pack .top.discartist.label .top.discartist.entry -side left; + + label .top.label -text "Artist/Title"; + pack .top.label; + + add_entries .top + + button .bot.revert -text Save -command save_names; + button .bot.save -text Revert -command revert; + pack .bot.revert .bot.save -side left; + + bind all {namer_exit} + bind all {save_names} + bind all {fill_down} + bind all {revert} + update; + + vwait state(exitnow); + destroy . + catch {update}; +} + + +proc swap {} { + global tracks; + + for { set i 1 } { $i <= $tracks(number) } { incr i } { + set tmp $tracks(tmp:title:$i); + set tracks(tmp:title:$i) $tracks(tmp:artist:$i); + set tracks(tmp:artist:$i) $tmp; + } +} + +proc fill_down {} { + global tracks; + + for { set i 2 } { $i <= $tracks(number) } { incr i } { + set tracks(tmp:artist:$i) $tracks(tmp:artist:1); + } +} + +proc revert {} { + global tracks; + + set tracks(tmp:albumname) $tracks(albumname); + set tracks(tmp:albumartist) $tracks(albumartist); + + for { set i 1 } { $i <= $tracks(number) } { incr i } { + set tracks(tmp:artist:$i) $tracks(artist:$i); + set tracks(tmp:title:$i) $tracks(title:$i); + } +} + +proc add_entries { parent } { + global tracks; + + for { set i 1 } { $i <= $tracks(number) } { incr i } { + frame $parent.fr_track:$i; + pack $parent.fr_track:$i -side top; + + label $parent.fr_track:$i.label -text "Track $i:"; + entry $parent.fr_track:$i.ar_entry -width 40 -relief sunken -textvariable tracks(tmp:artist:$i); + entry $parent.fr_track:$i.ti_entry -width 40 -relief sunken -textvariable tracks(tmp:title:$i); + pack $parent.fr_track:$i.label $parent.fr_track:$i.ar_entry $parent.fr_track:$i.ti_entry -side left; + +# log "Title $i"; + } +} +proc save_names {} { + global tracks; + + set tracks(albumname) $tracks(tmp:albumname); + set $tracks(albumartist) tracks(tmp:albumartist); + + for { set i 1 } { $i <= $tracks(number) } { incr i } { + set tracks(artist:$i) $tracks(tmp:artist:$i); + set tracks(title:$i) $tracks(tmp:title:$i); + } + + set tracks(updated) 1; +# print_info; + +} + +proc print_info {} { + global tracks; + + puts "Title: $tracks(albumname)"; + puts "Artist: $tracks(albumartist)"; + + for { set i 1 } { $i <= $tracks(number) } { incr i } { + puts "Track $i: $tracks(artist:$i) - $tracks(title:$i)"; + } +} +proc namer_exit {} { + global state; + +# log "Bye"; +# print_info; + set state(exitnow) 1; +} + +################################################################## +# Load a list of libraries. +# Takes a list of the form { "foo" "bar" } to look for +# libfoo.so.n.m and libbar.so.n.m. +# Also looks at the LD_LIBRARY_PATH variable for extra places to look +# +proc loadlibs {liblist} { + global env; + + set file [open {|/sbin/ldconfig -r} r] + while { ! [eof $file] } { + if { [ regexp {[0-9]+:-l(.*) => (.*)/lib(.*)\.so\.(.*)} [gets $file] a b c d e ] == 0 } { + continue; + } + + # List of partially processed libs + # eg '/usr/local/lib' 'tiff34' '1.0' + if { [ regexp {(.*)\.(.*)} $e f g h ] == 0 } { + set maj $e; + set min 0; + } else { + set maj $g; + set min $h; + } + set tmp [ list $c $d $maj $min ]; +# puts "ldconfig - $tmp"; + lappend all_list $tmp; + } + + close $file; + + if { [ info exists env(LD_LIBRARY_PATH) ] == 1} { + set ld_path [ split $env(LD_LIBRARY_PATH) ":"]; + + foreach dir $ld_path { + set found [glob -nocomplain -- "$dir/lib*.so.*"]; + if { $found != "" } { + foreach foo $found { + if { [ regexp {(.*)/lib(.*)\.so\.(.*)} $foo a b c d ] == 0 } { + continue; + } + + if { [ regexp {(.*)\.(.*)} $d e f g ] == 0 } { + set maj $d; + set min 0; + } else { + set maj $f; + set min $g; + } + set tmp [ list $b $c $maj $min ]; +# puts "LD_LIB - $tmp"; + lappend all_list $tmp; + } + } + } + } + + set libs_to_load ""; + + foreach lib $liblist { + set found_lib ""; + set found_maj 0; + set found_min 0; + + foreach line $all_list { + # Path + set b [ lindex $line 0 ]; + # Lib name + set e [ lindex $line 1 ]; + # Major + set c [ lindex $line 2 ]; + # Minor + set d [ lindex $line 3 ]; + if { ($e == $lib) && (($c > $found_maj) || (($c == $found_maj) && ($d > $found_min))) } { + set found_maj $c; + set found_min $d; + set found_lib $e; + set found_path $b; +# puts "Found $found_lib ($found_maj.$found_min)"; + } + } + + if { $found_lib != "" } { + lappend libs_to_load [ list $found_lib $found_path $found_maj $found_min ]; + } else { + error "Unable to find library for $lib"; + } + } + + set loaded_OK ""; + + foreach lib $libs_to_load { + set libname [ lindex $lib 0 ]; + set libpath [ lindex $lib 1 ]; + set libmaj [ lindex $lib 2 ]; + set libmin [ lindex $lib 3 ]; + # Try no extension for ELF + if { $libmin == 0 } { + if { [ file exists $libpath/lib$libname.so.$libmaj ] } { + set loadname $libpath/lib$libname.so.$libmaj + } else { + set loadname $libpath/lib$libname.so.$libmaj.$libmin + } + } else { + set loadname $libpath/lib$libname.so.$libmaj.$libmin + } + if { [catch {load $loadname} msg ] } { + # Ignore the error if it's because it couldn't find the procedure - needed for X11 + if { [regexp -nocase .*couldn\'t\ find\ procedure.* $msg ] == 0 } { + error "Warning: Couldn't load $lib because $msg"; + } else { + lappend loaded_OK $libname; + } + } else { + lappend loaded_OK $lib; + } + } + + return $loaded_OK; +} + +proc log {format args} { + # Extract the calling function's name + set fname [lindex [info level -1] 0]; + + # Evaluate the supplied format string and arguments + if {[catch {set csm [eval format {$format} $args]} msg]} { + set csm "bad log message. format='$format' args='$args'"; + } + + # Emit the message + puts stderr "[clock format [clock seconds] -format {%y/%m/%d %H:%M:%S} -gmt yes]:$fname: $csm"; + flush stderr; +} + +