rahims / SoCo

SoCo (Sonos Controller) is a simple Python class that allows you to programmatically control Sonos speakers.
331 stars 33 forks source link

[BUG] Parsing error when sonos was new startet #13

Closed avjui closed 11 years ago

avjui commented 11 years ago

When I startet sonos new or on one zone was display 'no Musikfile' then the parser give me an error.

File "/mnt/Media/Downloads/Homematic/core/DBFunctions.py", line 379, in UpdateSonosTable devices = Sonos().GetTrackInfo() File "/mnt/Media/Downloads/Homematic/core/module/sonos.py", line 36, in GetTrackInfo track = sonosdevice.get_current_track_info() File "/mnt/Media/Downloads/Homematic/lib/sonos/soco.py", line 588, in get_current_track_info metadata = XML.fromstring(d.encode('utf-8')) File "", line 107, in XML ParseError: no element found: line 1, column 0

perhaps one try except will fix this :-)

DPH commented 11 years ago

I had the same problem. It started after the change 'Add minor support for getting track info when playing radio' 14 days ago. I discovered it occurs when no music is playing on a zone: d = dom.findtext('.//TrackMetaData') returns nothing. This causes the metadata = XML.fromstring(d.encode('utf-8')) to fail.

I have added a check for this in my code, but need to learn how to post it as a change.
In the meantime this is my replacement code for get_current_track_info(self) - only the addition of an extra if:

def get_current_track_info(self):
    """ Get information about the currently playing track.

    Returns:
    A dictionary containing the following information about the currently
    playing track: playlist_position, duration, title, artist, album, and
    a link to the album art.

    If we're unable to return data for a field, we'll return an empty
    string. This can happen for all kinds of reasons so be sure to check
    values. For example, a track may not have complete metadata and be
    missing an album name. In this case track['album'] will be an empty string.

    """
    response = self.__send_command(TRANSPORT_ENDPOINT, GET_CUR_TRACK_ACTION, GET_CUR_TRACK_BODY)

    print response

    dom = XML.fromstring(response)

    track = {}

    track['playlist_position'] = dom.findtext('.//Track')
    track['duration'] = dom.findtext('.//TrackDuration')
    track['uri'] = dom.findtext('.//TrackURI')
    track['time_played'] = dom.findtext('.//RelTime')    ####DPH Add

    d = dom.findtext('.//TrackMetaData')

    #DPH==================
    if track['duration'] is not 'NOT_IMPLEMENTED':               #then nothing playing
        track['title'] = ''
        track['artist'] = ''
        track['album'] = ''
        track['album_art'] = ''
        #====================================================

    # Duration seems to be '0:00:00' when listening to radio
    elif track['duration'] == '0:00:00':
        metadata = XML.fromstring(d.encode('utf-8'))

        # #Try parse trackinfo
        trackinfo = metadata.findtext('.//{urn:schemas-rinconnetworks-com:metadata-1-0/}streamContent')

        try:
            index = trackinfo.find(' - ')

            if index > -1:
                track['artist'] = trackinfo[:index]
                track['title'] = trackinfo[index+3:]
        except:
            logger.warning('Could not handle track info: "%s"', trackinfo)
            logger.warning(traceback.format_exc())
            track['artist'] = ''
            track['title'] = trackinfo

        track['album'] = ''
        track['album_art'] = ''

    # If the speaker is playing from the line-in source, querying for track
    # metadata will return "NOT_IMPLEMENTED".
    elif d is not '' or d is not 'NOT_IMPLEMENTED':
        # Track metadata is returned in DIDL-Lite format
        metadata = XML.fromstring(d.encode('utf-8'))

        track['title'] = metadata.findtext('.//{http://purl.org/dc/elements/1.1/}title')
        track['artist'] = metadata.findtext('.//{http://purl.org/dc/elements/1.1/}creator')
        track['album'] = metadata.findtext('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}album')

        album_art = metadata.findtext('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}albumArtURI')

        if album_art is not None:
            track['album_art'] = 'http://' + self.speaker_ip + ':1400' + metadata.findtext('.//{urn:schemas-upnp-org:metadata-1-0/upnp/}albumArtURI')
        else:
            track['album_art'] = ''
    else:
        track['title'] = ''
        track['artist'] = ''
        track['album'] = ''
        track['album_art'] = ''

    return track

Regards DPH

rahims commented 11 years ago

Thanks for reporting. Just pushed a fix.