class PlaybackControlSkill(MediaSkill):
    def __init__(self):
        super(PlaybackControlSkill, self).__init__('Playback Control Skill')
        logger.info('Playback Control Inited')

    def initialize(self):
        logger.info('initializing Playback Control Skill')
        super(PlaybackControlSkill, self).initialize()
        self.load_data_files(dirname(__file__))
        self.audio_service = AudioService(self.emitter)

    def handle_next(self, message):
        self.audio_service.next()

    def handle_prev(self, message):
        self.audio_service.prev()

    def handle_pause(self, message):
        self.audio_service.pause()

    def handle_play(self, message):
        """Resume playback if paused"""
        self.audio_service.resume()

    def handle_currently_playing(self, message):
        return

    def stop(self, message=None):
        logger.info("Stopping audio")
        self.emitter.emit(Message('mycroft.audio.service.stop'))
class PlaybackControlSkill(MycroftSkill):
    def __init__(self):
        super(PlaybackControlSkill, self).__init__('Playback Control Skill')

    def initialize(self):
        self.log.info('initializing Playback Control Skill')
        self.audio_service = AudioService(self.emitter)

    # Handle common audio intents.  'Audio' skills should listen for the
    # common messages:
    #   self.add_event('mycroft.audio.service.next', SKILL_HANDLER)
    #   self.add_event('mycroft.audio.service.prev', SKILL_HANDLER)
    #   self.add_event('mycroft.audio.service.pause', SKILL_HANDLER)
    #   self.add_event('mycroft.audio.service.resume', SKILL_HANDLER)

    @intent_handler(IntentBuilder('').require('Next').require("Track"))
    def handle_next(self, message):
        self.audio_service.next()

    @intent_handler(IntentBuilder('').require('Prev').require("Track"))
    def handle_prev(self, message):
        self.audio_service.prev()

    @intent_handler(IntentBuilder('').require('Pause'))
    def handle_pause(self, message):
        self.audio_service.pause()

    @intent_handler(IntentBuilder('').one_of('PlayResume', 'Resume'))
    def handle_play(self, message):
        """Resume playback if paused"""
        self.audio_service.resume()

    def stop(self, message=None):
        self.log.info("Stopping audio")
        self.emitter.emit(Message('mycroft.audio.service.stop'))
Esempio n. 3
0
class TestAudioServiceControls(TestCase):
    def assertLastMessageTypeEqual(self, bus, msg_type):
        message = bus.emit.call_args_list[-1][0][0]
        self.assertEqual(message.msg_type, msg_type)

    def setUp(self):
        self.bus = mock.Mock(name='bus')
        self.audioservice = AudioService(self.bus)

    def test_pause(self):
        self.audioservice.pause()
        self.assertLastMessageTypeEqual(self.bus,
                                        'mycroft.audio.service.pause')

    def test_resume(self):
        self.audioservice.resume()
        self.assertLastMessageTypeEqual(self.bus,
                                        'mycroft.audio.service.resume')

    def test_next(self):
        self.audioservice.next()
        self.assertLastMessageTypeEqual(self.bus, 'mycroft.audio.service.next')

    def test_prev(self):
        self.audioservice.prev()
        self.assertLastMessageTypeEqual(self.bus, 'mycroft.audio.service.prev')

    def test_stop(self):
        self.audioservice.stop()
        self.assertLastMessageTypeEqual(self.bus, 'mycroft.audio.service.stop')

    def test_seek(self):
        self.audioservice.seek()
        message = self.bus.emit.call_args_list[-1][0][0]
        self.assertEqual(message.msg_type,
                         'mycroft.audio.service.seek_forward')
        self.assertEqual(message.data['seconds'], 1)
        self.audioservice.seek(5)
        message = self.bus.emit.call_args_list[-1][0][0]
        self.assertEqual(message.msg_type,
                         'mycroft.audio.service.seek_forward')
        self.assertEqual(message.data['seconds'], 5)
        self.audioservice.seek(-5)
        message = self.bus.emit.call_args_list[-1][0][0]
        self.assertEqual(message.msg_type,
                         'mycroft.audio.service.seek_backward')
        self.assertEqual(message.data['seconds'], 5)
