mr_eko 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -11,10 +11,10 @@ Example:
11
11
  mreko scan jakob-semaphore.mp3 pelican-drought.mp3
12
12
 
13
13
  # Output a PLS playlist of fast, minor-key music
14
- mreko playlist --tempo '>120' --mode minor --format pls > rainy_day_suicidal_playlist.pls
14
+ mreko playlist --tempo '>120' --mode minor > rainy_day_suicidal_playlist.pls
15
15
 
16
16
  # Output a playlist of shorter, up-tempo, danceable, major-keyed songs
17
- mreko playlist --preset gym --format pls > sweaty_playlist.pls
17
+ mreko playlist --preset gym > sweaty_playlist.pls
18
18
 
19
19
  # Output a 30 minute playlist which builds from tempo 120 to 185 BPM. See notes on TimedPlaylists below.
20
20
  mreko playlist --timed 1800 --tempo 120 --final 185 > morning_commute.pls
data/lib/mr_eko/song.rb CHANGED
@@ -72,14 +72,14 @@ class MrEko::Song < Sequel::Model
72
72
  end
73
73
  end
74
74
 
75
- # Parses the file's ID3 tags and converts and strange encoding.
75
+ # Parses the file's ID3 tags
76
76
  #
77
77
  # @param [String] The file path
78
- # @return [ID3Lib::Tag]
78
+ # @return [MrEko::TagParser::Result]
79
79
  def self.parse_id3_tags(filename)
80
80
  log "Parsing ID3 tags"
81
81
 
82
- clean_tags ID3Lib::Tag.new(filename, ID3Lib::V_ALL)
82
+ MrEko::TagParser.parse(filename)
83
83
  end
84
84
 
85
85
 
@@ -89,7 +89,8 @@ class MrEko::Song < Sequel::Model
89
89
  # @return [MrEko::Song]
90
90
  def self.catalog_via_tags(filename, opts={})
91
91
  tags = parse_id3_tags(filename)
92
- return unless has_required_tags? tags
92
+
93
+ return unless tags.reject{ |k, v| v.blank? }.size >= REQUIRED_ID3_TAGS.size
93
94
 
94
95
  md5 = opts[:md5] || MrEko.md5(filename)
95
96
  begin
@@ -98,7 +99,7 @@ class MrEko::Song < Sequel::Model
98
99
  :bucket => 'audio_summary',
99
100
  :limit => 1).songs.first
100
101
  rescue => e
101
- log "BAD TAGS? #{tags.artist} - #{tags.title} - #{filename}"
102
+ log "BAD TAGS? #{tags.inspect} #{filename}"
102
103
  log e.message
103
104
  log e.backtrace.join("\n")
104
105
  return
@@ -126,13 +127,6 @@ class MrEko::Song < Sequel::Model
126
127
  end if analysis
127
128
  end
128
129
 
129
- def self.has_required_tags?(tags)
130
- found = REQUIRED_ID3_TAGS.inject([]) do |present, meth|
131
- present << tags.send(meth)
132
- end
133
-
134
- found.compact.size == REQUIRED_ID3_TAGS.size ? true : false
135
- end
136
130
 
137
131
  # Using the Echonest Musical Fingerprint lib in the hopes
138
132
  # of sidestepping the mp3 upload process.
@@ -218,21 +212,4 @@ class MrEko::Song < Sequel::Model
218
212
  File.expand_path File.join(MrEko::FINGERPRINTS_DIR, "#{md5}.json")
219
213
  end
220
214
 
221
- # @param [Array<ID3Lib::Tag>]
222
- # @return [Array<ID3Lib::Tag>]
223
- def self.clean_tags(tags)
224
-
225
- (REQUIRED_ID3_TAGS + [:album]).each do |rt|
226
- tag = tags.send(rt).to_s
227
- if tag.encoding != Encoding::UTF_8
228
- decoded = tag.encode
229
- else
230
- decoded = tag
231
- end
232
-
233
- tags.send("#{rt}=", decoded)
234
- end
235
-
236
- tags
237
- end
238
215
  end
