hallon 0.11.0 → 0.12.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.
Files changed (68) hide show
  1. data/.yardopts +1 -0
  2. data/{CHANGELOG → CHANGELOG.md} +82 -27
  3. data/Gemfile +1 -0
  4. data/README.markdown +1 -1
  5. data/Rakefile +8 -6
  6. data/examples/adding_tracks_to_playlist.rb +3 -0
  7. data/examples/logging_in.rb +3 -0
  8. data/examples/playing_audio.rb +130 -0
  9. data/examples/printing_link_information.rb +3 -0
  10. data/examples/show_published_playlists_of_user.rb +5 -13
  11. data/hallon.gemspec +2 -2
  12. data/lib/hallon.rb +15 -0
  13. data/lib/hallon/album.rb +1 -1
  14. data/lib/hallon/album_browse.rb +4 -3
  15. data/lib/hallon/artist.rb +1 -1
  16. data/lib/hallon/artist_browse.rb +5 -4
  17. data/lib/hallon/base.rb +7 -2
  18. data/lib/hallon/error.rb +1 -1
  19. data/lib/hallon/ext/spotify.rb +26 -42
  20. data/lib/hallon/image.rb +7 -8
  21. data/lib/hallon/observable.rb +134 -62
  22. data/lib/hallon/observable/album_browse.rb +30 -0
  23. data/lib/hallon/observable/artist_browse.rb +31 -0
  24. data/lib/hallon/observable/image.rb +31 -0
  25. data/lib/hallon/observable/player.rb +13 -0
  26. data/lib/hallon/observable/playlist.rb +194 -0
  27. data/lib/hallon/observable/playlist_container.rb +74 -0
  28. data/lib/hallon/observable/post.rb +30 -0
  29. data/lib/hallon/observable/search.rb +29 -0
  30. data/lib/hallon/observable/session.rb +236 -0
  31. data/lib/hallon/observable/toplist.rb +30 -0
  32. data/lib/hallon/player.rb +8 -17
  33. data/lib/hallon/playlist.rb +11 -7
  34. data/lib/hallon/playlist_container.rb +11 -4
  35. data/lib/hallon/queue.rb +71 -0
  36. data/lib/hallon/search.rb +10 -7
  37. data/lib/hallon/session.rb +18 -21
  38. data/lib/hallon/toplist.rb +4 -3
  39. data/lib/hallon/user.rb +5 -5
  40. data/lib/hallon/version.rb +1 -1
  41. data/spec/hallon/album_browse_spec.rb +4 -0
  42. data/spec/hallon/artist_browse_spec.rb +4 -0
  43. data/spec/hallon/base_spec.rb +26 -9
  44. data/spec/hallon/hallon_spec.rb +0 -18
  45. data/spec/hallon/image_spec.rb +0 -1
  46. data/spec/hallon/link_spec.rb +14 -0
  47. data/spec/hallon/observable/album_browse_spec.rb +7 -0
  48. data/spec/hallon/observable/artist_browse_spec.rb +7 -0
  49. data/spec/hallon/observable/image_spec.rb +8 -0
  50. data/spec/hallon/observable/playlist_container_spec.rb +21 -0
  51. data/spec/hallon/observable/playlist_spec.rb +85 -0
  52. data/spec/hallon/observable/post_spec.rb +8 -0
  53. data/spec/hallon/observable/search_spec.rb +7 -0
  54. data/spec/hallon/observable/session_spec.rb +143 -0
  55. data/spec/hallon/observable/toplist_spec.rb +7 -0
  56. data/spec/hallon/observable_spec.rb +134 -65
  57. data/spec/hallon/playlist_container_spec.rb +24 -18
  58. data/spec/hallon/playlist_spec.rb +2 -0
  59. data/spec/hallon/queue_spec.rb +35 -0
  60. data/spec/hallon/session_spec.rb +4 -4
  61. data/spec/hallon/spotify_spec.rb +35 -9
  62. data/spec/mockspotify.rb +2 -3
  63. data/spec/spec_helper.rb +0 -1
  64. data/spec/support/common_objects.rb +27 -15
  65. data/spec/support/enumerable_comparison.rb +9 -0
  66. data/spec/support/shared_for_callbacks.rb +60 -0
  67. data/spec/support/shared_for_linkable_objects.rb +1 -1
  68. metadata +56 -20