Esempio n. 4
0
class PlaybackControlSkill(MycroftSkill):
    def __init__(self):
        super(PlaybackControlSkill, self).__init__('Playback Control Skill')
        logger.info('Playback Control Inited')

    def initialize(self):
        logger.info('initializing Playback Control Skill')
        self.audio_service = AudioService(self.emitter)

        # Register common intents, these include basically all intents
        # except the intents to start playback (which should be implemented by
        # specific audio skills
        intent = IntentBuilder('NextIntent').require('NextKeyword')
        self.register_intent(intent, self.handle_next)

        intent = IntentBuilder('PrevIntent').require('PrevKeyword')
        self.register_intent(intent, self.handle_prev)

        intent = IntentBuilder('PauseIntent').require('PauseKeyword')
        self.register_intent(intent, self.handle_pause)

        intent = IntentBuilder('PlayIntent') \
            .one_of('PlayResumeKeyword', 'ResumeKeyword')
        self.register_intent(intent, self.handle_play)

    def handle_next(self, message):
        self.audio_service.next()

    def handle_prev(self, message):
        self.audio_service.prev()

    def handle_pause(self, message):
        self.audio_service.pause()

    def handle_play(self, message):
        """Resume playback if paused"""
        self.audio_service.resume()

    def stop(self, message=None):
        logger.info("Stopping audio")
        self.emitter.emit(Message('mycroft.audio.service.stop'))