@@ -0,0 +1,22 @@
1
+ class MrEko::TagParser
2
+
3
+ def self.parse(filename)
4
+ TagLib::FileRef.open(filename, false) do |file|
5
+ tag = file.tag
6
+ result = Result.new
7
+ result.artist = tag.artist
8
+ result.title = tag.title
9
+ result.album = tag.album
10
+
11
+ result
12
+ end
13
+
14
+ end
15
+
16
+ class Result < Hash
17
+ include Hashie::Extensions::MethodAccess
18
+ include Hashie::Extensions::IndifferentAccess
19
+ end
20
+
21
+ end
22
+
data/lib/mr_eko.rb CHANGED
@@ -9,7 +9,7 @@ require 'sequel/extensions/migration'
9
9
  require "logger"
10
10
  require "hashie"
11
11
  require "digest/md5"
12
- require 'id3lib'
12
+ require 'taglib'
13
13
  require "echonest"
14
14
  begin
15
15
  require 'debugger'
@@ -22,7 +22,7 @@ EKO_ENV = ENV['EKO_ENV'] || 'development'
22
22
  Sequel.default_timezone = :utc
23
23
 
24
24
  module MrEko
25
- VERSION = '0.6.0'
25
+ VERSION = '0.6.1'
26
26
  USER_DIR = File.join(ENV['HOME'], ".mreko")
27
27
  FINGERPRINTS_DIR = File.join(USER_DIR, 'fingerprints')
28
28
  LOG_DIR = File.join(USER_DIR, 'logs')
@@ -144,3 +144,4 @@ require "mr_eko/playlist"
144
144
  require "mr_eko/timed_playlist"
145
145
  require "mr_eko/song"
146
146
  require "mr_eko/playlist_entry"
147
+ require "mr_eko/tag_parser"
data/mr_eko.gemspec CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  ## If your rubyforge_project name is different, then edit it and comment out
14
14
  ## the sub! line in the Rakefile
15
15
  s.name = 'mr_eko'
16
- s.version = '0.6.0'
16
+ s.version = '0.6.1'
17
17
  s.date = '2013-08-13'
18
18
  s.rubyforge_project = 'mr_eko'
19
19
 
@@ -51,7 +51,7 @@ Gem::Specification.new do |s|
51
51
  s.add_dependency('httpclient', "~> 2.1")
52
52
  s.add_dependency('bassnode-ruby-echonest')
53
53
  s.add_dependency('json', "= 1.4.6")
54
- s.add_dependency('id3lib-ruby')
54
+ s.add_dependency('taglib-ruby')
55
55
 
56
56
  ## List your development dependencies here. Development dependencies are
57
57
  ## those that are only needed during development
@@ -101,13 +101,16 @@ Gem::Specification.new do |s|
101
101
  lib/mr_eko/playlist_entry.rb
102
102
  lib/mr_eko/presets.rb
103
103
  lib/mr_eko/song.rb
104
+ lib/mr_eko/tag_parser.rb
104
105
  lib/mr_eko/timed_playlist.rb
105
106
  mr_eko.gemspec
106
107
  test/data/tagless.mp3
107
108
  test/data/they_want_a_test.mp3
109
+ test/data/unicode.mp3
108
110
  test/mr_eko_test.rb
109
111
  test/playlist_test.rb
110
112
  test/song_test.rb
113
+ test/tag_parser_test.rb
111
114
  test/test.rb
112
115
  test/timed_playlist_test.rb
113
116
  ]
Binary file
data/test/song_test.rb CHANGED
@@ -1,9 +1,6 @@
1
1
  require 'ostruct'
2
2
  class SongTest < Test::Unit::TestCase
3
3
 
4
- TEST_MP3 = File.join(File.dirname(__FILE__), 'data', 'they_want_a_test.mp3')
5
- TAGLESS_MP3 = File.join(File.dirname(__FILE__), 'data', 'tagless.mp3')
6
-
7
4
  def enmfp_data_stub(overrides={})
