Beispiel #1
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 #3
0
    def connect_to_server(self):
        server = Server(hostname=self.server_hostname, port=self.server_port)
        server.connect()

        logger = logging.getLogger("LMS")
        logger.info("Logged in: %s" % server.logged_in)
        logger.info("Version: %s" % server.get_version())

        return server
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"
class CommonNetLMS(object):
    def __init__(self, hostname="192.168.1.1", port=9090, username="******",
                 password="******"):
        self.lms_device = Server(hostname=hostname, port=port,
                                 username=username, password=password)
        self.lms_device.connect()

    def com_net_lms_version(self):
        return self.lms_device.get_version()

    def com_net_lms_logged_in(self):
        return self.lms_device.logged_in

    def com_net_lms_close(self):
        self.lms_device.disconnect()

    def com_net_lms_play_count(self):
        return self.lms_device.get_player_count()

    def com_net_lms_get_players(self, update=True):
        return self.lms_device.get_players(update=update)

    def com_net_lms_connect(self):
        self.lms_device.login()

    def com_net_lms_request(self, command_string, preserve_encoding=False):
        self.lms_device.request(
            command_string, preserve_encoding=preserve_encoding)

    def com_net_lms_request_results(self, command_string, preserve_encoding=False):
        self.lms_device.request_with_results(
            command_string, preserve_encoding=preserve_encoding)

    def com_net_lms_rescan(self, mode='fast'):
        # ‘fast’ for update changes on library, ‘full’ for complete library scan
        #  and ‘playlists’ for playlists scan only
        self.lms_device.rescan(mode=mode)

    def com_net_lms_rescanprogress(self):
        self.lms_device.rescanprogress()

    def com_net_lms_search(self, search_term, mode='albums'):
        self.lms_device.search(search_term, mode=mode)

    def com_net_lms_telnet_connect(self):
        self.lms_device.telnet_connect()
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"
Beispiel #7
0
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)

  print "posting..."
  conn.request('GET', url)
