LOLastfm 0.0.3.3 → 0.0.3.5

Sign up to get free protection for your applications and to get access to all the features.
data/LOLastfm.gemspec CHANGED
@@ -14,6 +14,7 @@ Gem::Specification.new {|s|
14
14
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
15
  s.require_paths = ['lib']
16
16
 
17
+ s.add_dependency 'eventmachine'
17
18
  s.add_dependency 'lastfm'
18
19
  s.add_dependency 'taglib-ruby'
19
20
  }
data/bin/LOLastfm CHANGED
@@ -28,8 +28,7 @@ EM.run {
28
28
  d.start
29
29
 
30
30
  EM.error_handler {|e|
31
- $stderr.puts e.message
32
- $stderr.puts e.backtrace
31
+ d.log e
33
32
  }
34
33
 
35
34
  %w[INT KILL].each {|sig|
data/lib/LOLastfm.rb CHANGED
@@ -53,6 +53,8 @@ class LOLastfm
53
53
  def start
54
54
  return if started?
55
55
 
56
+ @started = true
57
+
56
58
  @server = if @host && @port
57
59
  EM.start_server(host, port, LOLastfm::Connection) {|conn|
58
60
  conn.fm = self
@@ -78,6 +80,8 @@ class LOLastfm
78
80
  EM.cancel_timer @timer
79
81
 
80
82
  @checker.stop if @checker
83
+
84
+ @started = false
81
85
  ensure
82
86
  save
83
87
  end
@@ -113,19 +117,16 @@ class LOLastfm
113
117
 
114
118
  def log (what, group = nil)
115
119
  io = StringIO.new
116
-
117
- io.print "[#{Time.now}#{" (#{group})" if group}] "
120
+ io.print "[#{Time.now}#{", #{group}" if group}] "
118
121
 
119
122
  if what.is_a? Exception
120
123
  io.puts "#{what.class.name}: #{what.message}"
121
- io.puts e.backtrace
124
+ io.puts what.backtrace
122
125
  else
123
126
  io.puts what
124
127
  end
125
128
 
126
- io.seek 0
127
-
128
- io.read.tap {|text|
129
+ io.string.tap {|text|
129
130
  $stderr.puts text
130
131
 
131
132
  File.open(@logs_at, 'a') { |f| f.print text }
@@ -179,6 +180,8 @@ class LOLastfm
179
180
 
180
181
  def listened! (song)
181
182
  @session.track.scrobble(song.artist, song.title, song.listened_at.to_time.to_i, song.album, song.track, song.id, song.length)
183
+ rescue SystemCallError, SocketError, EOFError
184
+ false
182
185
  rescue Exception => e
183
186
  log e, :listened
184
187
 
@@ -204,6 +207,8 @@ class LOLastfm
204
207
 
205
208
  def love! (song)
206
209
  @session.track.love(song.artist, song.title)
210
+ rescue SystemCallError, SocketError, EOFError
211
+ false
207
212
  rescue Exception => e
208
213
  log e, :love
209
214
 
@@ -229,6 +234,8 @@ class LOLastfm
229
234
 
230
235
  def unlove! (song)
231
236
  @session.track.unlove(song.artist, song.title)
237
+ rescue SystemCallError, SocketError, EOFError
238
+ false
232
239
  rescue Exception => e
233
240
  log e, :unlove
234
241
 
@@ -262,7 +269,7 @@ class LOLastfm
262
269
  name = args.shift.to_sym
263
270
 
264
271
  if args.first.is_a? String
265
- require args.pop
272
+ require args.shift
266
273
  elsif !self.class.checkers[name]
267
274
  begin
268
275
  require "LOLastfm/checkers/#{name}"
@@ -24,19 +24,19 @@ class Cache
24
24
  end
25
25
 
26
26
  def listened (song)
27
- return if song.nil? || @listened.member?(song)
27
+ return if song.nil?
28
28
 
29
29
  @listened << song
30
30
  end
31
31
 
32
32
  def love (song)
33
- return if song.nil? || @loved.member?(song)
33
+ return if song.nil?
34
34
 
35
35
  @loved << song
36
36
  end
37
37
 
38
38
  def unlove (song)
39
- return if song.nil? || @unloved.member?(song)
39
+ return if song.nil?
40
40
 
41
41
  @unloved << song
42
42
  end
@@ -47,19 +47,19 @@ class Cache
47
47
 
48
48
  def flush!
49
49
  until @listened.empty?
50
- break unless fm.listened! Song.new(@listened.first)
50
+ break unless fm.listened! @listened.first
51
51
 
52
52
  @listened.shift
53
53
  end
54
54
 
55
55
  until @loved.empty?
56
- break unless fm.love! Song.new(@loved.first)
56
+ break unless fm.love! @loved.first
57
57
 
58
58
  @loved.shift
59
59
  end
60
60
 
61
61
  until @unloved.empty?
62
- break unless fm.unlove! Song.new(@unloved.first)
62
+ break unless fm.unlove! @unloved.first
63
63
 
64
64
  @unloved.shift
65
65
  end
@@ -87,13 +87,17 @@ class Checker
87
87
 
88
88
  def set_timeout (*args, &block)
89
89
  EM.schedule {
90
- @timers << EM.add_timer(*args, &block)
90
+ EM.add_timer(*args, &block).tap {|timer|
91
+ @timers << timer
92
+ }
91
93
  }
92
94
  end
93
95
 
94
96
  def set_interval (*args, &block)
95
97
  EM.schedule {
96
- @timers << EM.add_periodic_timer(*args, &block)
98
+ EM.add_periodic_timer(*args, &block).tap {|timer|
99
+ @timers << timer
100
+ }
97
101
  }
98
102
  end
99
103
 
@@ -102,6 +106,8 @@ class Checker
102
106
  EM.cancel_timer(what)
103
107
  }
104
108
  end
109
+
110
+ alias clear_interval clear_timeout
105
111
  end
106
112
 
107
113
  end
@@ -29,8 +29,8 @@ end
29
29
 
30
30
  LOLastfm.define_checker :cmus do
31
31
  settings.default[:socket] = '~/.cmus/socket'
32
- settings.default[:every] = 5
33
32
  settings.default[:timeout] = 0.005
33
+ settings.default[:every] = 5
34
34
 
35
35
  if @cmus = Cmus::Controller.new(settings[:socket], settings[:timeout]) rescue false
36
36
  @last = @cmus.status
@@ -41,12 +41,9 @@ LOLastfm.define_checker :cmus do
41
41
  end
42
42
 
43
43
  set_interval settings[:every] do
44
- unless @cmus
45
- @cmus = Cmus::Controller.new(settings[:socket], settings[:timeout]) rescue next
46
- @last = @cmus.status
47
- end
44
+ next unless @cmus = Cmus::Controller.new(settings[:socket], settings[:timeout]) rescue false
48
45
 
49
- unless status = @cmus.status rescue nil
46
+ unless status = @cmus.status rescue false
50
47
  @cmus = nil
51
48
  next
52
49
  end
@@ -41,61 +41,61 @@ LOLastfm.define_checker :moc do
41
41
  settings.default[:every] = 5
42
42
 
43
43
  create = proc {
44
- unless moc = Moc::Controller.new(settings[:socket]) rescue false
44
+ unless @moc = Moc::Controller.new(settings[:socket]) rescue false
45
45
  set_timeout settings[:every], &create unless stopped?
46
46
 
47
47
  next
48
48
  end
49
49
 
50
50
  Thread.new {
51
- song, position = nil
52
-
53
51
  begin
54
- moc.loop {|e|
52
+ @moc.loop {|e|
55
53
  if e == :audio_stop
56
- next unless song
54
+ next unless @song
57
55
 
58
- if song.stream?
59
- listened song
56
+ if @song.stream?
57
+ listened @song
58
+ elsif LOLastfm::Song.is_scrobblable?(@position, @song.length)
59
+ listened @song
60
60
  else
61
- if LOLastfm::Song.is_scrobblable?(position, song.length)
62
- listened song
63
- else
64
- stopped_playing!
65
- end
61
+ stopped_playing!
66
62
  end
67
63
 
68
- song = nil
64
+ @song = nil
69
65
  elsif e == :audio_start
70
- now_playing song = moc.status(true).to_song
71
- elsif e == :state && moc.status(true) == :paused
66
+ now_playing @song = @moc.status(true).to_song
67
+ elsif e == :state && @moc.status(true) == :paused
72
68
  stopped_playing!
73
69
  elsif e == :ctime
74
- unless song
75
- now_playing song = moc.status(true).to_song
70
+ unless @song
71
+ now_playing @song = @moc.status(true).to_song
76
72
  end
77
73
 
78
- if song.stream?
79
- if moc.status(true).song.title != song.title
80
- listened song
81
- now_playing song = moc.status(true).to_song
74
+ if @song.stream?
75
+ if @moc.status(true).song.title != @song.title
76
+ listened @song
77
+ now_playing @song = @moc.status(true).to_song
82
78
  end
83
79
  else
84
- position = moc.status(true).song.position
80
+ @position = @moc.status(true).song.position rescue nil
85
81
  end
86
82
  end
87
83
  }
88
84
  rescue Exception => e
89
85
  log e, 'checker: moc'
86
+
87
+ retry if @moc.active?
90
88
  end
91
89
 
92
- if song.stream?
93
- listened song
94
- else
95
- if LOLastfm::Song.is_scrobblable?(position, song.length)
96
- listened song
90
+ if @song
91
+ if @song.stream?
92
+ listened @song
97
93
  else
98
- stopped_playing!
94
+ if LOLastfm::Song.is_scrobblable?(@position, @song.length)
95
+ listened @song
96
+ else
97
+ stopped_playing!
98
+ end
99
99
  end
100
100
  end
101
101
 
@@ -0,0 +1,128 @@
1
+ #--
2
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3
+ # Version 2, December 2004
4
+ #
5
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
6
+ # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
7
+ #
8
+ # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
+ #++
10
+
11
+ require 'mpd'
12
+
13
+ class MPD::Controller::Status
14
+ def to_song
15
+ return unless song
16
+
17
+ if song.file =~ %r{\w+://}
18
+ comment = song.file
19
+ else
20
+ path = song.file
21
+ end
22
+
23
+ LOLastfm::Song.new(true,
24
+ track: song.track,
25
+ title: song.title,
26
+ artist: song.artist,
27
+ album: song.album,
28
+ length: song.duration,
29
+ comment: comment,
30
+ path: path,
31
+ stream: !!comment
32
+ )
33
+ end
34
+ end
35
+
36
+ LOLastfm.define_checker :mpd do
37
+ settings.default[:host] = 'localhost'
38
+ settings.default[:port] = 6600
39
+ settings.default[:every] = 5
40
+
41
+ create = proc {
42
+ unless @mpd = MPD::Controller.new(settings[:socket] || settings[:host], settings[:port])
43
+ set_timeout settings[:every], &create unless stopped?
44
+
45
+ next
46
+ end
47
+
48
+ if settings[:password]
49
+ @mpd.authenticate(settings[:password])
50
+ end
51
+
52
+ @last = @mpd.status
53
+
54
+ if @last == :play
55
+ now_playing @last.to_song
56
+ end
57
+
58
+ Thread.new {
59
+ timeout = set_interval settings[:every] do
60
+ @mpd.stop_waiting
61
+ end
62
+
63
+ begin
64
+ @mpd.loop {|e|
65
+ if e == :player
66
+ status = @mpd.status
67
+
68
+ if status == :stop
69
+ next unless @last
70
+
71
+ song = @last.to_song
72
+
73
+ if song.stream?
74
+ listened song
75
+ elsif LOLastfm::Song.is_scrobblable?(@position, song.length)
76
+ listened song
77
+ else
78
+ stopped_playing!
79
+ end
80
+ elsif status == :pause
81
+ stopped_playing!
82
+ else
83
+ if @last == :play
84
+ song = @last.to_song
85
+
86
+ if song.stream?
87
+ listened song
88
+ elsif LOLastfm::Song.is_scrobblable?(@position, song.length)
89
+ listened song
90
+ end
91
+ end
92
+
93
+ @position = 0
94
+
95
+ now_playing status.to_song
96
+ end
97
+
98
+ @last = @mpd.status
99
+ elsif e == :break
100
+ @position = @mpd.status.song.position
101
+ end
102
+ }
103
+ rescue Exception => e
104
+ log e, 'checker: mpd'
105
+
106
+ retry if mpd.active?
107
+ end
108
+
109
+ if song
110
+ if song.stream?
111
+ listened song
112
+ else
113
+ if LOLastfm::Song.is_scrobblable?(position, song.length)
114
+ listened song
115
+ else
116
+ stopped_playing!
117
+ end
118
+ end
119
+ end
120
+
121
+ clear_timeout timeout
122
+
123
+ set_timeout settings[:every], &create unless stopped?
124
+ }
125
+ }
126
+
127
+ create.call
128
+ end
@@ -29,18 +29,22 @@ module Glyr
29
29
  end
30
30
  end
31
31
 
32
- File.join(Dir.tmpdir, rand.to_s).tap {|path|
32
+ File.expand_path(ENV['GLYR_CACHE'] || '~/.LOLastfm/glyr.cache').tap {|path|
33
33
  FileUtils.mkpath(path)
34
34
  cache_at path
35
35
  }
36
36
  end
37
37
 
38
- LOLastfm.define_command :lyrics? do
39
- song = now_playing?
38
+ LOLastfm.define_command :lyrics? do |song|
39
+ song = song ? Song.new(song) : now_playing?
40
40
 
41
- EM.defer -> {
42
- Glyr.query(title: song.title, artist: song.artist, album: song.album).lyrics
43
- }, -> results {
44
- send_response results.map(&:to_hash)
45
- }
41
+ if song
42
+ EM.defer -> {
43
+ Glyr.query(title: song.title, artist: song.artist, album: song.album).lyrics
44
+ }, -> results {
45
+ send_response results.map(&:to_hash)
46
+ }
47
+ else
48
+ send_response nil
49
+ end
46
50
  end
data/lib/LOLastfm/song.rb CHANGED
@@ -34,9 +34,9 @@ class Song
34
34
  data = Hash[data.map { |key, value| [key.to_sym, value] }]
35
35
 
36
36
  @track = data[:track] && data[:track].to_i
37
- @title = data[:title]
38
- @album = data[:album]
39
- @artist = data[:artist]
37
+ @title = data[:title] && data[:title].strip
38
+ @album = data[:album] && data[:album].strip
39
+ @artist = data[:artist] && data[:artist].strip
40
40
  @length = data[:length] && data[:length].to_i
41
41
  @comment = data[:comment]
42
42
  @listened_at = data[:listened_at]
@@ -60,6 +60,10 @@ class Song
60
60
  @listened_at = DateTime.now
61
61
  end
62
62
  end
63
+
64
+ @title = nil if @title && @title.strip.empty?
65
+ @album = nil if @album && @album.empty?
66
+ @arist = nil if @artist && @artist.empty?
63
67
  end
64
68
 
65
69
  def fill!
@@ -10,6 +10,6 @@
10
10
 
11
11
  class LOLastfm
12
12
  def self.version
13
- '0.0.3.3'
13
+ '0.0.3.5'
14
14
  end
15
15
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: LOLastfm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3.3
4
+ version: 0.0.3.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-05 00:00:00.000000000 Z
12
+ date: 2012-11-01 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: eventmachine
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: lastfm
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +82,7 @@ files:
66
82
  - lib/LOLastfm/checker.rb
67
83
  - lib/LOLastfm/checkers/cmus.rb
68
84
  - lib/LOLastfm/checkers/moc.rb
85
+ - lib/LOLastfm/checkers/mpd.rb
69
86
  - lib/LOLastfm/checkers/process.rb
70
87
  - lib/LOLastfm/client.rb
71
88
  - lib/LOLastfm/commands/glyr.rb