hallon 0.18.0 → 0.18.1

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.
Files changed (65) hide show
  1. data/.rspec +1 -1
  2. data/CHANGELOG.md +12 -1
  3. data/README.markdown +13 -5
  4. data/Rakefile +23 -74
  5. data/examples/example_support.rb +2 -0
  6. data/hallon.gemspec +1 -1
  7. data/lib/hallon.rb +1 -6
  8. data/lib/hallon/album.rb +4 -4
  9. data/lib/hallon/album_browse.rb +6 -6
  10. data/lib/hallon/artist.rb +3 -3
  11. data/lib/hallon/artist_browse.rb +9 -9
  12. data/lib/hallon/audio_queue.rb +2 -1
  13. data/lib/hallon/base.rb +10 -10
  14. data/lib/hallon/enumerator.rb +3 -3
  15. data/lib/hallon/ext/spotify.rb +1 -47
  16. data/lib/hallon/image.rb +4 -4
  17. data/lib/hallon/link.rb +4 -4
  18. data/lib/hallon/linkable.rb +10 -10
  19. data/lib/hallon/observable/playlist.rb +2 -3
  20. data/lib/hallon/observable/playlist_container.rb +3 -12
  21. data/lib/hallon/player.rb +2 -2
  22. data/lib/hallon/playlist.rb +6 -6
  23. data/lib/hallon/playlist_container.rb +8 -8
  24. data/lib/hallon/scrobbler.rb +4 -4
  25. data/lib/hallon/search.rb +20 -5
  26. data/lib/hallon/session.rb +18 -17
  27. data/lib/hallon/toplist.rb +4 -4
  28. data/lib/hallon/track.rb +5 -5
  29. data/lib/hallon/user.rb +7 -7
  30. data/lib/hallon/version.rb +1 -1
  31. data/spec/hallon/album_browse_spec.rb +1 -1
  32. data/spec/hallon/artist_browse_spec.rb +1 -1
  33. data/spec/hallon/base_spec.rb +6 -3
  34. data/spec/hallon/enumerator_spec.rb +2 -2
  35. data/spec/hallon/hallon_spec.rb +0 -4
  36. data/spec/hallon/link_spec.rb +1 -1
  37. data/spec/hallon/linkable_spec.rb +4 -4
  38. data/spec/hallon/observable/playlist_container_spec.rb +3 -3
  39. data/spec/hallon/observable/playlist_spec.rb +1 -1
  40. data/spec/hallon/player_spec.rb +9 -9
  41. data/spec/hallon/playlist_container_spec.rb +2 -2
  42. data/spec/hallon/playlist_spec.rb +8 -8
  43. data/spec/hallon/scrobbler_spec.rb +8 -7
  44. data/spec/hallon/search_spec.rb +3 -3
  45. data/spec/hallon/session_spec.rb +10 -10
  46. data/spec/hallon/toplist_spec.rb +4 -4
  47. data/spec/hallon/track_spec.rb +6 -6
  48. data/spec/hallon/user_post_spec.rb +1 -1
  49. data/spec/hallon/user_spec.rb +1 -1
  50. data/spec/mockspotify.rb +36 -42
  51. data/spec/mockspotify/mockspotify_spec.rb +15 -15
  52. data/spec/spec_helper.rb +25 -21
  53. data/spec/support/album_mocks.rb +4 -4
  54. data/spec/support/artist_mocks.rb +5 -5
  55. data/spec/support/image_mocks.rb +4 -4
  56. data/spec/support/playlist_container_mocks.rb +4 -4
  57. data/spec/support/playlist_mocks.rb +6 -6
  58. data/spec/support/search_mocks.rb +2 -2
  59. data/spec/support/session_mocks.rb +1 -1
  60. data/spec/support/shared_for_callbacks.rb +1 -1
  61. data/spec/support/shared_for_linkable_objects.rb +3 -2
  62. data/spec/support/toplist_mocks.rb +2 -2
  63. data/spec/support/track_mocks.rb +4 -4
  64. data/spec/support/user_mocks.rb +2 -2
  65. metadata +5 -5
@@ -82,8 +82,8 @@ module Hallon
82
82
  # @param [#to_s] appkey
83
83
  # @param [Hash] options
