hallon 0.16.0 → 0.17.0
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/.gitignore +2 -1
- data/.travis.yml +2 -0
- data/CHANGELOG.md +22 -1
- data/Gemfile +2 -2
- data/README.markdown +2 -2
- data/Rakefile +69 -42
- data/hallon.gemspec +1 -1
- data/lib/hallon.rb +3 -2
- data/lib/hallon/album.rb +6 -4
- data/lib/hallon/artist.rb +6 -4
- data/lib/hallon/audio_queue.rb +1 -1
- data/lib/hallon/base.rb +4 -0
- data/lib/hallon/blob.rb +6 -0
- data/lib/hallon/error.rb +10 -41
- data/lib/hallon/ext/spotify.rb +1 -146
- data/lib/hallon/image.rb +8 -0
- data/lib/hallon/linkable.rb +6 -0
- data/lib/hallon/loadable.rb +6 -0
- data/lib/hallon/observable.rb +1 -1
- data/lib/hallon/observable/playlist_container.rb +2 -2
- data/lib/hallon/observable/session.rb +34 -0
- data/lib/hallon/player.rb +7 -3
- data/lib/hallon/playlist.rb +5 -1
- data/lib/hallon/playlist_container.rb +9 -8
- data/lib/hallon/scrobbler.rb +103 -0
- data/lib/hallon/search.rb +1 -0
- data/lib/hallon/session.rb +69 -13
- data/lib/hallon/toplist.rb +1 -1
- data/lib/hallon/track.rb +2 -2
- data/lib/hallon/version.rb +1 -1
- data/spec/hallon/album_spec.rb +16 -0
- data/spec/hallon/artist_spec.rb +16 -0
- data/spec/hallon/base_spec.rb +1 -1
- data/spec/hallon/error_spec.rb +3 -3
- data/spec/hallon/hallon_spec.rb +1 -1
- data/spec/hallon/image_spec.rb +6 -0
- data/spec/hallon/observable/session_spec.rb +20 -0
- data/spec/hallon/scrobbler_spec.rb +119 -0
- data/spec/hallon/session_spec.rb +38 -4
- data/spec/hallon/spotify_spec.rb +0 -45
- data/spec/mockspotify.rb +6 -1
- data/spec/spec_helper.rb +4 -5
- metadata +59 -20
- data/spec/support/cover_me.rb +0 -7
data/lib/hallon/search.rb
CHANGED
data/lib/hallon/session.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'singleton'
|
3
3
|
require 'timeout'
|
4
4
|
require 'thread'
|
5
|
+
require 'uri'
|
5
6
|
|
6
7
|
module Hallon
|
7
8
|
# The Session is fundamental for all communication with Spotify.
|
@@ -82,6 +83,7 @@ module Hallon
|
|
82
83
|
# @option options [String] :cache_path ("") where to save cache files (`""` to disable)
|
83
84
|
# @option options [String] :tracefile (nil) path to libspotify API tracefile (`nil` to disable)
|
84
85
|
# @option options [String] :device_id (nil) device ID for offline synchronization (`nil` to disable)
|
86
|
+
# @option options [String] :proxy (nil) proxy URI (supports http, https, socks4, socks5)
|
85
87
|
# @option options [Bool] :load_playlists (true) load playlists into RAM on startup
|
86
88
|
# @option options [Bool] :compress_playlists (true) compress local copies of playlists
|
87
89
|
# @option options [Bool] :cache_playlist_metadata (true) cache metadata for playlists locally
|
@@ -90,6 +92,14 @@ module Hallon
|
|
90
92
|
# @raise [Hallon::Error] if `sp_session_create` fails
|
91
93
|
# @see http://developer.spotify.com/en/libspotify/docs/structsp__session__config.html
|
92
94
|
def initialize(appkey, options = {}, &block)
|
95
|
+
if options[:proxy]
|
96
|
+
proxy_uri = URI(options[:proxy])
|
97
|
+
options[:proxy_username] ||= proxy_uri.user
|
98
|
+
options[:proxy_password] ||= proxy_uri.password
|
99
|
+
proxy_uri.user = proxy_uri.password = nil
|
100
|
+
options[:proxy] = proxy_uri.to_s
|
101
|
+
end
|
102
|
+
|
93
103
|
@options = {
|
94
104
|
:user_agent => "Hallon",
|
95
105
|
:settings_path => "tmp/hallon/",
|
@@ -98,6 +108,9 @@ module Hallon
|
|
98
108
|
:compress_playlists => true,
|
99
109
|
:cache_playlist_metadata => true,
|
100
110
|
:device_id => nil,
|
111
|
+
:proxy => nil,
|
112
|
+
:proxy_username => nil,
|
113
|
+
:proxy_password => nil,
|
101
114
|
:tracefile => nil,
|
102
115
|
}.merge(options)
|
103
116
|
|
@@ -164,7 +177,7 @@ module Hallon
|
|
164
177
|
# @note it also supports logging in via a credentials blob, if you pass
|
165
178
|
# a Hallon::Blob(blob_string) as the password instead of the real password
|
166
179
|
# @param [String] username
|
167
|
-
# @param [String]
|
180
|
+
# @param [String] password your password, or user credentials blob
|
168
181
|
# @param [Boolean] remember_me have libspotify remember credentials for {#relogin}
|
169
182
|
# @return [Session]
|
170
183
|
# @see login!
|
@@ -179,10 +192,10 @@ module Hallon
|
|
179
192
|
|
180
193
|
# Login the remembered user (see {#login}).
|
181
194
|
#
|
182
|
-
# @raise [
|
195
|
+
# @raise [Spotify::Error] if no credentials are stored in libspotify
|
183
196
|
# @see #relogin!
|
184
197
|
def relogin
|
185
|
-
|
198
|
+
Spotify.session_relogin!(pointer)
|
186
199
|
end
|
187
200
|
|
188
201
|
# Log in to Spotify using the given credentials.
|
@@ -219,7 +232,13 @@ module Hallon
|
|
219
232
|
tap { wait_for(:logged_out) { logged_out? } }
|
220
233
|
end
|
221
234
|
|
222
|
-
# @return [String] username of the
|
235
|
+
# @return [String, nil] username of the currently logged in user.
|
236
|
+
def username
|
237
|
+
username = Spotify.session_user_name(pointer)
|
238
|
+
username unless username.nil? or username.empty?
|
239
|
+
end
|
240
|
+
|
241
|
+
# @return [String, nil] username of the user stored in libspotify-remembered credentials.
|
223
242
|
def remembered_user
|
224
243
|
bufflen = Spotify.session_remembered_user(pointer, nil, 0)
|
225
244
|
FFI::Buffer.alloc_out(bufflen + 1) do |b|
|
@@ -254,15 +273,30 @@ module Hallon
|
|
254
273
|
Spotify.session_connectionstate(pointer)
|
255
274
|
end
|
256
275
|
|
257
|
-
#
|
276
|
+
# @return [Boolean] true if the session is currently set to private.
|
277
|
+
def private?
|
278
|
+
Spotify.session_is_private_session(pointer)
|
279
|
+
end
|
280
|
+
alias_method :britney_spears_mode?, :private?
|
281
|
+
|
282
|
+
# Set private session.
|
258
283
|
#
|
259
|
-
# @
|
260
|
-
#
|
284
|
+
# @note mode is reverted to normal after some time without user activity,
|
285
|
+
# see official libspotify documentation for details.
|
286
|
+
# @param [Boolean] is_private
|
287
|
+
def private=(is_private)
|
288
|
+
Spotify.session_set_private_session(pointer, !! is_private)
|
289
|
+
end
|
290
|
+
alias_method :britney_spears_mode=, :private=
|
291
|
+
|
292
|
+
# Set session cache size.
|
293
|
+
#
|
294
|
+
# @param [Integer] size new session cache size, in megabytes.
|
261
295
|
def cache_size=(size)
|
262
296
|
Spotify.session_set_cache_size(pointer, @cache_size = size)
|
263
297
|
end
|
264
298
|
|
265
|
-
# @return [String] currently logged in
|
299
|
+
# @return [String] currently logged in user’s country.
|
266
300
|
def country
|
267
301
|
coded = Spotify.session_user_country(pointer)
|
268
302
|
country = ((coded >> 8) & 0xFF).chr
|
@@ -275,7 +309,10 @@ module Hallon
|
|
275
309
|
# track = Hallon::Track.new("spotify:track:2LFQV2u6wXZmmySCWBkYGu")
|
276
310
|
# session.star(track)
|
277
311
|
#
|
278
|
-
# @
|
312
|
+
# @note (see #unstar)
|
313
|
+
# @raise (see #unstar)
|
314
|
+
#
|
315
|
+
# @param [Track…] tracks
|
279
316
|
# @return [Session]
|
280
317
|
def star(*tracks)
|
281
318
|
tap { tracks_starred(tracks, true) }
|
@@ -287,7 +324,13 @@ module Hallon
|
|
287
324
|
# track = Hallon::Track.new("spotify:track:2LFQV2u6wXZmmySCWBkYGu")
|
288
325
|
# session.unstar(track)
|
289
326
|
#
|
290
|
-
# @
|
327
|
+
# @note this method might raise a Spotify::Error, however when this might
|
328
|
+
# occur is not documented in libspotify (and I have yet to find any
|
329
|
+
# way to trigger it myself). it’s entirely possible that this method
|
330
|
+
# never returns an error, but we can’t know for sure.
|
331
|
+
#
|
332
|
+
# @raise [Spotify:Error] if libspotify reports an error (when this happens is unknown and undocumented)
|
333
|
+
# @param [Track…] tracks
|
291
334
|
# @return [Session]
|
292
335
|
def unstar(*tracks)
|
293
336
|
tap { tracks_starred(tracks, false) }
|
@@ -295,6 +338,7 @@ module Hallon
|
|
295
338
|
|
296
339
|
# Set the connection rules for this session.
|
297
340
|
#
|
341
|
+
# @raise [ArgumentError] if given invalid connection rules
|
298
342
|
# @param [Symbol, …] connection_rules
|
299
343
|
# @see Session.connection_rules
|
300
344
|
def connection_rules=(connection_rules)
|
@@ -307,6 +351,7 @@ module Hallon
|
|
307
351
|
|
308
352
|
# Set the connection type for this session.
|
309
353
|
#
|
354
|
+
# @raise [ArgumentError] if given invalid connection type
|
310
355
|
# @param [Symbol] connection_type
|
311
356
|
# @see Session.connection_types
|
312
357
|
def connection_type=(connection_type)
|
@@ -345,15 +390,25 @@ module Hallon
|
|
345
390
|
|
346
391
|
# Set preferred offline bitrate.
|
347
392
|
#
|
348
|
-
# @example
|
393
|
+
# @example setting offline bitrate without resync
|
394
|
+
# session.offline_bitrate = :'96k'
|
395
|
+
#
|
396
|
+
# @example setting offline bitrate and resync already-synced tracks
|
349
397
|
# session.offline_bitrate = :'96k', true
|
350
398
|
#
|
399
|
+
# @note under normal circumstances, ArgumentError is the error that will
|
400
|
+
# be raised on an invalid bitrate. However, if Hallon fails the type
|
401
|
+
# checking (for whatever reason), libspotify will itself return an
|
402
|
+
# error as well.
|
403
|
+
#
|
404
|
+
# @raise [ArgumentError] if given invalid bitrate
|
405
|
+
# @raise [Spotify::Error] if libspotify does not accept the given bitrate (see note)
|
351
406
|
# @param [Symbol] bitrate
|
352
407
|
# @param [Boolean] resync (default: false)
|
353
408
|
# @see Player.bitrates
|
354
409
|
def offline_bitrate=(bitrate)
|
355
410
|
bitrate, resync = Array(bitrate)
|
356
|
-
Spotify.session_preferred_offline_bitrate(pointer, bitrate, !! resync)
|
411
|
+
Spotify.session_preferred_offline_bitrate!(pointer, bitrate, !! resync)
|
357
412
|
end
|
358
413
|
|
359
414
|
# @note Returns nil when no user is logged in.
|
@@ -397,12 +452,13 @@ module Hallon
|
|
397
452
|
private
|
398
453
|
# Set starred status of given tracks.
|
399
454
|
#
|
455
|
+
# @raise [Spotify::Error] … maybe, it’s undocumented in libspotify, who knows?
|
400
456
|
# @param [Array<Track>] tracks
|
401
457
|
# @param [Boolean] starred
|
402
458
|
def tracks_starred(tracks, starred)
|
403
459
|
FFI::MemoryPointer.new(:pointer, tracks.size) do |ptr|
|
404
460
|
ptr.write_array_of_pointer tracks.map(&:pointer)
|
405
|
-
Spotify.track_set_starred(pointer, ptr, tracks.size, starred)
|
461
|
+
Spotify.track_set_starred!(pointer, ptr, tracks.size, starred)
|
406
462
|
end
|
407
463
|
end
|
408
464
|
|
data/lib/hallon/toplist.rb
CHANGED
@@ -114,7 +114,7 @@ module Hallon
|
|
114
114
|
# Convert a given two-character region to a Spotify
|
115
115
|
# compliant region (encoded in a 16bit integer).
|
116
116
|
#
|
117
|
-
# @param [#to_s]
|
117
|
+
# @param [#to_s] region
|
118
118
|
# @return [Integer]
|
119
119
|
def to_country(region)
|
120
120
|
code = region.to_s.upcase
|
data/lib/hallon/track.rb
CHANGED
@@ -210,9 +210,9 @@ module Hallon
|
|
210
210
|
|
211
211
|
# Set {#starred?} status of current track.
|
212
212
|
#
|
213
|
-
# @note
|
213
|
+
# @note (see Session#star)
|
214
|
+
# @raise (see Session#star)
|
214
215
|
# @param [Boolean] starred
|
215
|
-
# @return [Boolean]
|
216
216
|
def starred=(starred)
|
217
217
|
starred ? session.star(self) : session.unstar(self)
|
218
218
|
end
|
data/lib/hallon/version.rb
CHANGED
data/spec/hallon/album_spec.rb
CHANGED
@@ -80,6 +80,14 @@ describe Hallon::Album do
|
|
80
80
|
it "should be nil if there is no image" do
|
81
81
|
empty_album.cover.should be_nil
|
82
82
|
end
|
83
|
+
|
84
|
+
it "should support specifying size" do
|
85
|
+
album.cover(:large).should eq Hallon::Image.new(mock_image_id)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should raise an error when given an invalid size" do
|
89
|
+
expect { album.cover(:lawl) }.to raise_error(ArgumentError)
|
90
|
+
end
|
83
91
|
end
|
84
92
|
|
85
93
|
describe "#cover_link" do
|
@@ -90,5 +98,13 @@ describe Hallon::Album do
|
|
90
98
|
it "should be nil if there is no image" do
|
91
99
|
empty_album.cover_link.should be_nil
|
92
100
|
end
|
101
|
+
|
102
|
+
it "should support specifying size" do
|
103
|
+
album.cover_link(:large).should eq Hallon::Link.new("spotify:image:3ad93423add99766e02d563605c6e76ed2b0e400")
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should raise an error when given an invalid size" do
|
107
|
+
expect { album.cover_link(:lawl) }.to raise_error(ArgumentError)
|
108
|
+
end
|
93
109
|
end
|
94
110
|
end
|
data/spec/hallon/artist_spec.rb
CHANGED
@@ -54,6 +54,14 @@ describe Hallon::Artist do
|
|
54
54
|
it "should be nil if an image is not available" do
|
55
55
|
empty_artist.portrait.should be_nil
|
56
56
|
end
|
57
|
+
|
58
|
+
it "should support specifying size" do
|
59
|
+
artist.portrait(:large).should eq Hallon::Image.new(mock_image_id)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should raise an error when given an invalid size" do
|
63
|
+
expect { artist.portrait(:lawl) }.to raise_error(ArgumentError)
|
64
|
+
end
|
57
65
|
end
|
58
66
|
|
59
67
|
describe "#portrait_link" do
|
@@ -64,5 +72,13 @@ describe Hallon::Artist do
|
|
64
72
|
it "should be nil if an image is not available" do
|
65
73
|
empty_artist.portrait_link.should be_nil
|
66
74
|
end
|
75
|
+
|
76
|
+
it "should support specifying size" do
|
77
|
+
artist.portrait_link(:large).should eq Hallon::Link.new(mock_image_uri)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should raise an error when given an invalid size" do
|
81
|
+
expect { artist.portrait_link(:lawl) }.to raise_error(ArgumentError)
|
82
|
+
end
|
67
83
|
end
|
68
84
|
end
|
data/spec/hallon/base_spec.rb
CHANGED
data/spec/hallon/error_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
describe Hallon::Error do
|
2
2
|
subject { described_class }
|
3
3
|
|
4
|
-
it { should <=
|
4
|
+
it { should <= StandardError }
|
5
5
|
|
6
6
|
describe ".disambiguate" do
|
7
7
|
it "should not fail on invalid numbers" do
|
@@ -15,11 +15,11 @@ describe Hallon::Error do
|
|
15
15
|
|
16
16
|
describe ".explain" do
|
17
17
|
it "should work properly given an integer" do
|
18
|
-
subject.explain(0).should
|
18
|
+
subject.explain(0).should match 'sp_error: 0'
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should work properly given a symbol" do
|
22
|
-
subject.explain(:bad_api_version).should
|
22
|
+
subject.explain(:bad_api_version).should match 'sp_error: 1'
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
data/spec/hallon/hallon_spec.rb
CHANGED
data/spec/hallon/image_spec.rb
CHANGED
@@ -18,6 +18,12 @@ describe Hallon::Image do
|
|
18
18
|
|
19
19
|
specify { image.should be_a Hallon::Loadable }
|
20
20
|
|
21
|
+
describe ".sizes" do
|
22
|
+
it "should list all sizes" do
|
23
|
+
Hallon::Image.sizes.should eq [:normal, :small, :large]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
21
27
|
describe "#loaded?" do
|
22
28
|
it "returns true when the image is loaded" do
|
23
29
|
image.should be_loaded
|
@@ -144,4 +144,24 @@ describe Hallon::Observable::Session do
|
|
144
144
|
let(:input) { [a_pointer, :ok] }
|
145
145
|
let(:output) { [:ok] }
|
146
146
|
end
|
147
|
+
|
148
|
+
specification_for_callback "credentials_blob_updated" do
|
149
|
+
let(:input) { [a_pointer, "credentials"] }
|
150
|
+
let(:output) { ["credentials"] }
|
151
|
+
end
|
152
|
+
|
153
|
+
specification_for_callback "connectionstate_updated" do
|
154
|
+
let(:input) { [a_pointer] }
|
155
|
+
let(:output) { [] }
|
156
|
+
end
|
157
|
+
|
158
|
+
specification_for_callback "scrobble_error" do
|
159
|
+
let(:input) { [a_pointer, :ok] }
|
160
|
+
let(:output) { [:ok] }
|
161
|
+
end
|
162
|
+
|
163
|
+
specification_for_callback "private_session_mode_changed" do
|
164
|
+
let(:input) { [a_pointer, true] }
|
165
|
+
let(:output) { [true] }
|
166
|
+
end
|
147
167
|
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
describe Hallon::Scrobbler do
|
2
|
+
let(:scrobbling) { Hallon::Scrobbler.new(:facebook) }
|
3
|
+
|
4
|
+
describe ".providers" do
|
5
|
+
it "returns a list of social providers" do
|
6
|
+
Hallon::Scrobbler.providers.should include :facebook
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "raises an error if given an invalid social provider" do
|
12
|
+
expect { Hallon::Scrobbler.new(:invalid_provider) }.to raise_error(ArgumentError, /social provider/)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#provider" do
|
17
|
+
it "returns the social provider the scrobbler was instantiated with" do
|
18
|
+
scrobbling.provider.should eq :facebook
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#credentials=" do
|
23
|
+
it "sets the credentials for the scrobbler provider" do
|
24
|
+
Spotify.should_receive(:session_set_social_credentials).with(anything, :facebook, "Kim", "password").and_return(:ok)
|
25
|
+
scrobbling.credentials = "Kim", "password"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#possible?" do
|
30
|
+
it "returns true if scrobbling is possible" do
|
31
|
+
Spotify.mocksp_session_set_is_scrobbling_possible(session.pointer, scrobbling.provider, true)
|
32
|
+
scrobbling.should be_possible
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns false if scrobbling is not possible" do
|
36
|
+
Spotify.mocksp_session_set_is_scrobbling_possible(session.pointer, scrobbling.provider, false)
|
37
|
+
scrobbling.should_not be_possible
|
38
|
+
end
|
39
|
+
|
40
|
+
it "raises an error if libspotify does not like us" do
|
41
|
+
Spotify.should_receive(:session_is_scrobbling_possible).and_return(:invalid_indata)
|
42
|
+
expect { scrobbling.possible? }.to raise_error(Spotify::Error)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#enabled=" do
|
47
|
+
it "sets the local scrobbling" do
|
48
|
+
scrobbling.should_not be_enabled
|
49
|
+
scrobbling.enabled = true
|
50
|
+
scrobbling.should be_enabled
|
51
|
+
scrobbling.enabled = false
|
52
|
+
scrobbling.should_not be_enabled
|
53
|
+
end
|
54
|
+
|
55
|
+
it "raises an error if setting scrobbling state fails" do
|
56
|
+
Spotify.should_receive(:session_set_scrobbling).and_return(:invalid_indata)
|
57
|
+
expect { scrobbling.enabled = true }.to raise_error(Spotify::Error, /INVALID_INDATA/)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#enabled?" do
|
62
|
+
before do
|
63
|
+
Spotify.should_receive(:session_is_scrobbling).and_return do |session, provider, buffer|
|
64
|
+
buffer.write_int(Spotify.enum_value(state_symbol))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "if the state is locally enabled" do
|
69
|
+
let(:state_symbol) { :local_enabled }
|
70
|
+
|
71
|
+
it "returns true" do
|
72
|
+
scrobbling.should be_enabled
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "if the state is locally disabled" do
|
77
|
+
let(:state_symbol) { :local_disabled }
|
78
|
+
|
79
|
+
it "returns false" do
|
80
|
+
scrobbling.should_not be_enabled
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "if the state is globally enabled" do
|
85
|
+
let(:state_symbol) { :global_enabled }
|
86
|
+
|
87
|
+
it "returns true" do
|
88
|
+
scrobbling.should be_enabled
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "if the state is globally disabled" do
|
93
|
+
let(:state_symbol) { :global_disabled }
|
94
|
+
|
95
|
+
it "returns false" do
|
96
|
+
scrobbling.should_not be_enabled
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#reset" do
|
102
|
+
def state(scrobbler)
|
103
|
+
session = scrobbling.send(:session)
|
104
|
+
state = nil
|
105
|
+
FFI::Buffer.alloc_out(:int) do |buffer|
|
106
|
+
Spotify.session_is_scrobbling!(session.pointer, scrobbling.provider, buffer)
|
107
|
+
state = buffer.read_int
|
108
|
+
end
|
109
|
+
Spotify.enum_type(:scrobbling_state)[state]
|
110
|
+
end
|
111
|
+
|
112
|
+
it "sets the local scrobbling state to use the global state" do
|
113
|
+
scrobbling.enabled = true
|
114
|
+
state(scrobbling).should eq :local_enabled
|
115
|
+
scrobbling.reset
|
116
|
+
state(scrobbling).should eq :global_enabled
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|