mr_eko 0.3.3 → 0.3.4

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/lib/mr_eko/core.rb CHANGED
@@ -4,6 +4,10 @@ module MrEko
4
4
  def self.included(base)
5
5
  base.send(:include, GlobalHelpers)
6
6
  base.extend GlobalHelpers
7
+
8
+ # The Sequel timestamps plugin doesn't seem to work, so...
9
+ def before_create; self.created_on = Time.now.utc; end
10
+ def before_update; self.updated_on = Time.now.utc; end
7
11
  end
8
12
 
9
13
  module GlobalHelpers
data/lib/mr_eko/song.rb CHANGED
@@ -45,12 +45,7 @@ class MrEko::Song < Sequel::Model
45
45
 
46
46
  begin
47
47
  fingerprint_json = enmfp_data(filename, md5)
48
-
49
48
  profile = identify_from_enmfp_data(fingerprint_json)
50
-
51
- # Get the extended audio data from the profile
52
- analysis = MrEko.nest.song.profile(:id => profile.id, :bucket => 'audio_summary').songs.first.audio_summary
53
-
54
49
  rescue EnmfpError => e
55
50
  log %Q{Issues using ENMFP data "(#{e})" #{e.backtrace.join("\n")}}
56
51
  analysis, profile = get_datapoints_by_upload(filename)
@@ -60,22 +55,20 @@ class MrEko::Song < Sequel::Model
60
55
  song.filename = File.expand_path(filename)
61
56
  song.md5 = md5
62
57
  song.code = fingerprint_json ? fingerprint_json.code : nil
63
- song.tempo = analysis.tempo
64
- song.duration = analysis.duration
65
- song.fade_in = analysis.end_of_fade_in
66
- song.fade_out = analysis.start_of_fade_out
67
- song.key = analysis.key
68
- song.mode = analysis.mode
69
- song.loudness = analysis.loudness
70
- song.time_signature = analysis.time_signature
58
+ song.tempo = profile.audio_summary.tempo
59
+ song.duration = profile.audio_summary.duration
60
+ song.key = profile.audio_summary.key
61
+ song.mode = profile.audio_summary.mode
62
+ song.loudness = profile.audio_summary.loudness
63
+ song.time_signature = profile.audio_summary.time_signature
71
64
  song.echonest_id = profile.id
72
- song.bitrate = profile.bitrate
65
+ song.bitrate = fingerprint_json ? fingerprint_json.metadata.bitrate : nil
73
66
  song.title = profile.title
74
67
  song.artist = profile.artist || profile.artist_name
75
68
  song.album = fingerprint_json ? fingerprint_json.metadata.release : profile.release
76
- song.danceability = profile.audio_summary? ? profile.audio_summary.danceability : analysis.danceability
77
- song.energy = profile.audio_summary? ? profile.audio_summary.energy : analysis.energy
78
- end if analysis && profile
69
+ song.danceability = profile.audio_summary.danceability
70
+ song.energy = profile.audio_summary.energy
71
+ end
79
72
  end
80
73
 
81
74
  # Parses the file's ID3 tags and converts and strange encoding.
@@ -95,7 +95,7 @@ class MrEko::TimedPlaylist
95
95
  end
96
96
 
97
97
  # XXX Just sketching this part out at the moment...
98
- # needs tests (and complete logic!)
98
+ # needs tests and to work with attributes other than tempo!
99
99
  def find_songs
100
100
  step_count, step_length = step_map[:tempo]
101
101
  return unless step_count && step_length
@@ -107,27 +107,32 @@ class MrEko::TimedPlaylist
107
107
  songs_to_examine_per_step = step_count > all_songs.size ? 1 : all_songs.size / step_count
108
108
 
109
109
  overall_seconds_used = 0
110
- all_songs.each_slice(songs_to_examine_per_step).each do |songs|
110
+ all_songs.each_slice(songs_to_examine_per_step).each do |step_songs|
111
111
  break if overall_seconds_used >= @length
112
112
 
113
113
  song_length_proximity = 0
114
- length_map = songs.inject({}) do |hsh, song|
114
+ length_map = step_songs.inject({}) do |hsh, song|
115
115
  song_length_proximity = (song.duration - step_length).abs
116
116
  hsh[song_length_proximity] = song
117
117
  hsh
118
118
  end
119
119
 
120
120
  step_seconds_used = 0
121
+ song_set = []
121
122
  length_map.sort_by{ |key, song| key }.each do |length, song|
122
- @songs << song
123
+ song_set << song
123
124
  step_seconds_used += song.duration
124
125
  overall_seconds_used += song.duration
125
126
  break if step_seconds_used >= step_length
126
127
  end
127
128
 
129
+ # Make sure the songs are added the required order as they have been
130
+ # sorted by duration and thus may be in an odd order.
131
+ song_set = direction == :asc ? song_set.sort_by(&:tempo) : song_set.sort_by(&:tempo).reverse
132
+ @songs = @songs + song_set
128
133
  end
129
134
  # Might need to make a cluster map here instead of just choosing enough
130
- # songs to fulfill the step_length. This is because the over
135
+ # songs to fulfill the step_length. This is because the
131
136
  # Playlist#length can be fulfilled even before we reach the target/final
132
137
  # target. I think a better rule would be to pluck a song having the
133
138
  # initial and final values and then try to evenly spread out the remaining
data/lib/mr_eko.rb CHANGED
@@ -19,7 +19,7 @@ EKO_ENV = ENV['EKO_ENV'] || 'development'
19
19
  Sequel.default_timezone = :utc
20
20
 
21
21
  module MrEko
22
- VERSION = '0.3.3'
22
+ VERSION = '0.3.4'
23
23
  USER_DIR = File.join(ENV['HOME'], ".mreko")
24
24
  FINGERPRINTS_DIR = File.join(USER_DIR, 'fingerprints')
25
25
  LOG_DIR = File.join(USER_DIR, 'logs')
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.3.3'
16
+ s.version = '0.3.4'
17
17
  s.date = '2011-12-02'
18
18
  s.rubyforge_project = 'mr_eko'
19
19
 
data/test/song_test.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'ostruct'
1
2
  class SongTest < Test::Unit::TestCase
2
3
 
3
4
  TEST_MP3 = File.join(File.dirname(__FILE__), 'data', 'they_want_a_test.mp3')
@@ -24,6 +25,16 @@ class SongTest < Test::Unit::TestCase
24
25
  Hashie::Mash.new(opts)
25
26
  end
26
27
 
28
+ def song_identify_stub
29
+ Hashie::Mash.new(:artist_id => "ARZQYSZ1187FB3AC39", :artist_name => "Sebastian",
30
+ :id => "SOEQMAC12A6701D920", :message => "OK (match type 6)", :score =>57, :tag => 0, :title => "Ross Ross Ross",
31
+ :audio_summary => Hashie::Mash.new(:analysis_url => "url", :audio_md5 => "fb592e1fa581a8ad0b0478a45130e9e0",
32
+ :danceability => 0.265574327869162, :duration =>1223,
33
+ :energy => 0.732951527606216, :key => 11, :loudness =>-10.328,
34
+ :mode => 0, :tempo => 137.538, :time_signature =>1)
35
+ )
36
+ end
37
+
27
38
  def setup
28
39
  MrEko::Song.delete
29
40
  end
@@ -67,7 +78,7 @@ class SongTest < Test::Unit::TestCase
67
78
 
68
79
  should 'try uploading if the ENMFP fingerprint contains errors' do
69
80
  MrEko::Song.stubs(:enmfp_data).raises(MrEko::Song::EnmfpError)
70
- MrEko::Song.expects(:get_datapoints_by_upload).once.with(TEST_MP3).returns([])
81
+ MrEko::Song.expects(:get_datapoints_by_upload).with(TEST_MP3).returns([stub_everything, stub_everything(:audio_summary => stub_everything, :id => 'yu82')])
71
82
  MrEko::Song.catalog_via_enmfp(TEST_MP3)
72
83
  end
73
84
 
@@ -78,36 +89,13 @@ class SongTest < Test::Unit::TestCase
78
89
  end
79
90
 
80
91
  should 'try to upload when no songs are returned from the Song#identify call' do
81
- stub_data = enmfp_data_stub
82
- empty_profile_stub = stub(:songs => [])
83
- id_opts = {
84
- :code => stub_data.raw_data,
85
- :artist => stub_data.metadata.artist,
86
- :title => stub_data.metadata.title,
87
- :release => stub_data.metadata.release,
88
- :bucket => 'audio_summary'
89
- }
90
- MrEko::Song.stubs(:enmfp_data).returns(stub_data)
91
- Echonest::ApiMethods::Song.any_instance.expects(:identify).with(id_opts).returns(empty_profile_stub)
92
- MrEko::Song.expects(:get_datapoints_by_upload).returns([stub_everything, stub_everything(:id => 'whatever')])
92
+ MrEko::Song.stubs(:enmfp_data).returns(enmfp_data_stub)
93
+ MrEko::Song.expects(:identify_from_enmfp_data).with(enmfp_data_stub).raises(MrEko::Song::EnmfpError.new("no songs"))
94
+ MrEko::Song.expects(:get_datapoints_by_upload).returns([stub_everything, stub_everything(:audio_summary => stub_everything, :id => 'yu82')])
95
+
93
96
  MrEko::Song.catalog_via_enmfp(TEST_MP3)
94
97
  end
95
98
 
96
- should 'try to get the profile data when a song is returned from the Song#identify call' do
97
- stub_data = enmfp_data_stub
98
- profile_stub = stub(:songs => [stub_everything(:id => 'FJJ299KLOP')])
99
- profile_details_stub = stub(:songs => [stub(:audio_summary => stub_everything)])
100
-
101
- MrEko::Song.stubs(:enmfp_data).returns(stub_data)
102
- Echonest::ApiMethods::Song.any_instance.expects(:identify).returns(profile_stub)
103
- Echonest::ApiMethods::Song.any_instance.expects(:profile).with(:id => 'FJJ299KLOP', :bucket => 'audio_summary').returns(profile_details_stub)
104
- MrEko::Song.expects(:get_datapoints_by_upload).never
105
-
106
-
107
- assert_difference 'MrEko::Song.count' do
108
- MrEko::Song.catalog_via_enmfp(TEST_MP3)
109
- end
110
- end
111
99
  end
112
100
 
113
101
  context 'catalog_via_tags' do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mr_eko
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 3
10
- version: 0.3.3
9
+ - 4
10
+ version: 0.3.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ed Hickey