etree 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +23 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +21 -0
- data/LICENSE +20 -0
- data/README.md +25 -0
- data/Rakefile +9 -0
- data/VERSION +1 -0
- data/bin/archive-dl +12 -0
- data/bin/flac2mp3 +70 -0
- data/bin/parse_info +21 -0
- data/bin/wav2mp3 +67 -0
- data/etree.gemspec +22 -0
- data/lib/etree.rb +2 -0
- data/lib/etree/info_file.rb +153 -0
- data/lib/etree/track.rb +32 -0
- data/test/etree_test.rb +71 -0
- data/test/examples/moe2010-05-30early.skm140.flac16/moe2010-05-30early.txt +28 -0
- data/test/examples/ph2010-06-11.mk4v.flac16/ph2010-06-11-1644-txt.txt +43 -0
- data/test/test_helper.rb +8 -0
- metadata +130 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 743abd75ab7027b7a33fd6a71a21d9714541491e
|
4
|
+
data.tar.gz: 44d570c94317cbc2c7cdf1d1214514d949392f10
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1e26f25488de8089f64148e7aed8d4d422fb3e0d9725aa12c72ee15fb6621c4361776c179ba5b1b43e26a07b7cfb1f965a6d07ea309f4106cccf03c528ec232b
|
7
|
+
data.tar.gz: 7c5658c253b48f28ef242cb3159ea81af7cad749e5ca6015924220ef20543d6204319b8ca54f23185ebe3cf0cc631efdfc86e5f98b93a49504b8c583cc6cc07d
|
data/.document
ADDED
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0-p247
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
etree (0.2.0)
|
5
|
+
chronic
|
6
|
+
escape
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
chronic (0.10.2)
|
12
|
+
escape (0.0.4)
|
13
|
+
rake (10.1.0)
|
14
|
+
|
15
|
+
PLATFORMS
|
16
|
+
ruby
|
17
|
+
|
18
|
+
DEPENDENCIES
|
19
|
+
bundler (~> 1.3)
|
20
|
+
etree!
|
21
|
+
rake
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Paul Barry
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# etree
|
2
|
+
|
3
|
+
This is a port of the [Perl Etree Scripts](http://etree-scripts.sourceforge.net/) to Ruby. This scripts can be used to download the flac source of audience recording of a concert from a site like [http://bt.etree.org](http://bt.etree.org) or [The Live Music Archive](http://www.archive.org/details/audio) and convert it to MP3s.
|
4
|
+
|
5
|
+
The main feature this provides, aside from converting the FLAC files to MP3, is extracting the track information from the text file in the folder and using that information to populate the MP3 ID3 tags such as Artist, Album, Track Title, Track Title, etc.
|
6
|
+
|
7
|
+
## Requirements
|
8
|
+
|
9
|
+
You will need `flac` and `lame` installed in order to use this. You can install them both using [homebrew][homebrew]:
|
10
|
+
|
11
|
+
$ brew install flac
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
$ gem install etree
|
16
|
+
$ cd ~/Downloads
|
17
|
+
$ flac2mp3 ph2010-06-12.flacf/ph2010-06-12.txt
|
18
|
+
|
19
|
+
Assuming there is a set of flacf files in `~/Downloads/ph2010-06-12.flacf` and `ph2010-06-12.txt` is a text file describing the show, that will create mp3 files in `~/Downloads/ph2010-06-12.mp3f`.
|
20
|
+
|
21
|
+
## Copyright
|
22
|
+
|
23
|
+
Copyright (c) 2010 Paul Barry. See LICENSE for details.
|
24
|
+
|
25
|
+
[homebrew]: http://brew.sh
|
data/Rakefile
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
data/bin/archive-dl
ADDED
data/bin/flac2mp3
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "rubygems"
|
3
|
+
require "etree"
|
4
|
+
require "escape"
|
5
|
+
|
6
|
+
info_file = Etree::InfoFile.new :info_file => ARGV[0]
|
7
|
+
info_file.parse
|
8
|
+
|
9
|
+
# If we are in test mode, just print what we would do
|
10
|
+
test_mode = false
|
11
|
+
|
12
|
+
puts "Band: #{info_file.band}"
|
13
|
+
puts "Date: #{info_file.date.strftime("%Y-%m-%d")}"
|
14
|
+
puts "Venue: #{info_file.venue}"
|
15
|
+
puts ""
|
16
|
+
|
17
|
+
out_dir = "#{info_file.directory}.mp3f"
|
18
|
+
|
19
|
+
Dir.mkdir(out_dir) unless File.exist?(out_dir)
|
20
|
+
|
21
|
+
total_track_count = info_file.tracks.size
|
22
|
+
flac_files = Dir["#{info_file.directory}/*.flac"]
|
23
|
+
|
24
|
+
unless total_track_count == flac_files.size
|
25
|
+
puts "ERROR: Based on the info file, there are #{total_track_count} tracks, but there are #{flac_files.size}"
|
26
|
+
info_file.tracks.each do |track|
|
27
|
+
puts track
|
28
|
+
end
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
|
32
|
+
puts info_file.tracks
|
33
|
+
|
34
|
+
disc_count = info_file.discs.size
|
35
|
+
prev_disc = nil
|
36
|
+
track_count = 0
|
37
|
+
flac_files.each_with_index do |flac_file, i|
|
38
|
+
track = info_file.tracks[i]
|
39
|
+
|
40
|
+
if prev_disc == track.disc
|
41
|
+
track_count += 1
|
42
|
+
else
|
43
|
+
track_count = 1
|
44
|
+
prev_disc = track.disc
|
45
|
+
end
|
46
|
+
|
47
|
+
flac_cmd = Escape.shell_command(["flac", "-c", "-d", "--totally-silent", flac_file])
|
48
|
+
lame_cmd = Escape.shell_command(["lame",
|
49
|
+
"-b", "128",
|
50
|
+
"-q", "7",
|
51
|
+
"--ta", info_file.band,
|
52
|
+
"--tl", "#{info_file.date.strftime("%Y-%m-%d")} #{info_file.venue}",
|
53
|
+
"--tt", track.name,
|
54
|
+
"--tc", Array(info_file.source).join("\n"),
|
55
|
+
"--ty", info_file.date.year.to_s,
|
56
|
+
"--tn", "#{track.number}/#{track_count}",
|
57
|
+
"--tv", "TPOS=#{track.disc}/#{disc_count}",
|
58
|
+
"-", File.join(out_dir, "#{track.file_name}.mp3")])
|
59
|
+
|
60
|
+
cmd = "#{flac_cmd} | #{lame_cmd}"
|
61
|
+
|
62
|
+
if test_mode
|
63
|
+
puts cmd
|
64
|
+
else
|
65
|
+
puts "Encoding #{track.name}..."
|
66
|
+
unless system(cmd)
|
67
|
+
raise "Error while trying to encode #{flac_file}:#{$?}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/bin/parse_info
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "rubygems"
|
3
|
+
require "etree"
|
4
|
+
|
5
|
+
info_file = Etree::InfoFile.new :directory => ARGV[0]
|
6
|
+
info_file.parse
|
7
|
+
|
8
|
+
puts "Band: #{info_file.band}"
|
9
|
+
puts "Date: #{info_file.date.strftime("%Y-%m-%d")}"
|
10
|
+
puts "Venue: #{info_file.venue}"
|
11
|
+
puts "Source: #{info_file.source}"
|
12
|
+
|
13
|
+
prev_disc = nil
|
14
|
+
info_file.tracks.each_with_index do |t, i|
|
15
|
+
unless prev_disc == t.disc
|
16
|
+
puts ""
|
17
|
+
prev_disc = t.disc
|
18
|
+
end
|
19
|
+
puts("%02d %s" % [(i+1), t.name])
|
20
|
+
#puts("%02d %s (%s)" % [(i+1), t.name, t.file_name])
|
21
|
+
end
|
data/bin/wav2mp3
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "rubygems"
|
3
|
+
require "etree"
|
4
|
+
require "escape"
|
5
|
+
|
6
|
+
info_file = Etree::InfoFile.new :info_file => ARGV[0]
|
7
|
+
info_file.parse
|
8
|
+
|
9
|
+
# If we are in test mode, just print what we would do
|
10
|
+
test_mode = false
|
11
|
+
|
12
|
+
puts "Band: #{info_file.band}"
|
13
|
+
puts "Date: #{info_file.date.strftime("%Y-%m-%d")}"
|
14
|
+
puts "Venue: #{info_file.venue}"
|
15
|
+
puts ""
|
16
|
+
|
17
|
+
out_dir = "#{info_file.directory}.mp3f"
|
18
|
+
|
19
|
+
Dir.mkdir(out_dir) unless File.exist?(out_dir)
|
20
|
+
|
21
|
+
total_track_count = info_file.tracks.size
|
22
|
+
wav_files = Dir["#{info_file.directory}/*.wav"]
|
23
|
+
|
24
|
+
unless total_track_count == wav_files.size
|
25
|
+
puts "ERROR: Based on the info file, there are #{total_track_count} tracks, but there are #{wav_files.size}"
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
|
29
|
+
puts info_file.tracks
|
30
|
+
|
31
|
+
disc_count = info_file.discs.size
|
32
|
+
prev_disc = nil
|
33
|
+
track_count = 0
|
34
|
+
wav_files.each_with_index do |wav_file, i|
|
35
|
+
track = info_file.tracks[i]
|
36
|
+
|
37
|
+
if prev_disc == track.disc
|
38
|
+
track_count += 1
|
39
|
+
else
|
40
|
+
track_count = 1
|
41
|
+
prev_disc = track.disc
|
42
|
+
end
|
43
|
+
|
44
|
+
lame_cmd = Escape.shell_command(["lame",
|
45
|
+
"-b", "128",
|
46
|
+
"-q", "7",
|
47
|
+
"--ta", info_file.band,
|
48
|
+
"--tl", "#{info_file.date.strftime("%Y-%m-%d")} #{info_file.venue}",
|
49
|
+
"--tt", track.name,
|
50
|
+
"--tc", info_file.source.join("\n"),
|
51
|
+
"--ty", info_file.date.year.to_s,
|
52
|
+
"--tn", "#{track.number}/#{track_count}",
|
53
|
+
"--tv", "TPOS=#{track.disc}/#{disc_count}",
|
54
|
+
wav_file,
|
55
|
+
File.join(out_dir, "#{track.file_name.sub(/\.wav$/,'')}.mp3")])
|
56
|
+
|
57
|
+
cmd = lame_cmd
|
58
|
+
|
59
|
+
if test_mode
|
60
|
+
puts cmd
|
61
|
+
else
|
62
|
+
puts "Encoding #{track.name}..."
|
63
|
+
unless system(cmd)
|
64
|
+
raise "Error while trying to encode #{wav_file}:#{$?}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/etree.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "etree"
|
5
|
+
spec.version = "0.2.0"
|
6
|
+
spec.authors = ["Paul Barry"]
|
7
|
+
spec.email = ["mail@paulbarry.com"]
|
8
|
+
spec.summary = %q{Scripts for converting flac files posted to http://bt.etree.org to MP3}
|
9
|
+
spec.description = %q{Scripts for converting flac files posted to http://bt.etree.org to MP3}
|
10
|
+
spec.homepage = "http://github.com/pjb3/etree"
|
11
|
+
spec.license = "MIT"
|
12
|
+
|
13
|
+
spec.files = `git ls-files`.split($/)
|
14
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
15
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
16
|
+
spec.require_paths = ["lib"]
|
17
|
+
|
18
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
19
|
+
spec.add_development_dependency "rake"
|
20
|
+
spec.add_runtime_dependency "chronic"
|
21
|
+
spec.add_runtime_dependency "escape"
|
22
|
+
end
|
data/lib/etree.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
require "chronic"
|
2
|
+
|
3
|
+
module Etree
|
4
|
+
|
5
|
+
# This will parse the info file that comes with a show
|
6
|
+
# Typical usage might look like:
|
7
|
+
# info_file = Etree::InfoFile.new :directory => "ph1999-12-31.flacf"
|
8
|
+
# info_file.parse
|
9
|
+
# info_file.band # => "Phish"
|
10
|
+
# info_file.date # => "1999-12-31"
|
11
|
+
# info_file.venue # => "Big Cypress Seminole Indian Reservation, Big Cypress, FL"
|
12
|
+
# info_file.discs.first # => ["Runaway Jim", "Funky Bitch", ...]
|
13
|
+
class InfoFile
|
14
|
+
|
15
|
+
REGEXPS = {
|
16
|
+
:spots => %r{fob|dfc|btp|d?aud|d?sbd|soundboard|on(\s*|-)stage|matrix|mix|balcony|rail|stand}ix,
|
17
|
+
:mics => %r{caps|omni|cardioid|sc?ho?ep[sz]|neumann|mbho|akg|b&k|dpa|audio.technica}ix,
|
18
|
+
:configs => %r{\b(?:ortf|x[-\/]?y|degrees|blumlein|binaural|nos|din)\b}ix,
|
19
|
+
:cables => %r{kc5|actives?|patch(?:ed)?|coax|optical}ix,
|
20
|
+
:pres => %r{lunatec|apogee|ad1000|ad2k\+?|oade|sonosax|sbm-?1|usb-pre|mini[\s-]?me}ix,
|
21
|
+
:dats => %r{dat|pcm|d[378]|da20|d10|m1|sv-25[05]|da-?p1|tascam|sony|teac|aiwa|panasonic|hhb|portadat|44\.1(?:k(?:hz))|mini-?disc|fostex}ix,
|
22
|
+
:laptops => %r{laptop|dell|ibm|apple|toshiba|(power|i)-?book}ix,
|
23
|
+
:digicards => %r{ieee1394|s.?pdif|zefiro|za-?2|rme|digiface|sb-?live|fiji|turtle\sbeach|delta\sdio|event\sgina|montego|zoltrix|prodif}ix,
|
24
|
+
:software => %r{cd-?wave?|mkwact|shn(?:v3)?|shorten|samplitude|cool[-\s]?edit|sound.?forge|wavelab}ix,
|
25
|
+
:venues => %r{(?:arts cent|theat)(?:er|re)|playhouse|arena|club|university|festival|lounge|room|cafe|field|house|airport|ballroom|college|hall|auditorium|village|temple}ix,
|
26
|
+
:states => %r{A[BLKZR]|BC|CA|CO|CT|DE|FL|GA|HI|I[DLNA]|KS|KY|LA|M[ABEDINSOT]|N[BCDEFVHJMSY]|O[HKNR]|P[AQ]|PEI|QC|RI|S[CDK]|TN|TX|UT|VT|VA|W[AVIY]|DC}x,
|
27
|
+
:countries => %r{Japan|England|Ireland|Brazil|Jamaica|United\s+Kingdom|Italy|South\s+Africa|Sweden|Portugal|Israel|Egypt|Norway|France|India|Finland|United\s+States|China|Mexico|Costa\s+Rica|Ecuador|New\s+Zealand|Puerto\s+Rico|Djibouti}i
|
28
|
+
}
|
29
|
+
|
30
|
+
TRACK_REGEXP = %r{^(?:d\d+)?t?(\d+) # sometimes you see d<n>t<m>
|
31
|
+
\s* (?:[[:punct:]]+)? # whitespace, some punctuation
|
32
|
+
\s* (.*)}mix; # whitespace, the track title
|
33
|
+
|
34
|
+
attr_accessor :directory, :info_file, :band, :date, :venue, :source, :discs, :comments
|
35
|
+
|
36
|
+
def initialize(attrs={})
|
37
|
+
attrs.each do |k,v|
|
38
|
+
send("#{k}=", v)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse(info_file=nil)
|
43
|
+
self.info_file = info_file if info_file
|
44
|
+
parse_info
|
45
|
+
end
|
46
|
+
|
47
|
+
def directory
|
48
|
+
@directory ||= info_file ? File.dirname(info_file) : Dir.pwd
|
49
|
+
end
|
50
|
+
|
51
|
+
def info_file
|
52
|
+
# The implementation in the perl version is much more complicated
|
53
|
+
# This should be good enough for now
|
54
|
+
# Grab the first text file that doesn't have ffp in the name
|
55
|
+
@info_file ||= Dir["#{directory}/*.txt"].detect{|f| File.basename(f) !~ /ffp/ }
|
56
|
+
end
|
57
|
+
|
58
|
+
def songs_count
|
59
|
+
Dir["#{directory}/*.flac"].size
|
60
|
+
end
|
61
|
+
|
62
|
+
def tracks
|
63
|
+
@tracks ||= begin
|
64
|
+
tracks = []
|
65
|
+
discs.each_with_index do |d, dn|
|
66
|
+
d.each_with_index do |t, tn|
|
67
|
+
tracks << Track.new(:name => t, :number => tn + 1, :disc => dn + 1)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
tracks
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
def info_file_paragraphs
|
76
|
+
@info_file_paras ||= File.read(info_file).split(/\s*\r?\n\r?\n/)
|
77
|
+
end
|
78
|
+
|
79
|
+
def parse_info
|
80
|
+
info_file_paragraphs.each do |paragraph|
|
81
|
+
next if $para =~ /\b[\da-f]{32}\b/i
|
82
|
+
if !band or !date or !venue
|
83
|
+
parse_band paragraph
|
84
|
+
elsif source_info_paragraph? paragraph
|
85
|
+
self.source ||= []
|
86
|
+
self.source << paragraph
|
87
|
+
elsif tracks_paragraph? paragraph
|
88
|
+
parse_tracks paragraph
|
89
|
+
else
|
90
|
+
self.comments ||= []
|
91
|
+
self.comments << paragraph
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_band(paragraph)
|
97
|
+
venue = []
|
98
|
+
paragraph.each_line do |line|
|
99
|
+
line.strip!
|
100
|
+
next if line.empty?
|
101
|
+
|
102
|
+
if !date
|
103
|
+
self.date = parse_date(line)
|
104
|
+
next if date
|
105
|
+
end
|
106
|
+
|
107
|
+
if band
|
108
|
+
venue << line
|
109
|
+
else
|
110
|
+
self.band = line
|
111
|
+
end
|
112
|
+
end
|
113
|
+
self.venue = Array(venue).join(", ")
|
114
|
+
end
|
115
|
+
|
116
|
+
def parse_date(s)
|
117
|
+
Chronic.parse(s.to_s.gsub(',','').gsub(/(?:mon|tue|wed|thu|fri|sat|sun)\w*/i,''))
|
118
|
+
end
|
119
|
+
|
120
|
+
def parse_tracks(paragraph)
|
121
|
+
tracks = []
|
122
|
+
paragraph.each_line do |line|
|
123
|
+
line.strip!
|
124
|
+
|
125
|
+
|
126
|
+
if match = line.match(TRACK_REGEXP)
|
127
|
+
tracks << format_track_name(match[2])
|
128
|
+
end
|
129
|
+
end
|
130
|
+
(self.discs ||= []) << tracks unless tracks.empty?
|
131
|
+
end
|
132
|
+
|
133
|
+
def format_track_name(track_name)
|
134
|
+
track_name = track_name.to_s
|
135
|
+
segue = track_name =~ />\s*$/
|
136
|
+
track_name.sub!(/^\d{1,2}:\d{2}\]?\s/,"") # strip timings
|
137
|
+
track_name.sub!(/[*^%>\s]*$/,"") # strip footnote markers
|
138
|
+
track_name << (segue ? ' >' : '')
|
139
|
+
end
|
140
|
+
|
141
|
+
def source_info_paragraph?(paragraph)
|
142
|
+
paragraph =~ %r{^(?:source|src|xfer|transfer|seede[rd]|tape[rd]|recorded)\b}mix or
|
143
|
+
paragraph =~ %r{\b(#{REGEXPS[:spots]}|#{REGEXPS[:mics]}|#{REGEXPS[:configs]}|#{REGEXPS[:cables]}|#{REGEXPS[:pres]}|#{REGEXPS[:dats]}|#{REGEXPS[:laptops]}|#{REGEXPS[:digicards]}|#{REGEXPS[:software]})\b}
|
144
|
+
end
|
145
|
+
|
146
|
+
def tracks_paragraph?(paragraph)
|
147
|
+
paragraph =~ /\b(cd|set|dis[ck]|volume|set)\b/i or
|
148
|
+
paragraph =~ TRACK_REGEXP or
|
149
|
+
paragraph =~ /^([\*\@\#\$\%\^]+)\s*[-=:]?\s*/
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|
data/lib/etree/track.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Etree
|
2
|
+
class Track
|
3
|
+
attr_accessor :name, :disc, :number
|
4
|
+
|
5
|
+
def initialize(attrs={})
|
6
|
+
attrs.each do |k,v|
|
7
|
+
send "#{k}=", v
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def file_name
|
12
|
+
("d%dt%02d %s" % [disc, number, name]).gsub(/\W/, '_').gsub(/_{2,}/,'_').gsub(/^_|_$/, '').downcase
|
13
|
+
end
|
14
|
+
|
15
|
+
def eql?(track)
|
16
|
+
self.class.equal?(track.class) &&
|
17
|
+
name == track.name &&
|
18
|
+
disc == track.disc &&
|
19
|
+
number == track.number
|
20
|
+
end
|
21
|
+
alias == eql?
|
22
|
+
|
23
|
+
def hash
|
24
|
+
name.hash ^ disc.hash ^ number.hash
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"d%dt%02d %s" % [disc, number, name]
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/test/etree_test.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class EtreeTest < MiniTest::Unit::TestCase
|
4
|
+
def test_parse_date
|
5
|
+
info_file = Etree::InfoFile.new
|
6
|
+
[
|
7
|
+
"Sunday June 13th 2010",
|
8
|
+
"June 13th 2010",
|
9
|
+
"sat, jun 13 10",
|
10
|
+
"6/13/2010",
|
11
|
+
"2010-06-13"
|
12
|
+
].each do |d|
|
13
|
+
assert_equal "2010-06-13", info_file.send(:parse_date, d).strftime("%Y-%m-%d")
|
14
|
+
end
|
15
|
+
assert_nil info_file.send(:parse_date, "foo")
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_parse_one_set
|
19
|
+
info_file = Etree::InfoFile.new :directory => File.expand_path(File.join(File.dirname(__FILE__), "examples", "moe2010-05-30early.skm140.flac16"))
|
20
|
+
info_file.parse
|
21
|
+
|
22
|
+
assert_equal "moe.", info_file.band
|
23
|
+
assert_equal "2010-05-30", info_file.date.strftime("%Y-%m-%d")
|
24
|
+
assert_equal "Summercamp Festival, Early Show, Moonshine Stage, Chillicothe, IL", info_file.venue
|
25
|
+
assert_equal [
|
26
|
+
"Intro",
|
27
|
+
"Bearsong >",
|
28
|
+
"Timmy Tucker",
|
29
|
+
"One Life",
|
30
|
+
"Deep This Time",
|
31
|
+
"Not Coming Down",
|
32
|
+
"Wind it up",
|
33
|
+
"San Ber'dino >",
|
34
|
+
"Muffin Man",
|
35
|
+
"A rare photo op..."
|
36
|
+
], info_file.discs.first
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_parse_multiple_sets_with_timings
|
40
|
+
info_file = Etree::InfoFile.new :directory => File.expand_path(File.join(File.dirname(__FILE__), "examples", "ph2010-06-11.mk4v.flac16"))
|
41
|
+
info_file.parse
|
42
|
+
|
43
|
+
assert_equal "Phish", info_file.band
|
44
|
+
assert_equal "2010-06-11", info_file.date.strftime("%Y-%m-%d")
|
45
|
+
assert_equal "Bridgeview, Illinois Toyota Park", info_file.venue
|
46
|
+
assert_equal [
|
47
|
+
Etree::Track.new(:name => "Down with Disease", :disc => 1, :number => 1 ),
|
48
|
+
Etree::Track.new(:name => "Wolfman's Brother", :disc => 1, :number => 2 ),
|
49
|
+
Etree::Track.new(:name => "Possum", :disc => 1, :number => 3 ),
|
50
|
+
Etree::Track.new(:name => "Boogie On Reggae Woman", :disc => 1, :number => 4 ),
|
51
|
+
Etree::Track.new(:name => "Reba", :disc => 1, :number => 5 ),
|
52
|
+
Etree::Track.new(:name => "Jesus Just Left Chicago", :disc => 1, :number => 6 ),
|
53
|
+
Etree::Track.new(:name => "The Divided Sky", :disc => 1, :number => 7 ),
|
54
|
+
Etree::Track.new(:name => "Golgi Apparatus", :disc => 1, :number => 8 ),
|
55
|
+
Etree::Track.new(:name => "David Bowie", :disc => 1, :number => 9 ),
|
56
|
+
Etree::Track.new(:name => "Light >", :disc => 2, :number => 1 ),
|
57
|
+
Etree::Track.new(:name => "Maze", :disc => 2, :number => 2 ),
|
58
|
+
Etree::Track.new(:name => "Ghost >", :disc => 2, :number => 3 ),
|
59
|
+
Etree::Track.new(:name => "Limb by Limb", :disc => 2, :number => 4 ),
|
60
|
+
Etree::Track.new(:name => "Prince Caspian >", :disc => 2, :number => 5 ),
|
61
|
+
Etree::Track.new(:name => "The Horse >", :disc => 2, :number => 6 ),
|
62
|
+
Etree::Track.new(:name => "Silent in the Morning", :disc => 2, :number => 7 ),
|
63
|
+
Etree::Track.new(:name => "Run Like an Antelope", :disc => 2, :number => 8 ),
|
64
|
+
Etree::Track.new(:name => "Show of Life", :disc => 2, :number => 9 ),
|
65
|
+
Etree::Track.new(:name => "crowd", :disc => 2, :number => 10),
|
66
|
+
Etree::Track.new(:name => "Cavern", :disc => 3, :number => 1 ),
|
67
|
+
Etree::Track.new(:name => "Julius", :disc => 3, :number => 2 )
|
68
|
+
], info_file.tracks
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
moe.
|
2
|
+
Summercamp Festival
|
3
|
+
2010-05-30
|
4
|
+
Early Show
|
5
|
+
Moonshine Stage
|
6
|
+
Chillicothe, IL
|
7
|
+
|
8
|
+
Neumann skm140(DIN/FOB/DFC/~50' FOS/~11' High) > Sound Devices Mixpre > Korg MR-1(24/44.1) > Audiogate > Cakewalk Sonar 7(Normalize to -0.1dB/dither to 16/44.1) > CDWave(Tracking) > FLAC(16/44.1/Level 8)
|
9
|
+
|
10
|
+
Recorded By: John Fairbairn
|
11
|
+
|
12
|
+
Set 1
|
13
|
+
=====
|
14
|
+
1. Intro
|
15
|
+
2. Bearsong >
|
16
|
+
3. Timmy Tucker
|
17
|
+
4. One Life*
|
18
|
+
5. Deep This Time
|
19
|
+
6. Not Coming Down
|
20
|
+
7. Wind it up
|
21
|
+
8. San Ber'dino^ >
|
22
|
+
9. Muffin Man%
|
23
|
+
10. A rare photo op...
|
24
|
+
|
25
|
+
* First Time Played
|
26
|
+
^ w/ Dweezil Zappa
|
27
|
+
% w/ moe./ZPZ band switch. one by one the members of Zappa Plays Zappa replaced moe. on stage and completed the set.
|
28
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
Phish
|
2
|
+
06/11/2010
|
3
|
+
Bridgeview, Illinois Toyota Park
|
4
|
+
|
5
|
+
Source: Schoeps mk4v> KC5> M222> NT222> Oade m148> SD 722 (@24bit/96kHz)
|
6
|
+
Location: FOB, DFC, NOS, 6' Stand, 60' from Stage
|
7
|
+
|
8
|
+
Transfer: SD 722> Samplitude SE 9.1.1(dither/resample)> CDWave> flac(16/44.1)
|
9
|
+
Taped, Transferred & Seeded by: taylorc (06/12/2010)
|
10
|
+
|
11
|
+
|
12
|
+
Set I
|
13
|
+
t01 [09:21] Down with Disease
|
14
|
+
t02 [10:02] Wolfman's Brother
|
15
|
+
t03 [10:11] Possum
|
16
|
+
t04 [05:15] Boogie On Reggae Woman
|
17
|
+
t05 [13:22] Reba
|
18
|
+
t06 [08:17] Jesus Just Left Chicago
|
19
|
+
t07 [14:28] The Divided Sky
|
20
|
+
t08 [04:34] Golgi Apparatus
|
21
|
+
t09 [11:16] David Bowie
|
22
|
+
|
23
|
+
Set II
|
24
|
+
t10 [13:20] Light>
|
25
|
+
t11 [09:37] Maze
|
26
|
+
t12 [15:10] Ghost>
|
27
|
+
t13 [10:43] Limb by Limb
|
28
|
+
t14 [07:52] Prince Caspian>
|
29
|
+
t15 [01:17] The Horse>
|
30
|
+
t16 [05:15] Silent in the Morning
|
31
|
+
t17 [11:14] Run Like an Antelope
|
32
|
+
t18 [06:12] Show of Life
|
33
|
+
t19 [02:52] crowd
|
34
|
+
|
35
|
+
Encore
|
36
|
+
t20 [04:13] Cavern
|
37
|
+
t21 [07:53] Julius
|
38
|
+
|
39
|
+
|
40
|
+
Notes:
|
41
|
+
Show of Life, first time played
|
42
|
+
Thanks to Jason Lonchar for the Schoeps tubes & Brian Porter for the Oade m148
|
43
|
+
Set I [1:26:46] Set II [1:23:32] Encore [12:06]
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: etree
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Paul Barry
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-10-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: chronic
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: escape
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Scripts for converting flac files posted to http://bt.etree.org to MP3
|
70
|
+
email:
|
71
|
+
- mail@paulbarry.com
|
72
|
+
executables:
|
73
|
+
- archive-dl
|
74
|
+
- flac2mp3
|
75
|
+
- parse_info
|
76
|
+
- wav2mp3
|
77
|
+
extensions: []
|
78
|
+
extra_rdoc_files: []
|
79
|
+
files:
|
80
|
+
- .document
|
81
|
+
- .gitignore
|
82
|
+
- .ruby-version
|
83
|
+
- Gemfile
|
84
|
+
- Gemfile.lock
|
85
|
+
- LICENSE
|
86
|
+
- README.md
|
87
|
+
- Rakefile
|
88
|
+
- VERSION
|
89
|
+
- bin/archive-dl
|
90
|
+
- bin/flac2mp3
|
91
|
+
- bin/parse_info
|
92
|
+
- bin/wav2mp3
|
93
|
+
- etree.gemspec
|
94
|
+
- lib/etree.rb
|
95
|
+
- lib/etree/info_file.rb
|
96
|
+
- lib/etree/track.rb
|
97
|
+
- test/etree_test.rb
|
98
|
+
- test/examples/moe2010-05-30early.skm140.flac16/moe2010-05-30early.txt
|
99
|
+
- test/examples/ph2010-06-11.mk4v.flac16/ph2010-06-11-1644-txt.txt
|
100
|
+
- test/test_helper.rb
|
101
|
+
homepage: http://github.com/pjb3/etree
|
102
|
+
licenses:
|
103
|
+
- MIT
|
104
|
+
metadata: {}
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - '>='
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
requirements: []
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 2.0.3
|
122
|
+
signing_key:
|
123
|
+
specification_version: 4
|
124
|
+
summary: Scripts for converting flac files posted to http://bt.etree.org to MP3
|
125
|
+
test_files:
|
126
|
+
- test/etree_test.rb
|
127
|
+
- test/examples/moe2010-05-30early.skm140.flac16/moe2010-05-30early.txt
|
128
|
+
- test/examples/ph2010-06-11.mk4v.flac16/ph2010-06-11-1644-txt.txt
|
129
|
+
- test/test_helper.rb
|
130
|
+
has_rdoc:
|