def play(track, immediately_play=True): """Play a track.""" if track is not None: if track is application.track and application.stream is not None: stream = application.stream elif isinstance(track, db.URLStream): stream = URLStream(track.url.encode()) elif not track.downloaded: try: url = application.api.get_stream_url(track.id) if track.artists[0].bio is None: track.artists[0].populate( application.api.get_artist_info(track.artists[0].id)) if not config.sound['pyglet']: stream = URLStream(url.encode()) if config.storage['download'] or config.sound['pyglet']: if config.sound['pyglet']: download_track(url, track.path) play(track, immediately_play=immediately_play) else: Thread(target=download_track, args=[url, track.path]).start() except NotLoggedIn: return do_login(callback=play, args=[track]) else: if config.sound['pyglet']: try: stream = PygletFileStream(track.path) except Exception as e: return do_error('Error playing track %s: %s' % (track, e)) else: stream = FileStream(file=track.path) if not isinstance(track, db.URLStream): track.last_played = datetime.now() if stream is not application.stream and application.stream is not None: if config.sound['pyglet']: application.stream.pause() else: Thread(target=fadeout, args=[application.stream]).start() if immediately_play: stream.play(True) logger.info('Playing track %r.', track) if config.interface['notify']: application.frame.tb_icon.notify('Now playing %s.' % track) set_volume(config.system['volume']) set_pan(config.system['pan']) set_frequency(config.system['frequency']) else: track = None stream = None if application.track is not track and not isinstance(track, db.URLStream): Thread(target=application.frame.update_lyrics, args=[track]).start() application.track = track application.stream = stream application.frame.SetTitle() application.frame.update_labels() return stream
def get_stream(self): """Check this track has been downloaded first.""" assert self.id is not None name = '%s.mp3' % self.id state = backend.get_download_state(name) if state is DownloadStates.downloaded: return FileStream(file=backend.get_full_path(name)) else: url = api.get_stream_url(self.id) if state is DownloadStates.none: add_job('Download track %r' % self, lambda: backend.download_file(url, name)) return URLStream(url.encode())
def on_search(value): if '://' not in value: value = 'http://' + value results = [] try: s = URLStream(value.encode()) results.append(StreamerTrack(None, None, None, None, url=value)) except BassError: # Probably a web page. Let's see what we can see. r = get(value) s = BeautifulSoup(r.content) for audio in s.find_all('audio'): for source in audio.find_all('source'): results.append( StreamerTrack(None, None, None, None, url=source['src'])) return results
def get_stream(self): """Get the stream associated with this station.""" url = stream_url + self.url logger.info('Downloading stream information from %s.', url) r = get(url) if not r.ok: raise SomaError('%d error.' % r.status_code) scp = SafeConfigParser() scp.read_string(r.content.decode()) section = scp['playlist'] n = section.getint('numberofentries') for i in range(n): key = 'File%d' % n try: return URLStream(section.get(key).encode()) except Exception as e: logger.warning('Failed to get %s of %r:', key, section) logger.exception(e) logger.critical('No stream URL found in %d entries for station %r.', n, self) raise SomaError('No stream URL found.')
def do_load(self, event): """OK button was clicked.""" frame = application.main_frame url = self.url.GetValue().strip() title = self.title.GetValue().strip() or url logger.info('Playing URL "%s" from url %s.', title, url) try: s = URLStream(url) result = [title, url] if result not in self._streams: self._streams.append(result) if frame.current_track: frame.current_track.stop() frame.current_track = s frame.duration = 0.0 frame.set_volume() frame.set_pan() frame.set_frequency() frame.SetTitle(title) frame.current_track.play() self.Close(True) except BassError as e: return wx.MessageBox(str(e), 'Error', style=wx.ICON_EXCLAMATION)
def get_stream(self): return URLStream(self.title.encode())
def play(self, item, history = True, play = True): """ Plays the track given in item. If history is True, add any current track to the history. If play is True, play the track immediately. """ logger.debug('Playing item: %s.', item) id = functions.get_id(item) track = None # The object to store the track in until it's ready for playing. error = None # Any error that occured. if id in library.downloaded: # The file has already been downloaded. try: track = FileStream(file = library.get_path(item)) if self.current_library and item in self.current_library: new_item = copy(item) if 'playCount' in new_item: new_item['playCount'] += 1 self.current_library[self.current_library.index(item)] = new_item # Save it with the modified play count so the poll thread doesn't screw anything up. except BassError as e: del library.downloaded[id] return self.play(item, history = history, play = play) # Try again... File's probably not there or something... else: if id in library.downloading: if time() - library.downloading[id] <= config.config.get('library', 'download_timeout'): return wx.MessageBox('This song is still downloading, please wait.', 'Download In Progress') else: del library.downloading[id] try: url = application.mobile_api.get_stream_url(id) except gmusicapi.exceptions.CallFailure as e: application.device_id = None return wx.MessageBox('Cannot play with that device: %s.' % e, 'Invalid Device') except functions.RE as e: if self.current_track: self.current_track.set_position(self.current_track.get_length() - 1) self.play_pause.SetLabel(config.config.get('windows', 'play_label')) return wx.MessageBox(*functions.format_requests_error(e)) try: track = URLStream(url = url) except BassError as e: error = e # Just store it for later alerting. if config.config.get('library', 'cache'): # The user wants their tracks downloaded. Thread(target = functions.download_file, args = [url, id, item]).start() if error: return wx.MessageBox(str(e), 'Error') if self.current_track: self.current_track.stop() if history: self.add_history(self.get_current_track()) self._current_track = item if application.lyrics_frame: Thread(target = application.lyrics_frame.populate_lyrics, args = [item.get('artist'), item.get('title')]).start() self.current_track = track self.SetTitle() self.duration = columns.parse_durationMillis(self.get_current_track().get('durationMillis')) self.update_hotkey_area() self.set_volume() self.set_pan() self.set_frequency() if play: self.current_track.play() self.play_pause.SetLabel(config.config.get('windows', 'pause_label')) else: self.play_pause.SetLabel(config.config.get('windows', 'play_label')) filename = os.path.join(application.artwork_directory, item['albumId'] + '.jpg') if filename != self.album_art_filename: if filename in os.listdir(application.artwork_directory): logger.debug('Loading album art from cache.') else: url = item['albumArtRef'][0]['url'] logger.debug('Downloading album art from %s.', url) art = requests.get(url) with open(filename, 'wb') as f: f.write(art.content) self.album_art_filename = filename i = wx.Image(filename) self.album_art.SetBitmap(i.ConvertToBitmap()) i.Destroy() logger.info('Loaded album art from %s.', filename) try: Thread(target = application.mobile_api.increment_song_playcount, args = [id]).start() self.artist_info = application.mobile_api.get_artist_info(item['artistId'][0]) try: self.set_artist_bio(self.artist_info.get('artistBio', 'No information available.')) except wx.PyDeadObjectError: pass # The frame has been deleted. except functions.RE: pass # We are not connected to the internet, but we can still play stuff.