Beispiel #8
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")
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()
def main(argv):
    """LCD MANAGER APP FOR LMS"""
    lmsserver = "127.0.0.1"
    lmsplayer = ""
    lcd_address = "0x3f"
    lcd_w = 20
    verbose = True
    clock_mode = False

    try:
        opts, args = getopt.getopt(argv,"hs:p:w:l:c",["server=","player=","lcd_width=","lcd_address=","clock"])
    except getopt.GetoptError:
        printhelp()
        sys.exit(2)

    for opt, arg in opts:
        if opt == '-h':
            printhelp()
            sys.exit()
        elif opt in ("-s", "--server"):
            lmsserver = arg
        elif opt in ("-p", "--player"):
            lmsplayer = arg
        elif opt in("-w","--lcd_width"):
            lcd_w = int(arg)
        elif opt in("-l","--lcd_address"):
            lcd_address = arg    
        elif opt in("-c","--clock"):
            clock_mode = True    
           

    myLCD = LCD(int(lcd_address,16), lcd_w)
    #myLCD.lcd_string"1234567890123456",1)
    myLCD.lcd_string("   TVC Audio    ",1)
    myLCD.lcd_string("  LMS LCD INFO  ",2)
    sleep(2)
    myLCD.lcd_string("(C)2017 Renaud  ",1)
    myLCD.lcd_string("Coustellier     ",2)
    sleep(1)
    
    sc = Server(hostname=lmsserver, port=9090, username="******", password="******")

    # Server connection
    # Clock mode waiting connection
    connected = False
    while connected <> True:
        try:
            sc.connect()
            sleep(1)
            connected = True
        except Exception as e:
            LCDTime(myLCD, lcd_w) 
            #myLCD.lcd_string(str(e),1)
    
    myLCD.lcd_string("LMS SERVER",1)
    myLCD.lcd_string("LMS v.: %s" % sc.get_version(),2)
    sleep(2)
    
    while sc.get_player_count() == 0:
        LCDTime(myLCD, lcd_w)
        sleep(2)
    
    if lmsplayer <> "":
        while True:
            LCDTime(myLCD, lcd_w)
            sq = playerAutodetect(sc, myLCD)
            ipPlayer = str(sq.get_ip_address())
            ipPlayer = ipPlayer[0:ipPlayer.find(":")]
            if ipPlayer == lmsplayer:
                break
            sleep(3)
    else:
        myLCD.lcd_string("autodetect player",3)
        myLCD.lcd_string("in play mode",3)
        sq = playerAutodetect(sc, myLCD)

    playerName = sq.get_name()
    playerModel = sq.get_model()
    
    if lcd_w == 20:
        myLCD.lcd_string(playerName,3)
        myLCD.lcd_string(playerModel,4)
    sleep(2)
    
    if lcd_w == 16:
        # 16x2 LCD Code
        while True:
            try:
                modePlayer = sq.get_mode()  
                if modePlayer == "pause":
                    myLCD.lcd_string("mode = pause",1)
                    myLCD.lcd_string(time.strftime('%Y-%m-%d %H:%M:%S'),2)
                    sleep(2)
                elif modePlayer == "stop":
                    LCDTime(myLCD, lcd_w)
                    sleep(2)
                    # when "stop", looking for a running player except if player defined by user...  
                    if lmsplayer == "":
                        sq = playerAutodetect(sc, myLCD)
                        
                elif modePlayer == "play":
                    trackAlbum = sq.get_track_album()
                    currentTrack = sq.get_track_current_title()
                    trackArtist = sq.get_track_artist()
                    currentVolume = sq.get_volume()
                    
                    print ("")
                    print ("album:" + trackAlbum)
                    print ("artist:" + trackArtist)
                    print ("title:" + currentTrack)

                    myLCD.lcd_string("Alb." + trackAlbum,1)
                    myLCD.lcd_string("Art." + trackArtist,2)
                    sleep(2)
                    myLCD.lcd_string(trackAlbum,1)
                    myLCD.lcd_string(trackArtist,2)
                    
                    td =  "/" + lms_time_to_string(sq.get_track_duration())        
                    ptc = str(sq.playlist_track_count()) 
                    linestatus = 0
                    charOffset = 0
                    while True:
                        linestatus = linestatus + 1
                        volume = (" - Volume %" + str(sq.get_volume()) )
                        #te =  "time " + lms_time_to_string(sq.get_time_elapsed())
                        te = lms_time_to_string(sq.get_time_elapsed()) 
                        te = te + td
                        cti = str(sq.playlist_current_track_index())
                        
                        if len(cti) > 1 and len(ptc) > 1:
                            if linestatus % 4 == 0:
                                te = te + "  /" + ptc
                            else:
                                
                                te = te + "  " + cti + "/"
                        else:
                            te = te + " " + cti + "/" + ptc
                        
                        while currentVolume != sq.get_volume():
                            # Volume
                            currentVolume = sq.get_volume()
                            myLCD.lcd_string("Volume %" + str(currentVolume), 1)    
                            sleep(0.3)
                        if linestatus < 2:
                            myLCD.lcd_string("tle:" + currentTrack, 1)
                            myLCD.lcd_string(te, 2)
                        else: 
                            # Track Name
                            if len(currentTrack) <= lcd_w:
                                # LENGHT is < LCD LCD_WIDTH
                                myLCD.lcd_string(currentTrack, 1)
                            else:
                                # LENGHT is > LCD_WIDTH
                                charOffset = linestatus - 2
                                myLCD.lcd_string(currentTrack[charOffset:], 1) 
                                if linestatus + lcd_w > len(currentTrack):
                                    linestatus = 0       
                            myLCD.lcd_string(te, 2)    
                        if sq.get_track_current_title() != currentTrack or sq.get_mode() !="play" :
                            # change detected
                            myLCD.lcd_string("Track/mode chang", 1)
                            myLCD.lcd_string("pls wait...     ", 2)
                            linestatus = 0
                            break
                        sleep(0.65)
            except:
                lcd(lcd_w)
               
    else:
        # 20x4 LCD Code
        while True:
            try:
            #if True == True:
                modePlayer = sq.get_mode()
                if modePlayer == "pause":
                    myLCD.lcd_string(sq.get_name(),1)
                    myLCD.lcd_string("Mode = Pause",2)
                    line3 = "RJ45"
                    ipPlayer = sq.get_ip_address()
                    ipPlayer = ipPlayer[0:ipPlayer.find(":")]
                    if int(sq.get_wifi_signal_strength()) > 1:
                        line3 = "wifi" + str(sq.get_wifi_signal_strength())
                    line3 = line3 + " " + ipPlayer
                    myLCD.lcd_string(line3,3)
                    myLCD.lcd_string(time.strftime('%Y-%m-%d %H:%M:%S'),4)
                    sleep(0.5)
                elif modePlayer == "stop":
                    LCDTime(myLCD, lcd_w)
                    sleep(2)
                    
                    if lmsplayer == "":
                        # when player mode is stop, looking for another running player except if...
                        sq = playerAutodetect(sc, myLCD)
                          
                elif modePlayer == "play" and lmsplayer == "":
                    trackAlbum = sq.get_track_album()
                    currentTrack = sq.get_track_current_title()
                    trackArtist = sq.get_track_artist()
                    currentVolume = sq.get_volume()
                    if verbose == True:
                        print ("")
                        print ("album:" + trackAlbum)
                        print ("artist:" + trackArtist)
                        print ("title:" + currentTrack)

                    td =  "/" + lms_time_to_string(sq.get_track_duration())                          
                    linestatus = 0
                    charOffset = 0
                    
                    while True:
                        if modePlayer <> "play":
                            break
                        linestatus = linestatus + 1
                        volume = (" - Volume %" + str(sq.get_volume()) )
                        te = lms_time_to_string(sq.get_time_elapsed()) 
                        te = te + td
                        te = te + "   " + str(sq.playlist_current_track_index()) + "/" + str(sq.playlist_track_count())
                        while currentVolume != sq.get_volume():
                            # Volume
                            currentVolume = sq.get_volume()
                            myLCD.lcd_string("Volume %" + str(currentVolume), 1)    
                            sleep(.25)
                        if sq.get_track_current_title() != currentTrack or sq.get_mode() !="play" :
                            # change detected
                            myLCD.lcd_string("Track/mode chang", 1)
                            #myLCD.lcd_string("pls wait...     ", 2)
                            break    
                        
                        # Track Name
                        myLCD.lcd_string(trackArtist, 1)
                        myLCD.lcd_string(trackAlbum, 2)
                        #----------------------------
                        if len(currentTrack) <= lcd_w:
                            # LENGHT is < LCD LCD_WIDTH
                            myLCD.lcd_string(currentTrack, 3)
                        else:
                            # LENGHT is > LCD_WIDTH
                            charOffset = linestatus - 1
                            myLCD.lcd_string(currentTrack[charOffset:], 3) 
                            if linestatus + lcd_w > len(currentTrack):
                                linestatus = 0       
                        #myLCD.lcd_string(currentTrack, 3)
                        if clock_mode != True:
                            myLCD.lcd_string(te, 4)
                            sleep(0.5)
                        else:
                            myLCD.lcd_string(time.strftime('%Y-%m-%d %H:%M:%S'),4)
                            sleep(0.5)
            except: #Exception as e:
            #else:
                #myLCD.lcd_string(str(e), 3)
                sq = playerAutodetect(sc, myLCD)
                sleep(2)
Beispiel #11
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()