hallon 0.4.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitmodules +3 -0
- data/.travis.yml +2 -0
- data/CHANGELOG +30 -6
- data/README.markdown +7 -7
- data/Rakefile +70 -16
- data/examples/logging_in.rb +3 -3
- data/examples/printing_link_information.rb +1 -1
- data/examples/show_published_playlists_of_user.rb +92 -0
- data/hallon.gemspec +7 -4
- data/lib/hallon.rb +16 -4
- data/lib/hallon/album.rb +16 -6
- data/lib/hallon/album_browse.rb +78 -0
- data/lib/hallon/artist.rb +59 -0
- data/lib/hallon/artist_browse.rb +89 -0
- data/lib/hallon/base.rb +7 -0
- data/lib/hallon/enumerator.rb +64 -0
- data/lib/hallon/error.rb +8 -6
- data/lib/hallon/ext/spotify.rb +3 -3
- data/lib/hallon/image.rb +25 -12
- data/lib/hallon/link.rb +4 -4
- data/lib/hallon/linkable.rb +4 -2
- data/lib/hallon/observable.rb +1 -4
- data/lib/hallon/player.rb +130 -0
- data/lib/hallon/search.rb +128 -0
- data/lib/hallon/session.rb +226 -25
- data/lib/hallon/toplist.rb +83 -0
- data/lib/hallon/track.rb +62 -7
- data/lib/hallon/user.rb +6 -6
- data/lib/hallon/version.rb +1 -1
- data/spec/hallon/album_browse_spec.rb +20 -0
- data/spec/hallon/album_spec.rb +12 -7
- data/spec/hallon/artist_browse_spec.rb +29 -0
- data/spec/hallon/artist_spec.rb +32 -0
- data/spec/hallon/enumerator_spec.rb +106 -0
- data/spec/hallon/error_spec.rb +10 -0
- data/spec/hallon/hallon_spec.rb +5 -1
- data/spec/hallon/image_spec.rb +39 -25
- data/spec/hallon/linkable_spec.rb +12 -4
- data/spec/hallon/observable_spec.rb +5 -0
- data/spec/hallon/player_spec.rb +73 -0
- data/spec/hallon/search_spec.rb +80 -0
- data/spec/hallon/session_spec.rb +187 -6
- data/spec/hallon/toplist_spec.rb +40 -0
- data/spec/hallon/track_spec.rb +43 -8
- data/spec/mockspotify.rb +47 -0
- data/spec/mockspotify/.gitignore +5 -0
- data/spec/mockspotify/extconf.rb +5 -0
- data/spec/mockspotify/mockspotify_spec.rb +41 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/support/common_objects.rb +84 -7
- metadata +72 -20
- data/lib/hallon/ext/object.rb +0 -16
data/.gitmodules
ADDED
data/.travis.yml
ADDED
data/CHANGELOG
CHANGED
@@ -1,16 +1,40 @@
|
|
1
1
|
Hallon’s Changelog
|
2
2
|
==================
|
3
3
|
|
4
|
-
|
4
|
+
v0.8.0
|
5
5
|
------------------
|
6
|
-
|
6
|
+
[ Added ]
|
7
|
+
- Add example for listing track information in playlists
|
8
|
+
- Updated to (lib)Spotify v9
|
9
|
+
- Full Track subsystem support
|
10
|
+
- Full Album subsystem support
|
11
|
+
- Full AlbumBrowse subsystem support
|
12
|
+
- Full Artist subsystem support
|
13
|
+
- Full ArtistBrowse subsystem support
|
14
|
+
- Full Toplist subsystem support
|
15
|
+
- Full Search subsystem support
|
16
|
+
- Allow setting Session connection type/rules
|
17
|
+
- Session offline query methods (offline_time_left et al)
|
18
|
+
- Work-in-progress Player
|
19
|
+
- Add Session relogin support
|
20
|
+
- Add Enumerator
|
21
|
+
- Use libmockspotify for testing (spec/mockspotify)
|
7
22
|
- Add Hallon::Base class
|
8
|
-
- Cleaned up specs to use same mocks everywhere
|
9
|
-
- Album subsystem support (except for #cover and #artist)
|
10
23
|
- Add optional parameter to have Image#id return raw id
|
11
|
-
- Make Hallon::URI match image URIs
|
12
24
|
- Allow Image.new to accept an image id
|
13
|
-
- Add
|
25
|
+
- Add Hallon::API_BUILD
|
26
|
+
|
27
|
+
[ Fixed ]
|
28
|
+
- Improve speed of Session#wait_for for already-loaded cases
|
29
|
+
- Error.maybe_raise no longer errors out on timeout
|
30
|
+
- from_link now checks for null pointers
|
31
|
+
- No longer uses autotest as development dependency
|
32
|
+
- Cleaned up specs to use same mocks everywhere
|
33
|
+
- Make Hallon::URI match image URIs
|
34
|
+
|
35
|
+
[ Broke ]
|
36
|
+
- Ignore Ruby v1.8.x compatibility
|
37
|
+
|
14
38
|
|
15
39
|
v0.3.0
|
16
40
|
------------------
|
data/README.markdown
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
What is Hallon?
|
1
|
+
[What is Hallon?][] [![Build Status][]](http://travis-ci.org/Burgestrand/Hallon) ([but that’s okay](https://github.com/Burgestrand/Hallon/issues/33))
|
2
2
|
===============
|
3
3
|
|
4
|
-
> [Hallon, delicious Ruby bindings for libspotify](http://burgestrand.se/articles/hallon-delicious-ruby-bindings-to-libspotify.html)
|
5
|
-
|
6
4
|
We rubyists have this awesome [spotify gem][] allowing us to use [libspotify][] from within Ruby, but it has a significant drawback: the `libspotify` API is very hard to use. Now, we can’t have that, so what do we do? We make Hallon!
|
7
5
|
|
8
6
|
Hallon is Swedish for “Raspberry”, and has been written to satisfy my needs for API simplicity. It provides you with a wrapper around the spotify gem, making the experience of using `libspotify` from Ruby much more enjoyable.
|
@@ -11,7 +9,7 @@ Hallon would not have been possible if not for these people:
|
|
11
9
|
|
12
10
|
- Per Reimers, cracking synchronization bugs with me in the deep night (4 AM) and correcting me when I didn’t know better
|
13
11
|
- [Spotify](http://www.spotify.com/), providing a service worth attention (and my money!)
|
14
|
-
- [Linus Oleander](https://github.com/oleander), involving me with the
|
12
|
+
- [Linus Oleander](https://github.com/oleander), involving me with the [radiofy.se](http://radiofy.se) project, ultimately spawning the necessity of Hallon
|
15
13
|
- [Jesper Särnesjö][], creator of [Greenstripes][], making me think of Hallon as an achievable goal
|
16
14
|
|
17
15
|
Code samples can be found under `examples/` directory.
|
@@ -55,7 +53,9 @@ License
|
|
55
53
|
-------
|
56
54
|
Hallon is licensed under a 2-clause (Simplified) BSD license. More information can be found in the `LICENSE.txt` file.
|
57
55
|
|
58
|
-
[spotify gem]:
|
59
|
-
[libspotify]:
|
60
|
-
[Greenstripes]:
|
56
|
+
[spotify gem]: https://rubygems.org/gems/spotify
|
57
|
+
[libspotify]: http://developer.spotify.com/en/libspotify/overview/
|
58
|
+
[Greenstripes]: http://github.com/sarnesjo/greenstripes
|
61
59
|
[Jesper Särnesjö]: http://jesper.sarnesjo.org/
|
60
|
+
[What is Hallon?]: http://burgestrand.se/articles/hallon-delicious-ruby-bindings-to-libspotify.html
|
61
|
+
[Build Status]: https://secure.travis-ci.org/Burgestrand/Hallon.png
|
data/Rakefile
CHANGED
@@ -27,24 +27,58 @@ task 'spotify:coverage' do
|
|
27
27
|
require 'set'
|
28
28
|
require 'spotify'
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
dynamicly_used << "user_release" # lib/ext/spotify.rb
|
39
|
-
dynamicly_used << "link_as_track" # IGNORE
|
40
|
-
dynamicly_used << "link_release" # lib/ext/spotify.rb
|
41
|
-
|
42
|
-
methods = Spotify.methods(false).map(&:to_s) - dynamicly_used
|
30
|
+
begin
|
31
|
+
require 'ruby_parser'
|
32
|
+
rescue LoadError
|
33
|
+
puts "You need ruby_parser for the spotify:coverage rake task"
|
34
|
+
abort
|
35
|
+
end
|
36
|
+
|
37
|
+
methods = Spotify.methods(false).map(&:to_s)
|
43
38
|
covered = Set.new(methods)
|
44
|
-
|
39
|
+
ignored = [
|
40
|
+
'session_release', # segfaults on libspotify <= 9
|
41
|
+
'session_userdata', # wont support this
|
42
|
+
'link_as_track', # using link_as_track_and_offset instead
|
43
|
+
'toplistbrowse_add_ref', # toplistbrowse creates its’ own pointer
|
44
|
+
'artistbrowse_add_ref', # artistbrowse creates its’ own pointer
|
45
|
+
'albumbrowse_add_ref', # albumbrowse creates its’ own pointer
|
46
|
+
'link_add_ref', # all creation of links has +1 ref
|
47
|
+
'image_add_ref', # all creation of image has +1 ref
|
48
|
+
'search_add_ref', # search creates its’ own pointer
|
49
|
+
]
|
50
|
+
|
51
|
+
covered -= ignored
|
52
|
+
|
53
|
+
# Handlers for different AST nodes
|
54
|
+
printer = proc { |*args| p args }
|
55
|
+
silencer = proc { }
|
56
|
+
handlers = Hash.new(Hash.new(silencer))
|
57
|
+
|
58
|
+
# Direct calls
|
59
|
+
handlers[Sexp.new(:const, :Spotify)] = Hash.new(proc { |_, meth, _| meth })
|
60
|
+
|
61
|
+
# Spotify Pointer
|
62
|
+
pointer = handlers[Sexp.new(:colon2, [:const, :Spotify], :Pointer)] = Hash.new(printer)
|
63
|
+
pointer[:new] = proc do |recv, meth, (_, ptr, name, release)|
|
64
|
+
name = name.value
|
65
|
+
release &&= release.value != :false
|
66
|
+
["#{name}_release", "#{name if release}_add_ref"]
|
67
|
+
end
|
68
|
+
|
69
|
+
# DSL Methods
|
70
|
+
no_receiver = handlers[nil] = Hash.new(silencer)
|
71
|
+
no_receiver[:from_link] = no_receiver[:to_link] = proc do |recv, meth, (_, name)|
|
72
|
+
prefix = meth == :to_link ? "link_create" : "link"
|
73
|
+
"%s_%s" % [prefix, name.value]
|
74
|
+
end
|
45
75
|
|
46
76
|
FileList['lib/**/*.rb'].each do |file|
|
47
|
-
File.read(file)
|
77
|
+
ast = RubyParser.new.parse File.read(file)
|
78
|
+
ast.each_of_type(:call) do |_, recv, meth, args, *rest|
|
79
|
+
name = handlers[recv][meth].call(recv, meth, args)
|
80
|
+
covered.subtract Array(name).map(&:to_s)
|
81
|
+
end
|
48
82
|
end
|
49
83
|
|
50
84
|
covered.group_by { |m| m[/[^_]+/] }.each_pair do |group, methods|
|
@@ -55,9 +89,24 @@ task 'spotify:coverage' do
|
|
55
89
|
puts
|
56
90
|
end
|
57
91
|
|
92
|
+
puts "Ignored:"
|
93
|
+
ignored.each_slice(3) do |slice|
|
94
|
+
puts "\t#{slice.join(', ')}"
|
95
|
+
end
|
96
|
+
puts
|
97
|
+
|
58
98
|
puts "Coverage: %.02f%%" % (100 * (1 - covered.size.fdiv(methods.size)))
|
59
99
|
end
|
60
100
|
|
101
|
+
desc "Compile mockspotify"
|
102
|
+
task 'mock:compile' do
|
103
|
+
Dir.chdir 'spec/mockspotify' do
|
104
|
+
sh 'ruby extconf.rb'
|
105
|
+
sh 'make'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
task :spec => 'mock:compile'
|
61
110
|
task :test => :spec
|
62
111
|
|
63
112
|
#
|
@@ -70,7 +119,12 @@ end
|
|
70
119
|
|
71
120
|
desc "Remove generated files"
|
72
121
|
task :clean do
|
73
|
-
|
122
|
+
print "Do you really want to delete all non-git tracked files? (y/n) [n]: "
|
123
|
+
if STDIN.gets.chomp == 'y'
|
124
|
+
sh 'git clean -fdx --exclude Gemfile.lock --exclude spec/support/config.rb'
|
125
|
+
else
|
126
|
+
puts "Whew. Close one!"
|
127
|
+
end
|
74
128
|
end
|
75
129
|
|
76
130
|
task :default => [:spec]
|
data/examples/logging_in.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
require 'hallon'
|
3
3
|
require './spec/support/config'
|
4
4
|
|
5
|
-
session = Hallon::Session.
|
5
|
+
session = Hallon::Session.initialize IO.read(ENV['HALLON_APPKEY']) do
|
6
6
|
on(:log_message) do |message|
|
7
7
|
puts "[LOG] #{message}"
|
8
8
|
end
|
@@ -10,8 +10,8 @@ end
|
|
10
10
|
|
11
11
|
session.login ENV['HALLON_USERNAME'], ENV['HALLON_PASSWORD']
|
12
12
|
|
13
|
-
session.
|
14
|
-
session.
|
13
|
+
session.wait_for(:logged_in) { |error| Hallon::Error.maybe_raise(error) }
|
14
|
+
session.wait_for(:connection_error) do |error|
|
15
15
|
session.logged_in? or Hallon::Error.maybe_raise(error)
|
16
16
|
end
|
17
17
|
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
#
|
3
|
+
# DISCLAIMER:
|
4
|
+
# This file was written without extensive testing, and is merely a proof
|
5
|
+
# of concept. Before using this yourself, I advice you to look through
|
6
|
+
# the code carefully.
|
7
|
+
#
|
8
|
+
# The below code uses the raw Spotify FFI API, and does not represent how
|
9
|
+
# this will be done when Hallon has API support for below operations!
|
10
|
+
#
|
11
|
+
# Hallon API in this file is only used for:
|
12
|
+
# - logging in
|
13
|
+
# - querying track information
|
14
|
+
#
|
15
|
+
# Raw Spotify FFI API is used for:
|
16
|
+
# - fetching playlist container
|
17
|
+
# - fetching playlists
|
18
|
+
# - fetching tracks from playlists
|
19
|
+
require 'hallon'
|
20
|
+
require './spec/support/config'
|
21
|
+
|
22
|
+
# Utility
|
23
|
+
def prompt(str)
|
24
|
+
print str
|
25
|
+
gets.chomp
|
26
|
+
end
|
27
|
+
|
28
|
+
session = Hallon::Session.initialize IO.read(ENV['HALLON_APPKEY']) do
|
29
|
+
on(:log_message) do |message|
|
30
|
+
puts "[LOG] #{message}"
|
31
|
+
end
|
32
|
+
|
33
|
+
on(:connection_error) do |error|
|
34
|
+
Hallon::Error.maybe_raise(error)
|
35
|
+
end
|
36
|
+
|
37
|
+
on(:logged_out) do
|
38
|
+
abort "[FAIL] Logged out!"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
session.login ENV['HALLON_USERNAME'], ENV['HALLON_PASSWORD']
|
43
|
+
|
44
|
+
session.wait_for(:logged_in) { |error| Hallon::Error.maybe_raise(error) }
|
45
|
+
session.wait_for(:connection_error) do |error|
|
46
|
+
session.logged_in? or Hallon::Error.maybe_raise(error)
|
47
|
+
end
|
48
|
+
|
49
|
+
puts "Successfully logged in!"
|
50
|
+
|
51
|
+
# Hallon does not have support for the below operations, so we resort
|
52
|
+
# to using the raw Spotify gem and FFI for now.
|
53
|
+
while username = prompt("Enter a Spotify username: ")
|
54
|
+
begin
|
55
|
+
username = nil if username.empty?
|
56
|
+
|
57
|
+
puts "Fetching container for #{username || "current user"}..."
|
58
|
+
container = Spotify::session_publishedcontainer_for_user_create(session.pointer, username)
|
59
|
+
if container.null?
|
60
|
+
puts "Failed (unknown reason)."
|
61
|
+
next
|
62
|
+
end
|
63
|
+
|
64
|
+
session.wait_for { Spotify::playlistcontainer_is_loaded(container) }
|
65
|
+
|
66
|
+
num_playlists = Spotify::playlistcontainer_num_playlists(container)
|
67
|
+
puts "Listing #{num_playlists} playlists."
|
68
|
+
|
69
|
+
num_playlists.times do |i|
|
70
|
+
playlist = Spotify::playlistcontainer_playlist(container, i)
|
71
|
+
session.wait_for { Spotify::playlist_is_loaded(playlist) }
|
72
|
+
|
73
|
+
puts
|
74
|
+
puts Spotify::playlist_name(playlist) << ": "
|
75
|
+
|
76
|
+
num_tracks = Spotify::playlist_num_tracks(playlist)
|
77
|
+
num_tracks.times do |j|
|
78
|
+
# Here we go back into Hallon API, passing the raw pointer
|
79
|
+
# to Hallon::Track.new; this means all of Hallon::Track API
|
80
|
+
# is supported on “track” here!
|
81
|
+
track = Hallon::Track.new(Spotify::playlist_track(playlist, j))
|
82
|
+
session.wait_for { track.loaded? }
|
83
|
+
|
84
|
+
puts "\t (#{j+1}/#{num_tracks}) #{track.name}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
rescue Interrupt
|
88
|
+
# do nothing, continue with loop
|
89
|
+
ensure
|
90
|
+
Spotify::playlistcontainer_release(container) unless container.nil?
|
91
|
+
end
|
92
|
+
end
|
data/hallon.gemspec
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
require 'hallon/version'
|
3
5
|
|
4
6
|
Gem::Specification.new do |gem|
|
5
7
|
gem.name = "hallon"
|
@@ -7,9 +9,10 @@ Gem::Specification.new do |gem|
|
|
7
9
|
gem.homepage = "http://github.com/Burgestrand/Hallon"
|
8
10
|
gem.authors = ["Kim Burgestrand"]
|
9
11
|
gem.email = 'kim@burgestrand.se'
|
10
|
-
gem.license = '
|
12
|
+
gem.license = 'X11 License'
|
11
13
|
|
12
14
|
gem.files = `git ls-files`.split("\n")
|
15
|
+
gem.files += `cd spec/mockspotify/libmockspotify && git ls-files src`.split("\n").map { |path| "spec/mockspotify/libmockspotify/#{path}" }
|
13
16
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
17
|
gem.executables = []
|
15
18
|
gem.require_paths = ["lib"]
|
@@ -18,8 +21,8 @@ Gem::Specification.new do |gem|
|
|
18
21
|
gem.platform = Gem::Platform::RUBY
|
19
22
|
gem.required_ruby_version = '~> 1.8'
|
20
23
|
|
21
|
-
gem.add_dependency 'spotify', '~>
|
22
|
-
gem.add_development_dependency '
|
24
|
+
gem.add_dependency 'spotify', '~> 9.0.0'
|
25
|
+
gem.add_development_dependency 'bundler', '~> 1.0'
|
23
26
|
gem.add_development_dependency 'rake', '~> 0.8'
|
24
27
|
gem.add_development_dependency 'rspec', '~> 2'
|
25
28
|
gem.add_development_dependency 'yard'
|
data/lib/hallon.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
require 'spotify'
|
3
3
|
require 'hallon/ext/spotify'
|
4
4
|
require 'hallon/ext/ffi'
|
5
|
-
require 'hallon/ext/object'
|
6
5
|
|
7
6
|
require 'hallon/synchronizable'
|
8
7
|
require 'hallon/observable'
|
@@ -11,12 +10,20 @@ require 'hallon/linkable'
|
|
11
10
|
require 'hallon/version'
|
12
11
|
require 'hallon/error'
|
13
12
|
require 'hallon/base'
|
13
|
+
require 'hallon/enumerator'
|
14
14
|
require 'hallon/session'
|
15
15
|
require 'hallon/link'
|
16
16
|
require 'hallon/user'
|
17
17
|
require 'hallon/image'
|
18
18
|
require 'hallon/track'
|
19
19
|
require 'hallon/album'
|
20
|
+
require 'hallon/artist'
|
21
|
+
require 'hallon/toplist'
|
22
|
+
|
23
|
+
require 'hallon/album_browse'
|
24
|
+
require 'hallon/artist_browse'
|
25
|
+
require 'hallon/player'
|
26
|
+
require 'hallon/search'
|
20
27
|
|
21
28
|
# The Hallon module wraps around all Hallon objects to avoid polluting
|
22
29
|
# the global namespace. To start using Hallon, you most likely want to
|
@@ -25,15 +32,20 @@ module Hallon
|
|
25
32
|
# @see Spotify::API_VERSION
|
26
33
|
API_VERSION = Spotify::API_VERSION
|
27
34
|
|
35
|
+
# Spotify API build.
|
36
|
+
#
|
37
|
+
# @see Spotify#api_build
|
38
|
+
API_BUILD = Spotify.build_id
|
39
|
+
|
28
40
|
# A regex that matches all Spotify URIs
|
29
41
|
#
|
30
42
|
# @example
|
31
43
|
# Hallon::URI === "spotify:user:burgestrand" # => true
|
32
44
|
URI = /(spotify:(?:
|
33
|
-
(?:artist|album|track|user:[^:]+:playlist)
|
45
|
+
(?:artist|album|track|user:[^:]+:playlist):[a-fA-F0-9]+
|
34
46
|
|user:[^:]+
|
35
|
-
|search:(?:[-\w$\.+!*'(),]
|
36
|
-
|image
|
47
|
+
|search:(?:[-\w$\.+!*'(),]+|%[a-fA-F0-9]{2})+
|
48
|
+
|image:[a-fA-F0-9]{40}
|
37
49
|
))
|
38
50
|
/x
|
39
51
|
end
|
data/lib/hallon/album.rb
CHANGED
@@ -9,8 +9,9 @@ module Hallon
|
|
9
9
|
#
|
10
10
|
# @see http://developer.spotify.com/en/libspotify/docs/group__album.html
|
11
11
|
class Album < Base
|
12
|
+
# An array of different kinds of albums. Singles, compilations etc.
|
12
13
|
def self.types
|
13
|
-
Spotify.enum_type(:albumtype).
|
14
|
+
Spotify.enum_type(:albumtype).symbols
|
14
15
|
end
|
15
16
|
|
16
17
|
extend Linkable
|
@@ -63,15 +64,24 @@ module Hallon
|
|
63
64
|
# Retrieve album cover art.
|
64
65
|
#
|
65
66
|
# @return [Image]
|
66
|
-
def cover
|
67
|
+
def cover
|
67
68
|
image_id = Spotify.album_cover(@pointer)
|
68
|
-
|
69
|
+
Image.new(image_id.read_string(20)) unless image_id.null?
|
69
70
|
end
|
70
71
|
|
71
|
-
#
|
72
|
+
# Retrieve the album Artist.
|
73
|
+
#
|
74
|
+
# @return [Artist, nil]
|
72
75
|
def artist
|
73
|
-
|
74
|
-
|
76
|
+
artist = Spotify.album_artist(@pointer)
|
77
|
+
Artist.new(artist) unless artist.null?
|
78
|
+
end
|
79
|
+
|
80
|
+
# Retrieve an AlbumBrowse object for this Album.
|
81
|
+
#
|
82
|
+
# @return [AlbumBrowse]
|
83
|
+
def browse
|
84
|
+
AlbumBrowse.new(pointer)
|
75
85
|
end
|
76
86
|
end
|
77
87
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Hallon
|
2
|
+
# AlbumBrowse objects are for retrieving additional data from
|
3
|
+
# an album that cannot otherwise be acquired. This includes
|
4
|
+
# tracks, reviews, copyright information.
|
5
|
+
#
|
6
|
+
# AlbumBrowse object triggers the `:load` callback on itself
|
7
|
+
# when it loads.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# browse = album.browse # album is a Hallon::Album
|
11
|
+
# browse.on(:load) do
|
12
|
+
# puts "Album browser for #{browse.album.name} has been loaded!"
|
13
|
+
# end
|
14
|
+
# session.wait_for { browse.loaded? } # will eventually trigger above callback
|
15
|
+
#
|
16
|
+
# @see Album
|
17
|
+
# @see http://developer.spotify.com/en/libspotify/docs/group__albumbrowse.html
|
18
|
+
class AlbumBrowse < Base
|
19
|
+
include Observable
|
20
|
+
|
21
|
+
# Creates an AlbumBrowse instance from an Album or an Album pointer.
|
22
|
+
#
|
23
|
+
# @note Use {Album#browse} to browse an Album.
|
24
|
+
# @param [Album, FFI::Pointer] album
|
25
|
+
def initialize(album)
|
26
|
+
album = album.pointer if album.respond_to?(:pointer)
|
27
|
+
@callback = proc { trigger(:load) }
|
28
|
+
|
29
|
+
albumbrowse = Spotify.albumbrowse_create(session.pointer, album, @callback, nil)
|
30
|
+
@pointer = Spotify::Pointer.new(albumbrowse, :albumbrowse, false)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Boolean] true if the album is loaded
|
34
|
+
def loaded?
|
35
|
+
Spotify.albumbrowse_is_loaded(@pointer)
|
36
|
+
end
|
37
|
+
|
38
|
+
# @see Error
|
39
|
+
# @return [Symbol] album browser error status
|
40
|
+
def error
|
41
|
+
Spotify.albumbrowse_error(@pointer)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [String] album review
|
45
|
+
def review
|
46
|
+
Spotify.albumbrowse_review(@pointer)
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Artist] artist performing this album
|
50
|
+
def artist
|
51
|
+
pointer = Spotify.albumbrowse_artist(@pointer)
|
52
|
+
Artist.new(pointer) unless pointer.null?
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Album] album this object is browsing
|
56
|
+
def album
|
57
|
+
pointer = Spotify.albumbrowse_album(@pointer)
|
58
|
+
Album.new(pointer) unless pointer.null?
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [Enumerator<String>] list of copyright notices
|
62
|
+
def copyrights
|
63
|
+
size = Spotify.albumbrowse_num_copyrights(@pointer)
|
64
|
+
Enumerator.new(size) do |i|
|
65
|
+
Spotify.albumbrowse_copyright(@pointer, i)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Enumerator<Track>] list of tracks
|
70
|
+
def tracks
|
71
|
+
size = Spotify.albumbrowse_num_tracks(@pointer)
|
72
|
+
Enumerator.new(size) do |i|
|
73
|
+
pointer = Spotify.albumbrowse_track(@pointer, i)
|
74
|
+
Track.new(pointer) unless pointer.null?
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|