8
5
  opts = {
9
6
  'code' => '98ouhajsnd081oi2he0da8sdoihjasdi2y9e8aASD3e8yaushdjQWD',
@@ -100,12 +97,12 @@ class SongTest < Test::Unit::TestCase
100
97
 
101
98
  context 'catalog_via_tags' do
102
99
 
103
- context 'for a mp3 with no useful tag information' do
100
+ context 'for a mp3 with no ID3 tag information' do
104
101
 
105
102
  setup do
106
103
  @mp3 = MrEko::Song.parse_id3_tags(TAGLESS_MP3)
107
- assert_empty @mp3.artist
108
- assert_empty @mp3.title
104
+ assert_nil @mp3.artist
105
+ assert_nil @mp3.title
109
106
  end
110
107
 
111
108
  should 'return nil' do
@@ -132,25 +129,4 @@ class SongTest < Test::Unit::TestCase
132
129
  end
133
130
  end
134
131
 
135
- context 'cleaning encoded ID3 tags' do
136
-
137
- should "decode iTunes' encoded tags" do
138
- dm = 'Dead Meadow'.encode(Encoding::UCS_2BE, Encoding::UTF_8)
139
- tag_stub = OpenStruct.new(:artist => dm, :title => 'Good Moaning')
140
- ID3Lib::Tag.expects(:new).once.returns(tag_stub)
141
- parsed_tags = MrEko::Song.parse_id3_tags(TEST_MP3)
142
-
143
- assert_equal "Dead Meadow", parsed_tags.artist
144
- end
145
-
146
- should "not alter the tags when they aren't encoded" do
147
- tag_stub = OpenStruct.new(:artist => 'Dead Meadow', :title => 'Good Moaning')
148
- ID3Lib::Tag.expects(:new).once.returns(tag_stub)
149
-
150
- parsed = MrEko::Song.parse_id3_tags(TEST_MP3)
151
-
152
- assert_equal parsed.artist, 'Dead Meadow'
153
- assert_equal parsed.title, 'Good Moaning'
154
- end
155
- end
156
132
  end
@@ -0,0 +1,21 @@
1
+ class TagParserTest < Test::Unit::TestCase
2
+
3
+ context 'parse' do
4
+
5
+ should 'return an abject with the tags' do
6
+ parser = MrEko::TagParser.parse(TEST_MP3)
7
+
8
+ assert_equal 'Swamp Rooters', parser.artist
9
+ assert_equal 'Swamp Cat Rag', parser.title
10
+ assert_equal 'Misc', parser.album
11
+ end
12
+
13
+ should 'handles files without tags' do
14
+ parser = MrEko::TagParser.parse(TAGLESS_MP3)
15
+
16
+ assert_nil parser.artist
17
+ assert_nil parser.title
18
+ assert_nil parser.album
19
+ end
20
+ end
21
+ end
data/test/test.rb CHANGED
@@ -13,6 +13,11 @@ end
13
13
 
14
14
  class Test::Unit::TestCase
15
15
 
16
+ TEST_MP3 = File.join(File.dirname(__FILE__), 'data', 'they_want_a_test.mp3')
17
+ TAGLESS_MP3 = File.join(File.dirname(__FILE__), 'data', 'tagless.mp3')
18
+ UNICODE_MP3 = File.join(File.dirname(__FILE__), 'data', 'unicode.mp3')
19
+
20
+
16
21
  # Could be fleshed out some more.
17
22
  def sequel_dataset_stub
18
23
  data = mock()
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mr_eko
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -108,7 +108,7 @@ dependencies:
108
108
  - !ruby/object:Gem::Version
109
109
  version: 1.4.6
110
110
  - !ruby/object:Gem::Dependency
111
- name: id3lib-ruby
111
+ name: taglib-ruby
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  none: false
114
114
  requirements:
@@ -276,13 +276,16 @@ files:
276
276
  - lib/mr_eko/playlist_entry.rb
277
277
  - lib/mr_eko/presets.rb
278
278
  - lib/mr_eko/song.rb
279
+ - lib/mr_eko/tag_parser.rb
279
280
  - lib/mr_eko/timed_playlist.rb
280
281
  - mr_eko.gemspec
281
282
  - test/data/tagless.mp3
282
283
  - test/data/they_want_a_test.mp3
284
+ - test/data/unicode.mp3
283
285
  - test/mr_eko_test.rb
284
286
  - test/playlist_test.rb
285
287
  - test/song_test.rb
288
+ - test/tag_parser_test.rb
286
289
  - test/test.rb
287
290
  - test/timed_playlist_test.rb
288
291
  homepage: http://github.com/bassnode/mreko
@@ -300,7 +303,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
300
303
  version: '0'
301
304
  segments:
302
305
  - 0
303
- hash: 2527726127632796201
306
+ hash: -723694834172722563
304
307
  required_rubygems_version: !ruby/object:Gem::Requirement
305
308
  none: false
306
309
  requirements: