Beispiel #1
0
def play_music():
	sc = Server(hostname="10.0.0.1", port=9090, username="******", password="******")
	sc.connect()
	p=sc.get_player('00:04:20:17:5b:41')
	p.playlist_play("file:///volume1/hdtl/Music/H3MusicArchive/Amazon%20MP3/Sam%20The%20Sham%20&%20The%20Pharaohs/20th%20Century%20Masters_%20The%20Millenium%20Collection_%20Best%20Of%20Sam%20The%20Sham%20&%20The%20Pharaohs/02%20-%20Lil%27%20Red%20Riding%20Hood.mp3")
	p.play()
	p.seek_to(0)
Beispiel #2
0
def player_change_process(textSync, volumeSync, playingSync, mac, host, port):
    try:

        # Http version
        sv = Server(hostname=host, port=port)
        sv.connect(update=False)

        # Telnet
        sc = RClient(hostname=host,
                     port=port,
                     mac_filter=mac,
                     textSync=textSync,
                     playingSync=playingSync,
                     volumeSync=volumeSync)
        sc.connect(update=False)

        print "Logged in: %s" % sv.logged_in
        print "Version: %s" % sv.get_version()

        sc.hplayer = sv.get_player(mac)
        trackname = sc.hplayer.get_track_title().strip()
        artist = sc.hplayer.get_track_artist().strip()

        sc.setText(artist, trackname)

        sc.start()
    except (KeyboardInterrupt, SystemExit):
        print "Exiting LMS Telnet Process"
def local_change_process(textSync, text2Sync, volumeSync, playingSync, MAC, host, port):

    try:
        sc = Server(hostname=host, port=port)
        sc.connect(update=False)

        print "Logged in: %s" % sc.logged_in
        print "Version: %s" % sc.get_version()


        localVolume = volumeSync.value
        localPlaying = playingSync.value

        player = sc.get_player(unicode(MAC))


        if player:
            localVolume = player.get_volume()
            text2Sync.value = player.get_name()
            volumeSync.value = localVolume
            print player.get_mode()

            mode = player.get_mode()

            if mode == "play":
                localPlaying = 1
            elif mode == "stop":
                localPlaying = -1
            else:
                localPlaying = 0

            playingSync.value = localPlaying
            print "Controlling player: %s (%s)" % (player.get_name(), MAC)
        else:
            print "No Player found"



        while (1):
            if player:
                if localVolume != volumeSync.value:
                    # Volume Changed by hardware
                    localVolume = volumeSync.value
                    player.set_volume(localVolume)


                if localPlaying != playingSync.value:
                    # State Changed by hardware
                    localPlaying = playingSync.value
                    if localPlaying == 1:
                        player.unpause()
                    elif localPlaying == 0:
                        player.pause()
                    elif localPlaying == -1:
                        pass# stop
            time.sleep(0.5)
    except (KeyboardInterrupt, SystemExit):
        print "Exiting Player Update Process"
Beispiel #4
0
def local_change_process(textSync, text2Sync, volumeSync, playingSync, MAC,
                         host, port):

    try:
        sc = Server(hostname=host, port=port)
        sc.connect(update=False)

        print "Logged in: %s" % sc.logged_in
        print "Version: %s" % sc.get_version()

        localVolume = volumeSync.value
        localPlaying = playingSync.value

        player = sc.get_player(unicode(MAC))

        if player:
            localVolume = player.get_volume()
            text2Sync.value = player.get_name()
            volumeSync.value = localVolume
            print player.get_mode()

            mode = player.get_mode()

            if mode == "play":
                localPlaying = 1
            elif mode == "stop":
                localPlaying = -1
            else:
                localPlaying = 0

            playingSync.value = localPlaying
            print "Controlling player: %s (%s)" % (player.get_name(), MAC)
        else:
            print "No Player found"

        while (1):
            if player:
                if localVolume != volumeSync.value:
                    # Volume Changed by hardware
                    localVolume = volumeSync.value
                    player.set_volume(localVolume)

                if localPlaying != playingSync.value:
                    # State Changed by hardware
                    localPlaying = playingSync.value
                    if localPlaying == 1:
                        player.unpause()
                    elif localPlaying == 0:
                        player.pause()
                    elif localPlaying == -1:
                        pass  # stop
            time.sleep(0.5)
    except (KeyboardInterrupt, SystemExit):
        print "Exiting Player Update Process"
Beispiel #5
0
class SqueezyPiMonitor(threading.Thread):
    def __init__(self, status_deque):
        threading.Thread.__init__(self)
        self.status_deque = status_deque

    def connect_server(self, server_config):
        """Connect to a Logitech Media server."""
        self.server = Server(hostname=server_config.hostname, port=server_config.port, username=server_config.username, password=server_config.password)
        self.server.connect()

    def connect_player(self, player_config):
        """Connect to the Squeezeslave player (must be connected to a server)."""
        self.player = self.server.get_player(player_config.name)

    def run(self):
        status = PlayerStatus()
        while True:
            status.update_track_artist(self.player.get_track_artist())
            status.update_track_title(self.player.get_track_title())
            status.update_time_elapsed(self.player.get_time_elapsed())
            self.status_deque.append(status)
            time.sleep(1)
def player_change_process(textSync, volumeSync, playingSync, mac, host, port):
    try:

        # Http version
        sv = Server(hostname=host, port=port)
        sv.connect(update=False)

        # Telnet
        sc = RClient(hostname=host, port=port, mac_filter=mac, textSync=textSync, playingSync=playingSync,
                     volumeSync=volumeSync)
        sc.connect(update=False)

        print "Logged in: %s" % sv.logged_in
        print "Version: %s" % sv.get_version()

        sc.hplayer = sv.get_player(mac)
        trackname = sc.hplayer.get_track_title().strip()
        artist = sc.hplayer.get_track_artist().strip()

        sc.setText(artist, trackname)

        sc.start()
    except (KeyboardInterrupt, SystemExit):
        print "Exiting LMS Telnet Process"
#!/usr/bin/env python

from pylms.server import Server
from pylms.player import Player

sc = Server(hostname="192.168.16.2", port=9090)
sc.connect()

print "Logged in: %s" % sc.logged_in
print "Version: %s" % sc.get_version()

sq = sc.get_player("00:00:00:00:00:44")

#print "Name: %s | Mode: %s | Time: %s | Connected: %s | WiFi: %s" % (sq.get_name(), sq.get_mode(), sq.get_time_elapsed(), sq.is_connected, sq.get_wifi_signal_strength())

#print sc.request("radios 0 100000")
#print sq.request("local items 0 100000")
#print sq.request("local playlist play item_id:7cec804f.15")
print sq.request("playlist play file:///E:/Public%20Shares/Music/Playlists/Test%20JD.m3u")



Beispiel #8
0
from pylms.player import Player
import subprocess

HOST = '192.168.1.30'
PORT = 9090
USER = ''
PW = ''
SPI_DEV = '/dev/spidev0.1'
SPI_ADR = '00'
BW_TOOLS = '/home/pi/bw_rpi_tools/bw_spi/bw_lcd'
PLAYER_ID = '00:04:20:26:97:a0'

sc = Server(hostname=HOST, port=PORT, username=USER, password=PW)
sc.connect()

