-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcue2psc.tcl
executable file
·399 lines (339 loc) · 14 KB
/
cue2psc.tcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
#!/bin/sh
# start Tcl-Interpreter \
exec tclsh "$0" "$@"
########################################################################
## ##
## CUE2PSC ##
## ##
## NAME ##
## cue to psc - converts a cue sheet into a podlove simple ##
## chapter file ##
## ##
## SYNOPSIS ##
## tclsh8.5 cue2psc.tcl [inputfile] [outputfile] ##
## ##
## DESCRIPTION ##
## cue2psc takes a cue sheet typicly generated by IDJC and ##
## generates a podlove simple chapter file typicly to feed ##
## auphonic. ##
## ##
## USAGE ##
## no argument ##
## cue2psc will take the cuesheet from standard input ##
## usually while piping the output of another process ##
## into cue2psc. The output of the psc-file apears on ##
## the standard output so you can pipe it into ##
## another process. ##
## ##
## Example: cat cuesheet.cue | tclsh cue2psc.tcl ##
## ##
## one argument ##
## cue2pcs will take the argument as input filename. ##
## The output filename will be generated from the ##
## input file. On the terminal you will get the ##
## output filename you can pipe somewhere else. ##
## ##
## Example: tclsh cue2psc.tcl cuesheet.cue ##
## ##
## two arguments ##
## cue2pcs will take the first argument as input ##
## filename and the second as output filename. ##
## You can specify -- as input or output to set ##
## standard input or output. This way you can ##
## use standard input and output to a file OR ##
## you can choose to use an input file but ##
## output on the terminal instead of letting ##
## cue2psc generate a file name. ##
## ##
## Example: tclsh cue2psc.tcl cuesheet.cue auphonic.psc ##
## ##
## ##
########################################################################
set scriptversion {1 0 1}
proc fixlength { s l f } {
#s = string
#l = length
#f = filler
while { [string length $s] < $l } {
set s "$f$s"
}
return $s
}
proc findoutputfilename { inputcontent inputfilename } {
if { [regexp {\s*FILE \"([^\"]+)\"} $inputcontent fileline audiofilename] } {
return "$audiofilename\.psc"
} else {
return "$inputfilename\.psc"
}
}
proc outputhelp {} {
puts " CUE2PCS"
puts " "
puts " NAME"
puts " cue to psc - converts a cue sheet into a podlove simple"
puts " chapter file"
puts " "
puts " SYNOPSIS"
puts " tclsh cue2psc.tcl \[options\] \[inputfile\] \[outputfile\]"
puts " "
puts " DESCRIPTION"
puts " cue2psc takes a cue sheet typicly generated by IDJC and"
puts " generates a podlove simple chapter file typicly to feed"
puts " auphonic."
puts " "
puts " OPTIONS"
puts " "
puts " -i interactive mode"
puts " "
puts " -help --help output this help"
puts " "
puts " -v --version output version"
puts " "
puts " INPUTFILE"
puts " defines the inputfile. Use -- for interactive (stdin) input"
puts " to pipe in for example. Default (no inputfile name) is also"
puts " standard input."
puts " "
puts " OUTPUTFILE"
puts " defines the outputfile. Use -- for standard output. Default"
puts " (no outputfile name) generates an output filename by the"
puts " cue sheet."
puts " "
puts " EXAMPLES"
puts " "
puts " tclsh cue2psc.tcl idjc.foo.mp3.cue"
puts " reads from the file idjc.foo.mp3.cue and generates an"
puts " output filename."
puts " "
puts " tclsh cue2psc.tcl idjc.foo.mp3.cue idjc.foo.mp3.psc"
puts " reads from he file idjc.foo.mp3.cue and writes to"
puts " idjc.foo.mp3.psc"
puts " "
puts " tclsh cue2psc.tcl --help -i idjc.foo.mp3.cue"
puts " puts out this help, reads from the file idjc.foo.mp3.cue"
puts " activates interactive mode to correct data and writes"
puts " to a generated output filename."
puts " "
puts " tclsh cue2psc.tcl -- output.psc"
puts " reads from standard input and writes to output.psc file."
puts " "
puts " cat idjc.foo.mp3.cue | tclsh cue2psc.tcl -- output.psc"
puts " same as tclsh cue2psc.tcl idjc.foo.mp3.cue output.psc"
puts " "
puts " "
puts "----------------------------------------------------------"
}
proc parsetime { stringinput } {
#parses something in the style 1:2:3 or 1:2:3.4
regexp {(\d+\:)?(\d+\:)?(\d+)?((?:\.|\,)\d+)?} $stringinput totaltime pt_h pt_min pt_s pt_s100
set pt_h [string trimright $pt_h ":"]
set pt_min [string trimright $pt_min ":"]
set pt_s100 [string trimleft $pt_s100 ".,"]
if { ( [string length $pt_h] > 0 ) && ( [string length $pt_min] == 0 ) } {
set pt_min $pt_h
set pt_h 0
}
if { ![string is integer -strict $pt_h] } { set pt_h 0 }
if { ![string is integer -strict $pt_min] } { set pt_min 0 }
if { ![string is integer -strict $pt_s] } { set pt_s 0 }
if { ![string is integer -strict $pt_s100] } { set pt_s100 0 }
## puts "$pt_h : $pt_min : $pt_s . $pt_s100"
while { $pt_s100 > 999 } {
set pt_s100 [expr round( $pt_s100 / 10.0 )]
}
while { $pt_s > 60 } {
incr pt_min
incr pt_s -60
}
while { $pt_min > 60 } {
incr pt_h
incr pt_min -60
}
return [list $pt_h $pt_min $pt_s $pt_s100]
}
set varcounter 0
set interactive 0
set nextvar "varcounter"
set inputfilename "--"
set outputfilename "FINDOUTPUTFILENAME"
for {set i 0} {$i < $argc} {incr i} {
set p [lindex $argv $i]
if { $p == "-i" } {
set interactive 1
} elseif { ( $p == "--help" ) || ( $p == "-help" ) || ( $p == "?" ) || ( $p == "??" ) || ( $p == "-?" ) } {
outputhelp
} elseif { ( $p == "--version" ) || ( $p == "-v" ) } {
puts "cue2psc [join $scriptversion .]"
puts "tcl [info tclversion]"
} else {
if { $nextvar == "varcounter" } {
if {$varcounter == 0} {
set inputfilename $p
} elseif {$varcounter == 1} {
set outputfilename $p
} else {
puts "too many parameters: $p"
exit 101
}
incr varcounter
} elseif { $nextvar == "input" } {
set inputfilename $p
} elseif { $nextvar == "output" } {
set outputfilename $p
} else {
puts "unknown parameter: $p"
exit 102
}
}
}
if { $inputfilename == "--" } {
set inputchannel stdin
} else {
set inputchannel [open $inputfilename r]
}
# okay, arguments parsed, let's parse the input…
set cuecontent [read -nonewline $inputchannel]
close $inputchannel
# split cue in a list of tracks
set tracklist [regexp -all -inline -indices -- {\n\s*TRACK \d+\s+[^\n]+\n} $cuecontent]
set trackarray [list]
#puts $tracklist
for { set i 0 } { $i < [llength $tracklist] } { incr i } {
set thistrackstart [lindex [lindex $tracklist $i] 0]
set thistrackend [string length $cuecontent]
if { $i < [expr [llength $tracklist] -1] } {
set thistrackend [lindex [lindex $tracklist [expr $i +1]] 0]
}
set thistrack [string range $cuecontent $thistrackstart $thistrackend]
set this_titleline [regexp -inline {\n\s*TITLE \"([^\"]+)\"} $thistrack]
if {[llength $this_titleline] > 1} {
set this_title [lindex $this_titleline 1]
} else {
set this_title $this_titleline
}
set this_performerline [regexp -inline {\n\s*PERFORMER \"([^\"]+)\"} $thistrack]
if {[llength $this_performerline] > 1} {
set this_artist [lindex $this_performerline 1]
} else {
set this_artist $this_performerline
}
set this_indexline [regexp -inline {\n\s*INDEX \d+\s+(\d+\:\d\d(\:\d\d)?)} $thistrack]
if {[llength $this_indexline] > 1} {
set this_starttime [lindex $this_indexline 1]
} else {
set this_starttime "00:00:00"
}
#puts $this_starttime
set this_starttime [regexp -inline -all {\d+} $this_starttime]
#puts $this_starttime
# should be an array of…
# { minutes seconds frames }
# calculate to
# { hours minutes seconds milliseconds }
set this_hour 0
set this_minutes [lindex $this_starttime 0]
set this_seconds [lindex $this_starttime 1]
set this_milliseconds [lindex $this_starttime 2]
if { $this_milliseconds == "00" } {
set this_milliseconds 0
} else {
set this_milliseconds [string trimleft $this_milliseconds "0"]
}
set this_milliseconds [expr round ($this_milliseconds / 0.075)]
while { $this_minutes >= 60 } {
incr this_hour
incr this_minutes -60
}
set this_starttime [list $this_hour $this_minutes $this_seconds $this_milliseconds]
if {[string first " - " $this_title] > 0} {
set this_artist [string range $this_title 0 [string first " - " $this_title]]
set this_title [string range $this_title [expr [string first " - " $this_title] +3] end]
}
set trackobject [list $this_starttime [string trim $this_artist] [string trim $this_title]]
lappend trackarray $trackobject
}
if { $outputfilename == "FINDOUTPUTFILENAME" } {
set outputfilename [findoutputfilename $cuecontent $inputfilename]
set outputchannel [open $outputfilename w]
}
if { $interactive } {
puts "STARTING INTERACTIVE MODE"
puts "Current values:"
puts "Outputfile: $outputfilename"
puts "Chapters: [llength $trackarray]"
if { [llength $trackarray] <= 12 } {
for { set i 0 } { $i < [llength $trackarray] } { incr i } {
puts "[fixlength [lrange [lindex [lindex $trackarray $i] 0] 0 2] 10 \ ] [fixlength [lindex [lindex $trackarray $i] 1] 25 \ ] - [fixlength [lindex [lindex $trackarray $i] 2] 25 \ ]"
}
}
puts ""
puts "CHANGES (hit return to change nothing)"
puts "Outputfilename ($outputfilename\)"
gets stdin userinput
if { [string length $userinput] } { set outputfilename $userinput }
for { set i 0 } { $i < [llength $trackarray] } { incr i } {
set remove_chapter 0
set trackobject [lindex $trackarray $i]
set trackstart [lindex $trackobject 0]
if { [llength $trackstart] > 0 } { set trackstart_h [lindex $trackstart 0] } else { set trackstart_h 0 }
if { [llength $trackstart] > 1 } { set trackstart_m [lindex $trackstart 1] } else { set trackstart_m 0 }
if { [llength $trackstart] > 2 } { set trackstart_s [lindex $trackstart 2] } else { set trackstart_s 0 }
if { [llength $trackstart] > 3 } { set trackstart_ms [lindex $trackstart 3] } else { set trackstart_ms 0 }
puts "[fixlength $trackstart_h 2 0]\:[fixlength $trackstart_m 2 0]\:[fixlength $trackstart_s 2 0]\.[fixlength $trackstart_ms 3 0]"
puts [lindex $trackobject 1]
puts [lindex $trackobject 2]
if { [expr $i + 1] < [llength $trackarray] } {
puts "(next: [lindex $trackarray [expr $i + 1]])"
} else {
puts "(last one)"
}
puts ""
puts "Starttime ([fixlength $trackstart_h 2 0]\:[fixlength $trackstart_m 2 0]\:[fixlength $trackstart_s 2 0]\.[fixlength $trackstart_ms 3 0] \"r\" to remove the chapter)"
gets stdin userinput
if { [string length $userinput] } {
if { $userinput == "r" } {
set remove_chapter 1
} else {
set trackobject [lreplace $trackobject 0 0 [parsetime $userinput]]
## puts $trackobject
}
}
if { $remove_chapter } {
set trackobject "deleted"
} else {
puts "Artist ([lindex $trackobject 1])"
gets stdin userinput
if { [string length $userinput] } {
set trackobject [lreplace $trackobject 1 1 $userinput]
}
puts "Title ([lindex $trackobject 2])"
gets stdin userinput
if { [string length $userinput] } {
set trackobject [lreplace $trackobject 2 2 $userinput]
}
}
set trackarray [lreplace $trackarray $i $i $trackobject]
}
}
if { $outputfilename == "--" } {
set outputchannel stdout
} else {
set outputchannel [open $outputfilename w]
}
for { set i 0 } { $i < [llength $trackarray] } { incr i } {
set trackobject [lindex $trackarray $i]
if { ( [llength $trackobject] <= 1 ) && ( $trackobject == "deleted" ) } {
#ignore this
} else {
set trackstart [lindex $trackobject 0]
if { [llength $trackstart] > 0 } { set trackstart_h [lindex $trackstart 0] } else { set trackstart_h 0 }
if { [llength $trackstart] > 1 } { set trackstart_m [lindex $trackstart 1] } else { set trackstart_m 0 }
if { [llength $trackstart] > 2 } { set trackstart_s [lindex $trackstart 2] } else { set trackstart_s 0 }
if { [llength $trackstart] > 3 } { set trackstart_ms [lindex $trackstart 3] } else { set trackstart_ms 0 }
set outputline "[fixlength $trackstart_h 2 0]\:[fixlength $trackstart_m 2 0]\:[fixlength $trackstart_s 2 0]\.[fixlength $trackstart_ms 3 0] [lindex $trackobject 1] - [lindex $trackobject 2]"
puts $outputchannel $outputline
}
}
if {$outputfilename != "--"} {
puts $outputfilename
}