@@ -0,0 +1,30 @@
1
+ module Hallon::Observable
2
+ # Callbacks related to {Hallon::AlbumBrowse} objects.
3
+ module AlbumBrowse
4
+ # Includes {Hallon::Observable} for you.
5
+ def self.extended(other)
6
+ other.send(:include, Hallon::Observable)
7
+ end
8
+
9
+ protected
10
+
11
+ # @return [Method] load callback
12
+ def initialize_callbacks
13
+ callback_for(:load)
14
+ end
15
+
16
+ # This callback is fired when the AlbumBrowse object is fully loaded.
17
+ #
18
+ # @example listening to this callback
19
+ # browse = AlbumBrowse.new(album)
20
+ # browse.on(:load) do
21
+ # puts "Album browser has loaded!"
22
+ # end
23
+ #
24
+ # @yield [self]
25
+ # @yieldparam [AlbumBrowse] self
26
+ def load_callback(pointer, userdata)
27
+ trigger(pointer, :load)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ module Hallon::Observable
2
+ # Callbacks related to {Hallon::ArtistBrowse} objects.
3
+ module ArtistBrowse
4
+ # Includes {Hallon::Observable} for you.
5
+ def self.extended(other)
6
+ other.send(:include, Hallon::Observable)
7
+ end
8
+
9
+ protected
10
+
11
+ # @return [Method] load callback
12
+ def initialize_callbacks
13
+ callback_for(:load)
14
+ end
15
+
16
+ # This callback is fired when the ArtistBrowse object is fully loaded.
17
+ #
18
+ # @example listening to this callback
19
+ # browse = ArtistBrowse.new(album)
20
+ # browse.on(:load) do
21
+ # puts "Artist browser has loaded!"
22
+ # end
23
+ #
24
+ # @yield [self]
25
+ # @yieldparam [ArtistBrowse] self
26
+ def load_callback(pointer, userdata)
27
+ trigger(pointer, :load)
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,31 @@
1
+ module Hallon::Observable
2
+ # Callbacks related to {Hallon::Image} objects.
3
+ module Image
4
+ # Includes {Hallon::Observable} for you.
5
+ def self.extended(other)
6
+ other.send(:include, Hallon::Observable)
7
+ end
8
+
9
+ protected
10
+
11
+ # @return [Method] load callback
12
+ def initialize_callbacks
13
+ callback_for(:load)
14
+ end
15
+
16
+ # This callback is fired when the Image object is fully loaded.
17
+ #
18
+ # @example listening to this callback
19
+ # image = Image.new("spotify:image:3ad93423add99766e02d563605c6e76ed2b0e450")
20
+ # image.on(:load) do
21
+ # puts "Image has loaded"
22
+ # end
23
+ #
24
+ # @yield [self]
25
+ # @yieldparam [Image] self
26
+ def load_callback(pointer, userdata)
27
+ trigger(pointer, :load)
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,13 @@
1
+ module Hallon::Observable
2
+ # We only care about a few of the Session callbacks, actually,
3
+ # but since this object is not *really* a Spotify object we do
4
+ # cheat a little bit.
5
+ module Player
6
+ # Includes {Hallon::Observable} for you.
7
+ def self.extended(other)
8
+ other.send(:include, Hallon::Observable)
9
+ end
10
+
11
+ include Hallon::Observable::Session
12
+ end
13
+ end
@@ -0,0 +1,194 @@
1
+ module Hallon::Observable
2
+ # Callbacks related to {Hallon::Playlist} objects.
3
+ module Playlist
4
+ # Includes {Hallon::Observable} for you.
5
+ def self.extended(other)
6
+ other.send(:include, Hallon::Observable)
7
+ end
8
+
9
+ protected
10
+
11
+ # @return [Spotify::PlaylistCallbacks]
12
+ def initialize_callbacks
13
+ struct = Spotify::PlaylistCallbacks.new
14
+ struct.members.each do |member|
15
+ struct[member] = callback_for(member)
16
+ end
17
+ struct
18
+ end
19
+
20
+ # @example listening to this event
21
+ # playlist.on(:tracks_added) do |tracks, position, playlist|
22
+ # puts "#{tracks.map(&:name).join(', ')} added at #{position} to #{playlist.name}"
23
+ # end
24
+ #
25
+ # @yield [tracks, position, self] tracks_added
26
+ # @yieldparam [Array<Track>] tracks
27
+ # @yieldparam [Integer] position
28
+ # @yieldparam [Playlist] self
29
+ def tracks_added_callback(pointer, tracks, num_tracks, position, userdata)
30
+ trigger(pointer, :tracks_added, callback_make_tracks(tracks, num_tracks), position)
31
+ end
32
+
33
+ # @example listening to this event
34
+ # playlist.on(:tracks_removed) do |tracks, playlist|
35
+ # puts "#{tracks.map(&:name).join(', ') removed from #{playlist.name}"
36
+ # end
37
+ #
38
+ # @yield [tracks, self] tracks_removed
39
+ # @yieldparam [Array<Track>] tracks
40
+ # @yieldparam [Playlist] self
41
+ def tracks_removed_callback(pointer, tracks, num_tracks, userdata)
42
+ trigger(pointer, :tracks_removed, callback_make_tracks(tracks, num_tracks))
43
+ end
44
+
45
+ # @example listening to this event
46
+ # playlist.on(:tracks_moved) do |tracks, new_position, playlist|
47
+ # puts "#{tracks.map(&:name).join(', ')} moved to #{new_position} to #{playlist.name}"
48
+ # end
49
+ #
50
+ # @yield [tracks, new_position, self] tracks_moved
51
+ # @yieldparam [Array<Track>] tracks
52
+ # @yieldparam [Integer] new_position
53
+ # @yieldparam [Playlist] self
54
+ def tracks_moved_callback(pointer, tracks, num_tracks, new_position, userdata)
55
+ trigger(pointer, :tracks_moved, callback_make_tracks(tracks, num_tracks), new_position)
56
+ end
57
+
58
+ # @example listening to this event
59
+ # playlist.on(:playlist_renamed) do |playlist|
60
+ # puts "#{playlist.name} was now previously named something else \o/"
61
+ # end
62
+ #
63
+ # @yield [self] playlist_renamed
64
+ # @yieldparam [Playlist] self
65
+ def playlist_renamed_callback(pointer, userdata)
66
+ trigger(pointer, :playlist_renamed)
67
+ end
68
+
69
+ # @example listening to this event
70
+ # playlist.on(:playlist_state_changed) do |playlist|
71
+ # puts "playlist state changed… to what? from what? D:"
72
+ # end
73
+ #
74
+ # @yield [self] playlist_state_changed
75
+ # @yieldparam [Playlist] self
76
+ def playlist_state_changed_callback(pointer, userdata)
77
+ trigger(pointer, :playlist_state_changed)
78
+ end
79
+
80
+ # @example listening to this event
81
+ # playlist.on(:playlist_update_in_progress) do |is_done, playlist|
82
+ # puts(is_done ? "DONE!" : "not done :(")
83
+ # end
84
+ #
85
+ # @yield [is_done, self] playlist_update_in_progress
86
+ # @yieldparam [Boolean] is_done
87
+ # @yieldparam [Playlist] self
88
+ def playlist_update_in_progress_callback(pointer, done, userdata)
89
+ trigger(pointer, :playlist_update_in_progress, done)
90
+ end
91
+
92
+ # @example listening to this event
93
+ # playlist.on(:playlist_metadata_updated) do |playlist|
94
+ # puts "#{playlist.name} metadata updated"
95
+ # end
96
+ #
97
+ # @yield [self] playlist_metadata_updated
98
+ # @yieldparam [Playlist] self
99
+ def playlist_metadata_updated_callback(pointer, userdata)
100
+ trigger(pointer, :playlist_metadata_updated)
101
+ end
102
+
103
+ # @example listening to this event
104
+ # playlist.on(:track_created_changed) do |position, user, created_at, playlist|
105
+ # track = playlist.tracks[position]
106
+ # puts "#{track.name} created-info changed"
107
+ # end
108
+ #
109
+ # @yield [position, user, created_at, self] track_created_changed
110
+ # @yieldparam [Integer] position
111
+ # @yieldparam [User] user
112
+ # @yieldparam [Time] created_at
113
+ # @yieldparam [Playlist] self
114
+ def track_created_changed_callback(pointer, position, user, created_at, userdata)
115
+ user = Spotify::Pointer.new(user, :user, true)
116
+ trigger(pointer, :track_created_changed, position, Hallon::User.new(user), Time.at(created_at))
117
+ end
118
+
119
+ # @example listening to this event
120
+ # playlist.on(:track_seen_changed) do |position, seen, playlist|
121
+ # track = playlist.tracks[position]
122
+ # puts "#{track.name}#seen? is #{seen}"
123
+ # end
124
+ #
125
+ # @yield [position, is_seen, self] track_seen_changed
126
+ # @yieldparam [Integer] position
127
+ # @yieldparam [Boolean] is_seen
128
+ # @yieldparam [Playlist] self
129
+ def track_seen_changed_callback(pointer, position, seen, userdata)
130
+ trigger(pointer, :track_seen_changed, position, seen)
131
+ end
132
+
133
+ # @example listening to this event
134
+ # playlist.on(:track_message_changed) do |position, message, playlist|
135
+ # track = playlist.tracks[position]
136
+ # puts "#{track.name} new message: #{message}"
137
+ # end
138
+ #
139
+ # @yield [position, message, self] track_message_changed
140
+ # @yieldparam [Integer] position
141
+ # @yieldparam [String] message
142
+ # @yieldparam [Playlist] self
143
+ def track_message_changed_callback(pointer, position, message, userdata)
144
+ trigger(pointer, :track_message_changed, position, message)
145
+ end
146
+
147
+ # @example listening to this event
148
+ # playlist.on(:description_changed) do |description, playlist|
149
+ # puts "#{playlist.name} new description: #{description}"
150
+ # end
151
+ #
152
+ # @yield [description, self] description_changed
153
+ # @yieldparam [String] description
154
+ # @yieldparam [Playlist] self
155
+ def description_changed_callback(pointer, description, userdata)
156
+ trigger(pointer, :description_changed, description)
157
+ end
158
+
159
+ # @example listening to this event
160
+ # playlist.on(:image_changed) do |image, playlist|
161
+ # puts "#{playlist.name} has got a new image: #{image.to_link}"
162
+ # end
163
+ #
164
+ # @yield [image, self] image_changed
165
+ # @yieldparam [Image, nil] image or nil
166
+ # @yieldparam [Playlist] self
167
+ def image_changed_callback(pointer, image, userdata)
168
+ image = Hallon::Image.from(image)
169
+ trigger(pointer, :image_changed, image)
170
+ end
171
+
172
+ # @example listening to this event
173
+ # playlist.on(:subscribers_changed) do |playlist|
174
+ # puts "#{playlist.name} updated its’ subscribers"
175
+ # end
176
+ #
177
+ # @yield [self] subscribers_changed
178
+ # @yieldparam [Playlist] self
179
+ def subscribers_changed_callback(pointer, userdata)
180
+ trigger(pointer, :subscribers_changed)
181
+ end
182
+
183
+ protected
184
+ # @param [FFI::Pointer] tracks
185
+ # @param [Integer] num_tracks
186
+ # @param [Array<Track>]
187
+ def callback_make_tracks(tracks, num_tracks)
188
+ tracks.read_array_of_pointer(num_tracks).map do |track|
189
+ ptr = Spotify::Pointer.new(track, :track, true)
190
+ Hallon::Track.new(ptr)
191
+ end
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,74 @@
1
+ module Hallon::Observable
2
+ # Callbacks related to {Hallon::PlaylistContainer} objects.
3
+ module PlaylistContainer
4
+ # Includes {Hallon::Observable} for you.
5
+ def self.extended(other)
6
+ other.send(:include, Hallon::Observable)
7
+ end
8
+
9
+ protected
10
+
11
+ # @return [Spotify::PlaylistContainerCallbacks]
12
+ def initialize_callbacks
13
+ struct = Spotify::PlaylistContainerCallbacks.new
14
+ struct.members.each do |member|
15
+ struct[member] = callback_for(member)
16
+ end
17
+ struct
18
+ end
19
+
20
+ # @example listening to this event
21
+ # playlist_container.on(:playlist_added) do |playlist, position, container|
22
+ # puts playlist.name + " added at #{position}."
23
+ # end
24
+ #
25
+ # @yield [playlist, position, self] playlist_added
26
+ # @yieldparam [Playlist] playlist
27
+ # @yieldparam [Integer] position
28
+ # @yieldparam [PlaylistContainer] self
29
+ def playlist_added_callback(pointer, playlist, position, userdata)
30
+ playlist = Spotify::Pointer.new(playlist, :playlist, true)
31
+ trigger(pointer, :playlist_added, Hallon::Playlist.new(playlist), position)
32
+ end
33
+
34
+ # @example listening to this event
35
+ # playlist_container.on(:playlist_removed) do |playlist, position, container|
36
+ # puts playlist.name + " removed from #{position}."
37
+ # end
38
+ #
39
+ # @yield [playlist, position, self] playlist_removed
40
+ # @yieldparam [Playlist] playlist
41
+ # @yieldparam [Integer] position
42
+ # @yieldparam [PlaylistContainer] self
43
+ def playlist_removed_callback(pointer, playlist, position, userdata)
44
+ playlist = Spotify::Pointer.new(playlist, :playlist, true)
45
+ trigger(pointer, :playlist_removed, Hallon::Playlist.new(playlist), position)
46
+ end
47
+
48
+ # @example listening to this event
49
+ # playlist_container.on(:playlist_moved) do |playlist, position, new_position, container|
50
+ # puts "moved #{playlist.name} from #{position} to #{new_position}"
51
+ # end
52
+ #
53
+ # @yield [playlist, position, new_position, self] playlist_moved
54
+ # @yieldparam [Playlist] playlist
55
+ # @yieldparam [Integer] position
56
+ # @yieldparam [Integer] new_position
57
+ # @yieldparam [PlaylistContainer] self
58
+ def playlist_moved_callback(pointer, playlist, position, new_position, userdata)
59
+ playlist = Spotify::Pointer.new(playlist, :playlist, true)
60
+ trigger(pointer, :playlist_moved, Hallon::Playlist.new(playlist), position, new_position)
61
+ end
62
+
63
+ # @example listening to this event
64
+ # playlist_container.on(:container_loaded) do |container|
65
+ # puts "#{container.owner.name}s container loaded!"
66
+ # end
67
+ #
68
+ # @yield [self] container_loaded
69
+ # @yieldparam [PlaylistContainer] self
70
+ def container_loaded_callback(pointer, userdata)
71
+ trigger(pointer, :container_loaded)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,30 @@
1
+ module Hallon::Observable
2
+ # Callbacks related to {Hallon::User::Post} objects.
3
+ module Post
4
+ # Includes {Hallon::Observable} for you.
5
+ def self.extended(other)
6
+ other.send(:include, Hallon::Observable)
7
+ end
8
+
9
+ protected
10
+
11
+ # @return [Method] complete callback
12
+ def initialize_callbacks
13
+ callback_for(:complete)
14
+ end
15
+
16
+ # This callback is fired when the Image object is fully loaded.
17
+ #
18
+ # @example listening to this callback
19
+ # post = user.post(track)
20
+ # post.on(:complete) do
21
+ # puts "ze user be havin’ sum posts"
22
+ # end
23
+ #
24
+ # @yield [self]
25
+ # @yieldparam [User::Post] self
26
+ def complete_callback(pointer, userdata)
27
+ trigger(pointer, :complete)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ module Hallon::Observable
2
+ # Callbacks related to {Hallon::Search} objects.
3
+ module Search
4
+ # Includes {Hallon::Observable} for you.
5
+ def self.extended(other)
6
+ other.send(:include, Hallon::Observable)
7
+ end
8
+
9
+ protected
10
+
11
+ # @return [Method] load callback
12
+ def initialize_callbacks
13
+ callback_for(:load)
14
+ end
15
+
16
+ # This callback is fired when the Image object is fully loaded.
17
+ #
18
+ # @example listening to this callback
19
+ # search.on(:load) do |search|
20
+ # puts "search for #{search.query} is complete!"
21
+ # end
22
+ #
23
+ # @yield [self]
24
+ # @yieldparam [Search] self
25
+ def load_callback(pointer, userdata)
26
+ trigger(pointer, :load)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,236 @@
1
+ # coding: utf-8
2
+ module Hallon::Observable
3
+ # Callbacks related to the {Hallon::Session} object.
4
+ module Session
5
+ # Includes {Hallon::Observable} for you.
6
+ def self.extended(other)
7
+ other.send(:include, Hallon::Observable)
8
+ end
9
+
10
+ protected
11
+
12
+ # @return [Spotify::SessionCallbacks]
13
+ def initialize_callbacks
14
+ struct = Spotify::SessionCallbacks.new
15
+ struct.members.each do |member|
16
+ struct[member] = callback_for(member)
17
+ end
18
+ struct
19
+ end
20
+
21
+ # @example listening to this event
22
+ # session.on(:logged_in) do |error|
23
+ # puts "Logged in: " + Hallon::Error.explain(error)
24
+ # end
25
+ #
26
+ # @yield [error, self] logged_in
27
+ # @yieldparam [Symbol] error
28
+ # @yieldparam [Session] self
29
+ # @see Error
30
+ def logged_in_callback(pointer, error)
31
+ trigger(pointer, :logged_in, error)
32
+ end
33
+
34
+ # @example listening to this event
35
+ # session.on(:logged_out) do
36
+ # puts "AHHH!"
37
+ # end
38
+ #
39
+ # @yield [self]
40
+ # @yieldparam [Session] self
41
+ def logged_out_callback(pointer)
42
+ trigger(pointer, :logged_out)
43
+ end
44
+
45
+ # @example listening to this event
46
+ # session.on(:metadata_updated) do
47
+ # puts "wut wut"
48
+ # end
49
+ #
50
+ # @yield [self]
51
+ # @yieldparam [Session] self
52
+ def metadata_updated_callback(pointer)
53
+ trigger(pointer, :metadata_updated)
54
+ end
55
+
56
+ # @example listening to this event
57
+ # session.on(:connection_error) do |error|
58
+ # puts "Oh noes: " + Hallon::Error.explain(error)
59
+ # end
60
+ #
61
+ # @yield [error, self]
62
+ # @yieldparam [Symbol] error
63
+ # @yieldparam [Session] self
64
+ # @see Error
65
+ def connection_error_callback(pointer, error)
66
+ trigger(pointer, :connection_error, error)
67
+ end
68
+
69
+ # @example listening to this event
70
+ # session.on(:message_to_user) do |message|
71
+ # puts "OH HAI: #{message}"
72
+ # end
73
+ #
74
+ # @yield [message, self]
75
+ # @yieldparam [String] message
76
+ # @yieldparam [Session] self
77
+ def message_to_user_callback(pointer, message)
78
+ trigger(pointer, :message_to_user, message)
79
+ end
80
+
81
+ # @example listening to this event
82
+ # session.on(:notify_main_thread) do
83
+ # puts "main thread turn on"
84
+ # end
85
+ #
86
+ # @yield [self]
87
+ # @yieldparam [Session] self
88
+ def notify_main_thread_callback(pointer)
89
+ trigger(pointer, :notify_main_thread)
90
+ end
91
+
92
+ # @example listening to this event
93
+ # session.on(:music_delivery) do |format, frames|
94
+ # puts ""
95
+ # end
96
+ #
97
+ # @yield [format, frames, self]
98
+ # @yieldparam [Hash] format (contains :type, :rate, :channels)
99
+ # @yieldparam [Enumerator<[Integer...]>] frames (each frame is an array containing format[:channels] integers of format[:type])
100
+ # @yieldparam [Session] self
101
+ def music_delivery_callback(pointer, format, frames, num_frames)
102
+ struct = Spotify::AudioFormat.new(format)
103
+
104
+ format = {}
105
+ format[:rate] = struct[:sample_rate]
106
+ format[:channels] = struct[:channels]
107
+ format[:type] = struct[:sample_type]
108
+
109
+ # read the frames of the given type
110
+ frames = frames.public_send("read_array_of_#{format[:type]}", num_frames * format[:channels])
111
+
112
+ # pass the frames to the callback, allowing it to do whatever
113
+ consumed_frames = trigger(pointer, :music_delivery, format, frames.each_slice(format[:channels]))
114
+
115
+ # finally return how many frames the callback reportedly consumed
116
+ consumed_frames.to_i # very important to return something good here!
117
+ end
118
+
119
+ # @example listening to this event
120
+ # session.on(:play_token_lost) do
121
+ # puts "another user set us up the bomb!"
122
+ # end
123
+ #
124
+ # @yield [self]
125
+ # @yieldparam [Session] self
126
+ def play_token_lost_callback(pointer)
127
+ trigger(pointer, :play_token_lost)
128
+ end
129
+
130
+ # @example listening to this event
131
+ # session.on(:end_of_track) do
132
+ # puts "all your base are belong to us"
133
+ # end
134
+ #
135
+ # @yield [self]
136
+ # @yieldparam [Session] self
137
+ def end_of_track_callback(pointer)
138
+ trigger(pointer, :end_of_track)
139
+ end
140
+
141
+ # @example listening to this event
142
+ # session.on(:start_playback) do
143
+ # puts "dum dum tiss"
144
+ # end
145
+ #
146
+ # @yield [self]
147
+ # @yieldparam [Session] self
148
+ def start_playback_callback(pointer)
149
+ trigger(pointer, :start_playback)
150
+ end
151
+
152
+ # @example listening to this event
153
+ # session.on(:stop_playback) do
154
+ # puts "dum dum tiss"
155
+ # end
156
+ #
157
+ # @yield [self]
158
+ # @yieldparam [Session] self
159
+ def stop_playback_callback(pointer)
160
+ trigger(pointer, :stop_playback)
161
+ end
162
+
163
+ # @example listening to this event
164
+ # session.on(:get_audio_buffer_stats) do
165
+ # puts "que?"
166
+ # end
167
+ #
168
+ # @yield [self]
169
+ # @yieldparam [Session] self
170
+ # @yieldreturn an integer pair, [samples, dropouts]
171
+ def get_audio_buffer_stats_callback(pointer, stats)
172
+ stats = Spotify::AudioBufferStats.new(stats)
173
+ samples, dropouts = trigger(pointer, :get_audio_buffer_stats)
174
+ stats[:samples] = samples.to_i
175
+ stats[:stutter] = dropouts.to_i
176
+ end
177
+
178
+ # @example listening to this event
179
+ # session.on(:streaming_error) do |error|
180
+ # puts "boo: " + Hallon::Error.explain(error)
181
+ # end
182
+ #
183
+ # @yield [error, self]
184
+ # @yieldparam [Symbol] error
185
+ # @yieldparam [Session] self
186
+ def streaming_error_callback(pointer, error)
187
+ trigger(pointer, :streaming_error, error)
188
+ end
189
+
190
+ # @example listening to this event
191
+ # session.on(:userinfo_updated) do
192
+ # puts "who am I?!"
193
+ # end
194
+ #
195
+ # @yield [self]
196
+ # @yieldparam [Session] self
197
+ def userinfo_updated_callback(pointer)
198
+ trigger(pointer, :userinfo_updated)
199
+ end
200
+
201
+ # @example listening to this event
202
+ # session.on(:log_message) do |message|
203
+ # puts "for great justice: #{message}"
204
+ # end
205
+ #
206
+ # @yield [message, self]
207
+ # @yieldparam [String] message
208
+ # @yieldparam [Session] self
209
+ def log_message_callback(pointer, message)
210
+ trigger(pointer, :log_message, message)
211
+ end
212
+
213
+ # @example listening to this event
214
+ # session.on(:offline_status_updated) do |session|
215
+ # puts "All systems: #{session.status}"
216
+ # end
217
+ #
218
+ # @yield [self]
219
+ # @yieldparam [Session] self
220
+ def offline_status_updated_callback(pointer)
221
+ trigger(pointer, :offline_status_updated)
222
+ end
223
+
224
+ # @example listening to this event
225
+ # session.on(:offline_error) do |error|
226
+ # puts "FAIL: " + Hallon::Error.explain(error)
227
+ # end
228
+ #
229
+ # @yield [error, self]
230
+ # @yieldparam [Symbol] error
231
+ # @yieldparam [Session] self
232
+ def offline_error_callback(pointer, error)
233
+ trigger(pointer, :offline_error, error)
234
+ end
235
+ end
236
+ end