sq = sc.get_player(PLAYER_ID)

title = sq.get_track_title()[0:20]
artist = sq.get_track_artist()[0:20]


def write_lcd(pos, content):
    subprocess.call(
        ['sudo', BW_TOOLS, '-a', SPI_ADR, '-D', SPI_DEV, '-T', pos, content])


def clear_lcd():
    subprocess.call(['sudo', BW_TOOLS, '-a', SPI_ADR, '-D', SPI_DEV, '-C'])


clear_lcd()
class PySqueezelite(object):
    """A small wrapper for launching squeezelite from within python scripts.

    Optional keyword arguments:
      path: path to squeezelite (defaults to /usr/bin/squeezelite)
      plname: name of player
      mac: mac address
      server: ipaddress of LMS (if not set, squeezelite will use discovery)
      args: other command line args to pass to squeezelite.
      lmsport: LMS server port (default 9000)
      telnetport: port for telnet communication to LMS (default 9090)

    Will raise SqueezeliteError if unable to locate squeezelite at given
    path.

    Will also raise error if no server and lms port are set and the scripts
    cannot locate the server using ssdp discovery.

    Methods:
      start: starts the squeezelite process
      kill: terminate the squeezelite process
      connect: connects to the LMS server to get track info
      get_player_info: retrieve additional player attributes
      play_pause: toggle the playback
      stop: stop playback
      next_track: play next track in playlist
      prev_track: play previous track in playlist

    Properties:
      track_title: track name
      track_artist: artist name
      track_album: album name
      track_duration: length of track
      track_time: time elapsed
    """

    def __init__(self, path="/usr/bin/squeezelite",
                 plname="Squeezelite",
                 mac="12:34:56:78:90:AB",
                 server=None,
                 args=None,
                 lmsport=9000,
                 telnetport=9090):

        # Set relevant constants for this player
        self.path = path
        self.playername = plname
        self.mac = mac
        self.server = server
        self.args = args
        self.lmsport=lmsport
        self.telnetport=telnetport

        # Check if squeezelite can be found and alert user if not
        if not os.path.isfile(self.path):
            raise PySqueezeliteError("Can't find "
                                   "squeezelite at {}".format(self.path))

    def start(self):
        """Launches the squeezelite player."""

        if not self.server:
            self.server = self.__discover_server()

        # Default command. "-z" flag daemonises process.
        command = [self.path, "-z"]

        # Set player name
        if self.playername:
            command += ["-n", self.playername]

        # Set MAC address
        if self.mac:
            command += ["-m", self.mac]

        # Set server address
        if self.server:
            command += ["-s", self.server]

        # Add other args
        if self.args:
            command += [self.args]

        # Launch player
        subprocess.call(command)

        self.connect(self.server, self.telnetport)

    def kill(self):
        """Kills all instances of squeezelite found on the machine."""

        # Get the PIDs of all matching processes
        pids = subprocess.check_output(["pidof", self.path]).strip()

        # Loop through and kill them!
        for pid in pids.split(" "):
            subprocess.call(["kill", "-9", pid])

    def __discover_server(self):
        self.devices = [x for x in discover("ssdp:all") if x]

        self.matches = [x.ip for x in self.devices if x.port == self.lmsport]

        if len(self.matches) > 1:
            raise PySqueezeliteError("Multiple servers found on "
                                     "port {}. Need to set server ip address "
                                     "when calling "
                                     "PySqueezelite.".format(self.lmsport))
        elif len(self.matches) == 0:
            raise PySqueezeliteError("No servers found on "
                                     "port {}. Please check LMS is "
                                     "running and the correct "
                                     "port has been set.".format(self.lmsport))
        else:
            return self.matches[0]

    def connect(self, hostname="localhost", port=9090):
        self.sc = Server(hostname=hostname, port=port)
        self.sc.connect()
        self.player = self.sc.get_player(self.mac)


    def get_player_info(self, info):

        if not self.player:
            self.connect

        if hasattr(self.player, info):
            return getattr(self.player, info)()
        else:
            return None

    def play_pause(self):
        self.player.toggle()

    def stop(self):
        self.player.stop()

    def next_track(self):
        self.player.next()

    def prev_track(self):
        self.player.prev()

    @property
    def track_title(self):

        return self.get_player_info("get_track_title")

    @property
    def track_artist(self):

        return self.get_player_info("get_track_artist")

    @property
    def track_album(self):

        return self.get_player_info("get_track_album")

    @property
    def track_duration(self):

        return self.get_player_info("get_track_duration")

    @property
    def track_time(self):

        return self.get_player_info("get_time_elapsed")
Beispiel #10
0
        sc.connect()    #throws ugly error if LMS not there
        RPizeBox.loggedin = sc.logged_in
        logging.debug('Success: Logged in to LMS.')
    except:
        logging.debug('LMS not there.  Trying again in %i seconds.' % RPizeBox.logInWait)
        wp.lcdPosition(lcd, 0, 0)
        wp.lcdPuts(lcd,welcomeMessage[0][:16])
        wp.lcdPosition(lcd, 0, 1)
        wp.lcdPuts(lcd,welcomeMessage[1][:16])        
        time.sleep(RPizeBox.logInWait)

        
# connected to server, now set up the player
# we know it is the RPi because we nab the local H/W address
try:
    sl = sc.get_player(getHwAddr("eth0"))	# http://stackoverflow.com/questions/159137/getting-mac-address
    logging.debug('Success: In contact with SqueezeLite.')
except:
    logging.warning('Can\'t contact SqueezeLite!  Check it is running')
#######################################################################
#                          END INITIALISE                             #
#                                                                     #
    
# no idea what blocking is
pylircConfigFile = "/remoteCodes.conf"
track_title = ""

# start looking for remote control calls
if(pylirc.init("pylirc", currDir + pylircConfigFile, blocking)):
    elapsed_time = 0
    start_time = 0 
Beispiel #11
0
# get the secret key
f = open('/Users/mgeraci/Web/Now-Playing/secretkey.txt', 'r')
secret = f.readline().strip()

# set the domain (pass test in as an arg to get localhost)
domain = "now-playing.meteor.com"

if len(sys.argv[1:]) > 0:
  if sys.argv[1:][0] == 'test':
    domain = "127.0.0.1:3000"

# connect to the squeezebox
sc = Server(hostname="192.168.1.111", port=9090)
sc.connect()
sq = sc.get_player("00:04:20:07:98:43")

print "Logged in: %s" % sc.logged_in
print "Version: %s" % sc.get_version()

if sq.get_mode() == 'play':
  artist = sq.get_track_artist()
  album = sq.get_track_album()
  title = sq.get_track_title()

  print "%s - %s - %s" % (artist, album, title)
  print ""

  params = urllib.urlencode({'artist': artist, 'album': album, 'title': title, 'secret': secret})
  conn = httplib.HTTPConnection(domain)
  url = "/add_song?%s" % (params)
Beispiel #12
0
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import time
from pylms.server import Server
from pylms.player import Player

sc = Server(hostname="192.168.2.109", port=9090, username="", password="")
sc.connect()

#print "Logged in: %s" % sc.logged_in
#print "Version: %s" % sc.get_version()

sq = sc.get_player("b8:27:eb:3c:1b:be")

