mr_eko 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: