spotify 12.2.0 → 12.3.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.
- data/.gitignore +3 -1
 - data/.rspec +5 -0
 - data/CHANGELOG.md +45 -27
 - data/Gemfile +4 -0
 - data/README.markdown +52 -19
 - data/Rakefile +16 -7
 - data/lib/spotify.rb +109 -8
 - data/lib/spotify/api.rb +61 -0
 - data/lib/spotify/api/album.rb +14 -0
 - data/lib/spotify/api/album_browse.rb +18 -0
 - data/lib/spotify/api/artist.rb +10 -0
 - data/lib/spotify/api/artist_browse.rb +23 -0
 - data/lib/spotify/api/error.rb +6 -0
 - data/lib/spotify/api/image.rb +16 -0
 - data/lib/spotify/api/inbox.rb +9 -0
 - data/lib/spotify/api/link.rb +25 -0
 - data/lib/spotify/api/playlist.rb +39 -0
 - data/lib/spotify/api/playlist_container.rb +23 -0
 - data/lib/spotify/api/search.rb +27 -0
 - data/lib/spotify/api/session.rb +46 -0
 - data/lib/spotify/api/toplist_browse.rb +17 -0
 - data/lib/spotify/api/track.rb +26 -0
 - data/lib/spotify/api/user.rb +10 -0
 - data/lib/spotify/defines.rb +109 -0
 - data/lib/spotify/error.rb +62 -0
 - data/lib/spotify/managed_pointer.rb +90 -0
 - data/lib/spotify/objects.rb +16 -0
 - data/lib/spotify/objects/album.rb +5 -0
 - data/lib/spotify/objects/album_browse.rb +5 -0
 - data/lib/spotify/objects/artist.rb +5 -0
 - data/lib/spotify/objects/artist_browse.rb +5 -0
 - data/lib/spotify/objects/image.rb +5 -0
 - data/lib/spotify/objects/inbox.rb +5 -0
 - data/lib/spotify/objects/link.rb +5 -0
 - data/lib/spotify/objects/playlist.rb +5 -0
 - data/lib/spotify/objects/playlist_container.rb +5 -0
 - data/lib/spotify/objects/search.rb +5 -0
 - data/lib/spotify/objects/session.rb +20 -0
 - data/lib/spotify/objects/toplist_browse.rb +5 -0
 - data/lib/spotify/objects/track.rb +5 -0
 - data/lib/spotify/objects/user.rb +5 -0
 - data/lib/spotify/structs.rb +46 -0
 - data/lib/spotify/structs/audio_buffer_stats.rb +10 -0
 - data/lib/spotify/structs/audio_format.rb +12 -0
 - data/lib/spotify/structs/offline_sync_status.rb +24 -0
 - data/lib/spotify/structs/playlist_callbacks.rb +32 -0
 - data/lib/spotify/structs/playlist_container_callbacks.rb +14 -0
 - data/lib/spotify/structs/session_callbacks.rb +48 -0
 - data/lib/spotify/structs/session_config.rb +64 -0
 - data/lib/spotify/structs/subscribers.rb +31 -0
 - data/lib/spotify/types.rb +3 -0
 - data/lib/spotify/types/image_id.rb +5 -0
 - data/lib/spotify/types/nul_string.rb +51 -0
 - data/lib/spotify/types/utf8_string.rb +24 -28
 - data/lib/spotify/util.rb +36 -0
 - data/lib/spotify/version.rb +7 -2
 - data/spec/api-linux.xml +1887 -0
 - data/spec/api-mac.xml +1886 -0
 - data/spec/spec_helper.rb +20 -0
 - data/spec/spotify/api_spec.rb +62 -0
 - data/spec/spotify/defines_spec.rb +22 -0
 - data/spec/spotify/enums_spec.rb +9 -0
 - data/spec/spotify/managed_pointer_spec.rb +75 -0
 - data/spec/spotify/spotify_spec.rb +69 -0
 - data/spec/spotify/structs/session_config_spec.rb +20 -0
 - data/spec/spotify/structs/struct_spec.rb +34 -0
 - data/spec/spotify/structs/subscribers_spec.rb +31 -0
 - data/spec/spotify/structs_spec.rb +19 -0
 - data/spec/spotify/types/image_id_spec.rb +44 -0
 - data/spec/spotify/types/nul_string_spec.rb +31 -0
 - data/spec/spotify/types/utf8_string_spec.rb +24 -0
 - data/spec/support/hook_spotify.rb +37 -0
 - data/spec/support/spotify_util.rb +17 -0
 - data/spotify.gemspec +6 -11
 - metadata +99 -26
 - data/lib/spotify/error_wrappers.rb +0 -165
 - data/lib/spotify/functions.rb +0 -755
 - data/lib/spotify/gc_wrappers.rb +0 -105
 - data/lib/spotify/types/pointer.rb +0 -59
 - data/spec/spotify_spec.rb +0 -467
 
    
        data/lib/spotify/gc_wrappers.rb
    DELETED
    
    | 
         @@ -1,105 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # This file contains a tiny (!) DSL that wraps existing Spotify
         
     | 
| 
       2 
     | 
    
         
            -
            # functions into versions that return Spotify::Pointers instead
         
     | 
| 
       3 
     | 
    
         
            -
            # of the usual FFI::Pointers. The Spotify::Pointer automatically
         
     | 
| 
       4 
     | 
    
         
            -
            # manages the underlying pointers reference count, which allows
         
     | 
| 
       5 
     | 
    
         
            -
            # us to piggyback on the Ruby GC mechanism.
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
            module Spotify
         
     | 
| 
       8 
     | 
    
         
            -
              # Wraps the function `function` so that it always returns
         
     | 
| 
       9 
     | 
    
         
            -
              # a Spotify::Pointer with correct refcount. Functions that
         
     | 
| 
       10 
     | 
    
         
            -
              # contain the word `create` are assumed to start out with
         
     | 
| 
       11 
     | 
    
         
            -
              # a refcount of `+1`.
         
     | 
| 
       12 
     | 
    
         
            -
              #
         
     | 
| 
       13 
     | 
    
         
            -
              # @note This method is removed at the bottom of this file.
         
     | 
| 
       14 
     | 
    
         
            -
              #
         
     | 
| 
       15 
     | 
    
         
            -
              # @param [#to_s] function
         
     | 
| 
       16 
     | 
    
         
            -
              # @param [#to_s] return_type
         
     | 
| 
       17 
     | 
    
         
            -
              # @raise [NoMethodError] if `function` is not defined
         
     | 
| 
       18 
     | 
    
         
            -
              # @see Spotify::Pointer
         
     | 
| 
       19 
     | 
    
         
            -
              def self.wrap_function(function, return_type)
         
     | 
| 
       20 
     | 
    
         
            -
                method(function) # make sure it exists
         
     | 
| 
       21 
     | 
    
         
            -
                define_singleton_method("#{function}!") do |*args, &block|
         
     | 
| 
       22 
     | 
    
         
            -
                  pointer = public_send(function, *args, &block)
         
     | 
| 
       23 
     | 
    
         
            -
                  Spotify::Pointer.new(pointer, return_type, function !~ /create/)
         
     | 
| 
       24 
     | 
    
         
            -
                end
         
     | 