phatbeat.set_all(0,128,0,0.1)
phatbeat.show()
time.sleep(1)
phatbeat.clear()
phatbeat.show()
	
GPIO.setmode(GPIO.BCM)

GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(6, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def myCallback(channel):
  if channel == 6:
Beispiel #13
0
from pylms.server import Server
from pylms.player import Player

sc = Server(hostname="10.0.0.1", port=9090, username="******", password="******")
sc.connect()

print "Logged in: %s" % sc.logged_in
print "Version: %s" % sc.get_version()
print "Num players: %s" % sc.get_player_count()
print "Players: %s" % sc.get_players()

players = sc.get_players()
print ("Type of player = %s" % type(players))
for p in players:
	print "Player number %s" % p
	#sq = sc.get_player("00:11:22:33:44:55")

	print "Name: %s | Mode: %s | Time: %s | Connected: %s | WiFi: %s" % (p.get_name(), p.get_mode(), p.get_time_elapsed(), p.is_connected, p.get_wifi_signal_strength())

	print p.get_track_title()
	print p.get_time_remaining()

p=sc.get_player('00:04:20:17:5b:41')
print("Current path = %s" % p.get_track_path())
with open('z.txt','w') as f:
	f.write("Current path = %s" % p.get_track_path())
	
p.playlist_play("file:///volume1/hdtl/Music/H3MusicArchive/Amazon%20MP3/Sam%20The%20Sham%20&%20The%20Pharaohs/20th%20Century%20Masters_%20The%20Millenium%20Collection_%20Best%20Of%20Sam%20The%20Sham%20&%20The%20Pharaohs/02%20-%20Lil%27%20Red%20Riding%20Hood.mp3")

p.play()
from pylms.player import Player
import subprocess

HOST = '192.168.1.30'
PORT = 9090
USER = ''
PW = ''
SPI_DEV = '/dev/spidev0.1'
SPI_ADR = '00'
BW_TOOLS = '/home/pi/bw_rpi_tools/bw_spi/bw_lcd'
PLAYER_ID = '00:04:20:26:97:a0'

sc = Server(hostname=HOST, port=PORT, username=USER, password=PW)
sc.connect()

sq = sc.get_player(PLAYER_ID)

title = sq.get_track_title()[0:20]
artist = sq.get_track_artist()[0:20]

def write_lcd(pos, content):
    subprocess.call(['sudo', BW_TOOLS, '-a', SPI_ADR, '-D', SPI_DEV, '-T', pos, content])

def clear_lcd():
    subprocess.call(['sudo', BW_TOOLS, '-a', SPI_ADR, '-D', SPI_DEV, '-C'])

clear_lcd()
write_lcd('0,0', 'Title: ')
write_lcd('0,1', title) 
write_lcd('0,2', 'Artist:')
write_lcd('0,3', artist)
Beispiel #15
0
# CHANGE the following to your LMS IP Address: hostIP, player_id
hostIP = '192.168.0.211'  # Change to the IP Address of your Logitech Media Server (LMS) - check your router

# insert miniz player MAC address here from LMS/Settings/Information
player_id = 'b8:27:eb:93:bb:81'

sc = Server(hostname=hostIP, port=9090)  # used for volume and play/pause
scNP = Server(hostname=hostIP,
              port=9090)  # used only to get Now Playing cover.jpg

sleep(60)  # allow time for LMS to start, otherwise get ConnectionError 111
sc.connect()
scNP.connect()

sq = sc.get_player(player_id)
sqNP = scNP.get_player(
    player_id
)  # UGLY KLUDGE! Avoids conflict with volume routine which caused bad refresh on album cover.jpg

DISPLAY = pi3d.Display.create(use_pygame=True, samples=4)
DISPLAY.set_background(0, 0, 0, 1)  #r,g,b and alpha
shader = pi3d.Shader("uv_flat")
CAMERA = pi3d.Camera(is_3d=False)

# Radio Dial Sprites
radio_needle = pi3d.ImageSprite("/home/pi/miniz/textures/needle.png",
                                shader,
                                w=64.0,
                                h=288.0,
                                x=0.0,
class SqueezePlayer:

  ##############################################################################
  #constructor - connect to the server and player so we can do stuff
  #other handy start up stuff
  def __init__(self,basicOnly=False):

    #optionally pass in a player MAC here to connect to a different player for the info display
    #if MAC is not None:
    #  log("Using MAC " + MAC)
    #  PLAYERMAC = MAC

    #serverIP still null, something went wrong...
    if SERVERIP=="":
      notify("Can't find LMS server","Try manually configuring one in XSqueeze settings")
      sys.exit()

    log("Attempting to connect to LMS named [" + SERVERNAME + "] at IP:  " + SERVERIP + " on CLI port: " + SERVERPORT)
    try:
      self.sc = Server(hostname=SERVERIP, port=SERVERPORT, username=SERVERUSER, password=SERVERPASS)
      self.sc.connect()
      log( "LMS Logged in: %s" % self.sc.logged_in )
      log( "LMS Version: %s" % self.sc.get_version() )
    except:
      log(" Couldn't connect to server!")
      notify(LANGUAGE(19613),LANGUAGE(19614))
      raise

    #connect to player
    log( "Attempting to connect to player: " + PLAYERMAC)
    try:
      self.sb = self.sc.get_player(PLAYERMAC)
      if self.sb:
        log( "Connected to: %s" % PLAYERMAC )
        state = self.sb.get_power_state()
        log ( "Power state is: " + str (state) )
      else:
        log( "Player is None! %s" % PLAYERMAC )
        raise Exception
    except Exception as inst:
        log(" Couldn't connect to player: " + PLAYERMAC , inst)
        notify(LANGUAGE(19615),LANGUAGE(19616))
        raise

    #initialise if we're called from XSqueeze as opposed to the chooser
    try:
        if not basicOnly:
          self.currentTrack = None
          self.coverURLs = None
          self.playlistDetails = None
          self.updatePlaylistDetails()
          self.updateCoverArtURLs()
          #if the user wants music to start straight away...
          if SENDPLAYONSTART:
            self.sb.request("play")
    except Exception as inst:
      log(" Error in initialisation of XSqueeze after connection to: " + PLAYERMAC , inst)
      raise


  ##############################################################################
  #get the current squeezebox two line display text and return it

  def getDisplay(self):
    displayText = self.sb.requestRaw("display ? ?", True)
    lines = displayText.split(" ")

    try:
      if lines[2] == "":
        lines[2] = "."
    except:
      lines[2] = "."

    try:
     if lines[3] == "":
        lines[3] = "."
    except:
      lines[3]="."

    cleanedLines=[]
    cleanedLines.append((lines[2]))
    cleanedLines.append((lines[3]))

    #print(cleanedLines)

    #clean out the wierd characters used to represent volume...
    newLines=[]
    for line in cleanedLines:
      line = line.replace(u'cursorpos', u"\u2334")
      line = line.replace(u'rightarrow', u"\u2192")
      line = line.replace(u'solidblock', u'*')
      line = line.replace(u'leftprogress4', u'*')
      line = line.replace(u'leftprogress2', u'*')
      line = line.replace(u'leftprogress0', u'(Mute)')
      line = line.replace(u'rightprogress0', u' ')
      line = line.replace(u'rightprogress4', u'(Max)')
      line = line.replace(u'middleprogress0', u' ')
      line = line.replace(u'%1E',u"")
      line = line.replace(u'%1F',u"")
      newLines.append(line)

    #print(newLines)

    return unquoteUni(newLines[0]), unquoteUni(newLines[1])

  ##############################################################################
  # check if song changed and update local reference if so
  # returns boolean - but of course only once on each change
  # called every window update to see if the song has changed and only if it has
  # do we update the playlist and cover arts...reduces traffic a lot!

  def songChanged(self):
    oldSong = self.currentTrack
    newSong = self.sb.get_track_title()
    #log("New Song [" + newSong +"], Old song [" + oldSong + "]")
    if newSong != oldSong:
      log("### Detected song change to: " + repr(newSong) + " - triggering playlist and cover art updates...")
      self.currentTrack = newSong
      self.updatePlaylistDetails()
      self.updateCoverArtURLs()
      return True;
    else:
      return False

  ##############################################################################
  # returns the URLs for the current and next three track cover art images

  def updateCoverArtURLs(self):

      coverURLs = []

      #print "Playlist is" + str(self.playlist)

      #start at this song , end at + 3
      index = int(self.sb.request("playlist index ?"))
      upcomer = index
      end = index + 4

      #currently uses the track_id in the url - works well
      #supposed to use the cover_id number but this doesn't work so well...
      for count in range(upcomer,end):
        if(count<len(self.playlist)):
          try:
            statusInfo = self.sb.request("status " + str(count) + " 1 tags:Kal")
            #log("Status info is " + str(statusInfo))
            if("artwork_url" in statusInfo):
              statusArtwork = statusInfo.split('artwork_url:')
              statusArtwork = statusArtwork.pop(1)
              statusArtwork = statusArtwork.split(' ')
              statusArtwork = statusArtwork.pop(0)
              #log("statusArtwork is " + str(statusArtwork))
              #check we have a full url....
              if("http" not in statusArtwork):
                coverURL = "http://" + SERVERHTTPURL + "/" + statusArtwork
              else:
                coverURL = statusArtwork
            else:
              statusId = statusInfo.split('id:')
              statusId = statusId.pop(1)
              statusId = statusId.split(' ')
              statusId = statusId.pop(0)
              #log("StatusID is " + str(statusId))
              coverURL = "http://" + SERVERHTTPURL + "/music/" + str(statusId) + "/cover.jpg"
            #now append the coverURL to our list of URLs
            #log ("Appending future cover: " + str(count) + " from " + coverURL)
            coverURLs.append(coverURL)

          #Something went wrong, go with null string just to be safe...
          except Exception as inst:
            log("No cover art so appending null string for playlist index " + str(count), inst)
            coverURLs.append("")

      self.coverURLs = coverURLs

##  ##############################################################################
##  # Gets more info about a particular song

  def getSongInfo(self, id):
    encoded = self.sb.requestRaw("songinfo 0 1000 track_id:" + str(id), True)

    #find the index of id: - track_id%3A
    start = encoded.find('track_id%3A')
    encoded = encoded[start:]

    #print(str(id) + " Encoded: " +str(encoded))
    list = encoded.split(" ")
    #print("list: " + str(list))

    decodedList = []
    for item in list:
      cleanItem = unquoteUni(item)
      decodedList.append(cleanItem)

    #print("DecodedList: " +str(decodedList))

    item = {}
    for info in decodedList:
        info = info.split(':')
        key = info.pop(0)
        if key:
            item[key] = ':'.join(info)

    # example...
    # 9 id:39 title:I'm Not The Man artist:10000 Maniacs coverid:94339a48 duration:226.36 album_id:4 filesize:22796274 genre:Pop coverart:1 artwork_track_id:94339a48
    # album:MTV Unplugged modificationTime:Thursday, November 27, 2008, 5:24 PM type:flc genre_id:4 bitrate:805kbps VBR artist_id:11 tracknum:4 year:1993 compilation:0
    # addedTime:Thursday, December 8, 2011, 11:15 PM channels:2 samplesize:16 samplerate:44100 lastUpdated:Thursday, December 8, 2011, 11:15 PM album_replay_gain:-6.46 replay_gain:-3.46

    #print "Item" + str(item)

    #convert all the data to the right types - there is a much more pythomnesque way to right this I am sure...

    try:
      item['id'] = int(item['id'])
    except KeyError:
      pass
    try:
       item['duration'] = float(item['duration'])
    except KeyError:
      pass
    try:
        item['album_id'] = int(item['album_id'])
    except KeyError:
      pass
    try:
        item['filesize'] = int(item['filesize'])
    except KeyError:
        pass
    try:
      item['coverart'] = int(item['coverart'])
    except KeyError:
      pass
    try:
        item['genre_id'] = int(item['genre_id'])
    except KeyError:
      pass
    try:
        item['artist_id'] = int(item['artist_id'])
    except KeyError:
      pass
    try:
        item['tracknum'] = int(item['tracknum'])
    except KeyError:
      pass
    try:
        item['year'] = int(item['year'])
    except KeyError:
      pass
    try:
        item['compilation'] = int(item['compilation'])
    except KeyError:
      pass
    try:
        item['channels'] = int(item['channels'])
    except KeyError:
      pass
    try:
      item['samplesize'] = int(item['samplesize'])
    except KeyError:
      pass
    try:
        item['samplerate'] = int(item['samplerate'])
    except KeyError:
      pass
    try:
        item['album_replay_gain'] = float(item['album_replay_gain'])
    except KeyError:
      pass
    try:
        item['replay_gain'] = float(item['replay_gain'])
    except KeyError:
      pass

    return item

  ##############################################################################
  # Send a button command text, e.g. 'pause' - to the player

  def button(self, text):
    self.sb.ir_button(text)
    #something probably changed, trigger an update test
    self.songChanged()

  ##############################################################################
  # returns all the details of up to 10 tracks...

  def updatePlaylistDetails(self):
    self.playlist = self.sb.playlist_get_info()
    currentIndex = int(self.sb.request("playlist index ?"))
    #log ("Current index: " + str(currentIndex) + " len(playlist): " + str(len(self.playlist)) + " Playlist is: " + str(self.playlist))
    playlistDetails = []
    #retrieve a maxiumum of 10 tracks details
    for trackOffset in range(currentIndex,currentIndex+10):
      #don't go off the end of the playlist
      if trackOffset < len(self.playlist):
        trackID = self.playlist[trackOffset]['id']
        #log("Getting full details for id: " + str(trackID))
        playlistDetails.append(self.getSongInfo(trackID))

    #the caller should check the length of the playlist and process all entries...
    self.playlistDetails = playlistDetails

  ##############################################################################
  # returns current track length if available (check for 0 etc. at other end)

  def getTrackLength(self):
    return self.sb.get_track_duration()

  ##############################################################################
  # Show some text on the player's screen

  def show(self,line1="", line2=""''"", duration=3, brightness=4, font="standard", centered=False):
    self.sb.show(line1,line2,duration,brightness,font,centered)

  def display(self, line1="", line2="", duration=1):
    self.sb.request("display " + line1 + " " + line2 + " " + str(duration))

  ##############################################################################
  # returns current mode ('play' 'pause' or 'stop')

  def getMode(self):
      return self.sb.get_mode()

  ##############################################################################
  # returns length of time in seconds the current track has played for

  def getTrackElapsed(self):
    return self.sb.get_time_elapsed()

  ##############################################################################
  # returns the full album info given an ID

  def getAlbumInfo(self, albumID):
    fullAlbumInfo = self.sc.request_with_results('albums 0 1 album_id:' + albumID + ' tags:yajl')
    #log("Full Album Info: " + str(fullAlbumInfo))
    return fullAlbumInfo[1][0]

  ##############################################################################
  # returns the latest 50 albums

  def getNewMusic(self):
    fullAlbums = []
    albums = self.sc.request_with_results("albums 0 50 sort:new")
    for album in albums[1]:
      fullAlbumInfo = self.getAlbumInfo(album['id'])
      fullAlbums.append(fullAlbumInfo)
    return fullAlbums

  ##############################################################################
  # returns all albums

  def getAlbums(self):
    fullAlbums = []
    albums = self.sc.request_with_results("albums 0 100000")
    for album in albums[1]:
      fullAlbumInfo = self.getAlbumInfo(album['id'])
      fullAlbums.append(fullAlbumInfo)
    return fullAlbums

  ##############################################################################
  # returns all artists

  def getArtists(self):
    artists = self.sc.request_with_results("artists 0 100000")
    #log(str(artists))
    return artists[1]

  ##############################################################################
  # returns all albums by a particular artist given an artist_id

  def getAlbumsByArtistID(self,artistID):
    fullAlbums = []
    albums = self.sc.request_with_results("albums 0 100000 artist_id:" + str(artistID))
    #log(str(albums))
    for album in albums[1]:
      fullAlbumInfo = self.getAlbumInfo(album['id'])
      fullAlbums.append(fullAlbumInfo)
    return fullAlbums

  ##############################################################################
  # returns all albums in a particular genre given a genre_id

  def getAlbumsByGenreID(self,genreID):
    fullAlbums = []
    albums = self.sc.request_with_results("albums 0 100000 genre_id:" + str(genreID))
    #log(str(albums))
    for album in albums[1]:
      fullAlbumInfo = self.getAlbumInfo(album['id'])
      fullAlbums.append(fullAlbumInfo)
    return fullAlbums

  ##############################################################################
  # returns all albums for a given year

  def getAlbumsByYear(self,year):
    fullAlbums = []
    albums = self.sc.request_with_results("albums 0 100000 year:" + str(year))
    #log(str(albums))
    for album in albums[1]:
      fullAlbumInfo = self.getAlbumInfo(album['id'])
      fullAlbums.append(fullAlbumInfo)
    return fullAlbums

  ##############################################################################
  # returns all genres

  def getGenres(self):
    genres = self.sc.request_with_results("genres 0 100000")
    log(str(genres))
    return genres[1][1:]

  ##############################################################################
  # returns all years

  def getYears(self):
    years = self.parseSpecial("years 0 100000", "year", True)
    #log(str(years))
    years.reverse()
    return years

  ##############################################################################
  # returns radios root menu

  def parseSpecial(self, cmdString, splitOn, playerRequest=False):
    quotedColon = urllib.quote(':')
    if playerRequest:
      log("Player Request: " + str(cmdString))
      results = self.sb.requestRaw(cmdString)
    else:
      log("Server Request: " + str(cmdString))
      results = self.sc.requestRaw(cmdString)
    log("Result string: "+ pprint.pformat(results))
    #strip off the request stuff at the start
    resultStr = results[results.find(splitOn):]
    log("Split string: "+ pprint.pformat(resultStr))
    #ok now split the string on 'splitOn' to get each radio station
    chunks = resultStr.split(splitOn + "%3A")[1:]
    log("Processed Chunks: " + pprint.pformat(chunks))
    output=[]
    for chunk in chunks:
      chunk = chunk.strip()
      subResults = chunk.split(" ")
      #log("SUB: " + str(subResults))

      #fix missing splitOn post split
      subResults[0] = splitOn + "%3A" + subResults[0]
      #log("SUB + splitOn: " + str(subResults))

      item={}
      for subResult in subResults:
          #save item
          key,value = subResult.split(quotedColon,1)
          item[unquoteUni(key)] = unquoteUni(value)
      output.append(item)

    return output

  def getRadios(self):
    return self.parseSpecial("radios 0 100000", "icon", playerRequest=True)

  def getRadioStations(self, cmd, itemid):
    if(itemid)!="" and itemid is not None:
      return self.parseSpecial(urllib.quote(cmd) + " items 0 100000 item_id:" + itemid,"id",playerRequest=True)
    else:
      return self.parseSpecial(urllib.quote(cmd) + " items 0 100000","id",playerRequest=True)

  def getAppItemsList(self, cmd, itemid):
    if(itemid)!="" and itemid is not None:
      return self.parseSpecial(urllib.quote(cmd) + " items 0 100000 item_id:" + itemid,"id",playerRequest=True)
    else:
      return self.parseSpecial(urllib.quote(cmd) + " items 0 100000","id",playerRequest=True)

  def getFavouritesSub(self, itemid):
    return self.parseSpecial("favorites items 0 100000 item_id:" + itemid,"id",playerRequest=True)

  def queueRadio(self, cmd, itemid):
      self.sb.request(urllib.quote(cmd) + " playlist play item_id:" + itemid)

  def getApps(self):
    return self.parseSpecial("apps 0 100000","cmd", playerRequest=True)

  def getFavourites(self):
    return self.parseSpecial("favorites items 0 100000","id", playerRequest=True)

  def getPlaylists(self):
    #return self.parseSpecial("playlists 0 100000","id", playerRequest=True)
    pls = self.sc.request_with_results("playlists 0 100000 tags:u")
    log(str(pls))
    return pls[1][1:]

  ##############################################################################
  # Clear playlist and queue up a favourite item given

  def queueFavourite(self, item_id):
     self.sb.request("favorites playlist play item_id:" + item_id)

  ##############################################################################
  # Clear playlist and queue up a playlist item given

  def queuePlaylist(self, item_id, url):
     self.sb.request("playlist play " + url)

  ##############################################################################
  # Clear playlist and queue up an album given an album title and artist

  def queueAlbum(self, title, artist):
    if artist=="Various Artists":
      self.sb.request("playlist loadalbum * * " + urllib.quote(title))
    else:
      self.sb.request("playlist loadalbum * " + urllib.quote(artist) + " " + urllib.quote(title))

  ##############################################################################
  # Clear playlist and queue up random albums

  def playRandomAlbums(self):
    self.sb.request("randomplay albums")

  ##############################################################################
  # Clear playlist and queue up random songs

  def playRandomTracks(self):
    self.sb.request("randomplay tracks")

  ##############################################################################
  # Clear playlist and queue up random songs

  def getShuffle(self):
    state = int(self.sb.request("playlist shuffle ?"))
    if state==0: return False
    else: return True

  def setShuffle(self):
    state = int(self.sb.request("playlist shuffle ?"))
    if state==0:
      state = 1
      notify("Shuffle Playlist: ON","")
    else:
      state = 0
      notify("Shuffle Playlist: OFF","")
    self.sb.request("playlist shuffle "+ str(state), debug=True)
    self.updatePlaylistDetails()

  def getRepeat(self):
    state = int(self.sb.request("playlist repeat ?"))
    if state==0: return False
    else: return True

  def setRepeat(self):
    state = int(self.sb.request("playlist repeat ?"))
    if state==0:
      state = 2
      notify("Repeat Playlist: ON")
    else:
      state = 0
      notify("Repeat Playlist: OFF")
    self.sb.request("playlist repeat "+ str(state), debug=True)

  def rewind(self):
    self.sb.rewind()

  def forward(self):
    self.sb.forward()

  def getVolume(self):
    return self.sb.get_volume()

  def getPowerState(self):
    return self.sb.get_power_state()
Beispiel #17
0
#!/usr/bin/env python

from pylms.server import Server
from pylms.player import Player

sc = Server(hostname="192.168.16.2", port=9090)
sc.connect()

print "Logged in: %s" % sc.logged_in
print "Version: %s" % sc.get_version()

sq = sc.get_player("00:00:00:00:00:44")

#print "Name: %s | Mode: %s | Time: %s | Connected: %s | WiFi: %s" % (sq.get_name(), sq.get_mode(), sq.get_time_elapsed(), sq.is_connected, sq.get_wifi_signal_strength())

#print sc.request("radios 0 100000")
#print sq.request("local items 0 100000")
#print sq.request("local playlist play item_id:7cec804f.15")
print sq.request(
    "playlist play file:///E:/Public%20Shares/Music/Playlists/Test%20JD.m3u")
Beispiel #18
0
def get_squeeze_player(server, player):
    print 'Connecting to server[%s] player[%s]' % (server, player)
    sc = Server(hostname=server, port=9090)
    sc.connect()
    return sc.get_player(player)
Beispiel #19
0
            setattr(namespace, self.dest, values)


agi = AGI()

parser = argparse.ArgumentParser(description='Process LMS commands.')
parser.add_argument('player', type=str, nargs=1, help="MAC adress of player", action=VerifyMacaddressAction)
parser.add_argument('command', type=str, nargs=1, default="mode",
                    choices=['mode', 'start', 'stop', 'toggle', 'pause', 'unpause'],
                    help='Command to execute on LMS player')

args = parser.parse_args()

sc = Server(hostname="lms.wi.kettenbach-it.de", port=9090)
sc.connect()
sq = sc.get_player(args.player[0])  # type: Player

if sq is None:
    sys.stderr.write("Player not found")
    sys.exit(-1)

if args.command[0] == "mode":
    # agi.set_variable("LMSSTATUS", str(sq.get_mode()))
    # agi_set_varaible is broken: https://github.com/rdegges/pyst2/issues/19
    print("SET VARIABLE LMSSTATUS " + sq.get_mode())

if args.command[0] == "stop":
    sq.stop()

if args.command[0] == "start":
    sq.play()
Beispiel #20
0
class SqueezePlayer:

    ##############################################################################
    #constructor - connect to the server and player so we can do stuff
    #other handy start up stuff
    def __init__(self, basicOnly=False):

        #optionally pass in a player MAC here to connect to a different player for the info display
        #if MAC is not None:
        #  log("Using MAC " + MAC)
        #  PLAYERMAC = MAC

        #serverIP still null, something went wrong...
        if SERVERIP == "":
            notify("Can't find LMS server",
                   "Try manually configuring one in XSqueeze settings")
            sys.exit()

        log("Attempting to connect to LMS named [" + SERVERNAME +
            "] at IP:  " + SERVERIP + " on CLI port: " + SERVERPORT)
        try:
            self.sc = Server(hostname=SERVERIP,
                             port=SERVERPORT,
                             username=SERVERUSER,
                             password=SERVERPASS)
            self.sc.connect()
            log("LMS Logged in: %s" % self.sc.logged_in)
            log("LMS Version: %s" % self.sc.get_version())
        except:
            log(" Couldn't connect to server!")
            notify(LANGUAGE(19613), LANGUAGE(19614))
            raise

        #connect to player
        log("Attempting to connect to player: " + PLAYERMAC)
        try:
            self.sb = self.sc.get_player(PLAYERMAC)
            if self.sb:
                log("Connected to: %s" % PLAYERMAC)
                state = self.sb.get_power_state()
                log("Power state is: " + str(state))
            else:
                log("Player is None! %s" % PLAYERMAC)
                raise Exception
        except Exception as inst:
            log(" Couldn't connect to player: " + PLAYERMAC, inst)
            notify(LANGUAGE(19615), LANGUAGE(19616))
            raise

        #initialise if we're called from XSqueeze as opposed to the chooser
        try:
            if not basicOnly:
                self.currentTrack = None
                self.coverURLs = None
                self.playlistDetails = None
                self.updatePlaylistDetails()
                self.updateCoverArtURLs()
                #if the user wants music to start straight away...
                if SENDPLAYONSTART:
                    self.sb.request("play")
        except Exception as inst:
            log(
                " Error in initialisation of XSqueeze after connection to: " +
                PLAYERMAC, inst)
            raise

    ##############################################################################
    #get the current squeezebox two line display text and return it

    def getDisplay(self):
        displayText = self.sb.requestRaw("display ? ?", True)
        lines = displayText.split(" ")

        try:
            if lines[2] == "":
                lines[2] = "."
        except:
            lines[2] = "."

        try:
            if lines[3] == "":
                lines[3] = "."
        except:
            lines[3] = "."

        cleanedLines = []
        cleanedLines.append((lines[2]))
        cleanedLines.append((lines[3]))

        #print(cleanedLines)

        #clean out the wierd characters used to represent volume...
        newLines = []
        for line in cleanedLines:
            line = line.replace(u'cursorpos', u"\u2334")
            line = line.replace(u'rightarrow', u"\u2192")
            line = line.replace(u'solidblock', u'*')
            line = line.replace(u'leftprogress4', u'*')
            line = line.replace(u'leftprogress2', u'*')
            line = line.replace(u'leftprogress0', u'(Mute)')
            line = line.replace(u'rightprogress0', u' ')
            line = line.replace(u'rightprogress4', u'(Max)')
            line = line.replace(u'middleprogress0', u' ')
            line = line.replace(u'%1E', u"")
            line = line.replace(u'%1F', u"")
            newLines.append(line)

        #print(newLines)

        return unquoteUni(newLines[0]), unquoteUni(newLines[1])

    ##############################################################################
    # check if song changed and update local reference if so
    # returns boolean - but of course only once on each change
    # called every window update to see if the song has changed and only if it has
    # do we update the playlist and cover arts...reduces traffic a lot!

    def songChanged(self):
        oldSong = self.currentTrack
        newSong = self.sb.get_track_title()
        #log("New Song [" + newSong +"], Old song [" + oldSong + "]")
        if newSong != oldSong:
            log("### Detected song change to: " + repr(newSong) +
                " - triggering playlist and cover art updates...")
            self.currentTrack = newSong
            self.updatePlaylistDetails()
            self.updateCoverArtURLs()
            return True
        else:
            return False

    ##############################################################################
    # returns the URLs for the current and next three track cover art images

    def updateCoverArtURLs(self):

        coverURLs = []

        #print "Playlist is" + str(self.playlist)

        #start at this song , end at + 3
        index = int(self.sb.request("playlist index ?"))
        upcomer = index
        end = index + 4

        #currently uses the track_id in the url - works well
        #supposed to use the cover_id number but this doesn't work so well...
        for count in range(upcomer, end):
            if (count < len(self.playlist)):
                try:
                    statusInfo = self.sb.request("status " + str(count) +
                                                 " 1 tags:Kal")
                    #log("Status info is " + str(statusInfo))
                    if ("artwork_url" in statusInfo):
                        statusArtwork = statusInfo.split('artwork_url:')
                        statusArtwork = statusArtwork.pop(1)
                        statusArtwork = statusArtwork.split(' ')
                        statusArtwork = statusArtwork.pop(0)
                        #log("statusArtwork is " + str(statusArtwork))
                        #check we have a full url....
                        if ("http" not in statusArtwork):
                            coverURL = "http://" + SERVERHTTPURL + "/" + statusArtwork
                        else:
                            coverURL = statusArtwork
                    else:
                        statusId = statusInfo.split('id:')
                        statusId = statusId.pop(1)
                        statusId = statusId.split(' ')
                        statusId = statusId.pop(0)
                        #log("StatusID is " + str(statusId))
                        coverURL = "http://" + SERVERHTTPURL + "/music/" + str(
                            statusId) + "/cover.jpg"
                    #now append the coverURL to our list of URLs
                    #log ("Appending future cover: " + str(count) + " from " + coverURL)
                    coverURLs.append(coverURL)

                #Something went wrong, go with null string just to be safe...
                except Exception as inst:
                    log(
                        "No cover art so appending null string for playlist index "
                        + str(count), inst)
                    coverURLs.append("")

        self.coverURLs = coverURLs


##  ##############################################################################
##  # Gets more info about a particular song

    def getSongInfo(self, id):
        encoded = self.sb.requestRaw("songinfo 0 1000 track_id:" + str(id),
                                     True)

        #find the index of id: - track_id%3A
        start = encoded.find('track_id%3A')
        encoded = encoded[start:]

        #print(str(id) + " Encoded: " +str(encoded))
        list = encoded.split(" ")
        #print("list: " + str(list))

        decodedList = []
        for item in list:
            cleanItem = unquoteUni(item)
            decodedList.append(cleanItem)

        #print("DecodedList: " +str(decodedList))

        item = {}
        for info in decodedList:
            info = info.split(':')
            key = info.pop(0)
            if key:
                item[key] = ':'.join(info)

        # example...
        # 9 id:39 title:I'm Not The Man artist:10000 Maniacs coverid:94339a48 duration:226.36 album_id:4 filesize:22796274 genre:Pop coverart:1 artwork_track_id:94339a48
        # album:MTV Unplugged modificationTime:Thursday, November 27, 2008, 5:24 PM type:flc genre_id:4 bitrate:805kbps VBR artist_id:11 tracknum:4 year:1993 compilation:0
        # addedTime:Thursday, December 8, 2011, 11:15 PM channels:2 samplesize:16 samplerate:44100 lastUpdated:Thursday, December 8, 2011, 11:15 PM album_replay_gain:-6.46 replay_gain:-3.46

        #print "Item" + str(item)

        #convert all the data to the right types - there is a much more pythomnesque way to right this I am sure...

        try:
            item['id'] = int(item['id'])
        except KeyError:
            pass
        try:
            item['duration'] = float(item['duration'])
        except KeyError:
            pass
        try:
            item['album_id'] = int(item['album_id'])
        except KeyError:
            pass
        try:
            item['filesize'] = int(item['filesize'])
        except KeyError:
            pass
        try:
            item['coverart'] = int(item['coverart'])
        except KeyError:
            pass
        try:
            item['genre_id'] = int(item['genre_id'])
        except KeyError:
            pass
        try:
            item['artist_id'] = int(item['artist_id'])
        except KeyError:
            pass
        try:
            item['tracknum'] = int(item['tracknum'])
        except KeyError:
            pass
        try:
            item['year'] = int(item['year'])
        except KeyError:
            pass
        try:
            item['compilation'] = int(item['compilation'])
        except KeyError:
            pass
        try:
            item['channels'] = int(item['channels'])
        except KeyError:
            pass
        try:
            item['samplesize'] = int(item['samplesize'])
        except KeyError:
            pass
        try:
            item['samplerate'] = int(item['samplerate'])
        except KeyError:
            pass
        try:
            item['album_replay_gain'] = float(item['album_replay_gain'])
        except KeyError:
            pass
        try:
            item['replay_gain'] = float(item['replay_gain'])
        except KeyError:
            pass

        return item

    ##############################################################################
    # Send a button command text, e.g. 'pause' - to the player

    def button(self, text):
        self.sb.ir_button(text)
        #something probably changed, trigger an update test
        self.songChanged()

    ##############################################################################
    # returns all the details of up to 10 tracks...

    def updatePlaylistDetails(self):
        self.playlist = self.sb.playlist_get_info()
        currentIndex = int(self.sb.request("playlist index ?"))
        #log ("Current index: " + str(currentIndex) + " len(playlist): " + str(len(self.playlist)) + " Playlist is: " + str(self.playlist))
        playlistDetails = []
        #retrieve a maxiumum of 10 tracks details
        for trackOffset in range(currentIndex, currentIndex + 10):
            #don't go off the end of the playlist
            if trackOffset < len(self.playlist):
                trackID = self.playlist[trackOffset]['id']
                #log("Getting full details for id: " + str(trackID))
                playlistDetails.append(self.getSongInfo(trackID))

        #the caller should check the length of the playlist and process all entries...
        self.playlistDetails = playlistDetails

    ##############################################################################
    # returns current track length if available (check for 0 etc. at other end)

    def getTrackLength(self):
        return self.sb.get_track_duration()

    ##############################################################################
    # Show some text on the player's screen

    def show(self,
             line1="",
             line2=""
             ''
             "",
             duration=3,
             brightness=4,
             font="standard",
             centered=False):
        self.sb.show(line1, line2, duration, brightness, font, centered)

    def display(self, line1="", line2="", duration=1):
        self.sb.request("display " + line1 + " " + line2 + " " + str(duration))

    ##############################################################################
    # returns current mode ('play' 'pause' or 'stop')

    def getMode(self):
        return self.sb.get_mode()

    ##############################################################################
    # returns length of time in seconds the current track has played for

    def getTrackElapsed(self):
        return self.sb.get_time_elapsed()

    ##############################################################################
    # returns the full album info given an ID

    def getAlbumInfo(self, albumID):
        fullAlbumInfo = self.sc.request_with_results('albums 0 1 album_id:' +
                                                     albumID + ' tags:yajl')
        #log("Full Album Info: " + str(fullAlbumInfo))
        return fullAlbumInfo[1][0]

    ##############################################################################
    # returns the latest 50 albums

    def getNewMusic(self):
        fullAlbums = []
        albums = self.sc.request_with_results("albums 0 50 sort:new")
        for album in albums[1]:
            fullAlbumInfo = self.getAlbumInfo(album['id'])
            fullAlbums.append(fullAlbumInfo)
        return fullAlbums

    ##############################################################################
    # returns all albums

    def getAlbums(self):
        fullAlbums = []
        albums = self.sc.request_with_results("albums 0 100000")
        for album in albums[1]:
            fullAlbumInfo = self.getAlbumInfo(album['id'])
            fullAlbums.append(fullAlbumInfo)
        return fullAlbums

    ##############################################################################
    # returns all artists

    def getArtists(self):
        artists = self.sc.request_with_results("artists 0 100000")
        #log(str(artists))
        return artists[1]

    ##############################################################################
    # returns all albums by a particular artist given an artist_id

    def getAlbumsByArtistID(self, artistID):
        fullAlbums = []
        albums = self.sc.request_with_results("albums 0 100000 artist_id:" +
                                              str(artistID))
        #log(str(albums))
        for album in albums[1]:
            fullAlbumInfo = self.getAlbumInfo(album['id'])
            fullAlbums.append(fullAlbumInfo)
        return fullAlbums

    ##############################################################################
    # returns all albums in a particular genre given a genre_id

    def getAlbumsByGenreID(self, genreID):
        fullAlbums = []
        albums = self.sc.request_with_results("albums 0 100000 genre_id:" +
                                              str(genreID))
        #log(str(albums))
        for album in albums[1]:
            fullAlbumInfo = self.getAlbumInfo(album['id'])
            fullAlbums.append(fullAlbumInfo)
        return fullAlbums

    ##############################################################################
    # returns all albums for a given year

    def getAlbumsByYear(self, year):
        fullAlbums = []
        albums = self.sc.request_with_results("albums 0 100000 year:" +
                                              str(year))
        #log(str(albums))
        for album in albums[1]:
            fullAlbumInfo = self.getAlbumInfo(album['id'])
            fullAlbums.append(fullAlbumInfo)
        return fullAlbums

    ##############################################################################
    # returns all genres

    def getGenres(self):
        genres = self.sc.request_with_results("genres 0 100000")
        log(str(genres))
        return genres[1][1:]

    ##############################################################################
    # returns all years

    def getYears(self):
        years = self.parseSpecial("years 0 100000", "year", True)
        #log(str(years))
        years.reverse()
        return years

    ##############################################################################
    # returns radios root menu

    def parseSpecial(self, cmdString, splitOn, playerRequest=False):
        quotedColon = urllib.quote(':')
        if playerRequest:
            log("Player Request: " + str(cmdString))
            results = self.sb.requestRaw(cmdString)
        else:
            log("Server Request: " + str(cmdString))
            results = self.sc.requestRaw(cmdString)
        log("Result string: " + pprint.pformat(results))
        #strip off the request stuff at the start
        resultStr = results[results.find(splitOn):]
        log("Split string: " + pprint.pformat(resultStr))
        #ok now split the string on 'splitOn' to get each radio station
        chunks = resultStr.split(splitOn + "%3A")[1:]
        log("Processed Chunks: " + pprint.pformat(chunks))
        output = []
        for chunk in chunks:
            chunk = chunk.strip()
            subResults = chunk.split(" ")
            #log("SUB: " + str(subResults))

            #fix missing splitOn post split
            subResults[0] = splitOn + "%3A" + subResults[0]
            #log("SUB + splitOn: " + str(subResults))

            item = {}
            for subResult in subResults:
                #save item
                key, value = subResult.split(quotedColon, 1)
                item[unquoteUni(key)] = unquoteUni(value)
            output.append(item)

        return output

    def getRadios(self):
        return self.parseSpecial("radios 0 100000", "icon", playerRequest=True)

    def getRadioStations(self, cmd, itemid):
        if (itemid) != "" and itemid is not None:
            return self.parseSpecial(urllib.quote(cmd) +
                                     " items 0 100000 item_id:" + itemid,
                                     "id",
                                     playerRequest=True)
        else:
            return self.parseSpecial(urllib.quote(cmd) + " items 0 100000",
                                     "id",
                                     playerRequest=True)

    def getAppItemsList(self, cmd, itemid):
        if (itemid) != "" and itemid is not None:
            return self.parseSpecial(urllib.quote(cmd) +
                                     " items 0 100000 item_id:" + itemid,
                                     "id",
                                     playerRequest=True)
        else:
            return self.parseSpecial(urllib.quote(cmd) + " items 0 100000",
                                     "id",
                                     playerRequest=True)

    def getFavouritesSub(self, itemid):
        return self.parseSpecial("favorites items 0 100000 item_id:" + itemid,
                                 "id",
                                 playerRequest=True)

    def queueRadio(self, cmd, itemid):
        self.sb.request(urllib.quote(cmd) + " playlist play item_id:" + itemid)

    def getApps(self):
        return self.parseSpecial("apps 0 100000", "cmd", playerRequest=True)

    def getFavourites(self):
        return self.parseSpecial("favorites items 0 100000",
                                 "id",
                                 playerRequest=True)

    def getPlaylists(self):
        #return self.parseSpecial("playlists 0 100000","id", playerRequest=True)
        pls = self.sc.request_with_results("playlists 0 100000 tags:u")
        log(str(pls))
        return pls[1][1:]

    ##############################################################################
    # Clear playlist and queue up a favourite item given

    def queueFavourite(self, item_id):
        self.sb.request("favorites playlist play item_id:" + item_id)

    ##############################################################################
    # Clear playlist and queue up a playlist item given

    def queuePlaylist(self, item_id, url):
        self.sb.request("playlist play " + url)

    ##############################################################################
    # Clear playlist and queue up an album given an album title and artist

    def queueAlbum(self, title, artist):
        if artist == "Various Artists":
            self.sb.request("playlist loadalbum * * " + urllib.quote(title))
        else:
            self.sb.request("playlist loadalbum * " + urllib.quote(artist) +
                            " " + urllib.quote(title))

    ##############################################################################
    # Clear playlist and queue up random albums

    def playRandomAlbums(self):
        self.sb.request("randomplay albums")

    ##############################################################################
    # Clear playlist and queue up random songs

    def playRandomTracks(self):
        self.sb.request("randomplay tracks")

    ##############################################################################
    # Clear playlist and queue up random songs

    def getShuffle(self):
        state = int(self.sb.request("playlist shuffle ?"))
        if state == 0: return False
        else: return True

    def setShuffle(self):
        state = int(self.sb.request("playlist shuffle ?"))
        if state == 0:
            state = 1
            notify("Shuffle Playlist: ON", "")
        else:
            state = 0
            notify("Shuffle Playlist: OFF", "")
        self.sb.request("playlist shuffle " + str(state), debug=True)
        self.updatePlaylistDetails()

    def getRepeat(self):
        state = int(self.sb.request("playlist repeat ?"))
        if state == 0: return False
        else: return True

    def setRepeat(self):
        state = int(self.sb.request("playlist repeat ?"))
        if state == 0:
            state = 2
            notify("Repeat Playlist: ON")
        else:
            state = 0
            notify("Repeat Playlist: OFF")
        self.sb.request("playlist repeat " + str(state), debug=True)

    def rewind(self):
        self.sb.rewind()

    def forward(self):
        self.sb.forward()

    def getVolume(self):
        return self.sb.get_volume()

    def getPowerState(self):
        return self.sb.get_power_state()