Esempio n. 5
0
class PlaybackControlSkill(MycroftSkill):
    def __init__(self):
        super(PlaybackControlSkill, self).__init__('Playback Control Skill')
        self.query_replies = {}  # cache of received replies
        self.query_extensions = {}  # maintains query timeout extensions
        self.has_played = False
        self.lock = Lock()

    # TODO: Make this an option for voc_match()?  Only difference is the
    #       comparison using "==" instead of "in"
    def voc_match_exact(self, utt, voc_filename, lang=None):
        """ Determine if the given utterance contains the vocabulary provided

        Checks for vocabulary match in the utterance instead of the other
        way around to allow the user to say things like "yes, please" and
        still match against "Yes.voc" containing only "yes". The method first
        checks in the current skill's .voc files and secondly the "res/text"
        folder of mycroft-core. The result is cached to avoid hitting the
        disk each time the method is called.

        Args:
            utt (str): Utterance to be tested
            voc_filename (str): Name of vocabulary file (e.g. 'yes' for
                                'res/text/en-us/yes.voc')
            lang (str): Language code, defaults to self.long

        Returns:
            bool: True if the utterance has the given vocabulary it
        """
        lang = lang or self.lang
        cache_key = lang + voc_filename

        if cache_key not in self.voc_match_cache:
            # Check for both skill resources and mycroft-core resources
            voc = self.find_resource(voc_filename + '.voc', 'vocab')
            if not voc:
                voc = self.resolve_resource_file(
                    join('text', lang, voc_filename + '.voc'))

            if not voc or not exists(voc):
                raise FileNotFoundError(
                    'Could not find {}.voc file'.format(voc_filename))

            with open(voc) as f:
                self.voc_match_cache[cache_key] = f.read().splitlines()

        # Check for exact match
        if utt and any(i.strip() == utt
                       for i in self.voc_match_cache[cache_key]):
            return True
        return False

    def initialize(self):
        self.audio_service = AudioService(self.bus)
        self.add_event('play:query.response', self.handle_play_query_response)
        self.add_event('play:status', self.handle_song_info)
        self.gui.register_handler('next', self.handle_next)
        self.gui.register_handler('prev', self.handle_prev)

        self.clear_gui_info()

    # Handle common audio intents.  'Audio' skills should listen for the
    # common messages:
    #   self.add_event('mycroft.audio.service.next', SKILL_HANDLER)
    #   self.add_event('mycroft.audio.service.prev', SKILL_HANDLER)
    #   self.add_event('mycroft.audio.service.pause', SKILL_HANDLER)
    #   self.add_event('mycroft.audio.service.resume', SKILL_HANDLER)

    def clear_gui_info(self):
        """Clear the gui variable list."""
        # Initialize track info variables
        for k in STATUS_KEYS:
            self.gui[k] = ''

    @intent_handler(IntentBuilder('').require('Next').require("Track"))
    def handle_next(self, message):
        self.audio_service.next()

    @intent_handler(IntentBuilder('').require('Prev').require("Track"))
    def handle_prev(self, message):
        self.audio_service.prev()

    @intent_handler(IntentBuilder('').require('Pause'))
    def handle_pause(self, message):
        self.audio_service.pause()

    @intent_handler(IntentBuilder('').one_of('PlayResume', 'Resume'))
    def handle_play(self, message):
        """Resume playback if paused"""
        self.audio_service.resume()

    def stop(self, message=None):
        self.clear_gui_info()

        self.log.info('Audio service status: '
                      '{}'.format(self.audio_service.track_info()))
        if self.audio_service.is_playing:
            self.audio_service.stop()
            return True
        else:
            return False

    def converse(self, utterances, lang="en-us"):
        if (utterances and self.has_played
                and self.voc_match_exact(utterances[0], "converse_resume")):
            # NOTE:  voc_match() will overmatch (e.g. it'll catch "play next
            #        song" or "play Some Artist")
            self.audio_service.resume()
            return True
        else:
            return False

    @intent_handler(IntentBuilder('').require('Play').require('Phrase'))
    def play(self, message):
        self.speak_dialog("just.one.moment")

        # Remove everything up to and including "Play"
        # NOTE: This requires a Play.voc which holds any synomyms for 'Play'
        #       and a .rx that contains each of those synonyms.  E.g.
        #  Play.voc
        #      play
        #      bork
        #  phrase.rx
        #      play (?P<Phrase>.*)
        #      bork (?P<Phrase>.*)
        # This really just hacks around limitations of the Adapt regex system,
        # which will only return the first word of the target phrase
        utt = message.data.get('utterance')
        phrase = re.sub('^.*?' + message.data['Play'], '', utt).strip()
        self.log.info("Resolving Player for: " + phrase)
        wait_while_speaking()
        self.enclosure.mouth_think()

        # Now we place a query on the messsagebus for anyone who wants to
        # attempt to service a 'play.request' message.  E.g.:
        #   {
        #      "type": "play.query",
        #      "phrase": "the news" / "tom waits" / "madonna on Pandora"
        #   }
        #
        # One or more skills can reply with a 'play.request.reply', e.g.:
        #   {
        #      "type": "play.request.response",
        #      "target": "the news",
        #      "skill_id": "<self.skill_id>",
        #      "conf": "0.7",
        #      "callback_data": "<optional data>"
        #   }
        # This means the skill has a 70% confidence they can handle that
        # request.  The "callback_data" is optional, but can provide data
        # that eliminates the need to re-parse if this reply is chosen.
        #
        self.query_replies[phrase] = []
        self.query_extensions[phrase] = []
        self.bus.emit(message.forward('play:query', data={"phrase": phrase}))

        self.schedule_event(self._play_query_timeout,
                            1,
                            data={"phrase": phrase},
                            name='PlayQueryTimeout')

    def handle_play_query_response(self, message):
        with self.lock:
            search_phrase = message.data["phrase"]

            if ("searching" in message.data
                    and search_phrase in self.query_extensions):
                # Manage requests for time to complete searches
                skill_id = message.data["skill_id"]
                if message.data["searching"]:
                    # extend the timeout by 5 seconds
                    self.cancel_scheduled_event("PlayQueryTimeout")
                    self.schedule_event(self._play_query_timeout,
                                        5,
                                        data={"phrase": search_phrase},
                                        name='PlayQueryTimeout')

                    # TODO: Perhaps block multiple extensions?
                    if skill_id not in self.query_extensions[search_phrase]:
                        self.query_extensions[search_phrase].append(skill_id)
                else:
                    # Search complete, don't wait on this skill any longer
                    if skill_id in self.query_extensions[search_phrase]:
                        self.query_extensions[search_phrase].remove(skill_id)
                        if not self.query_extensions[search_phrase]:
                            self.cancel_scheduled_event("PlayQueryTimeout")
                            self.schedule_event(self._play_query_timeout,
                                                0,
                                                data={"phrase": search_phrase},
                                                name='PlayQueryTimeout')

            elif search_phrase in self.query_replies:
                # Collect all replies until the timeout
                self.query_replies[message.data["phrase"]].append(message.data)

    def _play_query_timeout(self, message):
        with self.lock:
            # Prevent any late-comers from retriggering this query handler
            search_phrase = message.data["phrase"]
            self.query_extensions[search_phrase] = []
            self.enclosure.mouth_reset()

            # Look at any replies that arrived before the timeout
            # Find response(s) with the highest confidence
            best = None
            ties = []
            self.log.debug("CommonPlay Resolution: {}".format(search_phrase))
            for handler in self.query_replies[search_phrase]:
                self.log.debug("    {} using {}".format(
                    handler["conf"], handler["skill_id"]))
                if not best or handler["conf"] > best["conf"]:
                    best = handler
                    ties = []
                elif handler["conf"] == best["conf"]:
                    ties.append(handler)

            if best:
                if ties:
                    # TODO: Ask user to pick between ties or do it
                    # automagically
                    pass

                # invoke best match
                self.gui.show_page("controls.qml", override_idle=True)
                self.log.info("Playing with: {}".format(best["skill_id"]))
                start_data = {
                    "skill_id": best["skill_id"],
                    "phrase": search_phrase,
                    "callback_data": best.get("callback_data")
                }
                self.bus.emit(message.forward('play:start', start_data))
                self.has_played = True
            elif self.voc_match(search_phrase, "Music"):
                self.speak_dialog("setup.hints")
            else:
                self.log.info("   No matches")
                self.speak_dialog("cant.play", data={"phrase": search_phrase})

            if search_phrase in self.query_replies:
                del self.query_replies[search_phrase]
            if search_phrase in self.query_extensions:
                del self.query_extensions[search_phrase]

    def handle_song_info(self, message):
        changed = False
        for key in STATUS_KEYS:
            val = message.data.get(key, '')
            changed = changed or self.gui[key] != val
            self.gui[key] = val

        if changed:
            self.log.info('\n-->Track: {}\n-->Artist: {}\n-->Image: {}'
                          ''.format(self.gui['track'], self.gui['artist'],
                                    self.gui['image']))