| 
       25 
     | 
    
         
            -
              end
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
              # @macro [attach] wrap_function
         
     | 
| 
       28 
     | 
    
         
            -
              #   Same as {Spotify}.`$1`, but wraps result in a {Spotify::Pointer}.
         
     | 
| 
       29 
     | 
    
         
            -
              #
         
     | 
| 
       30 
     | 
    
         
            -
              #   @method $1!
         
     | 
| 
       31 
     | 
    
         
            -
              #   @return [Spotify::Pointer<$2>]
         
     | 
| 
       32 
     | 
    
         
            -
              #   @see #$1
         
     | 
| 
       33 
     | 
    
         
            -
              wrap_function :session_user, :user
         
     | 
| 
       34 
     | 
    
         
            -
              wrap_function :session_playlistcontainer, :playlistcontainer
         
     | 
| 
       35 
     | 
    
         
            -
              wrap_function :session_inbox_create, :playlist
         
     | 
| 
       36 
     | 
    
         
            -
              wrap_function :session_starred_create, :playlist
         
     | 
| 
       37 
     | 
    
         
            -
              wrap_function :session_starred_for_user_create, :playlist
         
     | 
| 
       38 
     | 
    
         
            -
              wrap_function :session_publishedcontainer_for_user_create, :playlistcontainer
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
              wrap_function :track_artist, :artist
         
     | 
| 
       41 
     | 
    
         
            -
              wrap_function :track_album, :album
         
     | 
| 
       42 
     | 
    
         
            -
              wrap_function :localtrack_create, :track
         
     | 
| 
       43 
     | 
    
         
            -
              wrap_function :track_get_playable, :track
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
              wrap_function :album_artist, :artist
         
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
              wrap_function :albumbrowse_create, :albumbrowse
         
     | 
| 
       48 
     | 
    
         
            -
              wrap_function :albumbrowse_album, :album
         
     | 
| 
       49 
     | 
    
         
            -
              wrap_function :albumbrowse_artist, :artist
         
     | 
| 
       50 
     | 
    
         
            -
              wrap_function :albumbrowse_track, :track
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
              wrap_function :artistbrowse_create, :artistbrowse
         
     | 
| 
       53 
     | 
    
         
            -
              wrap_function :artistbrowse_artist, :artist
         
     | 
| 
       54 
     | 
    
         
            -
              wrap_function :artistbrowse_track, :track
         
     | 
| 
       55 
     | 
    
         
            -
              wrap_function :artistbrowse_album, :album
         
     | 
| 
       56 
     | 
    
         
            -
              wrap_function :artistbrowse_similar_artist, :artist
         
     | 
| 
       57 
     | 
    
         
            -
              wrap_function :artistbrowse_tophit_track, :track
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
              wrap_function :image_create, :image
         
     | 
| 
       60 
     | 
    
         
            -
              wrap_function :image_create_from_link, :image
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
              wrap_function :link_as_track, :track
         
     | 
| 
       63 
     | 
    
         
            -
              wrap_function :link_as_track_and_offset, :track
         
     | 
| 
       64 
     | 
    
         
            -
              wrap_function :link_as_album, :album
         
     | 
| 
       65 
     | 
    
         
            -
              wrap_function :link_as_artist, :artist
         
     | 
| 
       66 
     | 
    
         
            -
              wrap_function :link_as_user, :user
         
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
              wrap_function :link_create_from_string, :link
         
     | 
| 
       69 
     | 
    
         
            -
              wrap_function :link_create_from_track, :link
         
     | 
| 
       70 
     | 
    
         
            -
              wrap_function :link_create_from_album, :link
         
     | 
| 
       71 
     | 
    
         
            -
              wrap_function :link_create_from_artist, :link
         
     | 
| 
       72 
     | 
    
         
            -
              wrap_function :link_create_from_search, :link
         
     | 
| 
       73 
     | 
    
         
            -
              wrap_function :link_create_from_playlist, :link
         
     | 
| 
       74 
     | 
    
         
            -
              wrap_function :link_create_from_artist_portrait, :link
         
     | 
| 
       75 
     | 
    
         
            -
              wrap_function :link_create_from_artistbrowse_portrait, :link
         
     | 
| 
       76 
     | 
    
         
            -
              wrap_function :link_create_from_album_cover, :link
         
     | 
| 
       77 
     | 
    
         
            -
              wrap_function :link_create_from_image, :link
         
     | 
| 
       78 
     | 
    
         
            -
              wrap_function :link_create_from_user, :link
         
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
              wrap_function :search_create, :search
         
     | 
| 
       81 
     | 
    
         
            -
              wrap_function :search_track, :track
         
     | 
| 
       82 
     | 
    
         
            -
              wrap_function :search_album, :album
         
     | 
| 
       83 
     | 
    
         
            -
              wrap_function :search_artist, :artist
         
     | 
| 
       84 
     | 
    
         
            -
              wrap_function :search_playlist, :playlist
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
              wrap_function :playlist_track, :track
         
     | 
| 
       87 
     | 
    
         
            -
              wrap_function :playlist_track_creator, :user
         
     | 
| 
       88 
     | 
    
         
            -
              wrap_function :playlist_owner, :user
         
     | 
| 
       89 
     | 
    
         
            -
              wrap_function :playlist_create, :playlist
         
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
              wrap_function :playlistcontainer_playlist, :playlist
         
     | 
| 
       92 
     | 
    
         
            -
              wrap_function :playlistcontainer_add_new_playlist, :playlist
         
     | 
| 
       93 
     | 
    
         
            -
              wrap_function :playlistcontainer_add_playlist, :playlist
         
     | 
| 
       94 
     | 
    
         
            -
              wrap_function :playlistcontainer_owner, :user
         
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
              wrap_function :toplistbrowse_create, :toplistbrowse
         
     | 
| 
       97 
     | 
    
         
            -
              wrap_function :toplistbrowse_artist, :artist
         
     | 
| 
       98 
     | 
    
         
            -
              wrap_function :toplistbrowse_album, :album
         
     | 
| 
       99 
     | 
    
         
            -
              wrap_function :toplistbrowse_track, :track
         
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
              wrap_function :inbox_post_tracks, :inbox
         
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
              # Clean up
         
     | 
| 
       104 
     | 
    
         
            -
              class << self; undef :wrap_function; end
         
     | 
| 
       105 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,59 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Spotify
         
     | 
| 
       2 
     | 
    
         
            -
              # The Pointer is a kind of AutoPointer specially tailored for Spotify
         
     | 
| 
       3 
     | 
    
         
            -
              # objects, that releases the raw pointer on GC.
         
     | 
| 
       4 
     | 
    
         
            -
              class Pointer < FFI::AutoPointer
         
     | 
| 
       5 
     | 
    
         
            -
                # Raised when #releaser_for is given an invalid type.
         
     | 
| 
       6 
     | 
    
         
            -
                class InvalidTypeError < StandardError
         
     | 
| 
       7 
     | 
    
         
            -
                end
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
                class << self
         
     | 
| 
       10 
     | 
    
         
            -
                  # Create a proc that will accept a pointer of a given type and
         
     | 
| 
       11 
     | 
    
         
            -
                  # release it with the correct function if it’s not null.
         
     | 
| 
       12 
     | 
    
         
            -
                  #
         
     | 
