class SpdifPlayback(WorkflowTestFixture): def setUpFixture(self): self.zone = self.get_testbed_device_by_model(SOUNDBAR) self.verifyTrueOrStop(self.zone.diag.is_toslink_connected(), 'TOSLINK should be connected') self.mplayer = Player(args=MPLAYER_ARGS) def tearDownFixture(self): self.mplayer.stop() self.mplayer.quit() def _is_stream_type_expected(self): """ Verifies TOSLINK Stream Type is expected :return: Is Stream Type expected? :rtype: :obj:`bool` """ return self.zone.diag.get_toslink_stream_type() == EXPECTED_STREAM_TYPE def test_spdif_playback(self): """ Verifies SPDIF playback by checking TOSLINK Stream Type """ self.mplayer.loadfile(TRACK) wait_until_true(lambda: self._is_stream_type_expected(), timeout_seconds=10, reason="Timed out waiting for expected stream type")
def playTheme(fileName): output('speaker',1) player = Player() player.loadfile(fileName) # Terminate MPlayer player.quit() output('speaker',0)
class MPlayer(object): def __init__(self, *args, **kwargs): self.argparser = None self.exit = False self.paused = False self.player = Player() def set_argparser(self, argparser): self.argparser = argparser def start(self, *args, **kwargs): pass @property def is_playing(self): if self.player.filename and not self.paused: status = True else: status = False return status def play(self, path, track, block=True): self.player.loadfile(path) self.player.pause() time.sleep(3) if block: while self.player.filename: if self.exit: break try: time.sleep(0.1) except KeyboardInterrupt: pass def pause(self): if self.is_playing: self.paused = True self.player.pause() def stop(self): self.player.stop() def resume(self): if not self.is_playing: self.pause = False self.player.pause() def shutdown(self): if self.player.is_alive(): self.player.quit()
class Sound(object): """ A Sound object is a simple abstraction of an underlying sound that can be played, stopped, etc. """ def __init__(self, path, volume=100): self.path = path # We need to set the volume when creating the mplayer process. If we # don't, the sound would start playing at 100% for about 1 sec before # the actual volume gets applied self.player = Player(stdout=PIPE, stderr=PIPE, args=('-volume {0}'.format(volume))) self.player.loadfile(self.path) # Pause the stream so we can't do something else before calling play() self.player.pause() def play(self, loop=False): if loop: self.player.loop = 0 self.player.pause() def pause(self): self.player.pause() def stop(self): self.player.stop() def get_volume(self): return self.player.volume def set_volume(self, volume): self.player.volume = volume def get_duration(self): return self.player.length def destroy(self): self.player.quit() def __del__(self): self.destroy()
class UbuntuDJ: def __init__(self, parent, mplayerloc, hideonplay, showonstop, controls): self.parent = parent self.hideonplay = hideonplay self.showonstop = showonstop self.controls = controls self.parent.title('UbuntuDJ') # initially visible and not playing self.visible = True self.playing = False self.selected = 0 # get mplayer info Player.exec_path = mplayerloc Player.introspect() self.p = Player() # bottom labels self.songname = StringVar() self.label1 = Label(parent, textvariable=self.songname, anchor=W) self.label1.pack(side=BOTTOM) self.status = StringVar() self.label2 = Label(parent, textvariable=self.status) self.label2.pack(side=BOTTOM) # scrollbar and listbox self.scrollbar = Scrollbar(parent) self.scrollbar.pack(side=LEFT, fill=Y) self.listbox = Listbox(parent, yscrollcommand=self.scrollbar.set, selectmode=BROWSE) for i in directorymap: self.listbox.insert(END, i) self.listbox.pack(side=LEFT, fill=BOTH, expand=1) self.scrollbar.config(command=self.listbox.yview) # select first item self.listbox.focus_set() self.listbox.selection_set(0) # bind to click too self.listbox.bind('<<ListboxSelect>>', self.OnClick) # topmost window self.parent.wm_attributes("-topmost", 1) # set up labels self.UpdateLabels() def ButtonPress(self, button): if button == self.controls['playstop']: # play/stop self.PlayStop() elif button == self.controls['navup']: # nav up if self.selected != 0: self.listbox.selection_clear(self.selected) self.selected -= 1 self.listbox.selection_set(self.selected) self.listbox.activate(self.selected) self.listbox.see(self.selected) elif button == self.controls['navdown']: # nav down if self.selected != self.listbox.size()-1: self.listbox.selection_clear(self.selected) self.selected += 1 self.listbox.selection_set(self.selected) self.listbox.activate(self.selected) self.listbox.see(self.selected) elif button == self.controls['volup']: # vol inc self.p.volume = Step(1) self.UpdateLabels() elif button == self.controls['voldown']: # vol dec self.p.volume = Step(-1) self.UpdateLabels() elif button == self.controls['showhide']: # show/hide self.ShowHide() elif button == self.controls['reset']: # reset self.Reset() elif button == self.controls['quit']: # exit self.Reset() self.parent.quit() def PlayStop(self): self.listbox.focus_set() if self.playing: self.playing = False self.p.quit() # quit and get new player self.p = Player() if self.showonstop: self.parent.update() self.parent.deiconify() self.visible = True self.UpdateLabels() else: self.playing = True song = self.listbox.get(ACTIVE) prefix = directorymap[song] self.p.loadfile(prefix+'/'+song) if self.hideonplay: self.parent.withdraw() self.visible = False self.UpdateLabels() def ShowHide(self): if self.visible: self.parent.withdraw() self.visible = False else: self.parent.update() self.parent.deiconify() self.visible = True def OnClick(self, event): w = event.widget index = int(w.curselection()[0]) self.selected = index self.listbox.activate(index) def UpdateLabels(self): playing = ('Playing' if self.playing else 'Stopped') volume = ('None' if self.p.volume is None else str(self.p.volume)) self.status.set(playing + ' | Volume: ' + volume) songname = (self.listbox.get(ACTIVE) if self.playing else '-') self.songname.set(songname) def Reset(self): self.p.quit() self.p = Player() self.playing = False self.UpdateLabels()
class alarm: dowlist = 'MO,TU,WE,TH,FR,SA,SU'.split(',') dow = {d:i for i,d in enumerate(dowlist)} def __init__(self, name, time, days = ('MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU'), date = None, path = './playlist/', volume = 40, active = True, color_onset = 300, duration = -1, color = 'FFFFFF' ): '''define an alarm. at the time of the alarm, a media file is played required parameters is time (datetime.time) optional parameters days, the days of the week for the alarm. days is one or more of 'MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU' date is the date for a specific alarm. date overrides the days parameter path is the path to media files if active is True, the alarm will play otherwise it will not. ''' self.name = name self.time = time self.days = days self.date = date self.repeating = True if date == None else False self.active = active self.volume = volume self.path = path +'/'if path[-1] != '/' else path # add a / to the end of the path if not present self.color_onset = color_onset # onset is the time before the alarm for sunrise self.duration = duration # duration of the alarm. -1 is manual off only self.color = color self.bulb_ip = '192.168.1.162' # these variables are not passed when initiating the alarm, but are used for housekeeping self.chkbox = {d:b for b,d in zip(('checked' if t in self.days else '' for t in self.dowlist),self.dowlist)} # used by the module web.py to format the ceckboxes for the recurrence self.playing = False self.track = None def update_alarm(self, **kwargs): '''update the the alarm. the function takes 0 or more inputs from the list name, time, days, date, path and repeating ''' self.name = kwargs.get('name', self.name) self.time = kwargs.get('time', self.time) self.days = kwargs.get('days', self.days) self.date = kwargs.get('date', self.date) self.repeating = kwargs.get('repeating', self.repeating) self.path = kwargs.get('path', self.path) self.volume = kwargs.get('volume', self.volume) self.active = kwargs.get ('active', self.active) self.color = kwargs.get('color', self.color) self.color_onset = kwargs.get('color_onset', self.color_onset) self.duration = kwargs.get('duration', self.duration) # housekeeping if self.path[-1] != '/': self.path += '/' self.chkbox = {d:b for b,d in zip(('checked' if t in self.days else '' for t in self.dowlist),self.dowlist)} self.volume = max(min(100, self.volume), 0) # volume should be between 0 and 100 def next_alarm(self, now): '''alarm.next(now) returns the next occurence of an alarm after the input eg alarm(time(10,0,0)).next(datetime(2015,1,1,11,0,0)) -> the next alarm at 10am if today is 11:00AM on Jan 1st 2015 will return datetime(2015,1,2,10,0,0) -> 10:00 AM on Jan 2nd 2015''' #offset now by 60 seconds so that next(now) = now now += datetime.timedelta(0,-60) # first determine the start date... # which is either a specific date (ie self.date != None # tomorrow (if now.time is past alarm.time # or today (in all other cases) if not self.active: return None if not self.repeating: date = self.date if self.date == None or datetime.datetime.combine(date, self.time) < now: return None elif now.time() > self.time: date = now.date() + datetime.timedelta(1) else: date = now.date() next_date = datetime.datetime.combine(date, self.time) #map the weekday numbers to the days in alarm.days, so that 'MO' = 0, TU = 1 #then increment the current date until the current dow matches a day in alarm.days wkdays = set(alarm.dow[x] for x in self.days) while next_date.weekday() not in wkdays: next_date += datetime.timedelta(1) return next_date def generate_playlist(self, path=None, ext = ('.mp3','.wav','.flac')): '''generates a list of files in path that ends with extension ext (default = .mp3, .wav and .flac''' if path == None: path = self.path return sorted(list(filter(lambda x: x.endswith(ext), os.listdir(path)))) def play(self): playlist = self.generate_playlist() path = self.path self.player = Player() self.playing = True while len(playlist) >0: track = playlist.pop(0) self.player.loadfile(path+track) i=0 while self.player.time_pos == None: time.sleep(0.1) print ('loading', path+track, i, end='\r') i+=1 print() self.player.volume = self.volume while self.player_active(): print (path+track, self.player.time_pos, end='\r') time.sleep(1) self.stop() def wakeup_light(self): r, g, b = webcolors.hex_to_rgb('#'+self.color) bulb = ledenet_api.bulb(self.bulb_ip) bulb.gradual(r,g,b,self.color_onset) def player_active(self): if self.playing: return self.player.time_pos != None else: return False def stop(self): self.turn_off_light() self.track = None if self.playing: self.playing = False self.player.quit() def turn_off_light(self): bulb = ledenet_api.bulb(self.bulb_ip) bulb.turn_off()
class MediaPlayer: def __init__(self): self.settings = Settings.Settings() self.player = False self.effect = False def playerActive(self): return self.player!=False def soundAlarm(self, alarmThread): log.info("Playing alarm") self.playStation() log.debug("Alarm process opened") # Wait a few seconds and see if the mplayer instance is still running time.sleep(self.settings.getInt('radio_delay')) if alarmThread.isSnoozing() or alarmThread.getNextAlarm() is None: # We've snoozed or cancelled the alarm, so no need to check for player log.debug("Media player senses alarm already cancelled/snoozed, so not checking for mplayer instance") return # Fetch the number of mplayer processes running processes = subprocess.Popen('ps aux | grep mplayer | egrep -v "grep" | wc -l', stdout=subprocess.PIPE, shell=True ) num = int(processes.stdout.read()) if num < 2 and self.player is not False: log.error("Could not find mplayer instance, playing panic alarm") self.stopPlayer() time.sleep(2) self.playMedia(PANIC_ALARM,0) def playStation(self,station=-1): if station==-1: station = self.settings.getInt('station') station = Settings.STATIONS[station] log.info("Playing station %s", station['name']) self.player = Player() self.player.loadlist(station['url']) self.player.loop = 0 def playMedia(self,file,loop=-1): log.info("Playing file %s", file) self.player = Player() self.player.loadfile(file) self.player.loop = loop # Play some speech. None-blocking equivalent of playSpeech, which also pays attention to sfx_enabled setting def playVoice(self,text): if self.settings.get('sfx_enabled')==0: # We've got sound effects disabled, so skip log.info("Sound effects disabled, not playing voice") return log.info("Playing voice: '%s'" % (text)) play = subprocess.Popen('/usr/bin/espeak "%s" >& /dev/null' % (text), shell=True) # Play some speech. Warning: Blocks until we're done speaking def playSpeech(self,text): log.info("Playing speech: '%s'" % (text)) play = subprocess.Popen('/usr/bin/espeak "%s" >& /dev/null' % (text), shell=True) play.wait() def stopPlayer(self): if self.player: self.player.quit() self.player = False log.info("Player process terminated")
class MediaPlayer: def __init__(self): self.settings = Settings.Settings() self.player = False self.effect = False def playerActive(self): return self.player != False def soundAlarm(self, alarmThread): log.info("Playing alarm") self.playStation() log.debug("Alarm process opened") # Wait a few seconds and see if the mplayer instance is still running time.sleep(self.settings.getInt('radio_delay')) if alarmThread.isSnoozing() or alarmThread.getNextAlarm() is None: # We've snoozed or cancelled the alarm, so no need to check for player log.debug( "Media player senses alarm already cancelled/snoozed, so not checking for mplayer instance" ) return # Fetch the number of mplayer processes running processes = subprocess.Popen( 'ps aux | grep mplayer | egrep -v "grep" | wc -l', stdout=subprocess.PIPE, shell=True) num = int(processes.stdout.read()) if num < 2 and self.player is not False: log.error("Could not find mplayer instance, playing panic alarm") self.stopPlayer() time.sleep(2) self.playMedia(PANIC_ALARM, 0) def playStation(self, station=-1): if station == -1: station = self.settings.getInt('station') station = Settings.STATIONS[station] log.info("Playing station %s", station['name']) self.player = Player() self.player.loadlist(station['url']) self.player.loop = 0 def playMedia(self, file, loop=-1): log.info("Playing file %s", file) self.player = Player() self.player.loadfile(file) self.player.loop = loop # Play some speech. None-blocking equivalent of playSpeech, which also pays attention to sfx_enabled setting def playVoice(self, text): if self.settings.get('sfx_enabled') == 0: # We've got sound effects disabled, so skip log.info("Sound effects disabled, not playing voice") return path = self.settings.get("tts_path") log.info("Playing voice: '%s' through `%s`" % (text, path)) play = subprocess.Popen('echo "%s" | %s' % (text, path), shell=True) # Play some speech. Warning: Blocks until we're done speaking def playSpeech(self, text): path = self.settings.get("tts_path") log.info("Playing speech: '%s' through `%s`" % (text, path)) play = subprocess.Popen('echo "%s" | %s' % (text, path), shell=True) play.wait() def stopPlayer(self): if self.player: self.player.quit() self.player = False log.info("Player process terminated")
class PiPlayBoxMode(BaseMode): def setup(self): self.modecolour = self.display.RED self.display.changeColour(self.modecolour) self.enabled = self.__ping() self.mplayer = None if self.enabled: self.actions = { 0: { "text": "Capital FM", "sound": "http://ice-sov.musicradio.com:80/CapitalMP3" }, 1: { "text": None, "sound": None }, 2: { "text": None, "sound": None }, 3: { "text": None, "sound": None }, 4: { "text": None, "sound": None }, 5: { "text": None, "sound": None }, 6: { "text": None, "sound": None }, 7: { "text": None, "sound": None } } self.addInterrupts() self.modename = "Internet Radio" self.subtext = "ONLINE" self.mplayer = Player() else: self.modename = "No Internet" self.subtext = "Connection" self.display.Update("%s\n%s" % (self.modename, self.subtext)) def __ping(self): self.display.Update("Checking if\nonline...") try: a = check_call( ["/bin/ping", "www.bbc.co.uk", "-c", "1", "-t", "200"]) return True except CalledProcessError: return False def addInterrupts(self): e = GPIO.add_event_detect for i in range(8): e(self.buttons[i], GPIO.RISING, lambda channel, x=i: self.buttonAction(x), bouncetime=600) def buttonAction(self, button): action = self.actions[button] if action["text"] is not None: self.display.Update(action["text"]) self.mplayer.stop() self.speaker.Unmute() self.mplayer.loadfile(action["sound"]) def quit(self): if self.mplayer is not None and self.mplayer.is_alive(): self.mplayer.stop() self.mplayer.quit() self.speaker.Mute() self.mplayer = None
global player if player is None: return redis.set("musicastatus", json.dumps({"paused": player.paused, "time": player.time_pos or 0, "length": player.length or 0})) while True: if player is not None and player.filename is not None and player.paused != should_be_paused: player.pause() status_update() p.get_message() quent = redis.lindex("musicaqueue", 0) removed_uuid = check_finished_uuid() if removed_uuid and quent and removed_uuid == json.loads(quent.decode())["uuid"]: print("DEQUEUE") ent = redis.lpop("musicaqueue") redis.set("musicatime.%s" % json.loads(quent.decode())["ytid"], time.time()) redis.rpush("musicaudit", "dequeued entry %s at %s because process ended" % (ent, time.ctime())); quent = redis.lindex("musicaqueue", 0) if quent: quent = json.loads(quent.decode()) if quent["uuid"] != current_uuid: redis.set("musicatime.%s" % quent["ytid"], time.time()) start_playing(quent["uuid"], quent["ytid"]) else: if current_uuid is not None: stop_playing() if player is not None: player.quit() player = None time.sleep(0.5)
class BasePlayer(object): def __init__(self, playEndedCallback): self.isPlaying = False self.mplayer = MPlayer(autospawn=False) self.timer = Timer(interval=1, function=Player.loop, args=[self]) self.timer.start() self.playEndedCallback = playEndedCallback def stop(self): self.isPlaying = False self.mplayer.stop() def pause_resume(self): self.mplayer.pause() def seek(self, amount): if self.mplayer.time_pos: self.mplayer.time_pos += amount def play(self, mediafile): self.isPlaying = True args = [] self.mplayer.args = args self.mplayer.spawn() if mediafile: self.mplayer.loadfile(mediafile) def quit(self): self.isPlaying = False self.timer.cancel() self.mplayer.quit() print "timer cancelled" @classmethod def loop(cls, player): #return if not playing if not player.isPlaying: return t = Timer(1, cls.loop, [player]) t.start() # from videotop import status_bar # status_bar.set_text("%s/%s -- curr: %s" % ( player.player.length, player.player.time_pos, player.current)) # print("%s/%s -- curr: %s" % ( player.mplayer.length, player.mplayer.time_pos, player.current)) if player.mplayer.length != None: time.sleep(1000) else: player.playEndedCallback() t.cancel() def __del__(self): self.quit()
def main(): try: print("Selecting stream...") sys.stdout.flush() if os.path.isfile(alt_music_list_path): alt_music_list_file = open(alt_music_list_path, 'r') alt_music_list = [f.strip() for f in alt_music_list_file.readlines()] print("Alternative list available") sys.stdout.flush() else: alt_music_list = [] if store in alt_music_list: CODE = 'f6403f66f656451f8fcbf4b4fe881d9b' else: CODE = '79c6519c9d1b46fc8d6d341d92f4eb4d' CURL = commands.getoutput("curl -s 'https://api.rebrandly.com/v1/links/%s' -H 'apikey: 77a44fcac24946679e800fadc4f84958'" % CODE) JSON = json.loads(CURL) STREAM = JSON["destination"] print("Checking stream...") sys.stdout.flush() if int(urllib.urlopen(STREAM).getcode()) != 200: raise Exception("Stream not available. Restarting") print("Starting player...") sys.stdout.flush() player = Player(args=('-ao alsa:device=hw=1.0')) player.loadfile(STREAM) print("Playing %s" % STREAM) sys.stdout.flush() print("Checking for announcements...") sys.stdout.flush() announcements = [] if os.path.exists(announcements_lang_path): announcements = [os.path.join(announcements_lang_path, f) for f in os.listdir(announcements_lang_path) if not f.startswith('.') and os.path.isfile(os.path.join(announcements_lang_path, f))] # announcements_date_file = "%s.mp3" % datetime.today().strftime('%Y-%m-%d') # if country == 'sweden' and os.path.exists(announcements_date_path) and os.path.isfile(os.path.join(announcements_date_path, announcements_date_file)): # announcements.append(os.path.join(announcements_date_path, announcements_date_file)) if announcements: print("Announcements found for %s" % country) sys.stdout.flush() print("Waiting for cache. Sleeping for 2 mins") sys.stdout.flush() sleep(120) while True: for announce in announcements: for n in range(GAP): if not player.is_alive(): raise Exception("Player not playing. Restarting") if player.filename is None: raise Exception("No internet connected. Restarting") sleep(1) player.pause() player_announce = Player(announce) sleep(1) duration = int(math.ceil(player_announce.length)) if (duration > 30): duration -= 27 else: duration -= 1 sleep(duration) player_announce.quit() player.pause() else: print("No announcements found for %s" % country) sys.stdout.flush() print("Waiting for cache. Sleeping for 2 mins") sys.stdout.flush() sleep(120) while True: if not player.is_alive(): raise Exception("Player not playing. Restarting") if player.filename is None: raise Exception("No internet connected. Restarting") sleep(1) except Exception as e: try: player.quit() except: pass print(e) sys.stdout.flush() main()
class PlayerThread(threading.Thread): def __init__(self, subsonic, msg_queue): # Read config and setup the player accordingly self.config = read_config() self.download_queue = [] subsonic = Subsonic() self.subsonic = subsonic.connection self.mplayer = MPlayer( args=("-really-quiet", "-msglevel", "global=6", "-nolirc") ) self.mplayer.stdout.connect(self._handle_data) self.msg_queue = msg_queue super(PlayerThread, self).__init__() def _handle_data(self, data): # Handle the stdout stream coming back from MPlayer. if data.startswith('EOF code:'): if data.split(": ")[1] == "1": # EOF Code: 1 means that the song finished playing # by itself. Therefore we want to try to play the # next song in the queue. self.msg_queue.put("EOF") def _get_stream(self, song_id): return self.subsonic.stream(song_id) def _get_song(self, song_id): song_file = os.path.join(MUSIC_CACHE_DIR, "%s.mp3" % song_id) if os.path.exists(song_file): logger.info("The song with id %s was found in the cache" % song_id) # Check if file already exists in cache if not os.path.exists(MUSIC_CACHE_DIR): # Make sure the cache dir is present. os.makedirs(MUSIC_CACHE_DIR) if not song_id in self.download_queue: # Check if the song is not already downloading logger.debug("Downloading song with id: %s" % song_id) self.download_queue.append(song_id) try: stream = self._get_stream(song_id) f = open(song_file, "wb") f.write(stream.read()) f.close() logger.debug("Finished downloading song with id: %s" % song_id) except Exception as e: logger.error( "Could not download song with id: %s - Error was: %s" % ( song_id, e ) ) self.download_queue = [ x for x in self.download_queue if x != song_id ] else: logger.info( "Song with id %s is already in download queue. \ Doing nothing." % song_id ) # TODO: Handle this. Should we wait here for a little bit # and see if it finishes downloading? # At this point, if it clashes, it gets stuck in stopped state. return song_file def play_song(self, song_id): song_file = self._get_song(song_id) self.mplayer.stop() self.mplayer.loadfile(song_file) # Hacky, but needed to work. Check if Linux or Darwin, if so # also play the file after loading it. On OS X, pressing play # is not needed. if "linux" or "darwin" in platform: self.mplayer.pause() def play(self): if self.is_paused(): self.mplayer.pause() def pause(self): self.mplayer.pause() def stop(self): self.mplayer.stop() def seek(self, timedelta): if not self.is_stopped() and isinstance(timedelta, int): time_pos = self.mplayer.time_pos length = self.mplayer.length new_time_pos = time_pos + timedelta if new_time_pos < 0: new_time_pos = 0 elif new_time_pos > length: # So we have seeked passed the length of the song? # Play next song. self.msg_queue.put("EOF") self.mplayer.time_pos = new_time_pos def player_state(self): if self.is_playing(): return "Playing" elif self.is_paused(): return "Paused" else: return "Stopped" def is_playing(self): return bool(self.mplayer.filename and not self.mplayer.paused) def is_paused(self): return bool(self.mplayer.filename and self.mplayer.paused) def is_stopped(self): return bool(not self.mplayer.filename) def progress(self): ret = None if self.mplayer.time_pos: try: ret = { "percent": self.mplayer.percent_pos, "time": int(self.mplayer.time_pos), "length": int(self.mplayer.length), } except: ret = { "percent": 0, "time": 0, "length": 0, } return ret def quit(self): self.mplayer.quit()
class MediaPlayer(threading.Thread): def __init__(self, mqttbroker, settings): threading.Thread.__init__(self) self.settings = settings self.player = False self.effect = False self.CurrentStation = "" self.CurrentStationNo = -1 self.CurrentURL = "" self.stopping = False self.message = "" self.mqttbroker = mqttbroker self.increasingvolume = -1 self.alarmThread = None self.playerrestarting = False def playerActive(self): # True if playing or mid restart return self.player!=False or self.playerrestarting def playerPaused(self): if self.player: return self.player.paused else: return True # not running actually! def playerActiveStation(self): if self.player: return self.CurrentStation else: return "None" def playerActiveStationNo(self): if self.player: return self.CurrentStationNo else: return -1 def soundAlarm(self, alarmThread, Station = -1, StartVolume = -1): # STation = Station Number # StartVolume = Increasing volume from this level log.info("Playing alarm") self.alarmThread = alarmThread self.increasingvolume = StartVolume if (StartVolume != -1): self.settings.setVolume(StartVolume) self.playStation(Station) log.debug("Alarm process opened") # Wait a few seconds and see if the mplayer instance is still running time.sleep(self.settings.getInt('radio_delay')) if alarmThread.isSnoozing() or alarmThread.getNextAlarm() is None: # We've snoozed or cancelled the alarm, so no need to check for player log.debug("Media player senses alarm already cancelled/snoozed, so not checking for mplayer instance") return # Fetch the number of mplayer processes running processes = subprocess.Popen('ps aux | grep mplayer | egrep -v "grep" | wc -l', stdout=subprocess.PIPE, shell=True ) num = int(processes.stdout.read()) if num < 2 and self.player is not False: log.error("Could not find mplayer instance, playing panic alarm") self.stopPlayer() time.sleep(2) self.playMedia(PANIC_ALARM,0) def playStation(self,station=-1): if station==-1: station = self.settings.getInt('station') try: stationinfo = self.settings.getStationInfo(station) except: log.debug("invalid station no '%s'", str(station)) stationinfo = None if (stationinfo != None): # Only change if its differant URL if (self.CurrentURL != stationinfo['url']): log.info("Playing station %s", stationinfo['name']) log.debug("Playing URL %s", stationinfo['url']) self.player = Player() # did have "-cache 2048" self.player.loadlist(stationinfo['url']) self.player.loop = 0 self.CurrentStation = stationinfo['name'] self.CurrentStationNo = station self.CurrentURL = stationinfo['url'] else: log.info("Already Playing %s", stationinfo['name']) if (self.mqttbroker != None): self.mqttbroker.publish("radio/station",self.CurrentStation) self.mqttbroker.publish("radio/stationno",str(self.CurrentStationNo)) self.mqttbroker.publish("radio/state","ON") self.mqttbroker.publish("radio/mute","OFF") def playStationURL(self,stationName, StationURL, StationNo = -1): log.info("Playing station %s", stationName) log.debug("Playing URL %s", StationURL) self.player = Player("-cache 320") # did have "-cache 2048" self.player.loadlist(StationURL) self.player.loop = 0 self.CurrentStation = stationName self.CurrentStationNo = StationNo self.CurrentURL = StationURL if (self.mqttbroker != None): self.mqttbroker.publish("radio/station",self.CurrentStation) self.mqttbroker.publish("radio/stationno",str(StationNo)) self.mqttbroker.publish("radio/state","ON") self.mqttbroker.publish("radio/mute","OFF") def playMedia(self,file,loop=-1): log.info("Playing file %s", file) self.player = Player() self.player.loadfile(file) self.player.loop = loop self.CurrentStation = file self.CurrentStationNo = -1 self.CurrentURL = file if (self.mqttbroker != None): self.mqttbroker.publish("radio/station",self.CurrentStation) self.mqttbroker.publish("radio/stationno",str(self.CurrentStationNo)) self.mqttbroker.publish("radio/state","ON") self.mqttbroker.publish("radio/mute","OFF") # Play some speech. None-blocking equivalent of playSpeech, which also pays attention to sfx_enabled setting def playVoice(self,text): if (self.settings.get('sfx_enabled')==0) or (self.settings.getIntOrSet('quiet_reboot') == 1): # We've got sound effects disabled, so skip log.info("Sound effects disabled, not playing voice") return path = self.settings.get("tts_path"); log.info("Playing voice: '%s' through `%s`" % (text,path)) if path == "pico2wave": play = subprocess.Popen('pico2wave -l en-GB -w /tmp/texttosay.wav "%s" && aplay -q /tmp/texttosay.wav' % (text), shell=True) else: play = subprocess.Popen('echo "%s" | %s 2>/dev/null' % (text,path), shell=True) # Play some speech. Warning: Blocks until we're done speaking def playSpeech(self,text): if (self.settings.get('sfx_enabled')==0) or (self.settings.getIntOrSet('quiet_reboot') == 1): # We've got sound effects disabled, so skip log.info("Sound effects disabled, not playing voice") return path = self.settings.get("tts_path"); log.info("Playing speech: '%s' through `%s`" % (text,path)) if path == "pico2wave": play = subprocess.Popen('pico2wave -l en-GB -w /tmp/texttosay.wav "%s" && aplay -q /tmp/texttosay.wav' % (text), shell=True) else: play = subprocess.Popen('echo "%s" | %s 2>/dev/null' % (text,path), shell=True) play.wait() def stopPlayer(self): if self.player: self.player.quit() self.player = False self.CurrentURL = "" self.CurrentStationNo = -1 self.CurrentStation = "N/A" log.info("Player process terminated") if (self.mqttbroker != None): self.mqttbroker.publish("radio/station",self.CurrentStation) self.mqttbroker.publish("radio/stationno",str(self.CurrentStationNo)) self.mqttbroker.publish("radio/state","OFF") self.mqttbroker.publish("radio/mute","OFF") def pausePlayer(self): if self.player: self.player.pause() log.info("Player process paused/unpaused") if (self.mqttbroker != None): self.mqttbroker.publish("radio/state","ON") self.mqttbroker.publish("radio/mute","ON") return self.player.paused else: return True # not running actually! def restartPlayer(self): self.playerrestarting = True CurrentURL = self.CurrentURL CurrentStation = self.CurrentStation CurrentStationNo = self.CurrentStationNo log.info("Player Restarting") self.stopPlayer() time.sleep(2) self.playerrestarting = False self.playStationURL(CurrentStation, CurrentURL, CurrentStationNo) def publish(self): self.mqttbroker.publish("radio/volumepercent", self.settings.getInt("volumepercent")) self.mqttbroker.publish("radio/station",self.CurrentStation) self.mqttbroker.publish("radio/stationno",str(self.CurrentStationNo)) if self.player: self.mqttbroker.publish("radio/state","ON") else: self.mqttbroker.publish("radio/state","OFF") def on_message(self, topic ,payload): method = topic[0:topic.find("/")] # before first "/" item = topic[topic.rfind("/")+1:] # after last "/" log.debug("radio method='%s', item='%s'", method, item) done = False try: if (method == "radio"): if item == "state": if (payload.upper() == "ON"): self.playStation(-1) elif (payload.upper() == "OFF"): self.stopPlayer() else: log.info("Invalid payload state '%s' [ON/OFF]", payload) done = True elif item == "stationno": try: stationno = int(payload) self.playStation(stationno) except ValueError: log.warn("Could not decode %s as station no", payload) done = True elif (item == "volumepercent"): try: self.settings.setVolume(int(payload)) except ValueError: log.warn("Could not decode %s as volume percent", payload) done = True except Exception as e: log.debug("on_message Error: %s" , e) return done def run(self): self.SleepTime = float(0.1) lastplayerpos = 1 # media player position NoneCount = 0 checkmessage = 50 lastmediatitle = "" if (self.mqttbroker != None): self.mqttbroker.set_radio(self) self.publish() log.info("Player thread started") while(not self.stopping): time.sleep(self.SleepTime) try: checkmessage -= 1 if (checkmessage <= 0): checkmessage = 25 if self.playerActive(): # self.menu.backgroundRadioActive(): checkmessage = 10 try: currentplayerpos = self.player.stream_pos if (currentplayerpos > lastplayerpos) and (currentplayerpos != None): self.message = ", Radio Playing" NoneCount = 0 elif (currentplayerpos == None) or (lastplayerpos == -1): log.info("last %s, current pos %s",lastplayerpos, currentplayerpos) #, self.media.player.stream_length) self.message = ", Radio Buffering" if (lastplayerpos == 0) and (currentplayerpos == None): NoneCount += 1 else: self.message = ", Radio Paused" log.info("last %s, current pos %s ",lastplayerpos, currentplayerpos) #, self.media.player.stream_length) if self.playerPaused() == False: NoneCount += 1 lastplayerpos = currentplayerpos try: if lastmediatitle != (self.player.media_title): log.info('media_title "%s" was "%s"', self.player.media_title, lastmediatitle) lastmediatitle = str(self.player.media_title) except: #log.info("no media title") lastmediatitle = "" try: metadata = self.player.metadata for item in metadata: log.info("metadata %s", item) except: #log.debug("no metadata, %s", metadata) metadata = "" try: log.info("metadata %s", self.player.metadata[0]) except: metadata = "" except Exception as e: # stream not valid I guess log.error("Error: %s" , e) self.message = ", Radio Erroring" NoneCount += 1 #~ lastplayerpos = currentplayerpos if (NoneCount > 20): # or (currentplayerpos == None): log.info("Player may be stuck, restarting") NoneCount = 0 self.restartPlayer() # DO we need to increase the volume? if (self.increasingvolume != -1): # if we have something to play increase volume if currentplayerpos != None: self.increasingvolume += 2 if self.increasingvolume >= self.alarmThread.alarmVolume: #settings.getInt('volume'): #self.settings.setVolume(self.settings.getInt('volume')) self.settings.setVolume(self.alarmThread.alarmVolume) self.increasingvolume = -1 # At required volume log.info("Reached alarm volume level") else: self.settings.setVolume(self.increasingvolume) #try: # metadata = self.player.metadata or {} # log.info("Track %s", metadata.get('track', '')) # log.info("Comment %s", metadata.get('comment', '')) # log.info("artist %s", metadata.get('artist', '')) # log.info("album %s", metadata.get('album', '')) #except Exception as e: # stream not valid I guess # log.error("metadata error: %s" , e) else: self.message = "" except: log.exception("Error in Media loop") self.stopping = True self.message = ", Errored"
class MediaPlayer: def __init__(self, settings): self.settings = settings self.player = False self.effect = False self.spotify = None self.alarm_media = settings.get("alarm_media") if self.alarm_media == "Spotify": log.debug("Loading Spotify") self.spotify = SpotifyThread.SpotifyThread(settings) self.spotify.setDaemon(True) self.spotify.start() # #self.spotify.setDaemon(True) # # log.debug("Spotify event loop") # # self.spotify.event_loop = self.spotify.EventLoop(self.session) # # self.spotify.event_loop.start() # #self.spotify.login(settings.get("spotify_user"), settings.get("spotify_pass")) def playerActive(self): # log.debug("playerActive: {0}".format(self.player != False)) if self.alarm_media == "Spotify": if self.spotify.spotify.session.player.state == "playing": return True else: return False else: if self.player != False: return True else: return False # return self.player != False def soundAlarm(self, snoozing=False): log.info("soundAlarm: Playing alarm") if self.alarm_media == "Spotify": self.playSpotify(snoozing) else: self.playStation() log.debug("Verifying Radio is playing") # Wait a few seconds and see if the mplayer instance is still running time.sleep(self.settings.getInt("radio_delay")) # Fetch the number of mplayer processes running processes = subprocess.Popen( 'ps aux | grep mplayer | egrep -v "grep" | wc -l', stdout=subprocess.PIPE, shell=True ) num = int(processes.stdout.read()) if num < 2 and self.player is not False: log.error("Radio fail: Could not find mplayer instance, playing panic alarm") self.stopPlayer() time.sleep(2) self.playMedia(PANIC_ALARM, 0) else: log.debug("Radio success") def playSpotify(self, snoozing=False): log.debug("playSpotify: ") # self.spotify = SpotifyThread() if snoozing: log.debug("resuming") self.spotify.resume() else: log.debug("play") # play_thread = self.spotify.play() # play_thread.join() self.spotify.play() log.debug("leaving playSpotify: ") def playStation(self): log.debug("playStation: ") station = self.settings.get("station") log.info("Playing station %s", station) self.player = Player() self.player.loadlist(station) self.player.loop = 0 def playMedia(self, file, loop=-1): log.info("playMedia: Playing file %s", file) self.player = Player() self.player.loadfile(file) self.player.loop = loop # Play some speech. None-blocking equivalent of playSpeech, which also pays attention to sfx_enabled setting def playVoice(self, text): log.debug("playVoice (non-blocking): {0}".format(text)) if self.settings.get("sfx_enabled") == 0: # We've got sound effects disabled, so skip log.info("Sound effects disabled, not playing voice") return log.info("Playing voice: '%s'" % (text)) play = subprocess.Popen('../speech/googletts "%s"' % (text), shell=True) # Play some speech. Warning: Blocks until we're done speaking def playSpeech(self, text): log.debug("playSpeech (blocking): {0}".format(text)) if self.settings.get("sfx_enabled") == 0: log.info("Playing speech: '%s'" % (text)) play = subprocess.Popen('../speech/googletts "%s"' % (text), shell=True) play.wait() def stopPlayer(self): log.debug("stopPlayer: ") if self.player: self.player.quit() self.player = False log.info("Player process terminated")
class MediaPlayer: def __init__(self, settings): self.settings = settings self.player = False self.effect = False self.spotify = None self.alarm_media = settings.get("alarm_media") if self.alarm_media == 'Spotify': log.debug("Loading Spotify") self.spotify = SpotifyThread.SpotifyThread(settings) self.spotify.setDaemon(True) self.spotify.start() # #self.spotify.setDaemon(True) # # log.debug("Spotify event loop") # # self.spotify.event_loop = self.spotify.EventLoop(self.session) # # self.spotify.event_loop.start() # #self.spotify.login(settings.get("spotify_user"), settings.get("spotify_pass")) def playerActive(self): # log.debug("playerActive: {0}".format(self.player != False)) if self.alarm_media == 'Spotify': if self.spotify.spotify.session.player.state == "playing": return True else: return False else: if self.player != False: return True else: return False # return self.player != False def soundAlarm(self, snoozing=False): log.info("soundAlarm: Playing alarm") if self.alarm_media == 'Spotify': self.playSpotify(snoozing) else: self.playStation() log.debug("Verifying Radio is playing") # Wait a few seconds and see if the mplayer instance is still running time.sleep(self.settings.getInt('radio_delay')) # Fetch the number of mplayer processes running processes = subprocess.Popen( 'ps aux | grep mplayer | egrep -v "grep" | wc -l', stdout=subprocess.PIPE, shell=True) num = int(processes.stdout.read()) if num < 2 and self.player is not False: log.error( "Radio fail: Could not find mplayer instance, playing panic alarm" ) self.stopPlayer() time.sleep(2) self.playMedia(PANIC_ALARM, 0) else: log.debug("Radio success") def playSpotify(self, snoozing=False): log.debug("playSpotify: ") #self.spotify = SpotifyThread() if snoozing: log.debug("resuming") self.spotify.resume() else: log.debug("play") #play_thread = self.spotify.play() #play_thread.join() self.spotify.play() log.debug("leaving playSpotify: ") def playStation(self): log.debug("playStation: ") station = self.settings.get('station') log.info("Playing station %s", station) self.player = Player() self.player.loadlist(station) self.player.loop = 0 def playMedia(self, file, loop=-1): log.info("playMedia: Playing file %s", file) self.player = Player() self.player.loadfile(file) self.player.loop = loop # Play some speech. None-blocking equivalent of playSpeech, which also pays attention to sfx_enabled setting def playVoice(self, text): log.debug("playVoice (non-blocking): {0}".format(text)) if self.settings.get('sfx_enabled') == 0: # We've got sound effects disabled, so skip log.info("Sound effects disabled, not playing voice") return log.info("Playing voice: '%s'" % (text)) play = subprocess.Popen('../speech/googletts "%s"' % (text), shell=True) # Play some speech. Warning: Blocks until we're done speaking def playSpeech(self, text): log.debug("playSpeech (blocking): {0}".format(text)) if self.settings.get('sfx_enabled') == 0: log.info("Playing speech: '%s'" % (text)) play = subprocess.Popen('../speech/googletts "%s"' % (text), shell=True) play.wait() def stopPlayer(self): log.debug("stopPlayer: ") if self.player: self.player.quit() self.player = False log.info("Player process terminated")