84
84
  # @option options [String] :user_agent ("Hallon") User-Agent to use (length < `256`)
85
- # @option options [String] :settings_path ("tmp") where to save settings and user-specific cache
86
- # @option options [String] :cache_path ("") where to save cache files (`""` to disable)
85
+ # @option options [String] :settings_location ("tmp") where to save settings and user-specific cache
86
+ # @option options [String] :cache_location ("") where to save cache files (`""` to disable)
87
87
  # @option options [String] :tracefile (nil) path to libspotify API tracefile (`nil` to disable)
88
88
  # @option options [String] :device_id (nil) device ID for offline synchronization (`nil` to disable)
89
89
  # @option options [String] :proxy (nil) proxy URI (supports http, https, socks4, socks5)
@@ -105,8 +105,8 @@ module Hallon
105
105
 
106
106
  @options = {
107
107
  :user_agent => "Hallon",
108
- :settings_path => "tmp/hallon/",
109
- :cache_path => "tmp/hallon/",
108
+ :settings_location => "tmp/hallon/",
109
+ :cache_location => "tmp/hallon/",
110
110
  :load_playlists => true,
111
111
  :compress_playlists => true,
112
112
  :cache_playlist_metadata => true,
@@ -125,18 +125,19 @@ module Hallon
125
125
  @cache_size = 0
126
126
 
127
127
  subscribe_for_callbacks do |callbacks|
128
- config = Spotify::SessionConfig.new
129
- config[:api_version] = Hallon::API_VERSION
130
- config.application_key = appkey
131
- @options.each { |(key, value)| config.send(:"#{key}=", value) }
132
- config[:callbacks] = callbacks
128
+ # not overridable
129
+ @options[:api_version] = Hallon::API_VERSION
130
+ @options[:initially_unload_playlists] = ! @options.delete(:load_playlists)
131
+ @options[:dont_save_metadata_for_playlists] = ! @options.delete(:cache_playlist_metadata)
132
+
133
+ config = Spotify::SessionConfig.new(@options.merge(application_key: appkey, callbacks: callbacks))
133
134
 
134
135
  instance_eval(&block) if block_given?
135
136
 
136
137
  # You pass a pointer to the session pointer to libspotify >:)
137
138
  FFI::MemoryPointer.new(:pointer) do |p|
138
139
  Error::maybe_raise Spotify.session_create(config, p)
139
- @pointer = p.read_pointer
140
+ @pointer = Spotify::Session.new(p.read_pointer)
140
141
  end
141
142
  end
142
143
  end
@@ -155,7 +156,7 @@ module Hallon
155
156
  # @note returns nil if the session is not logged in.
156
157
  # @return [PlaylistContainer, nil]
157
158
  def container
158
- container = Spotify.session_playlistcontainer!(pointer)
159
+ container = Spotify.session_playlistcontainer(pointer)
159
160
  PlaylistContainer.from(container)
160
161
  end
161
162
 
@@ -198,7 +199,7 @@ module Hallon
198
199
  # @raise [Spotify::Error] if no credentials are stored in libspotify
199
200
  # @see #relogin!
200
201
  def relogin
201
- Spotify.session_relogin!(pointer)
202
+ Spotify.try(:session_relogin, pointer)
202
203
  end
203
204
 
204
205
  # Log in to Spotify using the given credentials.
@@ -267,7 +268,7 @@ module Hallon
267
268
 
268
269
  # @return [User] the User currently logged in.
269
270
  def user
270
- user = Spotify.session_user!(pointer)
271
+ user = Spotify.session_user(pointer)
271
272
  User.from(user)
272
273
  end
273
274
 
@@ -411,20 +412,20 @@ module Hallon
411
412
  # @see Player.bitrates
412
413
  def offline_bitrate=(bitrate)
413
414
  bitrate, resync = Array(bitrate)
414
- Spotify.session_preferred_offline_bitrate!(pointer, bitrate, !! resync)
415
+ Spotify.try(:session_preferred_offline_bitrate, pointer, bitrate, !! resync)
415
416
  end
416
417
 
417
418
  # @note Returns nil when no user is logged in.
418
419
  # @return [Playlist, nil] currently logged in user’s starred playlist.
419
420
  def starred
420
- playlist = Spotify.session_starred_create!(pointer)
421
+ playlist = Spotify.session_starred_create(pointer)
421
422
  Playlist.from(playlist)
422
423
  end
423
424
 
424
425
  # @note Returns nil when no user is logged in.
425
426
  # @return [Playlist, nil] currently logged in user’s inbox playlist.
426
427
  def inbox
427
- playlist = Spotify.session_inbox_create!(pointer)
428
+ playlist = Spotify.session_inbox_create(pointer)
428
429
  Playlist.from(playlist)
429
430
  end
430
431
 
@@ -461,7 +462,7 @@ module Hallon
461
462
  def tracks_starred(tracks, starred)
462
463
  FFI::MemoryPointer.new(:pointer, tracks.size) do |ptr|
463
464
  ptr.write_array_of_pointer tracks.map(&:pointer)
464
- Spotify.track_set_starred!(pointer, ptr, tracks.size, starred)
465
+ Spotify.try(:track_set_starred, pointer, ptr, tracks.size, starred)
465
466
  end
466
467
  end
467
468
 
@@ -11,7 +11,7 @@ module Hallon
11
11
  size :toplistbrowse_num_tracks
12
12
 
13
13
  # @return [Track, nil]
14
- item :toplistbrowse_track! do |track|
14
+ item :toplistbrowse_track do |track|
15
15
  Track.from(track)
16
16
  end
17
17
  end
@@ -21,7 +21,7 @@ module Hallon
21
21
  size :toplistbrowse_num_albums
22
22
 
23
23
  # @return [Album, nil]
24
- item :toplistbrowse_album! do |album|
24
+ item :toplistbrowse_album do |album|
25
25
  Album.from(album)
26
26
  end
27
27
  end
@@ -31,7 +31,7 @@ module Hallon
31
31
  size :toplistbrowse_num_artists
32
32
 
33
33
  # @return [Artist, nil]
34
- item :toplistbrowse_artist! do |artist|
34
+ item :toplistbrowse_artist do |artist|
35
35
  Artist.from(artist)
36
36
  end
37
37
  end
@@ -72,7 +72,7 @@ module Hallon
72
72
 
73
73
  subscribe_for_callbacks do |callback|
74
74
  @type = type
75
- @pointer = Spotify.toplistbrowse_create!(session.pointer, type, region, user, callback, nil)
75
+ @pointer = Spotify.toplistbrowse_create(session.pointer, type, region, user, callback, nil)
76
76
  end
77
77
  end
78
78
 
@@ -10,7 +10,7 @@ module Hallon
10
10
  size :track_num_artists
11
11
 
12
12
  # @return [Artist, nil]
13
- item :track_artist! do |artist|
13
+ item :track_artist do |artist|
14
14
  Artist.from(artist)
15
15
  end
16
16
  end
@@ -43,7 +43,7 @@ module Hallon
43
43
  # @param [String, Link, FFI::Pointer] link
44
44
  def initialize(link)
45
45
  FFI::MemoryPointer.new(:int) do |ptr|
46
- @pointer = to_pointer(link, :track, ptr)
46
+ @pointer = to_pointer(link, Spotify::Track, ptr)
47
47
  @offset = Rational(ptr.read_int, 1000)
48
48
  end
49
49
  end
@@ -74,7 +74,7 @@ module Hallon
74
74
  # @param [Integer] length
75
75
  # @return [Track]
76
76
  def self.local(title, artist, album = nil, length = nil)
77
- track = Spotify.localtrack_create!(artist, title, album || "", length || -1)
77
+ track = Spotify.localtrack_create(artist, title, album || "", length || -1)
78
78
  new(track)
79
79
  end
80
80
 
@@ -157,7 +157,7 @@ module Hallon
157
157
 
158
158
  # @return [Hallon::Album] album this track belongs to.
159
159
  def album
160
- album = Spotify.track_album!(pointer)
160
+ album = Spotify.track_album(pointer)
161
161
  Album.from(album)
162
162
  end
163
163
 
@@ -188,7 +188,7 @@ module Hallon
188
188
  # @see autolinked?
189
189
  # @return [Track] the track this track is autolinked to for audio playback.
190
190
  def playable_track
191
- track = Spotify.track_get_playable!(session.pointer, pointer)
191
+ track = Spotify.track_get_playable(session.pointer, pointer)
192
192
  Track.from(track)
193
193
  end
194
194
 
@@ -47,7 +47,7 @@ module Hallon
47
47
  @tracks = tracks
48
48
  @message = message
49
49
  @recipient_name = recipient_name
50
- @pointer = Spotify.inbox_post_tracks!(session.pointer, @recipient_name, ary, tracks.length, @message, callback, nil)
50
+ @pointer = Spotify.inbox_post_tracks(session.pointer, @recipient_name, ary, tracks.length, @message, callback, nil)
51
51
  end
52
52
  end
53
53
 
@@ -72,7 +72,7 @@ module Hallon
72
72
  include Loadable
73
73
 
74
74
  from_link :profile do |link|
75
- Spotify.link_as_user!(link)
75
+ Spotify.link_as_user(link)
76
76
  end
77
77
 
78
78
  to_link :from_user
@@ -86,11 +86,11 @@ module Hallon
86
86
  # Hallon::User.new("spotify:user:burgestrand")
87
87
  #
88
88
  # @note You can also instantiate User with a canonical username
89
- # @param [String, Link, Spotify::Pointer] link
89
+ # @param [String, Link, Spotify::User] link
90
90
  def initialize(link)
91
- @pointer = to_pointer(link, :user) do
91
+ @pointer = to_pointer(link, Spotify::User) do
92
92
  if link.is_a?(String) and link !~ /\Aspotify:user:/
93
- to_pointer("spotify:user:#{link}", :user)
93
+ to_pointer("spotify:user:#{link}", Spotify::User)
94
94
  end
95
95
  end
96
96
  end
@@ -114,14 +114,14 @@ module Hallon
114
114
  # @note Returns nil unless {User#loaded?}
115
115
  # @return [Playlist, nil] starred playlist of the User.
116
116
  def starred
117
- playlist = Spotify.session_starred_for_user_create!(session.pointer, name)
117
+ playlist = Spotify.session_starred_for_user_create(session.pointer, name)
118
118
  Playlist.from(playlist)
119
119
  end
120
120
 
121
121
  # @note Returns nil unless {#loaded?}
122
122
  # @return [PlaylistContainer, nil] published playlists of the User.
123
123
  def published
124
- container = Spotify.session_publishedcontainer_for_user_create!(session.pointer, name)
124
+ container = Spotify.session_publishedcontainer_for_user_create(session.pointer, name)
125
125
  PlaylistContainer.from(container)
126
126
  end
127
127
 
@@ -3,5 +3,5 @@ module Hallon
3
3
  # Current release version of Hallon
4
4
  #
5
5
  # @see http://semver.org/
6
- VERSION = [0, 18, 0].join('.')
6
+ VERSION = [0, 18, 1].join('.')
7
7
  end
@@ -14,7 +14,7 @@ describe Hallon::AlbumBrowse do
14
14
 
15
15
  describe ".new" do
16
16
  it "should raise an error if the browse request failed" do
17
- Spotify.should_receive(:albumbrowse_create).and_return(null_pointer)
17
+ spotify_api.should_receive(:albumbrowse_create).and_return(null_pointer)
18
18
  expect { Hallon::AlbumBrowse.new(mock_album) }.to raise_error(FFI::NullPointerError)
19
19
  end
20
20
 
@@ -15,7 +15,7 @@ describe Hallon::ArtistBrowse do
15
15
 
16
16
  describe ".new" do
17
17
  it "should raise an error if the browse request failed" do
18
- Spotify.should_receive(:artistbrowse_create).and_return(null_pointer)
18
+ spotify_api.should_receive(:artistbrowse_create).and_return(null_pointer)
19
19
  expect { Hallon::ArtistBrowse.new(mock_artist) }.to raise_error(FFI::NullPointerError)
20
20
  end
21
21
 
@@ -1,15 +1,18 @@
1
+ class Spotify::BasePointer < Spotify::ManagedPointer
2
+ end
3
+
1
4
  describe Hallon::Base do
2
5
  let(:klass) do
3
6
  Class.new(Hallon::Base) do
4
7
  def initialize(pointer)
5
- @pointer = to_pointer(pointer, :base) { |x| x }
8
+ @pointer = to_pointer(pointer, Spotify::BasePointer) { |x| x }
6
9
  end
7
10
  end
8
11
  end
9
12
 
10
13
  let(:base_pointer) do
11
- Spotify.stub(:base_add_ref! => nil, :base_release! => nil)
12
- Spotify::Pointer.new(a_pointer, :base, true)
14
+ spotify_api.stub(:base_pointer_release => nil)
15
+ Spotify::BasePointer.new(a_pointer)
13
16
  end
14
17
 
15
18
  describe "#to_pointer" do
@@ -1,8 +1,8 @@
1
1
  # coding: utf-8
2
2
  describe Hallon::Enumerator do
3
3
  def enumerator(items)
4
- Spotify.stub(:enumerator_size => items)
5
- Spotify.stub(:enumerator_item).and_return { |_, i| alphabet[i] }
4
+ spotify_api.stub(:enumerator_size => items)
5
+ spotify_api.stub(:enumerator_item).and_return { |_, i| alphabet[i] }
6
6
 
7
7
  klass = Class.new(Hallon::Enumerator) do
8
8
  size :enumerator_size
@@ -8,10 +8,6 @@ describe Hallon do
8
8
  specify { Hallon::API_VERSION.should == 12 }
9
9
  end
10
10
 
11
- describe "API_BUILD" do
12
- specify { Hallon::API_BUILD.should be_a String }
13
- end
14
-
15
11
  describe "URI" do
16
12
  example_uris.keys.each do |uri|
17
13
  specify(uri) { Hallon::URI.match(uri)[0].should eq uri }
@@ -13,7 +13,7 @@ describe Hallon::Link do
13
13
  end
14
14
 
15
15
  it "should raise an error given a null pointer" do
16
- expect { Hallon::Link.new(Spotify::Pointer.new(null_pointer, :link, false)) }.to raise_error(ArgumentError)
16
+ expect { Hallon::Link.new(Spotify::Link.new(null_pointer)) }.to raise_error(ArgumentError)
17
17
  end
18
18
 
19
19
  it "should raise an error when no session instance is about" do
@@ -10,7 +10,7 @@ describe Hallon::Linkable do
10
10
  let(:object) { klass.new }
11
11
  let(:pointer) { FFI::Pointer.new(1) }
12
12
 
13
- before(:each) { Spotify.stub(:link_as_search!) }
13
+ before(:each) { spotify_api.stub(:link_as_search) }
14
14
 
15
15
  it "should define the #from_link method" do
16
16
  object.respond_to?(:from_link, true).should be_false
@@ -24,7 +24,7 @@ describe Hallon::Linkable do
24
24
 
25
25
  describe "#to_link" do
26
26
  it "should return nil if link creation failed" do
27
- Spotify.should_receive(:link_create_from_user).and_return(null_pointer)
27
+ spotify_api.should_receive(:link_create_from_user).and_return(null_pointer)
28
28
 
29
29
  klass.instance_eval do
30
30
  to_link(:from_user)
@@ -48,7 +48,7 @@ describe Hallon::Linkable do
48
48
 
49
49
  describe "#from_link" do
50
50
  it "should call the appropriate Spotify function" do
51
- Spotify.should_receive(:link_as_search!).and_return(pointer)
51
+ spotify_api.should_receive(:link_as_search).and_return(pointer)
52
52
 
53
53
  klass.instance_eval do
54
54
  from_link(:as_search)
@@ -58,7 +58,7 @@ describe Hallon::Linkable do
58
58
  end
59
59
 
60
60
  it "should call the given block if necessary" do
61
- Spotify.should_not_receive(:link_as_search!)
61
+ spotify_api.should_not_receive(:link_as_search)
62
62
 
63
63
  called = false
64
64
  pointer = double(:null? => false)
@@ -1,16 +1,16 @@
1
1
  describe Hallon::Observable::PlaylistContainer do
2
2
  specification_for_callback "playlist_added" do
3
- let(:input) { [a_pointer, mock_playlist_raw, 3, :userdata] }
3
+ let(:input) { [a_pointer, mock_playlist, 3, :userdata] }
4
4
  let(:output) { [Hallon::Playlist.new(mock_playlist), 3] }
5
5
  end
6
6
 
7
7
  specification_for_callback "playlist_removed" do
8
- let(:input) { [a_pointer, mock_playlist_raw, 3, :userdata] }
8
+ let(:input) { [a_pointer, mock_playlist, 3, :userdata] }
9
9
  let(:output) { [Hallon::Playlist.new(mock_playlist), 3] }
10
10
  end
11
11
 
12
12
  specification_for_callback "playlist_moved" do
13
- let(:input) { [a_pointer, mock_playlist_raw, 3, 8, :userdata] }
13
+ let(:input) { [a_pointer, mock_playlist, 3, 8, :userdata] }
14
14
  let(:output) { [Hallon::Playlist.new(mock_playlist), 3, 8] }
15
15
  end
16
16
 
@@ -52,7 +52,7 @@ describe Hallon::Observable::Playlist do
52
52
  end
53
53
 
54
54
  specification_for_callback "track_created_changed" do
55
- let(:input) { [a_pointer, 7, mock_user_raw, 15, :userdata] }
55
+ let(:input) { [a_pointer, 7, mock_user, 15, :userdata] }
56
56
  let(:output) { [7, Hallon::User.new(mock_user), Time.at(15)] }
57
57
  end
58
58
 
@@ -31,43 +31,43 @@ describe Hallon::Player do
31
31
 
32
32
  describe "#load" do
33
33
  it "should load the given track" do
34
- Spotify.should_receive(:session_player_load).with(session.pointer, track.pointer)
34
+ spotify_api.should_receive(:session_player_load).with(session.pointer, track.pointer)
35
35
  player.load(track)
36
36
  end
37
37
 
38
38
  it "should try to instantiate the track if it’s not a track" do
39
- Spotify.should_receive(:session_player_load).with(session.pointer, track.pointer)
39
+ spotify_api.should_receive(:session_player_load).with(session.pointer, track.pointer)
40
40
  player.load(track.to_str)
41
41
  end
42
42
 
43
43
  it "should raise an error if load was unsuccessful" do
44
- Spotify.should_receive(:session_player_load).and_return(:is_loading)
44
+ spotify_api.should_receive(:session_player_load).and_return(:is_loading)
45
45
  expect { player.load(track) }.to raise_error(Hallon::Error, /IS_LOADING/)
46
46
  end
47
47
  end
48
48
 
49
49
  describe "#stop" do
50
50
  it "should unload the currently loaded track" do
51
- Spotify.should_receive(:session_player_unload).with(session.pointer)
51
+ spotify_api.should_receive(:session_player_unload).with(session.pointer)
52
52
  player.stop
53
53
  end
54
54
  end
55
55
 
56
56
  describe "#prefetch" do
57
57
  it "should set up given track for prefetching" do
58
- Spotify.should_receive(:session_player_prefetch).with(session.pointer, track.pointer)
58
+ spotify_api.should_receive(:session_player_prefetch).with(session.pointer, track.pointer)
59
59
  player.prefetch(track)
60
60
  end
61
61
  end
62
62
 
63
63
  describe "#play" do
64
64
  it "should start playback of given track" do
65
- Spotify.should_receive(:session_player_play).with(session.pointer, true)
65
+ spotify_api.should_receive(:session_player_play).with(session.pointer, true)
66
66
  player.play
67
67
  end
68
68
 
69
69
  it "should load and play given track if one was given" do
70
- Spotify.should_receive(:session_player_play).with(session.pointer, true)
70
+ spotify_api.should_receive(:session_player_play).with(session.pointer, true)
71
71
  player.should_receive(:load).with(track)
72
72
  player.play(track)
73
73
  end
@@ -75,14 +75,14 @@ describe Hallon::Player do
75
75
 
76
76
  describe "#pause" do
77
77
  it "should stop playback of given track" do
78
- Spotify.should_receive(:session_player_play).with(session.pointer, false)
78
+ spotify_api.should_receive(:session_player_play).with(session.pointer, false)
79
79
  player.pause
80
80
  end
81
81
  end
82
82
 
83
83
  describe "#seek" do
84
84
  it "should set up the currently loaded track at given position" do
85
- Spotify.should_receive(:session_player_seek).with(session.pointer, 1000)
85
+ spotify_api.should_receive(:session_player_seek).with(session.pointer, 1000)
86
86
  player.seek(1)
87
87
  end
88
88
  end