Esempio n. 6
0
class Deezer(CommonPlaySkill):
    def __init__(self):
        super(Deezer, self).__init__()
        self.regexes = {}
        self.playlist_data = None
        self.playing_wait_thread = None
        self.playing_thread = None
        self.playlist_playing_index = Value('i', -1)
        self.playing_seconds = Value('i', -1)

    def initialize(self):
        super().initialize()
        self.audio_service = AudioService(self.bus)
        self.add_event('mycroft.audio.service.next', self.next_track)
        self.add_event('mycroft.audio.service.prev', self.prev_track)
        self.add_event('mycroft.audio.service.pause', self.pause)
        self.add_event('mycroft.audio.service.resume', self.resume)
        self.arl = self.settings.get('arl')
        # TODO directory should probably default to self.file_system.path
        # This is a unique directory for each Skill.
        # There's also mycroft.util.get_cache_directory if you intend it to be temporary
        self.music_dir = self.settings.get('music_dir', self.file_system.path)
        self.track_directory = os.path.join(self.music_dir, "track")

    def CPS_match_query_phrase(self, phrase):
        self.log.info(f"Check Query Phrase: {phrase}")

        phrase, cps_match_level, data = self.specific_query(phrase=phrase)
        if cps_match_level is None:
            track = deezer_utils.search_first_track(track_name=phrase,
                                                    arl=self.arl)
            if track is None:
                return None
            else:
                track_id = track.get('id')
                self.speak_dialog(key="track_found",
                                  data={
                                      'title_short': track["title_short"],
                                      'artist': track['artist']['name']
                                  })
                download_path = deezer_utils.download_track(
                    track_id=track_id,
                    track_directory=self.track_directory,
                    arl=self.arl)
                data = {
                    "type": 0,
                    "track": download_path,
                    "track_id": track_id
                }
                if 'deezer' in phrase:
                    cps_match_level = CPSMatchLevel.EXACT
                else:
                    cps_match_level = CPSMatchLevel.TITLE

        return phrase, cps_match_level, data

    """ This method responds wether the skill can play the input phrase.

        The method is invoked by the PlayBackControlSkill.

        Returns: tuple (matched phrase(str),
                        match level(CPSMatchLevel),
                        optional data(dict))
                 or None if no match was found.
    """

    def CPS_start(self, phrase, data):
        if self.playing_thread is not None:
            self.playing_thread.kill()
            self.playing_thread = None
        if self.playlist_data is not None:
            self.playlist_data = None
        if self.playlist_playing_index.value is not None:
            self.playlist_playing_index.value = -1

        if data['type'] == 0:
            self.log.info("TrackType is Track")
            self.CPS_play(data['track'])
        elif data['type'] == 1:
            self.log.info("TrackType is Playlist")
            playlist = data['playlist']
            self.playlist_data = data
            playlist_search_results = data['playlist_search_results']
            track_directory = os.path.join(self.music_dir,
                                           str(playlist_search_results['id']))
            self.playing_thread = Process(target=self.playing_playlist,
                                          args=(playlist, track_directory, 0,
                                                -1))
            self.playing_thread.start()
            self.playing_thread.join()
            shutil.rmtree(track_directory, ignore_errors=True)

    """ Starts playback.
    
        Called by the playback control skill to start playback if the
        skill is selected (has the best match level)
    """

    def specific_query(self, phrase):
        # Check if saved
        # match = re.match(self.translate_regex('saved_songs'), phrase)
        # if match and self.saved_tracks:
        #     return (1.0, {'data': None,
        #                   'type': 'saved_tracks'})

        # Check if playlist
        phrase = phrase.lower()
        match = re.match(self.translate_regex('playlist'), phrase)
        if match:
            playlist_search_results = deezer_utils.search_first_playlist(
                match.groupdict()['playlist'], self.arl)
            if playlist_search_results:
                tracklist = requests.get(
                    playlist_search_results['tracklist']).json()
                try:
                    data = tracklist["data"]
                    next_tracklist_url = tracklist['next']
                    try:
                        while True:
                            next_tracklist = requests.get(
                                next_tracklist_url).json()
                            data += next_tracklist['data']
                            next_tracklist_url = next_tracklist['next']
                            self.log.info(next_tracklist_url)
                    except KeyError as index:
                        pass
                except KeyError as dataError:
                    pass
                return_data = {
                    'type': 1,
                    'playlist': data,
                    'playlist_search_results': playlist_search_results
                }
                return phrase, CPSMatchLevel.TITLE, return_data
            else:
                return phrase, CPSMatchLevel.GENERIC, None
        # Check album
        # match = re.match(self.translate_regex('album'), phrase)
        # if match:
        #     album = match.groupdict()['album']
        #     return self.query_album(album)
        #
        # # Check artist
        # match = re.match(self.translate_regex('artist'), phrase)
        # if match:
        #     artist = match.groupdict()['artist']
        #     return self.query_artist(artist)
        # match = re.match(self.translate_regex('song'), phrase)
        # if match:
        #     song = match.groupdict()['track']
        #     return self.query_song(song)

        return phrase, None, None

    def playing_playlist(self, playlist, track_directory, start_index, seek):
        for i in range(start_index, len(playlist)):
            try:
                self.playlist_playing_index.value = i
                track_id = playlist[i]['id']
                downloaded_track = deezer_utils.download_track(
                    track_id=track_id,
                    track_directory=track_directory,
                    arl=self.arl)

                self.log.info(str(downloaded_track))
                if seek > -1:
                    self.audio_service.seek(seconds=seek)
                    self.audio_service.resume()
                else:
                    self.CPS_play(downloaded_track)
                self.log.info("Playing now ...")
                duration = playlist[i]['duration']
                for d in range(0, duration):
                    self.playing_seconds.value = d
                    time.sleep(1)

                shutil.rmtree(downloaded_track, ignore_errors=True)
            except Exception as e:
                print(e)
                self.log.error(e)

    def next_track(self):
        if self.playlist_data is not None:
            if self.playing_thread is not None:
                self.playing_thread.kill()
                self.playing_thread = None
            playlist_search_results = self.playlist_data[
                'playlist_search_results']
            track_directory = os.path.join(self.music_dir,
                                           str(playlist_search_results['id']))
            if self.playlist_playing_index.value + 1 >= len(
                    self.playlist_data['playlist']):
                self.speak_dialog(
                    key='playlist.end',
                    data={
                        'title':
                        self.playlist_data['playlist_search_results']['title']
                    })
                self.playlist_data = None
                self.playlist_playing_index.value = -1
                shutil.rmtree(track_directory)
                return
            self.playing_thread = Process(
                target=self.playing_playlist,
                args=(self.playlist_data['playlist'], track_directory,
                      self.playlist_playing_index.value + 1, -1))
            self.playing_thread.start()
            self.playing_thread.join()

    def prev_track(self):
        if self.playlist_data is not None:
            if self.playing_thread is not None:
                self.playing_thread.kill()
                self.playing_thread = None
            playlist_search_results = self.playlist_data[
                'playlist_search_results']
            track_directory = os.path.join(self.music_dir,
                                           str(playlist_search_results['id']))
            if self.playlist_playing_index.value + 1 >= len(
                    self.playlist_data['playlist']):
                self.speak_dialog(
                    key='playlist.end',
                    data={
                        'title':
                        self.playlist_data['playlist_search_results']['title']
                    })
                self.playlist_data = None
                self.playlist_playing_index.value = -1
                shutil.rmtree(track_directory)
                return
            index = self.playlist_playing_index.value - 1
            if index < 0:
                index = index + 1

            self.playing_thread = Process(target=self.playing_playlist,
                                          args=(self.playlist_data['playlist'],
                                                track_directory, index, -1))
            self.playing_thread.start()
            self.playing_thread.join()

    def pause(self):
        if self.playlist_data is not None:
            if self.playing_thread is not None:
                self.playing_thread.kill()
                self.playing_thread = None

            self.audio_service.pause()

    def resume(self):
        if self.playlist_data is not None:
            if self.playing_thread is not None:
                self.playing_thread.kill()
                self.playing_thread = None
            playlist_search_results = self.playlist_data[
                'playlist_search_results']
            track_directory = os.path.join(self.music_dir,
                                           str(playlist_search_results['id']))

            self.playing_thread = Process(
                target=self.playing_playlist,
                args=(self.playlist_data['playlist'], track_directory,
                      self.playlist_playing_index.value,
                      self.playing_seconds.value))
            self.playing_thread.start()
            self.playing_thread.join()
        pass

    def translate_regex(self, regex):
        if regex not in self.regexes:
            path = self.find_resource(regex + '.regex')
            if path:
                with open(path) as f:
                    string = f.read().strip()
                self.regexes[regex] = string
        return self.regexes[regex]

    @intent_handler('user.intent')
    def speak_user_name(self, message):
        self.log.info("Username Intent")
        self.speak_dialog(
            key='user',
            data={'user_name': deezer_utils.get_user_info(arl=self.arl)})
