LOLastfm 0.0.3.3 → 0.0.3.5

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/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