spotify 12.5.3 → 12.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +20 -5
- data/CHANGELOG.md +29 -1
- data/Gemfile +5 -0
- data/MIT-LICENSE +21 -0
- data/README.markdown +75 -50
- data/Rakefile +1 -1
- data/examples/example-audio_delivery_speed.rb +48 -0
- data/examples/{audio-stream_example.rb → example-audio_stream.rb} +14 -29
- data/examples/example-console.rb +9 -0
- data/examples/example-listing_playlists.rb +89 -0
- data/examples/example-loading_object.rb +25 -0
- data/examples/example-random_related_artists.rb +53 -0
- data/examples/support.rb +106 -0
- data/lib/spotify.rb +36 -55
- data/lib/spotify/api.rb +54 -26
- data/lib/spotify/api/album.rb +45 -2
- data/lib/spotify/api/album_browse.rb +81 -3
- data/lib/spotify/api/artist.rb +21 -2
- data/lib/spotify/api/artist_browse.rb +121 -3
- data/lib/spotify/api/error.rb +5 -1
- data/lib/spotify/api/image.rb +72 -6
- data/lib/spotify/api/inbox.rb +33 -4
- data/lib/spotify/api/link.rb +117 -4
- data/lib/spotify/api/miscellaneous.rb +12 -0
- data/lib/spotify/api/playlist.rb +321 -16
- data/lib/spotify/api/playlist_container.rb +168 -9
- data/lib/spotify/api/search.rb +156 -3
- data/lib/spotify/api/session.rb +390 -26
- data/lib/spotify/api/toplist_browse.rb +74 -3
- data/lib/spotify/api/track.rb +134 -4
- data/lib/spotify/api/user.rb +18 -2
- data/lib/spotify/api_helpers.rb +47 -0
- data/lib/spotify/data_converters.rb +7 -0
- data/lib/spotify/{types → data_converters}/best_effort_string.rb +1 -1
- data/lib/spotify/{types → data_converters}/byte_string.rb +0 -0
- data/lib/spotify/data_converters/country_code.rb +30 -0
- data/lib/spotify/{types → data_converters}/image_id.rb +1 -1
- data/lib/spotify/{type_safety.rb → data_converters/type_safety.rb} +0 -0
- data/lib/spotify/{types → data_converters}/utf8_string.rb +2 -2
- data/lib/spotify/{types → data_converters}/utf8_string_pointer.rb +2 -2
- data/lib/spotify/error.rb +180 -47
- data/lib/spotify/managed_pointer.rb +32 -12
- data/lib/spotify/monkey_patches/ffi_buffer.rb +11 -0
- data/lib/spotify/monkey_patches/ffi_enums.rb +4 -0
- data/lib/spotify/monkey_patches/ffi_pointer.rb +1 -0
- data/lib/spotify/structs.rb +4 -0
- data/lib/spotify/structs/session_callbacks.rb +97 -26
- data/lib/spotify/structs/session_config.rb +1 -1
- data/lib/spotify/structs/subscribers.rb +4 -3
- data/lib/spotify/types.rb +104 -5
- data/lib/spotify/{objects → types}/album.rb +0 -0
- data/lib/spotify/{objects → types}/album_browse.rb +0 -0
- data/lib/spotify/{objects → types}/artist.rb +0 -0
- data/lib/spotify/{objects → types}/artist_browse.rb +0 -0
- data/lib/spotify/{objects → types}/image.rb +0 -0
- data/lib/spotify/{objects → types}/inbox.rb +0 -0
- data/lib/spotify/{objects → types}/link.rb +0 -0
- data/lib/spotify/{objects → types}/playlist.rb +0 -0
- data/lib/spotify/{objects → types}/playlist_container.rb +0 -0
- data/lib/spotify/{objects → types}/search.rb +0 -0
- data/lib/spotify/{objects → types}/session.rb +0 -0
- data/lib/spotify/{objects → types}/toplist_browse.rb +0 -0
- data/lib/spotify/{objects → types}/track.rb +0 -0
- data/lib/spotify/{objects → types}/user.rb +0 -0
- data/lib/spotify/util.rb +38 -35
- data/lib/spotify/version.rb +1 -1
- data/spec/spec_helper.rb +24 -13
- data/spec/spotify/api/image_spec.rb +32 -0
- data/spec/spotify/api/inbox_spec.rb +34 -0
- data/spec/spotify/api/link_spec.rb +40 -0
- data/spec/spotify/api/playlist_spec.rb +99 -0
- data/spec/spotify/api/playlistcontainer_spec.rb +82 -0
- data/spec/spotify/api/session_spec.rb +97 -0
- data/spec/spotify/api/track_spec.rb +29 -0
- data/spec/spotify/api_error_spec.rb +55 -0
- data/spec/spotify/api_spec.rb +17 -11
- data/spec/spotify/{types → data_converters}/best_effort_string_spec.rb +4 -4
- data/spec/spotify/{types → data_converters}/byte_string_spec.rb +0 -0
- data/spec/spotify/data_converters/country_code_spec.rb +16 -0
- data/spec/spotify/{types → data_converters}/image_id_spec.rb +1 -1
- data/spec/spotify/{type_safety_spec.rb → data_converters/type_safety_spec.rb} +0 -0
- data/spec/spotify/{types → data_converters}/utf8_string_pointer_spec.rb +0 -0
- data/spec/spotify/{types → data_converters}/utf8_string_spec.rb +1 -1
- data/spec/spotify/{api/functions_spec.rb → functions_spec.rb} +2 -0
- data/spec/spotify/managed_pointer_spec.rb +13 -13
- data/spec/spotify/structs/subscribers_spec.rb +5 -3
- data/spec/spotify/{defines_spec.rb → types_spec.rb} +16 -3
- data/spec/spotify/util_spec.rb +24 -0
- data/spec/spotify_spec.rb +74 -0
- data/spec/support/spotify_util.rb +6 -2
- data/spec/support/spy_output.rb +16 -0
- data/spotify.gemspec +4 -2
- metadata +111 -71
- data/examples/README.md +0 -15
- data/examples/console_example.rb +0 -22
- data/examples/example_support.rb +0 -66
- data/examples/loading-object_example.rb +0 -43
- data/examples/logging-in_example.rb +0 -58
- data/lib/spotify/defines.rb +0 -109
- data/lib/spotify/objects.rb +0 -17
- data/spec/spotify/enums_spec.rb +0 -9
- data/spec/spotify/spotify_spec.rb +0 -69
@@ -0,0 +1,29 @@
|
|
1
|
+
describe "Spotify::API" do
|
2
|
+
describe "#track_set_starred" do
|
3
|
+
let(:session) { double }
|
4
|
+
let(:track_a) { FFI::MemoryPointer.new(:pointer) }
|
5
|
+
let(:track_b) { FFI::MemoryPointer.new(:pointer) }
|
6
|
+
let(:tracks) { [track_a, track_b] }
|
7
|
+
|
8
|
+
it "changes the starred state of the given tracks" do
|
9
|
+
api.should_receive(:sp_track_set_starred) do |ptr, buffer, buffer_size, starred|
|
10
|
+
ptr.should eq(session)
|
11
|
+
buffer.read_array_of_pointer(buffer_size).should eq(tracks)
|
12
|
+
starred.should eq(true)
|
13
|
+
:ok
|
14
|
+
end
|
15
|
+
|
16
|
+
api.track_set_starred(session, tracks, true).should eq(:ok)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "automatically casts the second parameter to an array" do
|
20
|
+
api.should_receive(:sp_track_set_starred) do |ptr, buffer, buffer_size, starred|
|
21
|
+
buffer.read_array_of_pointer(1).should eq([track_a])
|
22
|
+
buffer_size.should eq(1)
|
23
|
+
:ok
|
24
|
+
end
|
25
|
+
|
26
|
+
api.track_set_starred(session, track_a, true).should eq(:ok)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
describe Spotify::APIError do
|
2
|
+
let(:context) { nil }
|
3
|
+
|
4
|
+
describe ".from_native" do
|
5
|
+
it "returns an error of the correct class" do
|
6
|
+
error = Spotify::APIError.from_native(15, context)
|
7
|
+
error.should be_a Spotify::UserNeedsPremiumError
|
8
|
+
end
|
9
|
+
|
10
|
+
it "returns nil if not an error" do
|
11
|
+
Spotify::APIError.from_native(0, context).should be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "raises an error if not a valid error code" do
|
15
|
+
expect { Spotify::APIError.from_native(1337, context) }
|
16
|
+
.to raise_error(ArgumentError, /unknown error code/)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".to_i" do
|
21
|
+
it "returns the error code" do
|
22
|
+
Spotify::APIError.to_i.should be_nil
|
23
|
+
Spotify::UserNeedsPremiumError.to_i.should eq(15)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#message" do
|
28
|
+
it "is a formatted message with an explanation of the error" do
|
29
|
+
error = Spotify::UserNeedsPremiumError.new
|
30
|
+
error.message.should match /Needs a premium account/
|
31
|
+
error.message.should match /15/
|
32
|
+
end
|
33
|
+
|
34
|
+
it "can be overridden if necessary" do
|
35
|
+
error = Spotify::UserNeedsPremiumError.new("hoola hoop")
|
36
|
+
error.message.should eq "hoola hoop"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "API mapping" do
|
41
|
+
sp_error = API_H_XML.enumerations.each { |enum| break enum if enum.name == "sp_error" }
|
42
|
+
sp_error.values.each do |value|
|
43
|
+
next if value.name =~ /sp_error_ok/i
|
44
|
+
class_name = value.name.downcase.sub(/^sp_error/, "").gsub(/(_|^)(\w)/) { $2.upcase }
|
45
|
+
class_name << "Error" unless class_name =~ /Error/
|
46
|
+
|
47
|
+
describe class_name do
|
48
|
+
it "should have the error code number" do
|
49
|
+
constant = Spotify.constants.grep(/#{class_name}/i)[0]
|
50
|
+
Spotify.const_get(constant).to_i.should eq(value["init"].to_i)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/spotify/api_spec.rb
CHANGED
@@ -1,18 +1,24 @@
|
|
1
1
|
describe Spotify::API do
|
2
|
-
describe ".
|
3
|
-
it "
|
4
|
-
|
5
|
-
|
2
|
+
describe ".attach_function" do
|
3
|
+
it "is a retaining class if the method is not creating" do
|
4
|
+
begin
|
5
|
+
Spotify::API.attach_function :whatever, [], Spotify::User
|
6
|
+
rescue FFI::NotFoundError
|
7
|
+
# expected, this method does not exist
|
8
|
+
end
|
6
9
|
|
10
|
+
$attached_methods["whatever"][:returns].should eq Spotify::User.retaining_class
|
11
|
+
end
|
12
|
+
|
13
|
+
it "is a non-retaining class if the method is creating" do
|
7
14
|
begin
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
$stderr.read.should include "LAWL"
|
12
|
-
ensure
|
13
|
-
$stderr = old_stderr
|
14
|
-
FFI::Platform::OS.replace(old_platform)
|
15
|
+
Spotify::API.attach_function :whatever_create, [], Spotify::User
|
16
|
+
rescue FFI::NotFoundError
|
17
|
+
# expected, this method does not exist
|
15
18
|
end
|
19
|
+
|
20
|
+
$attached_methods["whatever_create"][:returns].should be Spotify::User
|
21
|
+
$attached_methods["whatever_create"][:returns].should_not be Spotify::User.retaining_class
|
16
22
|
end
|
17
23
|
end
|
18
24
|
end
|
@@ -4,19 +4,19 @@ describe Spotify::BestEffortString do
|
|
4
4
|
it "simply reads a null-terminated string" do
|
5
5
|
source = "hello wörld"
|
6
6
|
string = Spotify::BestEffortString.to_native(source, nil)
|
7
|
-
string.should eq "hello wörld".force_encoding(
|
7
|
+
string.should eq "hello wörld".force_encoding(Encoding::BINARY)
|
8
8
|
end
|
9
9
|
|
10
10
|
it "cuts the string at the first encountered NULL-byte" do
|
11
|
-
source = "hello\x00wörld".force_encoding(
|
11
|
+
source = "hello\x00wörld".force_encoding(Encoding::BINARY)
|
12
12
|
string = Spotify::BestEffortString.to_native(source, nil)
|
13
|
-
string.should eq "hello".force_encoding(
|
13
|
+
string.should eq "hello".force_encoding(Encoding::BINARY)
|
14
14
|
end
|
15
15
|
|
16
16
|
it "treats empty string as empty string, and not null" do
|
17
17
|
source = ""
|
18
18
|
string = Spotify::BestEffortString.to_native(source, nil)
|
19
|
-
string.should eq "".force_encoding(
|
19
|
+
string.should eq "".force_encoding(Encoding::BINARY)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
describe Spotify::CountryCode do
|
2
|
+
let(:context) { nil }
|
3
|
+
subject(:type) { Spotify::API.find_type(Spotify::CountryCode) }
|
4
|
+
|
5
|
+
describe ".from_native" do
|
6
|
+
it "decodes a country code" do
|
7
|
+
type.from_native(21317, context).should eq "SE"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ".to_native" do
|
12
|
+
it "encodes a country code" do
|
13
|
+
type.to_native("SE", context).should eq 21317
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -12,7 +12,7 @@ describe Spotify::ImageID do
|
|
12
12
|
let(:image_id) do
|
13
13
|
# deliberate NULL in middle of string
|
14
14
|
image_id = ":\xD94#\xAD\xD9\x97f\xE0\x00V6\x05\xC6\xE7n\xD2\xB0\xE4P"
|
15
|
-
image_id.force_encoding(
|
15
|
+
image_id.force_encoding(Encoding::BINARY)
|
16
16
|
image_id
|
17
17
|
end
|
18
18
|
|
File without changes
|
File without changes
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
describe Spotify::ManagedPointer do
|
3
|
-
let(:klass) { described_class }
|
4
3
|
let(:null) { FFI::Pointer::NULL }
|
5
4
|
let(:pointer) { FFI::Pointer.new(1) }
|
6
5
|
let(:klass) { Spotify::User }
|
@@ -17,19 +16,17 @@ describe Spotify::ManagedPointer do
|
|
17
16
|
api.should_not_receive(:user_release)
|
18
17
|
|
19
18
|
ptr = retaining_klass.new(FFI::Pointer::NULL)
|
20
|
-
ptr.autorelease = false
|
21
19
|
ptr.free
|
22
20
|
end
|
23
21
|
|
24
22
|
describe "#release" do
|
25
23
|
it "wraps the release pointer properly to avoid type-failures" do
|
26
|
-
api.should_receive(:user_release)
|
24
|
+
api.should_receive(:user_release) do |pointer|
|
27
25
|
pointer.should be_instance_of(klass)
|
28
26
|
pointer.should_not be_autorelease # autorelease should be off
|
29
27
|
end
|
30
28
|
|
31
29
|
ptr = klass.new(FFI::Pointer.new(1))
|
32
|
-
ptr.autorelease = false
|
33
30
|
ptr.free
|
34
31
|
end
|
35
32
|
end
|
@@ -61,6 +58,13 @@ describe Spotify::ManagedPointer do
|
|
61
58
|
end
|
62
59
|
end
|
63
60
|
|
61
|
+
describe ".from_native" do
|
62
|
+
it "returns nil if pointer is null" do
|
63
|
+
native = FFI::Pointer::NULL
|
64
|
+
klass.from_native(native, nil).should be_nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
64
68
|
describe ".size" do
|
65
69
|
it "returns the size of a pointer" do
|
66
70
|
Spotify::ManagedPointer.size.should eq FFI.type_size(:pointer)
|
@@ -106,21 +110,17 @@ describe Spotify::ManagedPointer do
|
|
106
110
|
next unless klass < Spotify::ManagedPointer
|
107
111
|
|
108
112
|
it "#{klass.name} has a valid retain method" do
|
109
|
-
Spotify.should_receive(:
|
110
|
-
|
111
|
-
method.should match(/_add_ref$/)
|
112
|
-
end
|
113
|
+
Spotify.should_receive(:"#{klass.type}_add_ref")
|
114
|
+
Spotify.should respond_to(:"#{klass.type}_add_ref")
|
113
115
|
|
114
116
|
klass.retain(FFI::Pointer.new(1))
|
115
117
|
end unless klass == Spotify::Session # has no valid retain
|
116
118
|
|
117
119
|
it "#{klass.name} has a valid release method" do
|
118
|
-
Spotify.should_receive(:
|
119
|
-
|
120
|
-
method.should match(/_release$/)
|
121
|
-
end
|
120
|
+
Spotify.should_receive(:"#{klass.type}_release")
|
121
|
+
Spotify.should respond_to(:"#{klass.type}_release")
|
122
122
|
|
123
|
-
klass.release(FFI::Pointer.new(1))
|
123
|
+
klass.release(FFI::Pointer.new(1)).value
|
124
124
|
end
|
125
125
|
end
|
126
126
|
end
|
@@ -100,10 +100,12 @@ describe Spotify::Subscribers do
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
+
it "returns an enumerator when not given a block" do
|
104
|
+
subscribers.each.should be_a Enumerator
|
105
|
+
end
|
106
|
+
|
103
107
|
it "returns an enumerator with a defined size when not given a block", :ruby_version => ">= 2.0.0" do
|
104
|
-
|
105
|
-
enumerator.should be_a Enumerator
|
106
|
-
enumerator.size.should eq 3
|
108
|
+
subscribers.each.size.should eq 3
|
107
109
|
end
|
108
110
|
|
109
111
|
it "yields every subscriber as an UTF-8 encoded string" do
|
@@ -1,6 +1,20 @@
|
|
1
|
-
describe "Spotify
|
1
|
+
describe "Spotify types" do
|
2
|
+
describe "audio sample types" do
|
3
|
+
Spotify::API.enum_type(:sampletype).symbols.each do |symbol|
|
4
|
+
specify "#{symbol} has a reader in FFI" do
|
5
|
+
FFI::Pointer.new(1).should respond_to "read_array_of_#{symbol}"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
2
10
|
API_H_XML.enumerations.each do |enum|
|
3
|
-
|
11
|
+
next if enum["name"] == "sp_error"
|
12
|
+
|
13
|
+
attached_tag = enum["name"].sub(/\Asp_/, '').to_sym
|
14
|
+
attached_enum = Spotify.enum_type(attached_tag)
|
15
|
+
unless attached_enum.tag == attached_tag
|
16
|
+
raise "Cannot find attached enum for #{enum["name"]}"
|
17
|
+
end
|
4
18
|
original_enum = enum.values.map { |v| [v["name"].downcase, v["init"]] }
|
5
19
|
|
6
20
|
describe enum["name"] do
|
@@ -19,4 +33,3 @@ describe "Spotify enums" do
|
|
19
33
|
end
|
20
34
|
end
|
21
35
|
end
|
22
|
-
|
@@ -0,0 +1,24 @@
|
|
1
|
+
describe "Spotify::Util" do
|
2
|
+
describe ".enum_value!" do
|
3
|
+
it "raises an error if given an invalid enum value" do
|
4
|
+
expect { Spotify::Util.enum_value!(:moo, "error value") }.to raise_error(ArgumentError)
|
5
|
+
end
|
6
|
+
|
7
|
+
it "gives back the enum value for that enum" do
|
8
|
+
Spotify::Util.enum_value!(:no_tracks, "search browse").should eq 1
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".platform" do
|
13
|
+
it "prints a warning containing the OS if platform unknown" do
|
14
|
+
suppress = true
|
15
|
+
_, err = spy_output(suppress) do
|
16
|
+
stub_const("FFI::Platform::OS", "LAWL")
|
17
|
+
Spotify::Util.platform
|
18
|
+
end
|
19
|
+
|
20
|
+
err.should match "unknown platform"
|
21
|
+
err.should match "LAWL"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
describe Spotify do
|
2
|
+
describe "VERSION" do
|
3
|
+
it "is defined" do
|
4
|
+
defined?(Spotify::VERSION).should eq "constant"
|
5
|
+
end
|
6
|
+
|
7
|
+
it "is the same version as in api.h" do
|
8
|
+
spotify_version = API_H_SRC.match(/#define\s+SPOTIFY_API_VERSION\s+(\d+)/)[1]
|
9
|
+
Spotify::API_VERSION.to_i.should eq spotify_version.to_i
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "proxying" do
|
14
|
+
it "responds to the spotify methods" do
|
15
|
+
Spotify.should respond_to :error_message
|
16
|
+
end
|
17
|
+
|
18
|
+
it "allows creating proxy methods" do
|
19
|
+
api.should_receive(:error_message).and_return("Some error")
|
20
|
+
Spotify.method(:error_message).call.should eq "Some error"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".log" do
|
25
|
+
it "print nothing if not debugging" do
|
26
|
+
out, err = spy_output do
|
27
|
+
old_debug, $DEBUG = $DEBUG, false
|
28
|
+
Spotify.log "They see me loggin'"
|
29
|
+
$DEBUG = old_debug
|
30
|
+
end
|
31
|
+
out.should be_empty
|
32
|
+
err.should be_empty
|
33
|
+
end
|
34
|
+
|
35
|
+
it "prints output and path if debugging" do
|
36
|
+
suppress = true
|
37
|
+
out, err = spy_output(suppress) do
|
38
|
+
old_debug, $DEBUG = $DEBUG, true
|
39
|
+
Spotify.log "Testin' Spotify log"
|
40
|
+
$DEBUG = old_debug
|
41
|
+
end
|
42
|
+
|
43
|
+
out.should match "Testin' Spotify log"
|
44
|
+
out.should match "spec/spotify_spec.rb"
|
45
|
+
|
46
|
+
err.should be_empty
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe ".try" do
|
51
|
+
it "raises an error when the result is not OK" do
|
52
|
+
api.should_receive(:error_example).and_return(Spotify::APIError.from_native(5, nil))
|
53
|
+
expect { Spotify.try(:error_example) }.to raise_error(Spotify::BadApplicationKeyError, /Invalid application key/)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "does not raise an error when the result is OK" do
|
57
|
+
api.should_receive(:error_example).and_return(nil)
|
58
|
+
Spotify.try(:error_example).should eq nil
|
59
|
+
end
|
60
|
+
|
61
|
+
it "does not raise an error when the result is not an error-type" do
|
62
|
+
result = Object.new
|
63
|
+
api.should_receive(:error_example).and_return(result)
|
64
|
+
Spotify.try(:error_example).should eq result
|
65
|
+
end
|
66
|
+
|
67
|
+
it "does not raise an error when the resource is loading" do
|
68
|
+
api.should_receive(:error_example).and_return(Spotify::APIError.from_native(17, nil))
|
69
|
+
error = Spotify.try(:error_example)
|
70
|
+
error.should be_a(Spotify::IsLoadingError)
|
71
|
+
error.message.should match /Resource not loaded yet/
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
module Spotify
|
2
2
|
# used to find the actual type of a thing
|
3
3
|
def self.resolve_type(type)
|
4
|
-
if type.is_a?(Class) and type <= Spotify::ManagedPointer
|
4
|
+
found = if type.is_a?(Class) and type <= Spotify::ManagedPointer
|
5
|
+
type
|
6
|
+
elsif type == Spotify::APIError
|
5
7
|
type
|
6
8
|
elsif type.respond_to?(:native_type)
|
7
9
|
type.native_type
|
8
10
|
else
|
9
11
|
type = Spotify::API.find_type(type)
|
10
|
-
type = type.type if type.respond_to?(:type)
|
11
12
|
type
|
12
13
|
end
|
14
|
+
|
15
|
+
found = found.type while found.respond_to?(:type)
|
16
|
+
found
|
13
17
|
end
|
14
18
|
|
15
19
|
# @return [Array<FFI::Struct>] all structs in Spotify namespace
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "stringio"
|
2
|
+
|
3
|
+
def spy_output(suppress = false)
|
4
|
+
old_out, $stdout = $stdout, StringIO.new
|
5
|
+
old_err, $stderr = $stderr, StringIO.new
|
6
|
+
yield
|
7
|
+
out = $stdout.tap(&:rewind).read
|
8
|
+
err = $stderr.tap(&:rewind).read
|
9
|
+
[out, err]
|
10
|
+
ensure
|
11
|
+
old_out.write(out) if not suppress and out
|
12
|
+
old_err.write(err) if not suppress and err
|
13
|
+
|
14
|
+
$stderr = old_err
|
15
|
+
$stdout = old_out
|
16
|
+
end
|