| 
       13 
     | 
    
         
            -
                  # @raise [InvalidTypeError] when given an invalid type
         
     | 
| 
       14 
     | 
    
         
            -
                  # @param [Symbol] type
         
     | 
| 
       15 
     | 
    
         
            -
                  # @return [Proc]
         
     | 
| 
       16 
     | 
    
         
            -
                  def releaser_for(type)
         
     | 
| 
       17 
     | 
    
         
            -
                    unless Spotify.respond_to?(:"#{type}_release!")
         
     | 
| 
       18 
     | 
    
         
            -
                      raise InvalidTypeError, "#{type} is not a valid Spotify type"
         
     | 
| 
       19 
     | 
    
         
            -
                    end
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                    lambda do |pointer|
         
     | 
| 
       22 
     | 
    
         
            -
                      $stdout.puts "Spotify::#{type}_release!(#{pointer})" if $DEBUG
         
     | 
| 
       23 
     | 
    
         
            -
                      Spotify.send(:"#{type}_release!", pointer) unless pointer.null?
         
     | 
| 
       24 
     | 
    
         
            -
                    end
         
     | 
| 
       25 
     | 
    
         
            -
                  end
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                  # Checks an object by pointer kind and type.
         
     | 
| 
       28 
     | 
    
         
            -
                  #
         
     | 
| 
       29 
     | 
    
         
            -
                  # @param [Object] object
         
     | 
| 
       30 
     | 
    
         
            -
                  # @param [Symbol] type
         
     | 
| 
       31 
     | 
    
         
            -
                  # @return [Boolean] true if object is a spotify pointer and of correct type
         
     | 
| 
       32 
     | 
    
         
            -
                  def typechecks?(object, type)
         
     | 
| 
       33 
     | 
    
         
            -
                    object.is_a?(Spotify::Pointer) && (object.type == type.to_s)
         
     | 
| 
       34 
     | 
    
         
            -
                  end
         
     | 
| 
       35 
     | 
    
         
            -
                end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                # @return [Symbol] type
         
     | 
| 
       38 
     | 
    
         
            -
                attr_reader :type
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                # Initialize a Spotify pointer, which will automatically decrease
         
     | 
| 
       41 
     | 
    
         
            -
                # the reference count of it’s pointer when garbage collected.
         
     | 
| 
       42 
     | 
    
         
            -
                #
         
     | 
| 
       43 
     | 
    
         
            -
                # @param [FFI::Pointer] pointer
         
     | 
| 
       44 
     | 
    
         
            -
                # @param [#to_s] type session, link, etc
         
     | 
| 
       45 
     | 
    
         
            -
                # @param [Boolean] add_ref will increase refcount by one if true
         
     | 
| 
       46 
     | 
    
         
            -
                def initialize(pointer, type, add_ref)
         
     | 
| 
       47 
     | 
    
         
            -
                  super pointer, self.class.releaser_for(@type = type.to_s)
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
                  unless pointer.null?
         
     | 
| 
       50 
     | 
    
         
            -
                    Spotify.send(:"#{type}_add_ref!", pointer)
         
     | 
| 
       51 
     | 
    
         
            -
                  end if add_ref
         
     | 
| 
       52 
     | 
    
         
            -
                end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                # @return [String] representation of the spotify pointer
         
     | 
| 
       55 
     | 
    
         
            -
                def to_s
         
     | 
| 
       56 
     | 
    
         
            -
                  "<#{self.class} address=0x#{address.to_s(16)} type=#{type}>"
         
     | 
| 
       57 
     | 
    
         
            -
                end
         
     | 
| 
       58 
     | 
    
         
            -
              end
         
     | 
| 
       59 
     | 
    
         
            -
            end
         
     | 
    
        data/spec/spotify_spec.rb
    DELETED
    
    | 
         @@ -1,467 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # coding: utf-8
         
     | 
| 
       2 
     | 
    
         
            -
            require 'rubygems' # needed for 1.8, does not matter in 1.9
         
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
            require 'ostruct'
         
     | 
| 
       5 
     | 
    
         
            -
            require 'set'
         
     | 
| 
       6 
     | 
    
         
            -
            require 'rbgccxml'
         
     | 
| 
       7 
     | 
    
         
            -
            require 'minitest/mock'
         
     | 
| 
       8 
     | 
    
         
            -
            require 'minitest/autorun'
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
            #
         
     | 
| 
       11 
     | 
    
         
            -
            # Hooking FFI for extra introspection
         
     | 
| 
       12 
     | 
    
         
            -
            #
         
     | 
| 
       13 
     | 
    
         
            -
            require 'ffi'
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
            module Spotify
         
     | 
| 
       16 
     | 
    
         
            -
              extend FFI::Library
         
     | 
| 
       17 
     | 
    
         
            -
              extend self
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
              def attach_function(name, func, arguments, returns = nil, options = nil)
         
     | 
| 
       20 
     | 
    
         
            -
                args = [name, func, arguments, returns, options].compact
         
     | 
| 
       21 
     | 
    
         
            -
                args.unshift name.to_s if func.is_a?(Array)
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                hargs = [:name, :func, :args, :returns].zip args
         
     | 
| 
       24 
     | 
    
         
            -
                @attached_methods ||= {}
         
     | 
| 
       25 
     | 
    
         
            -
                @attached_methods[name.to_s] = hash = Hash[hargs]
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                super
         
     | 
| 
       28 
     | 
    
         
            -
              end
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
              def resolve_type(type)
         
     | 
| 
       31 
     | 
    
         
            -
                type = find_type(type)
         
     | 
| 
       32 
     | 
    
         
            -
                type = type.type if type.respond_to?(:type)
         
     | 
| 
       33 
     | 
    
         
            -
                type
         
     | 
| 
       34 
     | 
    
         
            -
              end
         
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
              attr_reader :attached_methods
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
              RUBY_PLATFORM = ENV.fetch('RUBY_PLATFORM') do
         
     | 
| 
       39 
     | 
    
         
            -
                puts "[WARN] Tests running with default ruby platform, #{::RUBY_PLATFORM}, please be"
         
     | 
| 
       40 
     | 
    
         
            -
                puts "[WARN] specific in which platform to target by setting ENV[RUBY_PLATFORM]"
         
     | 
| 
       41 
     | 
    
         
            -
                puts "(warnings coming from #{__FILE__}:#{__LINE__})"
         
     | 
| 
       42 
     | 
    
         
            -
                puts
         
     | 
| 
       43 
     | 
    
         
            -
                ::RUBY_PLATFORM
         
     | 
| 
       44 
     | 
    
         
            -
              end
         
     | 
| 
       45 
     | 
    
         
            -
            end
         
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
            require 'spotify'
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
            module C
         
     | 
| 
       50 
     | 
    
         
            -
              extend FFI::Library
         
     | 
| 
       51 
     | 
    
         
            -
              ffi_lib 'C'
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
              typedef Spotify::UTF8String, :utf8_string
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
              attach_function :strncpy, [ :pointer, :utf8_string, :size_t ], :utf8_string
         
     | 
| 
       56 
     | 
    
         
            -
            end
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
            # Used for checking Spotify::Pointer things.
         
     | 
| 
       59 
     | 
    
         
            -
            module Spotify
         
     | 
