mr_eko 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
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