def async_fetch(self, song):    
        uri = song.get("uri")
        ntry = 2
        uris = None
        mime_type = get_mime_type(uri)
        while not uris:
            if mime_type == "audio/x-scpls":
                uris = get_uris_from_pls(uri)
            elif mime_type == "audio/x-mpegurl":
                uris = get_uris_from_m3u(uri)
            elif mime_type == "video/x-ms-asf":
                uris = get_uris_from_asx(uri)
            elif mime_type == "application/xspf+xml":
                uris = get_uris_from_xspf(uri)
            ntry += 1
            if ntry > 3: break

        # TODO: Improve multiple webradio url
        if uris:
            self.loginfo("%s choosen in %s", uris[0], uri)
            uri = uris[0]
        else:
            self.loginfo("no playable uri found in %s", uri)
            uri = None
        return song, uri    
    def set_song(self, song, play=False, crossfade=None, seek=None):
        '''set song'''
        if not song:
            return
        # report playcount
        self.perhap_report()
        
        self.stop_after_this_track = False
        self.__need_load_prefs = False
        
        if seek:
            self.__current_stream_seeked = True
        else:    
            self.__current_stream_seeked = False
            
        # get crossfade.    
        if crossfade is None:    
            crossfade = self.get_crossfade()
        
        uri = song.get('uri')    
        self.logdebug("player try to load %s", uri)
        
        # if has xiami , then stop xiami of the previous song.
        
        mime_type = get_mime_type(uri)

        if mime_type in [ "audio/x-scpls", "audio/x-mpegurl"]:
            try_num = 2
            uris = None
            while not uris:
                if mime_type == "audio/x-scpls":
                    uris = get_uris_from_pls(uri)
                elif mime_type == "audio/x-mpegurl":    
                    uris = get_uris_from_m3u(uri)
                try_num += 1    
                if try_num > 3:
                    break
            if uris:        
                self.logdebug("%s choosen in %s", uris[0], uri)
                uri = uris[0]
            else:    
                self.logdebug("no playable uri found in %s", uri)
                uri = None
                
        # remove old stream for pipeline excepted when need to fade
        if self.song and (crossfade == -1 or self.is_paused() or not self.is_playable()):        
            self.logdebug("force remove stream:%s", self.song.get("uri"))
            self.bin.xfade_close(self.song.get("uri"))
            
        # set current song and try play it.
        self.song = song    
        self.__current_song_reported = False
        self.emit("instant-new-song", self.song)
        ret = uri and self.bin.xfade_open(uri)
        if not ret:
            gobject.idle_add(self.emit, "play-end")
            self.next()
        elif play:    
            self.play(crossfade, seek)
            self.logdebug("play %s", song.get_path())
    def __set_song(self, song, play=False, crossfade=None, seek=None):
        '''set song'''
        if not song:
            return

        is_stop = False
        
        # report playcount        
        self.perhap_report()
        
        self.stop_after_this_track = False
        self.__need_load_prefs = False
        
        if seek:
            self.__current_stream_seeked = True
        else:    
            self.__current_stream_seeked = False
            
        # get crossfade.    
        if crossfade is None:    
            crossfade = self.get_crossfade()
        
        if song.get_type() == "cue":    
            uri = song.get("real_uri")
        else:    
            uri = song.get('uri')    
            
        self.logdebug("player try to load %s", uri)
        
        # remove old stream for pipeline excepted when need to fade
        if self.song:
            if self.song.get_type() == "webcast":
                self.force_fade_close()
                is_stop = True
            
        if song and song.get_type() == "webcast":
            if not is_stop:
                self.force_fade_close()
                is_stop = True
            
        if self.song and (crossfade == -1 or self.is_paused() or not self.is_playable()):        
            if not is_stop:
                self.force_fade_close()
                
        # if song.get_scheme() in BAD_STREAM_SCHEMES:
        #     self.bin.dispose_streams()
            
        # set current song and try play it.
        self.song = song    
        self.__current_song_reported = False
        self.emit("instant-new-song", self.song)
        
        mime_type = get_mime_type(uri)
        if mime_type in [ "audio/x-scpls", "audio/x-mpegurl", "video/x-ms-asf", "application/xspf+xml" ]:
            # TODO: Read playlist need to be async
            ntry = 2
            uris = None
            while not uris:
                if mime_type == "audio/x-scpls":
                    uris = get_uris_from_pls(uri)
                elif mime_type == "audio/x-mpegurl":
                    uris = get_uris_from_m3u(uri)
                elif mime_type == "video/x-ms-asf":
                    uris = get_uris_from_asx(uri)
                elif mime_type == "application/xspf+xml":
                    uris = get_uris_from_xspf(uri)
                ntry += 1
                if ntry > 3: break

            # TODO: Improve multiple webradio url
            if uris:
                self.loginfo("%s choosen in %s", uris[0], uri)
                uri = uris[0]
            else:
                self.loginfo("no playable uri found in %s", uri)
                uri = None

        if song.get_scheme() in BAD_STREAM_SCHEMES:
            self.play_thread_id += 1            
            play_thread_id = copy.deepcopy(self.play_thread_id)
            self.thread_play(uri, song, play, play_thread_id)
        else:    
            ret = uri and self.bin.xfade_open(uri)
            if not ret:
                # gobject.idle_add(self.emit, "play-end")
                if self.song:
                    if getattr(self.__source, 'add_invaild_song', None):
                        self.__source.add_invaild_song(self.song)
                        self.skip_error_song_flag = True
                self.next()
            elif play:    
                self.play(crossfade, seek)