from thread import start_new_thread
import threading
import spotify
from random import shuffle

# Make Spotify a singleton object
_spotify = None
def Spotify(profile = None):
  global _spotify
  if _spotify is None:
    _spotify = _Spotify(profile)
  return _spotify

class _Spotify:

  def play(self, name, category, shuffle=False):
    if not category in ["tracks", "artists", "albums"]:
      raise ValueError("Category must be 'tracks', 'artists', or 'albums'")
    start_new_thread(self._search_and_play, (name, category, shuffle, ))

  def next_track(self):
    # Seek to the end of the song, 10,000,000 milliseconds > 2.5 hours
    self.session.player.seek(10000000)
    self.playing = True

  def pause_toggle(self):
    if self.playing is None:
      self.playing = True
    self.playing = not self.playing
    self.session.player.play(self.playing)

  def pause(self):
    self.playing = False
    self.session.player.pause()

  def resume(self):
    self.playing = True
    self.session.player.play()

  def _play(self, track):
    self.session.player.load(track)
    self.session.player.play()

  def _search_and_play(self, name, category, shuffle):
    if category == "tracks":
      self._play(self._search(x, category))
    else:
      track_list = self._get_tracks(name, category)
      if shuffle:
        self._shuffle_seq(track_list)
      else:
        self._play_tracks(track_list)
    self.playing = True

  #Returns best search result
  def _search(self, term, category):
    return getattr(self.session.search(term).load(), category)[0].load()

  def _get_tracks(self, name, category):
    grouping = self._search(name, category)
    return grouping.browse().load().tracks

  def _play_tracks(self, tracks):
    for track in tracks:
      if track.availability is spotify.TrackAvailability.AVAILABLE:
        self._play(track)
        while not self.end_of_track.wait(0.1):
          pass
        self.end_of_track.clear()

  def _shuffle_seq(self, track_seq):
    tracks = []
    for track in track_seq:
      tracks.append(track)
    shuffle(tracks)
    self._play_tracks(tracks)

  def __init__(self, profile):
    if not profile.has_key("spotify_name") or \
       not profile.has_key("spotify_password") or \
       profile["spotify_name"] is "" or \
       profile["spotify_password"] is "":
      raise("Pass in a profile with spotify_name and spotify_password")

    # Assuming a spotify_appkey.key in the current dir
    session = spotify.Session()
    loop = spotify.EventLoop(session)
    loop.start()

    # Connect an audio sink
    audio = spotify.AlsaSink(session)

    def on_login(session):
      if session.connection.state is spotify.ConnectionState.LOGGED_IN:
        logged_in.set()
    def on_end_of_track(self):
      end_of_track.set()

    # Register event listeners
    logged_in = threading.Event()
    end_of_track = threading.Event()
    session.on(spotify.SessionEvent.CONNECTION_STATE_UPDATED, on_login)
    session.on(spotify.SessionEvent.END_OF_TRACK, on_end_of_track)

    session.login(profile["spotify_name"], profile["spotify_password"])
    logged_in.wait()

    self.session = session
    self.end_of_track = end_of_track
    self.playing = None

if __name__ == "__main__":
  #To use this example, fill in the empty 'profile.yml'
  import yaml
  import time
  profile = yaml.load(open("profile.yml", 'rb').read())

  Spotify(profile).play("Stadium Arcadium", "albums")
  print("I can print while the song plays")
  time.sleep(2)
  Spotify().pause_toggle()
  time.sleep(2)
  Spotify().next_track()
  time.sleep(2)
  Spotify().play("Taylor Swift", "artists", True)

  raw_input()

@@ -87,16 +87,40 @@
  shuffle
+%0Afrom Queue import Queue
 %0A%0A# Make
@@ -1175,24 +1175,48 @@
 , shuffle):%0A
+    self._clear_queue()%0A
     if categ
@@ -1262,17 +1262,20 @@
 _search(
-x
+name
 , catego
@@ -1337,24 +1337,246 @@
 , category)%0A
+      if category == %22artists%22:%0A        #TODO: The first artist on the first track isn't necessarily correct%0A        artist = track_list%5B0%5D.artists%5B0%5D%0A        track_list = filter(lambda x: artist in x.artists, track_list)%0A
       if shu
@@ -1637,36 +1637,37 @@
 :%0A        self._
-play
+queue
 _tracks(track_li
@@ -1695,16 +1695,167 @@
 = True%0A%0A
+  def _clear_queue(self):%0A    while not self.track_queue.empty():%0A      try:%0A        self.track_queue.get(False)%0A      except Empty:%0A        continue%0A%0A
   #Retur
@@ -2132,54 +2132,78 @@
 lay_
-tracks(self, tracks):%0A    for track in tracks:
+from_queue(self):%0A    while True:%0A      track = self.track_queue.get()
 %0A   
@@ -2386,24 +2386,172 @@
 ck.clear()%0A%0A
+  def _queue_tracks(self, tracks):%0A    for track in tracks:%0A      self.track_queue.put(track)%0A    if self.playing == True:%0A      self.next_track()%0A%0A
   def _shuff
@@ -2676,20 +2676,21 @@
   self._
-play
+queue
 _tracks(
@@ -3799,16 +3799,95 @@
 g = None
+%0A    self.track_queue = Queue()%0A    start_new_thread(self._play_from_queue, ())
 %0A%0Aif __n
@@ -4217,26 +4217,28 @@
 otify().
-next_track
+pause_toggle
 ()%0A  tim
@@ -4301,16 +4301,37 @@
 rue)%0A%0A  
+while True:%0A    exec(
 raw_inpu
@@ -4332,10 +4332,17 @@
 w_input(
+%22%3E%3E%3E %22)
 )%0A

Use a queue to manage playing tracks