| 
       60 
     | 
    
         
            -
              def bogus_add_ref!(pointer)
         
     | 
| 
       61 
     | 
    
         
            -
              end
         
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
              def bogus_release!(pointer)
         
     | 
| 
       64 
     | 
    
         
            -
              end
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
              # This may be called after our GC test. Randomly.
         
     | 
| 
       67 
     | 
    
         
            -
              def garbage_release!(pointer)
         
     | 
| 
       68 
     | 
    
         
            -
              end
         
     | 
| 
       69 
     | 
    
         
            -
            end
         
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
            #
         
     | 
| 
       72 
     | 
    
         
            -
            # Utility
         
     | 
| 
       73 
     | 
    
         
            -
            #
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
            API_H_PATH = File.expand_path("../api-#{Spotify.platform}.h", __FILE__)
         
     | 
| 
       76 
     | 
    
         
            -
            API_H_SRC  = File.read(API_H_PATH)
         
     | 
| 
       77 
     | 
    
         
            -
            API_H_XML  = RbGCCXML.parse(API_H_PATH)
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
            #
         
     | 
| 
       80 
     | 
    
         
            -
            # General
         
     | 
| 
       81 
     | 
    
         
            -
            #
         
     | 
| 
       82 
     | 
    
         
            -
            describe Spotify do
         
     | 
| 
       83 
     | 
    
         
            -
              describe "VERSION" do
         
     | 
| 
       84 
     | 
    
         
            -
                it "should be defined" do
         
     | 
| 
       85 
     | 
    
         
            -
                  defined?(Spotify::VERSION).must_equal "constant"
         
     | 
| 
       86 
     | 
    
         
            -
                end
         
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
                it "should be the same version as in api.h" do
         
     | 