Esempio n. 7
0
class Mediaplayer(CommonPlaySkill):
    def __init__(self):
        #MycroftSkill.__init__(self)
        super().__init__(name="Mediaplayer")

    def initialize(self):
        super().initialize()
        self.playlists = []
        self.vlc_all_tracks = []
        self.vlc_all_tracks_info = []
        self.audio_service = AudioService(self.bus)
        self.vlc_audio_path = Path(str(self.settings.get('vlc_audio_path')))
        self.current_track = []
        self.track_change_request_in_progress = False
        #self.add_event("")
        self.register_all_intents()

    def register_all_intents(self):
        #self.register_intent_file('mediaplayer.next.intent', self.handle_mediaplayer_next)
        #self.register_intent_file('mediaplayer.prev.intent', self.handle_mediaplayer_prev)
        #self.register_intent_file('mediaplayer.stop.intent', self.handle_mediaplayer_stop)
        #self.register_intent_file('mediaplayer.pause.intent', self.handle_mediaplayer_pause)
        #self.register_intent_file('mediaplayer.resume.intent', self.handle_mediaplayer_resume)
        #self.register_intent_file('mediaplayer.info.intent', self.handle_mediaplayer_info)
        pass

    def enable_play_control_intents(self):
        self.enable_intent("mediaplayer.next.intent")
        self.enable_intent("mediaplayer.prev.intent")
        self.enable_intent("mediaplayer.stop.intent")
        self.enable_intent("mediaplayer.pause.intent")
        self.enable_intent("mediaplayer.resume.intent")

    def disable_play_controls(self):
        self.disable_intent("mediaplayer.next.intent")
        self.disable_intent("mediaplayer.prev.intent")
        self.disable_intent("mediaplayer.stop.intent")
        self.disable_intent("mediaplayer.pause.intent")
        self.disable_intent("mediaplayer.resume.intent")

    def handle_mediaplayer_info(self, message):
        self.speak_dialog('mediaplayer')
        self.speak("looking for backends.")
        for backend in self.audio_service.available_backends().keys():
            backend_text = "found " + str(backend)
            self.speak(backend_text)

    def handle_mediaplayer_next(self, message):
        if self.audio_service.is_playing:
            if not self.is_track_change_request_in_progress():
                self.play_next(message)
        else:
            self.speak("Nothing playing")

    def handle_mediaplayer_prev(self, message):
        if self.audio_service.is_playing:
            self.play_prev(message)
        else:
            self.speak("Nothing playing")

    def handle_mediaplayer_stop(self, message):
        if self.audio_service.is_playing:
            self.play_stop(message)
        else:
            self.speak("Nothing playing")

    def handle_mediaplayer_pause(self, message):
        self.speak("pause")
        self.play_pause(message)

    def handle_mediaplayer_resume(self, message):
        self.speak("resume")
        pass

    # @intent_handler('mediaplayer.play.intent')
    # def handle_mediaplayer_play(self, message):
    #     if not self.is_playing:
    #         self.play(message)
    #     else:
    #         self.speak("Already playing")

    def load_files_in_audio_path(self, path):
        tracks = []

        for dirpath, dirnames, filenames in os.walk(path):
            for file in filenames:
                track_path = Path(dirpath)
                track_path = track_path / file
                track_uri = 'file://' + str(track_path.resolve())
                track_data = (track_uri)
                tracks.append(track_data)
        return tracks

    def init_vlc_audio_list(self):
        self.vlc_all_tracks = self.load_files_in_audio_path(
            self.vlc_audio_path)
        # for track in self.vlc_all_tracks:
        #     self.audio_service.play(track)
        #     self.vlc_all_tracks_info.append([ track, self.audio_service.track_info()])
        #     self.audio_service.pause()

        #self.queue_tracks(self.vlc_all_tracks)
        self.current_track = []

    def get_vlc_track_info(self):
        pass

    def queue_tracks(self, tracks):
        self.audio_service.queue(tracks)

    def add_track_to_list(self, track, list):
        pass

    def add_tracks_to_list(self, tracks, list):
        pass

    def play(self, message):

        if not self.audio_service.is_playing:
            if not self.vlc_all_tracks:
                self.init_vlc_audio_list()
                self.audio_service.play(self.vlc_all_tracks, 'vlc')
                self.set_init_track()
            else:
                self.audio_service.play(self.vlc_all_tracks, 'vlc')
                self.set_init_track()
            #self.audio_service.play(self.audio_service.)
            #self.audio_service.play(self.vlc_all_tracks, 'vlc')
        pass

    def play_next(self, message):

        if self.audio_service.is_playing:
            self.audio_service.next()
            #if not self.is_track_change_request_in_progress():
            #    self.start_track_change_request()
            #    self.audio_service.next()
        pass

    def play_prev(self, message):
        pass

    def play_random(self, message):
        pass

    def play_resume(self, message):
        if self.audio_service.is_playing:
            self.audio_service.resume()

    def play_stop(self, message):
        if self.audio_service.is_playing:
            self.audio_service.pause()

    def play_pause(self, message):
        if self.audio_service.is_playing:
            self.audio_service.pause()

    def track_info(self, message):
        return self.audio_service.track_info()

    def track_info_reply(self, message):
        self.speak("request: track_info_reply")
        #return self.audio_service.track_info()

    def queue_track(self, message):
        self.speak("event: queue_track")
        pass

    def set_init_track(self):
        self.current_track = self.audio_service.track_info()

    def is_track_change_request_in_progress(self):
        if self.track_change_request_in_progress == True:
            if self.current_track != self.audio_service.track_info():
                self.complete_track_change_request()

        return self.track_change_request_in_progress

    def start_track_change_request(self):
        self.track_change_request_in_progress = True

    def complete_track_change_request(self):
        self.current_track = self.audio_service.track_info()
        self.track_change_request_in_progress = False

    def CPS_match_query_phrase(self, phrase):
        self.speak("phrase : " + str(phrase))

        if self.voc_match(phrase, "mediaplayer"):
            level = CPSMatchLevel.GENERIC
            phrase = "mediaplayer"
        else:
            level = CPSMatchLevel.GENERIC
        return (phrase, level)

    def CPS_start(self, phrase, data):
        data = {
            "phrase": phrase,
            "skill_id": self.skill_id,
            "service_name": self.spoken_name,
        }
        self.play(phrase)
        pass

    def CPS_send_status(self, artist='', track='', image=''):
        data = {
            'skill': self.name,
            'artist': artist,
            'track': track,
            'image': image,
            'status': None  # TODO Add status system
        }
        self.bus.emit(Message('play:status', data))