Пример #1
0
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")
Пример #2
0
def playTheme(fileName):
	output('speaker',1)
	player = Player()
	player.loadfile(fileName)
	# Terminate MPlayer
	player.quit()	
	output('speaker',0)
Пример #3
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()
Пример #4
0
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()
Пример #5
0
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()
Пример #6
0
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()
Пример #7
0
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")
Пример #8
0
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")
Пример #9
0
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
Пример #10
0
	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)
Пример #11
0
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()
Пример #12
0
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()
Пример #13
0
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()
Пример #14
0
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"
Пример #15
0
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")
Пример #16
0
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")