| 
       89 
     | 
    
         
            -
                  spotify_version = API_H_SRC.match(/#define\s+SPOTIFY_API_VERSION\s+(\d+)/)[1]
         
     | 
| 
       90 
     | 
    
         
            -
                  Spotify::API_VERSION.must_equal spotify_version.to_i
         
     | 
| 
       91 
     | 
    
         
            -
                end
         
     | 
| 
       92 
     | 
    
         
            -
              end
         
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
              describe ".enum_value!" do
         
     | 
| 
       95 
     | 
    
         
            -
                it "raises an error if given an invalid enum value" do
         
     | 
| 
       96 
     | 
    
         
            -
                  proc { Spotify.enum_value!(:moo, "error value") }.must_raise(ArgumentError)
         
     | 
| 
       97 
     | 
    
         
            -
                end
         
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
                it "gives back the enum value for that enum" do
         
     | 
| 
       100 
     | 
    
         
            -
                  Spotify.enum_value!(:ok, "error value").must_equal 0
         
     | 
| 
       101 
     | 
    
         
            -
                end
         
     | 
| 
       102 
     | 
    
         
            -
              end
         
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
       104 
     | 
    
         
            -
              describe Spotify::SessionConfig do
         
     | 
| 
       105 
     | 
    
         
            -
                it "allows setting boolean values with bools" do
         
     | 
| 
       106 
     | 
    
         
            -
                  subject = Spotify::SessionConfig.new
         
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
                  subject[:compress_playlists].must_equal false
         
     | 
| 
       109 
     | 
    
         
            -
                  subject[:dont_save_metadata_for_playlists].must_equal false
         
     | 
| 
       110 
     | 
    
         
            -
                  subject[:initially_unload_playlists].must_equal false
         
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
                  subject[:compress_playlists] = true
         
     | 
| 
       113 
     | 
    
         
            -
                  subject[:dont_save_metadata_for_playlists] = true
         
     | 
| 
       114 
     | 
    
         
            -
                  subject[:initially_unload_playlists] = true
         
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
                  subject[:compress_playlists].must_equal true
         
     | 
| 
       117 
     | 
    
         
            -
                  subject[:dont_save_metadata_for_playlists].must_equal true
         
     | 
| 
       118 
     | 
    
         
            -
                  subject[:initially_unload_playlists].must_equal true
         
     | 
| 
       119 
     | 
    
         
            -
                end
         
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
                it "should be possible to set the callbacks" do
         
     | 
| 
       122 
     | 
    
         
            -
                  subject = Spotify::SessionConfig.new
         
     | 
| 
       123 
     | 
    
         
            -
                  subject[:callbacks] = Spotify::SessionCallbacks.new
         
     | 
| 
       124 
     | 
    
         
            -
                end
         
     | 
| 
       125 
     | 
    
         
            -
              end
         
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
     | 
    
         
            -
              describe Spotify::OfflineSyncStatus do
         
     | 
| 
       128 
     | 
    
         
            -
                it "allows setting boolean values with bools" do
         
     | 
| 
       129 
     | 
    
         
            -
                  subject = Spotify::OfflineSyncStatus.new
         
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
                  subject[:syncing].must_equal false
         
     | 
| 
       132 
     | 
    
         
            -
                  subject[:syncing] = true
         
     | 
| 
       133 
     | 
    
         
            -
                  subject[:syncing].must_equal true
         
     | 
| 
       134 
     | 
    
         
            -
                end
         
     | 
| 
       135 
     | 
    
         
            -
              end
         
     | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
       137 
     | 
    
         
            -
              describe "audio sample types" do
         
     | 
| 
       138 
     | 
    
         
            -
                # this is so we can just read audio frames easily based on the sample type
         
     | 
| 
       139 
     | 
    
         
            -
                Spotify.enum_type(:sampletype).symbols.each do |type|
         
     | 
| 
       140 
     | 
    
         
            -
                  describe type do
         
     | 
| 
       141 
     | 
    
         
            -
                    it "should have a corresponding FFI::Pointer#read_array_of_#{type}" do
         
     | 
| 
       142 
     | 
    
         
            -
                      FFI::Pointer.new(1).must_respond_to "read_array_of_#{type}"
         
     | 
| 
       143 
     | 
    
         
            -
                    end
         
     | 
| 
       144 
     | 
    
         
            -
                  end
         
     | 
| 
       145 
     | 
    
         
            -
                end
         
     | 
| 
       146 
     | 
    
         
            -
              end
         
     | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
              describe "error wrapped functions" do
         
     | 
| 
       149 
     | 
    
         
            -
                wrapped_methods = Spotify.attached_methods.find_all { |meth, info| info[:returns] == :error }
         
     | 
| 
       150 
     | 
    
         
            -
                wrapped_methods.each do |meth, info|
         
     | 
| 
       151 
     | 
    
         
            -
                  it "raises an error if #{meth}! returns non-ok" do
         
     | 
| 
       152 
     | 
    
         
            -
                    Spotify.stub(meth, :bad_application_key) do
         
     | 
| 
       153 
     | 
    
         
            -
                      proc { Spotify.send("#{meth}!") }.must_raise(Spotify::Error, /BAD_APPLICATION_KEY/)
         
     | 
| 
       154 
     | 
    
         
            -
                    end
         
     | 
| 
       155 
     | 
    
         
            -
                  end
         
     | 
| 
       156 
     | 
    
         
            -
                end
         
     | 
| 
       157 
     | 
    
         
            -
              end
         
     | 
| 
       158 
     | 
    
         
            -
             
     | 
| 
       159 
     | 
    
         
            -
              describe "GC wrapped functions" do
         
     | 
| 
       160 
     | 
    
         
            -
                gc_types = Set.new([:session, :track, :user, :playlistcontainer, :playlist, :link, :album, :artist, :search, :image, :albumbrowse, :artistbrowse, :toplistbrowse, :inbox])
         
     | 
| 
       161 
     | 
    
         
            -
                wrapped_methods = Spotify.attached_methods.find_all { |meth, info| gc_types.member?(info[:returns]) }
         
     | 
| 
       162 
     | 
    
         
            -
                wrapped_methods.each do |meth, info|
         
     | 
| 
       163 
     | 
    
         
            -
                  it "returns a Spotify::Pointer for #{meth}!" do
         
     | 
| 
       164 
     | 
    
         
            -
                    Spotify.stub(meth, lambda { FFI::Pointer.new(0) }) do
         
     | 
| 
       165 
     | 
    
         
            -
                      Spotify.send("#{meth}!").must_be_instance_of Spotify::Pointer
         
     | 
| 
       166 
     | 
    
         
            -
                    end
         
     | 
| 
       167 
     | 
    
         
            -
                  end
         
     | 
| 
       168 
     | 
    
         
            -
                end
         
     | 
| 
       169 
     | 
    
         
            -
             
     | 
| 
       170 
     | 
    
         
            -
                it "adds a ref to the pointer if required" do
         
     | 
| 
       171 
     | 
    
         
            -
                  session = FFI::Pointer.new(1)
         
     | 
| 
       172 
     | 
    
         
            -
                  ref_added = false
         
     | 
| 
       173 
     | 
    
         
            -
             
     | 
| 
       174 
     | 
    
         
            -
                  Spotify.stub(:session_user, FFI::Pointer.new(1)) do
         
     | 
| 
       175 
     | 
    
         
            -
                    Spotify.stub(:user_add_ref, proc { ref_added = true; :ok }) do
         
     | 
| 
       176 
     | 
    
         
            -
                      Spotify.session_user!(session)
         
     | 
| 
       177 
     | 
    
         
            -
                    end
         
     | 
| 
       178 
     | 
    
         
            -
                  end
         
     | 
| 
       179 
     | 
    
         
            -
             
     | 
| 
       180 
     | 
    
         
            -
                  ref_added.must_equal true
         
     | 
| 
       181 
     | 
    
         
            -
                end
         
     | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
       183 
     | 
    
         
            -
                it "does not add a ref when the result is null" do
         
     | 
| 
       184 
     | 
    
         
            -
                  session = FFI::Pointer.new(1)
         
     | 
| 
       185 
     | 
    
         
            -
                  ref_added = false
         
     | 
| 
       186 
     | 
    
         
            -
             
     | 
| 
       187 
     | 
    
         
            -
                  Spotify.stub(:session_user, FFI::Pointer.new(0)) do
         
     | 
| 
       188 
     | 
    
         
            -
                    Spotify.stub(:user_add_ref, proc { ref_added = true }) do
         
     | 
| 
       189 
     | 
    
         
            -
                      Spotify.session_user!(session)
         
     | 
| 
       190 
     | 
    
         
            -
                    end
         
     | 
| 
       191 
     | 
    
         
            -
                  end
         
     | 
| 
       192 
     | 
    
         
            -
             
     | 
| 
       193 
     | 
    
         
            -
                  ref_added.must_equal false
         
     | 
| 
       194 
     | 
    
         
            -
                end
         
     | 
| 
       195 
     | 
    
         
            -
             
     | 
| 
       196 
     | 
    
         
            -
                it "does not add a ref when the result already has one" do
         
     | 
| 
       197 
     | 
    
         
            -
                  session = FFI::Pointer.new(1)
         
     | 
| 
       198 
     | 
    
         
            -
                  ref_added = false
         
     | 
| 
       199 
     | 
    
         
            -
             
     | 
| 
       200 
     | 
    
         
            -
                  Spotify.stub(:albumbrowse_create, FFI::Pointer.new(1)) do
         
     | 
| 
       201 
     | 
    
         
            -
                    Spotify.stub(:albumbrowse_add_ref, proc { ref_added = true }) do
         
     | 
| 
       202 
     | 
    
         
            -
                      # to avoid it trying to GC our fake pointer later, and cause a
         
     | 
| 
       203 
     | 
    
         
            -
                      # segfault in our tests
         
     | 
| 
       204 
     | 
    
         
            -
                      Spotify::Pointer.stub(:releaser_for, proc { proc {} }) do
         
     | 
| 
       205 
     | 
    
         
            -
                        Spotify.albumbrowse_create!(session)
         
     | 
| 
       206 
     | 
    
         
            -
                      end
         
     | 
| 
       207 
     | 
    
         
            -
                    end
         
     | 
| 
       208 
     | 
    
         
            -
                  end
         
     | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
       210 
     | 
    
         
            -
                  ref_added.must_equal false
         
     | 
| 
       211 
     | 
    
         
            -
                end
         
     | 
| 
       212 
     | 
    
         
            -
              end
         
     | 
| 
       213 
     | 
    
         
            -
             
     | 
| 
       214 
     | 
    
         
            -
              describe Spotify::Pointer do
         
     | 
| 
       215 
     | 
    
         
            -
                describe ".new" do
         
     | 
| 
       216 
     | 
    
         
            -
                  it "adds a reference on the given pointer" do
         
     | 
| 
       217 
     | 
    
         
            -
                    ref_added = false
         
     | 
| 
       218 
     | 
    
         
            -
             
     | 
| 
       219 
     | 
    
         
            -
                    Spotify.stub(:bogus_add_ref!, proc { ref_added = true; :ok }) do
         
     | 
| 
       220 
     | 
    
         
            -
                      Spotify::Pointer.new(FFI::Pointer.new(1), :bogus, true)
         
     | 
| 
       221 
     | 
    
         
            -
                    end
         
     | 
| 
       222 
     | 
    
         
            -
             
     | 
| 
       223 
     | 
    
         
            -
                    ref_added.must_equal true
         
     | 
| 
       224 
     | 
    
         
            -
                  end
         
     | 
| 
       225 
     | 
    
         
            -
             
     | 
| 
       226 
     | 
    
         
            -
                  it "does not add a reference on the given pointer if it is NULL" do
         
     | 
| 
       227 
     | 
    
         
            -
                    ref_added = false
         
     | 
| 
       228 
     | 
    
         
            -
             
     | 
| 
       229 
     | 
    
         
            -
                    Spotify.stub(:bogus_add_ref!, proc { ref_added = true; :ok }) do
         
     | 
| 
       230 
     | 
    
         
            -
                      Spotify::Pointer.new(FFI::Pointer::NULL, :bogus, true)
         
     | 
| 
       231 
     | 
    
         
            -
                    end
         
     | 
| 
       232 
     | 
    
         
            -
             
     | 
| 
       233 
     | 
    
         
            -
                    ref_added.must_equal false
         
     | 
| 
       234 
     | 
    
         
            -
                  end
         
     | 
| 
       235 
     | 
    
         
            -
             
     | 
| 
       236 
     | 
    
         
            -
                  it "raises an error when given an invalid type" do
         
     | 
| 
       237 
     | 
    
         
            -
                    proc { Spotify::Pointer.new(FFI::Pointer.new(1), :really_bogus, true) }.
         
     | 
| 
       238 
     | 
    
         
            -
                      must_raise(Spotify::Pointer::InvalidTypeError, /invalid/)
         
     | 
| 
       239 
     | 
    
         
            -
                  end
         
     | 
| 
       240 
     | 
    
         
            -
                end
         
     | 
| 
       241 
     | 
    
         
            -
             
     | 
| 
       242 
     | 
    
         
            -
                describe ".typechecks?" do
         
     | 
| 
       243 
     | 
    
         
            -
                  it "typechecks a given spotify pointer" do
         
     | 
| 
       244 
     | 
    
         
            -
                    pointer = Spotify::Pointer.new(FFI::Pointer.new(1), :bogus, true)
         
     | 
| 
       245 
     | 
    
         
            -
                    bogus   = OpenStruct.new(:type => :bogus)
         
     | 
| 
       246 
     | 
    
         
            -
                    Spotify::Pointer.typechecks?(bogus, :bogus).must_equal false
         
     | 
| 
       247 
     | 
    
         
            -
                    Spotify::Pointer.typechecks?(pointer, :link).must_equal false
         
     | 
| 
       248 
     | 
    
         
            -
                    Spotify::Pointer.typechecks?(pointer, :bogus).must_equal true
         
     | 
| 
       249 
     | 
    
         
            -
                  end
         
     | 
| 
       250 
     | 
    
         
            -
                end
         
     | 
| 
       251 
     | 
    
         
            -
             
     | 
| 
       252 
     | 
    
         
            -
                describe "garbage collection" do
         
     | 
| 
       253 
     | 
    
         
            -
                  let(:my_pointer) { FFI::Pointer.new(1) }
         
     | 
| 
       254 
     | 
    
         
            -
             
     | 
| 
       255 
     | 
    
         
            -
                  it "should work" do
         
     | 
| 
       256 
     | 
    
         
            -
                    gc_count = 0
         
     | 
| 
       257 
     | 
    
         
            -
             
     | 
| 
       258 
     | 
    
         
            -
                    Spotify.stub(:garbage_release!, proc { gc_count += 1 }) do
         
     | 
| 
       259 
     | 
    
         
            -
                      5.times { Spotify::Pointer.new(my_pointer, :garbage, false) }
         
     | 
| 
       260 
     | 
    
         
            -
                      5.times { GC.start; sleep 0.01 }
         
     | 
| 
       261 
     | 
    
         
            -
                    end
         
     | 
| 
       262 
     | 
    
         
            -
             
     | 
| 
       263 
     | 
    
         
            -
                    # GC tests are a bit funky, but as long as we garbage_release at least once, then
         
     | 
| 
       264 
     | 
    
         
            -
                    # we can assume our GC works properly, but up the stakes just for the sake of it
         
     | 
| 
       265 
     | 
    
         
            -
                    gc_count.must_be :>, 3
         
     | 
| 
       266 
     | 
    
         
            -
                  end
         
     | 
| 
       267 
     | 
    
         
            -
                end
         
     | 
| 
       268 
     | 
    
         
            -
              end
         
     | 
| 
       269 
     | 
    
         
            -
             
     | 
| 
       270 
     | 
    
         
            -
              describe Spotify::UTF8String do
         
     | 
| 
       271 
     | 
    
         
            -
                let(:char) do
         
     | 
| 
       272 
     | 
    
         
            -
                  char = "\xC4"
         
     | 
| 
       273 
     | 
    
         
            -
                  char.force_encoding('ISO-8859-1') if char.respond_to?(:force_encoding)
         
     | 
| 
       274 
     | 
    
         
            -
                  char
         
     | 
| 
       275 
     | 
    
         
            -
                end
         
     | 
| 
       276 
     | 
    
         
            -
             
     | 
| 
       277 
     | 
    
         
            -
                it "should convert any strings to UTF-8 before reading and writing" do
         
     | 
| 
       278 
     | 
    
         
            -
                  dest   = FFI::MemoryPointer.new(:char, 3) # two bytes for the ä, one for the NULL
         
     | 
| 
       279 
     | 
    
         
            -
                  result = C.strncpy(dest, char, 3)
         
     | 
| 
       280 
     | 
    
         
            -
             
     | 
| 
       281 
     | 
    
         
            -
                  result.encoding.must_equal Encoding::UTF_8
         
     | 
| 
       282 
     | 
    
         
            -
                  result.must_equal "Ä"
         
     | 
| 
       283 
     | 
    
         
            -
                  result.bytesize.must_equal 2
         
     | 
| 
       284 
     | 
    
         
            -
                end if "".respond_to?(:force_encoding)
         
     | 
| 
       285 
     | 
    
         
            -
             
     | 
| 
       286 
     | 
    
         
            -
                it "should do nothing if strings does not respond to #encode or #force_encoding" do
         
     | 
| 
       287 
     | 
    
         
            -
                  dest   = FFI::MemoryPointer.new(:char, 3) # two bytes for the ä, one for the NULL
         
     | 
| 
       288 
     | 
    
         
            -
                  result = C.strncpy(dest, char, 3)
         
     | 
| 
       289 
     | 
    
         
            -
             
     | 
| 
       290 
     | 
    
         
            -
                  result.must_equal "\xC4"
         
     | 
| 
       291 
     | 
    
         
            -
                  result.bytesize.must_equal 1
         
     | 
| 
       292 
     | 
    
         
            -
                end unless "".respond_to?(:force_encoding)
         
     | 
| 
       293 
     | 
    
         
            -
              end
         
     | 
| 
       294 
     | 
    
         
            -
             
     | 
| 
       295 
     | 
    
         
            -
              describe Spotify::ImageID do
         
     | 
| 
       296 
     | 
    
         
            -
                let(:context) { nil }
         
     | 
| 
       297 
     | 
    
         
            -
                let(:subject) { Spotify.find_type(:image_id) }
         
     | 
| 
       298 
     | 
    
         
            -
                let(:null_pointer) { FFI::Pointer::NULL }
         
     | 
| 
       299 
     | 
    
         
            -
             
     | 
| 
       300 
     | 
    
         
            -
                let(:image_id_pointer) do
         
     | 
| 
       301 
     | 
    
         
            -
                  pointer = FFI::MemoryPointer.new(:char, 20)
         
     | 
| 
       302 
     | 
    
         
            -
                  pointer.write_string(image_id)
         
     | 
| 
       303 
     | 
    
         
            -
                  pointer
         
     | 
| 
       304 
     | 
    
         
            -
                end
         
     | 
| 
       305 
     | 
    
         
            -
             
     | 
| 
       306 
     | 
    
         
            -
                let(:image_id) do
         
     | 
| 
       307 
     | 
    
         
            -
                  # deliberate NULL in middle of string
         
     | 
| 
       308 
     | 
    
         
            -
                  image_id = ":\xD94#\xAD\xD9\x97f\xE0\x00V6\x05\xC6\xE7n\xD2\xB0\xE4P"
         
     | 
| 
       309 
     | 
    
         
            -
                  image_id.force_encoding("BINARY") if image_id.respond_to?(:force_encoding)
         
     | 
| 
       310 
     | 
    
         
            -
                  image_id
         
     | 
| 
       311 
     | 
    
         
            -
                end
         
     | 
| 
       312 
     | 
    
         
            -
             
     | 
| 
       313 
     | 
    
         
            -
                describe "from_native" do
         
     | 
| 
       314 
     | 
    
         
            -
                  it "should be nil given a null pointer" do
         
     | 
| 
       315 
     | 
    
         
            -
                    subject.from_native(null_pointer, context).must_be_nil
         
     | 
| 
       316 
     | 
    
         
            -
                  end
         
     | 
| 
       317 
     | 
    
         
            -
             
     | 
| 
       318 
     | 
    
         
            -
                  it "should be an image id given a non-null pointer" do
         
     | 
| 
       319 
     | 
    
         
            -
                    subject.from_native(image_id_pointer, context).must_equal image_id
         
     | 
| 
       320 
     | 
    
         
            -
                  end
         
     | 
| 
       321 
     | 
    
         
            -
                end
         
     | 
| 
       322 
     | 
    
         
            -
             
     | 
| 
       323 
     | 
    
         
            -
                describe "to_native" do
         
     | 
| 
       324 
     | 
    
         
            -
                  it "should be a null pointer given nil" do
         
     | 
| 
       325 
     | 
    
         
            -
                    subject.to_native(nil, context).must_be_nil
         
     | 
| 
       326 
     | 
    
         
            -
                  end
         
     | 
| 
       327 
     | 
    
         
            -
             
     | 
| 
       328 
     | 
    
         
            -
                  it "should be a 20-byte C string given an actual string" do
         
     | 
| 
       329 
     | 
    
         
            -
                    pointer = subject.to_native(image_id, context)
         
     | 
| 
       330 
     | 
    
         
            -
                    pointer.read_string(20).must_equal image_id_pointer.read_string(20)
         
     | 
| 
       331 
     | 
    
         
            -
                  end
         
     | 
| 
       332 
     | 
    
         
            -
             
     | 
| 
       333 
     | 
    
         
            -
                  it "should raise an error given more or less than a 20 byte string" do
         
     | 
| 
       334 
     | 
    
         
            -
                    proc { subject.to_native(image_id + image_id, context) }.must_raise ArgumentError
         
     | 
| 
       335 
     | 
    
         
            -
                    proc { subject.to_native(image_id[0..10], context) }.must_raise ArgumentError
         
     | 
| 
       336 
     | 
    
         
            -
                  end
         
     | 
| 
       337 
     | 
    
         
            -
                end
         
     | 
| 
       338 
     | 
    
         
            -
              end
         
     | 
| 
       339 
     | 
    
         
            -
            end
         
     | 
| 
       340 
     | 
    
         
            -
             
     | 
| 
       341 
     | 
    
         
            -
            describe "functions" do
         
     | 
| 
       342 
     | 
    
         
            -
              API_H_XML.functions.each do |func|
         
     | 
| 
       343 
     | 
    
         
            -
                next unless func["name"] =~ /\Asp_/
         
     | 
| 
       344 
     | 
    
         
            -
                attached_name = func["name"].sub(/\Asp_/, '')
         
     | 
| 
       345 
     | 
    
         
            -
             
     | 
| 
       346 
     | 
    
         
            -
                def type_of(type, return_type = false)
         
     | 
| 
       347 
     | 
    
         
            -
                  return case type.to_cpp
         
     | 
| 
       348 
     | 
    
         
            -
                    when "const char*"
         
     | 
| 
       349 
     | 
    
         
            -
                      :utf8_string
         
     | 
| 
       350 
     | 
    
         
            -
                    when /\A(::)?(char|int|size_t|bool|sp_scrobbling_state|sp_session\*|byte)\*/
         
     | 
| 
       351 
     | 
    
         
            -
                      return_type ? :pointer : :buffer_out
         
     | 
| 
       352 
     | 
    
         
            -
                    when /::(.+_cb)\*/
         
     | 
| 
       353 
     | 
    
         
            -
                      $1.to_sym
         
     | 
| 
       354 
     | 
    
         
            -
                    else :pointer
         
     | 
| 
       355 
     | 
    
         
            -
                  end if type.is_a?(RbGCCXML::PointerType)
         
     | 
| 
       356 
     | 
    
         
            -
             
     | 
| 
       357 
     | 
    
         
            -
                  case type["name"]
         
     | 
| 
       358 
     | 
    
         
            -
                  when "unsigned int"
         
     | 
| 
       359 
     | 
    
         
            -
                    :uint
         
     | 
| 
       360 
     | 
    
         
            -
                  else
         
     | 
| 
       361 
     | 
    
         
            -
                    type["name"].sub(/\Asp_/, '').to_sym
         
     | 
| 
       362 
     | 
    
         
            -
                  end
         
     | 
| 
       363 
     | 
    
         
            -
                end
         
     | 
| 
       364 
     | 
    
         
            -
             
     | 
| 
       365 
     | 
    
         
            -
                describe func["name"] do
         
     | 
| 
       366 
     | 
    
         
            -
                  it "should be attached" do
         
     | 
| 
       367 
     | 
    
         
            -
                    Spotify.must_respond_to attached_name
         
     | 
| 
       368 
     | 
    
         
            -
                  end
         
     | 
| 
       369 
     | 
    
         
            -
             
     | 
| 
       370 
     | 
    
         
            -
                  it "should expect the correct number of arguments" do
         
     | 
| 
       371 
     | 
    
         
            -
                    Spotify.attached_methods[attached_name][:args].count.
         
     | 
| 
       372 
     | 
    
         
            -
                      must_equal func.arguments.count
         
     | 
| 
       373 
     | 
    
         
            -
                  end
         
     | 
| 
       374 
     | 
    
         
            -
             
     | 
| 
       375 
     | 
    
         
            -
                  it "should return the correct type" do
         
     | 
| 
       376 
     | 
    
         
            -
                    current = Spotify.attached_methods[attached_name][:returns]
         
     | 
| 
       377 
     | 
    
         
            -
                    actual  = type_of(func.return_type, true)
         
     | 
| 
       378 
     | 
    
         
            -
             
     | 
| 
       379 
     | 
    
         
            -
                    Spotify.resolve_type(current).must_equal Spotify.resolve_type(actual)
         
     | 
| 
       380 
     | 
    
         
            -
                  end
         
     | 
| 
       381 
     | 
    
         
            -
             
     | 
| 
       382 
     | 
    
         
            -
                  it "should expect the correct types of arguments" do
         
     | 
| 
       383 
     | 
    
         
            -
                    current = Spotify.attached_methods[attached_name][:args]
         
     | 
| 
       384 
     | 
    
         
            -
                    actual  = func.arguments.map { |arg| type_of(arg.cpp_type) }
         
     | 
| 
       385 
     | 
    
         
            -
             
     | 
| 
       386 
     | 
    
         
            -
                    current = current.map { |x| Spotify.resolve_type(x) }
         
     | 
| 
       387 
     | 
    
         
            -
                    actual  = actual.map  { |x| Spotify.resolve_type(x) }
         
     | 
| 
       388 
     | 
    
         
            -
             
     | 
| 
       389 
     | 
    
         
            -
                    current.must_equal actual
         
     | 
| 
       390 
     | 
    
         
            -
                  end
         
     | 
| 
       391 
     | 
    
         
            -
                end
         
     | 
| 
       392 
     | 
    
         
            -
              end
         
     | 
| 
       393 
     | 
    
         
            -
            end
         
     | 
| 
       394 
     | 
    
         
            -
             
     | 
| 
       395 
     | 
    
         
            -
            describe "enums" do
         
     | 
| 
       396 
     | 
    
         
            -
              API_H_XML.enumerations.each do |enum|
         
     | 
| 
       397 
     | 
    
         
            -
                attached_enum = Spotify.enum_type enum["name"].sub(/\Asp_/, '').to_sym
         
     | 
| 
       398 
     | 
    
         
            -
                original_enum = enum.values.map { |v| [v["name"].downcase, v["init"]] }
         
     | 
| 
       399 
     | 
    
         
            -
             
     | 
| 
       400 
     | 
    
         
            -
                describe enum["name"] do
         
     | 
| 
       401 
     | 
    
         
            -
                  it "should exist" do
         
     | 
| 
       402 
     | 
    
         
            -
                    attached_enum.wont_be_nil
         
     | 
| 
       403 
     | 
    
         
            -
                  end
         
     | 
| 
       404 
     | 
    
         
            -
             
     | 
| 
       405 
     | 
    
         
            -
                  it "should match the definition" do
         
     | 
| 
       406 
     | 
    
         
            -
                    attached_enum_map = attached_enum.symbol_map
         
     | 
| 
       407 
     | 
    
         
            -
                    original_enum.each do |(name, value)|
         
     | 
| 
       408 
     | 
    
         
            -
                      a_name, a_value = attached_enum_map.max_by { |(n, v)| (n.to_s.length if name.match(n.to_s)).to_i }
         
     | 
| 
       409 
     | 
    
         
            -
                      attached_enum_map.delete(a_name)
         
     | 
| 
       410 
     | 
    
         
            -
                      a_value.to_s.must_equal value
         
     | 
| 
       411 
     | 
    
         
            -
                    end
         
     | 
| 
       412 
     | 
    
         
            -
                  end
         
     | 
| 
       413 
     | 
    
         
            -
                end
         
     | 
| 
       414 
     | 
    
         
            -
              end
         
     | 
| 
       415 
     | 
    
         
            -
            end
         
     | 
| 
       416 
     | 
    
         
            -
             
     | 
| 
       417 
     | 
    
         
            -
            describe "structs" do
         
     | 
| 
       418 
     | 
    
         
            -
              API_H_XML.structs.each do |struct|
         
     | 
| 
       419 
     | 
    
         
            -
                next if struct["incomplete"]
         
     | 
| 
       420 
     | 
    
         
            -
             
     | 
| 
       421 
     | 
    
         
            -
                attached_struct = Spotify.constants.find do |const|
         
     | 
| 
       422 
     | 
    
         
            -
                  struct["name"].gsub('_', '').match(/#{const}/i)
         
     | 
| 
       423 
     | 
    
         
            -
                end
         
     | 
| 
       424 
     | 
    
         
            -
             
     | 
| 
       425 
     | 
    
         
            -
                attached_members = Spotify.const_get(attached_struct).members.map(&:to_s)
         
     | 
| 
       426 
     | 
    
         
            -
             
     | 
| 
       427 
     | 
    
         
            -
                describe struct["name"] do
         
     | 
| 
       428 
     | 
    
         
            -
                  it "should contain the same attributes" do
         
     | 
| 
       429 
     | 
    
         
            -
                    struct.variables.map(&:name).each_with_index do |member, index|
         
     | 
| 
       430 
     | 
    
         
            -
                      attached_members[index].must_equal member
         
     | 
| 
       431 
     | 
    
         
            -
                    end
         
     | 
| 
       432 
     | 
    
         
            -
                  end
         
     | 
| 
       433 
     | 
    
         
            -
                end
         
     | 
| 
       434 
     | 
    
         
            -
              end
         
     | 
| 
       435 
     | 
    
         
            -
             
     | 
| 
       436 
     | 
    
         
            -
              describe Spotify::Subscribers do
         
     | 
| 
       437 
     | 
    
         
            -
                it "should create the subscribers array using count" do
         
     | 
| 
       438 
     | 
    
         
            -
                  # Memory looks like this:
         
     | 
| 
       439 
     | 
    
         
            -
                  #
         
     | 
| 
       440 
     | 
    
         
            -
                  # 00 00 00 00 <- count of subscribers
         
     | 
| 
       441 
     | 
    
         
            -
                  # 00 00 00 00 <- pointer to subscriber 1
         
     | 
| 
       442 
     | 
    
         
            -
                  # …… …… …… ……
         
     | 
| 
       443 
     | 
    
         
            -
                  # 00 00 00 00 <- pointer to subscriber n
         
     | 
| 
       444 
     | 
    
         
            -
                  real_struct = FFI::MemoryPointer.new(:char, 24)
         
     | 
| 
       445 
     | 
    
         
            -
                  real_struct.put_uint(0, 2)
         
     | 
| 
       446 
     | 
    
         
            -
                  subscribers = %w[a bb].map { |x| FFI::MemoryPointer.from_string(x) }
         
     | 
| 
       447 
     | 
    
         
            -
                  real_struct.put_array_of_pointer(8, subscribers)
         
     | 
| 
       448 
     | 
    
         
            -
             
     | 
| 
       449 
     | 
    
         
            -
                  struct = Spotify::Subscribers.new(real_struct)
         
     | 
| 
       450 
     | 
    
         
            -
                  struct[:count].must_equal 2
         
     | 
| 
       451 
     | 
    
         
            -
                  struct[:subscribers].size.must_equal 2
         
     | 
| 
       452 
     | 
    
         
            -
                  struct[:subscribers][0].read_string.must_equal "a"
         
     | 
| 
       453 
     | 
    
         
            -
                  struct[:subscribers][1].read_string.must_equal "bb"
         
     | 
| 
       454 
     | 
    
         
            -
                  proc { struct[:subscribers][2] }.must_raise IndexError
         
     | 
| 
       455 
     | 
    
         
            -
                end
         
     | 
| 
       456 
     | 
    
         
            -
             
     | 
| 
       457 
     | 
    
         
            -
             
     | 
| 
       458 
     | 
    
         
            -
                it "should not fail given an empty subscribers struct" do
         
     | 
| 
       459 
     | 
    
         
            -
                  subscribers = FFI::MemoryPointer.new(:uint)
         
     | 
| 
       460 
     | 
    
         
            -
                  subscribers.write_uint(0)
         
     | 
| 
       461 
     | 
    
         
            -
             
     | 
| 
       462 
     | 
    
         
            -
                  subject = Spotify::Subscribers.new(subscribers)
         
     | 
| 
       463 
     | 
    
         
            -
                  subject[:count].must_equal 0
         
     | 
| 
       464 
     | 
    
         
            -
                  proc { subject[:subscribers] }.must_raise ArgumentError
         
     | 
| 
       465 
     | 
    
         
            -
                end
         
     | 
| 
       466 
     | 
    
         
            -
              end
         
     | 
| 
       467 
     | 
    
         
            -
            end
         
     |