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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e5e929a7c03551703eebf95485b6f4fc8d91d2b
|
4
|
+
data.tar.gz: 329f09f809e753dd0993bcd51c95dfcedeb84e13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 929d6bfcdec85e642e301f6278d9b2c52cf42975304ad0fc5aa7fbceee404af6dbf9598011a9bc8d43921d7a95d97f9f1ed41b6cbd41cdf10c872f6bdb4e92f2
|
7
|
+
data.tar.gz: fd761313e677f2556992ca4fde3fb2fe27bcb9e7af5af1b2de1b30c425b0647ef1241ce5bfaaf18e0774d216fa15132b81af05979e3d2115a8812fa72813f7f1
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,6 +1,21 @@
|
|
1
|
+
language: ruby
|
2
|
+
script: "bundle exec ruby -W -S rspec spec"
|
3
|
+
cache: bundler
|
1
4
|
rvm:
|
2
|
-
-
|
3
|
-
- 1
|
4
|
-
-
|
5
|
-
- rbx-
|
6
|
-
- jruby
|
5
|
+
- 2.0
|
6
|
+
- 2.1
|
7
|
+
- ruby-head
|
8
|
+
- rbx-2
|
9
|
+
- jruby
|
10
|
+
env:
|
11
|
+
- RUBY_PLATFORM="x86_64-linux"
|
12
|
+
- RUBY_PLATFORM="x86_64-darwin11.3.0"
|
13
|
+
matrix:
|
14
|
+
allow_failures:
|
15
|
+
- rvm: ruby-head
|
16
|
+
notifications:
|
17
|
+
email:
|
18
|
+
recipients:
|
19
|
+
- kim@burgestrand.se
|
20
|
+
on_success: change
|
21
|
+
on_failure: change
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,34 @@
|
|
1
1
|
[HEAD][]
|
2
2
|
-----------
|
3
3
|
|
4
|
+
This change features a few large improvements:
|
5
|
+
|
6
|
+
- A bunch of API calls have been improved to remove FFI pointer juggling. Methods
|
7
|
+
such as e.g. #session_create, or #link_as_string are now much easier to use. See
|
8
|
+
https://github.com/Burgestrand/spotify/issues/19 for more details.
|
9
|
+
- Documentation has been much improved by (more or less) copying documentation
|
10
|
+
from libspotify docs, and adding some notes and examples to it.
|
11
|
+
- All API calls are now called in a specific background thread, powered by the
|
12
|
+
[Performer](https://rubygems.org/gems/performer) gem. This replaces the previous
|
13
|
+
mutex lock around all API calls, and possibly fixes a lot of random deadlocks.
|
14
|
+
See https://github.com/Burgestrand/spotify/issues/23.
|
15
|
+
- API reference documentation (YARD) has been added to all methods.
|
16
|
+
- Errors are no longer symbols, but actual errors inheriting from Spotify::APIError
|
17
|
+
|
18
|
+
Keep in mind that these changes are not backwards-compatible.
|
19
|
+
|
20
|
+
- [d80b9249] Make one class for each kind of error, instead of using symbols
|
21
|
+
- [0da56807] Move utility methods to Spotify::Util
|
22
|
+
- [72ee2526] Officially drop support for Ruby 1.9
|
23
|
+
- [dc492876] Perform *all* API calls in a specific Spotify thread
|
24
|
+
- [f5244743] A warning is now displayed on API mismatch instead of an error
|
25
|
+
- [dda1bc53] null pointers have been replaced by `nil`
|
26
|
+
- [98b5b1e0] Automatically encode country codes in #session_user_country
|
27
|
+
- [c8ad624e] Add #code and #symbol to Spotify::Error
|
28
|
+
- [77d1b978] Do not raise an error in Spotify.try when the resource is loading
|
29
|
+
- [f8293775] Print to stderr instead of stdout when libspotify cannot be found
|
30
|
+
- [c7042db6] Added Spotify.log (private API)
|
31
|
+
|
4
32
|
[v12.5.3][]
|
5
33
|
-----------
|
6
34
|
|
@@ -208,7 +236,7 @@ v0.0.0
|
|
208
236
|
|
209
237
|
[HEAD]: https://github.com/Burgestrand/spotify/compare/v12.5.3...HEAD
|
210
238
|
|
211
|
-
[v12.5.
|
239
|
+
[v12.5.3]: https://github.com/Burgestrand/spotify/compare/v12.5.2...v12.5.3
|
212
240
|
[v12.5.2]: https://github.com/Burgestrand/spotify/compare/v12.5.1...v12.5.2
|
213
241
|
[v12.5.1]: https://github.com/Burgestrand/spotify/compare/v12.5.0...v12.5.1
|
214
242
|
[v12.5.0]: https://github.com/Burgestrand/spotify/compare/v12.4.0...v12.5.0
|
data/Gemfile
CHANGED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
License
|
2
|
+
-------
|
3
|
+
Copyright (c) 2011-2013 Kim Burgestrand <kim@burgestrand.se>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.markdown
CHANGED
@@ -20,85 +20,110 @@ The Spotify gem has:
|
|
20
20
|
|
21
21
|
- [100% API coverage][], including callback support. You’ll be able to use any function from the libspotify library.
|
22
22
|
- [Automatic garbage collection][]. Piggybacking on Ruby’s GC to manage pointer lifecycle.
|
23
|
-
- [Parallell function call protection][]. libspotify is not thread-safe, but Spotify protects you by
|
23
|
+
- [Parallell function call protection][]. libspotify is not thread-safe, but Spotify protects you by making all API calls in a specific background thread.
|
24
24
|
- [Type conversion and type safety][]. Special pointers for every Spotify type, protecting you from accidental mix-ups.
|
25
|
-
- [Support for JRuby and Rubinius][]. Thanks to FFI, the gem runs fine on the main three Ruby implementations!
|
25
|
+
- [Support for Ruby, JRuby and Rubinius][]. Thanks to FFI, the gem runs fine on the main three Ruby implementations!
|
26
26
|
|
27
27
|
[100% API coverage]: http://rdoc.info/github/Burgestrand/spotify/master/Spotify/API
|
28
28
|
[Automatic garbage collection]: http://rdoc.info/github/Burgestrand/spotify/master/Spotify/ManagedPointer
|
29
29
|
[Parallell function call protection]: http://rdoc.info/github/Burgestrand/spotify/master/Spotify#method_missing-class_method
|
30
30
|
[Type conversion and type safety]: http://rdoc.info/github/Burgestrand/spotify/master/Spotify/ManagedPointer
|
31
|
-
[Support for JRuby and Rubinius]: https://github.com/Burgestrand/spotify/blob/master/.travis.yml
|
31
|
+
[Support for Ruby, JRuby and Rubinius]: https://github.com/Burgestrand/spotify/blob/master/.travis.yml
|
32
32
|
|
33
33
|
Contact details
|
34
34
|
---------------
|
35
35
|
|
36
|
-
- __Got questions?__ Ask on the mailing list: [ruby-
|
36
|
+
- __Got questions?__ Ask on the mailing list: [ruby-spotify@googlegroups.com][] (<https://groups.google.com/d/forum/ruby-spotify>)
|
37
37
|
- __Found a bug?__ Report an issue: <https://github.com/Burgestrand/spotify/issues/new>
|
38
38
|
- __Have feedback?__ I ❤ feedback! Please send it to the mailing list.
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
As the raw libspotify API is exposed, the Spotify gem is best coupled with a supporting
|
43
|
-
library. This library would take a more focused approach to which kind of applications
|
44
|
-
you can write using it. The Spotify gem itself, however, has very few opinions.
|
40
|
+
Questions, notes and answers
|
41
|
+
----------------------------
|
45
42
|
|
46
|
-
|
43
|
+
### Links to keep close at hand when using libspotify
|
47
44
|
|
48
|
-
- [
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
- [spotify gem API reference](http://rdoc.info/github/Burgestrand/spotify/master/Spotify/API) — YARDoc reference for the spotify gem, maps to the [libspotify function list](https://developer.spotify.com/docs/libspotify/12.1.51/api_8h.html).
|
46
|
+
- [libspotify C API reference](https://developer.spotify.com/docs/libspotify/12.1.51/) — the one true source of documentation.
|
47
|
+
- [libspotify FAQ](https://developer.spotify.com/technologies/libspotify/faq/) — you should read this at least once.
|
48
|
+
- [spotify gem examples](https://github.com/Burgestrand/spotify/tree/master/examples) — located in the spotify gem repository.
|
49
|
+
- [spotify gem FAQ](#questions-notes-and-answers) — this README section.
|
52
50
|
|
53
|
-
The Spotify API is well suited for experimentation, and it can be awfully fun to play with.
|
54
|
-
The examples/ directory contains example code for achieving certain tasks with the Spotify gem.
|
55
51
|
|
56
|
-
|
52
|
+
### How to run the examples
|
57
53
|
|
58
|
-
|
59
|
-
------------------------------
|
60
|
-
By default, Spotify uses [the libspotify gem](https://rubygems.org/gems/libspotify) which means you do
|
61
|
-
not need to install libspotify yourself. However, if your platform is not supported by the libspotify
|
62
|
-
gem you will need to install libspotify yourself.
|
54
|
+
You’ll need:
|
63
55
|
|
64
|
-
|
65
|
-
|
66
|
-
|
56
|
+
1. Your [Spotify](http://spotify.com/) premium account credentials. If you sign in with Facebook, you’ll need your Facebook account e-mail and password.
|
57
|
+
2. Your [Spotify application key](https://developer.spotify.com/technologies/libspotify/keys/). Download the binary key, and put it in the `examples/` directory.
|
58
|
+
|
59
|
+
Running the examples is as simple as:
|
60
|
+
|
61
|
+
```
|
62
|
+
ruby example-audio_stream.rb
|
63
|
+
```
|
64
|
+
|
65
|
+
Available examples are:
|
66
|
+
|
67
|
+
- **example-audio_stream.rb**: plays songs from Spotify with the [plaything](https://github.com/Burgestrand/plaything) gem, using OpenAL.
|
68
|
+
- **example-console.rb**: logs in to Spotfify, and initiates a pry session to allow experimentation with the spotify gem API.
|
69
|
+
- **example-listing_playlists.rb**: list all playlists available for a certain user.
|
70
|
+
- **example-loading_object.rb**: loads a track using polling and the spotify gem API.
|
71
|
+
- **example-random_related_artists.rb**: looks up an artist and its similar artists on spotify, then it picks a similar artist at random and does the same to that artist, over and over. I have used this example file to test prolonged usage of the API.
|
72
|
+
|
73
|
+
### Creating a Session, the first thing you should do
|
74
|
+
|
75
|
+
Almost all functions require you to have created a session before calling them. Forgetting to do so won’t work at best, and will segfault at worst. You'll also want to log in before doing things as well, or objects will never load.
|
76
|
+
|
77
|
+
See [Spotify::API#session_create](http://rdoc.info/github/Burgestrand/spotify/master/Spotify/API#session_create-instance_method) for how to create a session.
|
78
|
+
See [Spotify::API#session_login](http://rdoc.info/github/Burgestrand/spotify/master/Spotify/API#session_login-instance_method) for logging in.
|
79
|
+
|
80
|
+
### libspotify is an asynchronous library
|
81
|
+
|
82
|
+
When creating objects in libspotify they are not populated with data instantly, instead libspotify schedules them for download from the Spotify backend. For libspotify to do it's work with downloading content, you need to call [Spotify::API#session_process_events](http://rdoc.info/github/Burgestrand/spotify/master/Spotify/API#session_process_events-instance_method) regularly.
|
83
|
+
|
84
|
+
### Facebook vs Spotify Classic
|
67
85
|
|
68
|
-
|
69
|
-
|
86
|
+
Users who signed up to Spotify with their Facebook account will have numeric IDs as usernames, so a link to their profile looks like [spotify:user:11101648092](spotify:user:11101648092). Spotify Classic users instead have their usernames as canonical name, so a link to their profile looks like [spotify:user:burgestrand](spotify:user:burgestrand).
|
87
|
+
|
88
|
+
This matters, for example, when you use the function [Spotify::API#session_publishedcontainer_for_user_create](http://rdoc.info/github/Burgestrand/spotify/master/Spotify/API#session_publishedcontainer_for_user_create-instance_method).
|
89
|
+
|
90
|
+
### Callbacks can be dangerous
|
91
|
+
|
92
|
+
libspotify allows you to pass callbacks that will be invoked by libspotify when events of interest occur, such as being logged out, or receiving audio data when playing a track.
|
93
|
+
|
94
|
+
Callbacks can be very tricky. They must never be garbage collected while they are in use by libspotify, or you may get very weird bugs with your Ruby interpreter randomly crashing. Do use them, but be careful.
|
95
|
+
|
96
|
+
### Opinions and the Spotify gem
|
97
|
+
|
98
|
+
The Spotify gem has very few opinions. It is build to closely resemble the libspotify C API, and has very little
|
99
|
+
to aid you in terms of how to structure your application. It aims to make calling the libspotify C API frictionless,
|
100
|
+
but not much more. It is up to you to decide your own path.
|
101
|
+
|
102
|
+
### A note about gem versioning
|
70
103
|
|
71
|
-
A note about versioning scheme
|
72
|
-
------------------------------
|
73
104
|
Given a version `X.Y.Z`, each segment corresponds to:
|
74
105
|
|
75
|
-
- X reflects supported libspotify version (12.1.45 => 12). There are __no guarantees__ of backwards-compatibility!
|
76
|
-
- Y
|
106
|
+
- `X` reflects supported libspotify version (12.1.45 => 12). There are __no guarantees__ of backwards-compatibility!
|
107
|
+
- `Y` is for backwards-**incompatible** changes.
|
108
|
+
- `Z` is for backwards-**compatible** changes.
|
109
|
+
|
110
|
+
You should use the following version constraint: `gem "spotify", "~> 12.5.3"`.
|
77
111
|
|
78
|
-
License
|
79
|
-
-------
|
80
|
-
Copyright (c) 2012 Kim Burgestrand <kim@burgestrand.se>
|
81
112
|
|
82
|
-
|
83
|
-
of this software and associated documentation files (the "Software"), to deal
|
84
|
-
in the Software without restriction, including without limitation the rights
|
85
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
86
|
-
copies of the Software, and to permit persons to whom the Software is
|
87
|
-
furnished to do so, subject to the following conditions:
|
113
|
+
### Manually installing libspotify
|
88
114
|
|
89
|
-
|
90
|
-
|
115
|
+
By default, Spotify uses [the libspotify gem](https://rubygems.org/gems/libspotify) which means you do
|
116
|
+
not need to install libspotify yourself. However, if your platform is not supported by the libspotify
|
117
|
+
gem you will need to install libspotify yourself.
|
118
|
+
|
119
|
+
Please note, that if your platform is not supported by the libspotify gem I’d very much appreciate it
|
120
|
+
if you could create an issue on [libspotify gem issue tracker](https://github.com/Burgestrand/libspotify/issues)
|
121
|
+
so I can fix the build for your platform.
|
91
122
|
|
92
|
-
|
93
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
94
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
95
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
96
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
97
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
98
|
-
THE SOFTWARE.
|
123
|
+
Instructions on installing libspotify manually are in the wiki: [How to install libspotify](https://github.com/Burgestrand/spotify/wiki)
|
99
124
|
|
100
125
|
[semantic versioning (semver.org)]: http://semver.org/
|
101
|
-
[ruby-
|
126
|
+
[ruby-spotify@googlegroups.com]: mailto:ruby-spotify@googlegroups.com
|
102
127
|
[libspotify]: https://developer.spotify.com/technologies/libspotify/
|
103
128
|
[Spotify]: https://www.spotify.com/
|
104
129
|
[Hallon]: https://github.com/Burgestrand/Hallon
|
data/Rakefile
CHANGED
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# NOTE: this example is merely here to count how fast audio frames
|
5
|
+
# can be delivered. It does not do anything useful.
|
6
|
+
|
7
|
+
require_relative "support"
|
8
|
+
require "json"
|
9
|
+
|
10
|
+
$frames = 0
|
11
|
+
$rate = 0
|
12
|
+
|
13
|
+
Support::DEFAULT_CONFIG[:callbacks] = Spotify::SessionCallbacks.new({
|
14
|
+
music_delivery: proc do |session, format, frames, num_frames|
|
15
|
+
$rate = format[:sample_rate]
|
16
|
+
$frames += num_frames
|
17
|
+
num_frames
|
18
|
+
end,
|
19
|
+
|
20
|
+
end_of_track: proc do |session|
|
21
|
+
puts "End of track!"
|
22
|
+
$end_of_track = true
|
23
|
+
end
|
24
|
+
})
|
25
|
+
|
26
|
+
session = Support.initialize_spotify!
|
27
|
+
|
28
|
+
link = Spotify.link_create_from_string("spotify:track:1Lm5kdSQX6x1uVz6ep3AIk")
|
29
|
+
track = Spotify.link_as_track(link)
|
30
|
+
|
31
|
+
Support.poll(session) { Spotify.track_is_loaded(track) }
|
32
|
+
|
33
|
+
Spotify.try(:session_player_load, session, track)
|
34
|
+
Spotify.try(:session_player_play, session, true)
|
35
|
+
|
36
|
+
measurer = Thread.new do
|
37
|
+
loop do
|
38
|
+
if $rate
|
39
|
+
frames, $frames = $frames, 0
|
40
|
+
puts "#{frames}f of #{$rate}f/s (#{frames.fdiv($rate).round(2)}s)"
|
41
|
+
end
|
42
|
+
sleep 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
$logger.info "Playing track until end. Use ^C to exit."
|
47
|
+
Support.silenced = true
|
48
|
+
Support.poll(session) { $end_of_track }
|
@@ -1,18 +1,20 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# encoding: utf-8
|
3
3
|
|
4
|
-
require_relative "
|
4
|
+
require_relative "support"
|
5
5
|
|
6
6
|
require "json"
|
7
7
|
require "plaything"
|
8
8
|
|
9
|
-
def play_track(uri)
|
9
|
+
def play_track(session, uri)
|
10
10
|
link = Spotify.link_create_from_string(uri)
|
11
11
|
track = Spotify.link_as_track(link)
|
12
|
-
Support.poll(
|
13
|
-
|
14
|
-
|
15
|
-
Spotify.try(:session_player_play,
|
12
|
+
Support.poll(session) { Spotify.track_is_loaded(track) }
|
13
|
+
|
14
|
+
# Pause before we load a new track. Fixes a quirk in libspotify.
|
15
|
+
Spotify.try(:session_player_play, session, false)
|
16
|
+
Spotify.try(:session_player_load, session, track)
|
17
|
+
Spotify.try(:session_player_play, session, true)
|
16
18
|
end
|
17
19
|
|
18
20
|
class FrameReader
|
@@ -55,7 +57,7 @@ $session_callbacks = {
|
|
55
57
|
end,
|
56
58
|
|
57
59
|
logged_in: proc do |session, error|
|
58
|
-
$logger.debug("session (logged in)") {
|
60
|
+
$logger.debug("session (logged in)") { error.message }
|
59
61
|
end,
|
60
62
|
|
61
63
|
logged_out: proc do |session|
|
@@ -63,7 +65,7 @@ $session_callbacks = {
|
|
63
65
|
end,
|
64
66
|
|
65
67
|
streaming_error: proc do |session, error|
|
66
|
-
$logger.error("session (player)") { "streaming error %s" %
|
68
|
+
$logger.error("session (player)") { "streaming error %s" % error.message }
|
67
69
|
end,
|
68
70
|
|
69
71
|
start_playback: proc do |session|
|
@@ -109,28 +111,11 @@ $session_callbacks = {
|
|
109
111
|
# You can read about what these session configuration options do in the
|
110
112
|
# libspotify documentation:
|
111
113
|
# https://developer.spotify.com/technologies/libspotify/docs/12.1.45/structsp__session__config.html
|
112
|
-
|
113
|
-
api_version: Spotify::API_VERSION.to_i,
|
114
|
-
application_key: $appkey,
|
115
|
-
cache_location: ".spotify/",
|
116
|
-
settings_location: ".spotify/",
|
117
|
-
tracefile: "spotify_tracefile.txt",
|
118
|
-
user_agent: "spotify for ruby",
|
119
|
-
callbacks: Spotify::SessionCallbacks.new($session_callbacks),
|
120
|
-
})
|
121
|
-
|
122
|
-
$logger.info "Creating session."
|
123
|
-
$session = Support.create_session(config)
|
124
|
-
|
125
|
-
$logger.info "Created! Logging in."
|
126
|
-
Spotify.session_login($session, $username, $password, false, $blob)
|
127
|
-
|
128
|
-
$logger.info "Log in requested. Waiting forever until logged in."
|
129
|
-
Support.poll($session) { Spotify.session_connectionstate($session) == :logged_in }
|
114
|
+
Support::DEFAULT_CONFIG[:callbacks] = Spotify::SessionCallbacks.new($session_callbacks)
|
130
115
|
|
131
|
-
|
116
|
+
session = Support.initialize_spotify!
|
132
117
|
|
133
|
-
play_track Support.prompt("Spotify track URI")
|
118
|
+
play_track(session, Support.prompt("Spotify track URI", "spotify:track:5iIeIeH3LBSMK92cMIXrVD"))
|
134
119
|
|
135
120
|
$logger.info "Playing track until end. Use ^C to exit."
|
136
|
-
Support.poll(
|
121
|
+
Support.poll(session) { $end_of_track }
|
@@ -0,0 +1,89 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require_relative "support"
|
5
|
+
|
6
|
+
session = Support.initialize_spotify!
|
7
|
+
|
8
|
+
username = Support.prompt("Please enter a username", "burgestrand")
|
9
|
+
|
10
|
+
# libspotify has no way of searching for users by name or e-mail, so
|
11
|
+
# this is the only way I know of to get a handle of a user from nothing,
|
12
|
+
# and probably won't work for users that do not have a classic Spotify
|
13
|
+
# username, i.e. users that only signed up through Facebook.
|
14
|
+
#
|
15
|
+
# If you can get a handle on a playlist created by that user, you'll be
|
16
|
+
# able to get the handle for them, but not otherwise!
|
17
|
+
#
|
18
|
+
# For users that signed up through Facebook only, I believe their Facebook
|
19
|
+
# user ID should work with this lookup.
|
20
|
+
user_link = "spotify:user:#{username}"
|
21
|
+
link = Spotify.link_create_from_string(user_link)
|
22
|
+
|
23
|
+
if link.null?
|
24
|
+
$logger.error "#{user_link} was apparently not parseable as a Spotify URI. Aborting."
|
25
|
+
abort
|
26
|
+
end
|
27
|
+
|
28
|
+
user = Spotify.link_as_user(link)
|
29
|
+
$logger.info "Attempting to load #{user_link}. Waiting forever until successful."
|
30
|
+
Support.poll(session) { Spotify.user_is_loaded(user) }
|
31
|
+
|
32
|
+
display_name = Spotify.user_display_name(user)
|
33
|
+
canonical_name = Spotify.user_canonical_name(user)
|
34
|
+
$logger.info "User loaded: #{display_name}."
|
35
|
+
|
36
|
+
$logger.info "Loading user playlists by loading their published container: #{canonical_name}."
|
37
|
+
container = Spotify.session_publishedcontainer_for_user_create(session, canonical_name)
|
38
|
+
|
39
|
+
$logger.info "Attempting to load container. Waiting forever until successful."
|
40
|
+
Support.poll(session) { Spotify.playlistcontainer_is_loaded(container) }
|
41
|
+
|
42
|
+
$logger.info "Container loaded. Loading playlists until no more are loaded for three tries!"
|
43
|
+
|
44
|
+
container_size = 0
|
45
|
+
previous_container_size = 0
|
46
|
+
break_counter = 0
|
47
|
+
|
48
|
+
loop do
|
49
|
+
container_size = Spotify.playlistcontainer_num_playlists(container)
|
50
|
+
new_playlists = container_size - previous_container_size
|
51
|
+
previous_container_size = container_size
|
52
|
+
$logger.info "Loaded #{new_playlists} more playlists."
|
53
|
+
|
54
|
+
# If we have loaded no new playlists for 4 tries, we assume we are done.
|
55
|
+
if new_playlists == 0
|
56
|
+
break_counter += 1
|
57
|
+
if break_counter >= 4
|
58
|
+
break
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
$logger.info "Loading…"
|
63
|
+
5.times do
|
64
|
+
Support.process_events(session)
|
65
|
+
sleep 0.2
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
$logger.info "#{container_size} published playlists for #{display_name} found. Loading each playlists and printing it."
|
70
|
+
container_size.times do |index|
|
71
|
+
type = Spotify.playlistcontainer_playlist_type(container, index)
|
72
|
+
playlist = Spotify.playlistcontainer_playlist(container, index)
|
73
|
+
Support.poll(session) { Spotify.playlist_is_loaded(playlist) }
|
74
|
+
|
75
|
+
playlist_name = Spotify.playlist_name(playlist)
|
76
|
+
num_tracks = Spotify.playlist_num_tracks(playlist)
|
77
|
+
|
78
|
+
# Retrieving link for playlist:
|
79
|
+
playlist_link = Spotify.link_create_from_playlist(playlist)
|
80
|
+
link_string = if playlist_link.nil?
|
81
|
+
"(no link)"
|
82
|
+
else
|
83
|
+
Spotify.link_as_string(playlist_link)
|
84
|
+
end
|
85
|
+
|
86
|
+
$logger.info " (#{type}) #{playlist_name}: #{link_string} (#{num_tracks} tracks)"
|
87
|
+
end
|
88
|
+
|
89
|
+
$logger.info "All done."
|