From d378caee59df005e94ba6f891976ceb64c2a48d2 Mon Sep 17 00:00:00 2001 From: schneefux Date: Tue, 30 Sep 2014 20:14:17 +0200 Subject: Remove music mode --- client/conversation.py | 33 +----- client/music.py | 261 ------------------------------------------------ client/musicmode.py | 183 --------------------------------- client/vocabcompiler.py | 2 - 4 files changed, 1 insertion(+), 478 deletions(-) delete mode 100644 client/music.py delete mode 100644 client/musicmode.py diff --git a/client/conversation.py b/client/conversation.py index 0746b7f..9b86295 100644 --- a/client/conversation.py +++ b/client/conversation.py @@ -1,10 +1,7 @@ # -*- coding: utf-8-*- import logging from notifier import Notifier -from musicmode import * from brain import Brain -from mpd import MPDClient - class Conversation(object): @@ -16,34 +13,6 @@ class Conversation(object): self.brain = Brain(mic, profile) self.notifier = Notifier(profile) - def delegateInput(self, texts): - """A wrapper for querying brain.""" - - # check if input is meant to start the music module - for text in texts: - if any(x in text.upper() for x in ["SPOTIFY", "MUSIC"]): - self._logger.debug("Preparing to start music module") - # check if mpd client is running - try: - client = MPDClient() - client.timeout = None - client.idletimeout = None - client.connect("localhost", 6600) - except: - self._logger.critical("Can't connect to mpd client, cannot start music mode.", exc_info=True) - self.mic.say( - "I'm sorry. It seems that Spotify is not enabled. Please read the documentation to learn how to configure Spotify.") - return - - self.mic.say("Please give me a moment, I'm loading your Spotify playlists.") - self._logger.debug("Starting music mode") - music_mode = MusicMode(self.persona, self.mic) - music_mode.handleForever() - self._logger.debug("Exiting music mode") - return - - self.brain.query(texts) - def handleForever(self): """Delegates user input to the handling function when activated.""" self._logger.info("Starting to handle conversation with keyword '%s'.", self.persona) @@ -67,6 +36,6 @@ class Conversation(object): self._logger.debug("Stopped to listen actively with threshold: %r", threshold) if input: - self.delegateInput(input) + self.brain.query(input) else: self.mic.say("Pardon?") diff --git a/client/music.py b/client/music.py deleted file mode 100644 index ca9b776..0000000 --- a/client/music.py +++ /dev/null @@ -1,261 +0,0 @@ -# -*- coding: utf-8-*- -import re -import difflib -from mpd import MPDClient - - -def reconnect(func, *default_args, **default_kwargs): - """ - Reconnects before running - """ - - def wrap(self, *default_args, **default_kwargs): - try: - self.client.connect("localhost", 6600) - except: - pass - - # sometimes not enough to just connect - try: - return func(self, *default_args, **default_kwargs) - except: - self.client = MPDClient() - self.client.timeout = None - self.client.idletimeout = None - self.client.connect("localhost", 6600) - - return func(self, *default_args, **default_kwargs) - - return wrap - - -class Song: - - def __init__(self, id, title, artist, album): - - self.id = id - self.title = title - self.artist = artist - self.album = album - - -class Music: - - client = None - songs = [] # may have duplicates - playlists = [] - - # capitalized strings - song_titles = [] - song_artists = [] - - def __init__(self): - """ - Prepare the client and music variables - """ - # prepare client - self.client = MPDClient() - self.client.timeout = None - self.client.idletimeout = None - self.client.connect("localhost", 6600) - - # gather playlists - self.playlists = [x["playlist"] for x in self.client.listplaylists()] - - # gather songs - self.client.clear() - for playlist in self.playlists: - self.client.load(playlist) - - soup = self.client.playlist() - for i in range(0, len(soup) / 10): - index = i * 10 - id = soup[index].strip() - title = soup[index + 3].strip().upper() - artist = soup[index + 2].strip().upper() - album = soup[index + 4].strip().upper() - - self.songs.append(Song(id, title, artist, album)) - - self.song_titles.append(title) - self.song_artists.append(artist) - - @reconnect - def play(self, songs=False, playlist_name=False): - """ - Plays the current song or accepts a song to play. - - Arguments: - songs -- a list of song objects - playlist_name -- user-defined, something like "Love Song Playlist" - """ - if songs: - self.client.clear() - for song in songs: - try: # for some reason, certain ids don't work - self.client.add(song.id) - except: - pass - - if playlist_name: - self.client.clear() - self.client.load(playlist_name) - - self.client.play() - - @reconnect - def current_song(self): - item = self.client.playlistinfo(int(self.client.status()["song"]))[0] - result = "%s by %s" % (item["title"], item["artist"]) - return result - - @reconnect - def volume(self, level=None, interval=None): - - if level: - self.client.setvol(int(level)) - return - - if interval: - level = int(self.client.status()['volume']) + int(interval) - self.client.setvol(int(level)) - return - - @reconnect - def pause(self): - self.client.pause() - - @reconnect - def stop(self): - self.client.stop() - - @reconnect - def next(self): - self.client.next() - return - - @reconnect - def previous(self): - self.client.previous() - return - - def get_soup(self): - """ - returns the list of unique words that comprise song and artist titles - """ - - soup = [] - - for song in self.songs: - song_words = song.title.split(" ") - artist_words = song.artist.split(" ") - soup.extend(song_words) - soup.extend(artist_words) - - title_trans = ''.join( - chr(c) if chr(c).isupper() or chr(c).islower() else '_' for c in range(256)) - soup = [x.decode('utf-8').encode("ascii", "ignore").upper().translate(title_trans).replace("_", "") - for x in soup] - soup = [x for x in soup if x != ""] - - return list(set(soup)) - - def get_soup_playlist(self): - """ - returns the list of unique words that comprise playlist names - """ - - soup = [] - - for name in self.playlists: - soup.extend(name.split(" ")) - - title_trans = ''.join( - chr(c) if chr(c).isupper() or chr(c).islower() else '_' for c in range(256)) - soup = [x.decode('utf-8').encode("ascii", "ignore").upper().translate(title_trans).replace("_", "") - for x in soup] - soup = [x for x in soup if x != ""] - - return list(set(soup)) - - def get_soup_separated(self): - """ - returns the list of PHRASES that comprise song and artist titles - """ - - title_soup = [song.title for song in self.songs] - artist_soup = [song.artist for song in self.songs] - - soup = list(set(title_soup + artist_soup)) - - title_trans = ''.join( - chr(c) if chr(c).isupper() or chr(c).islower() else '_' for c in range(256)) - soup = [x.decode('utf-8').encode("ascii", "ignore").upper().translate(title_trans).replace("_", " ") - for x in soup] - soup = [re.sub(' +', ' ', x) for x in soup if x != ""] - - return soup - - def fuzzy_songs(self, query): - """ - Returns songs matching a query best as possible on either artist field, etc - """ - - query = query.upper() - - matched_song_titles = difflib.get_close_matches( - query, self.song_titles) - matched_song_artists = difflib.get_close_matches( - query, self.song_artists) - - # if query is beautifully matched, then forget about everything else - strict_priority_title = [x for x in matched_song_titles if x == query] - strict_priority_artists = [ - x for x in matched_song_artists if x == query] - - if strict_priority_title: - matched_song_titles = strict_priority_title - if strict_priority_artists: - matched_song_artists = strict_priority_artists - - matched_songs_bytitle = [ - song for song in self.songs if song.title in matched_song_titles] - matched_songs_byartist = [ - song for song in self.songs if song.artist in matched_song_artists] - - matches = list(set(matched_songs_bytitle + matched_songs_byartist)) - - return matches - - def fuzzy_playlists(self, query): - """ - returns playlist names that match query best as possible - """ - query = query.upper() - lookup = {n.upper(): n for n in self.playlists} - results = [lookup[r] for r in difflib.get_close_matches(query, lookup)] - return results - -if __name__ == "__main__": - """ - Plays music and performs unit-testing - """ - - print "Creating client" - - music = Music() - - print "Playing" - - music.play(songs=[music.songs[3]]) - - print music.get_soup_separated() - - while True: - query = raw_input("Query: ") - songs = music.fuzzy_songs(query) - print "Results" - print "=======" - for song in songs: - print "Title: %s Artist: %s" % (song.title, song.artist) - music.play(songs=songs) diff --git a/client/musicmode.py b/client/musicmode.py deleted file mode 100644 index 900c4f1..0000000 --- a/client/musicmode.py +++ /dev/null @@ -1,183 +0,0 @@ -# -*- coding: utf-8-*- -""" - Manages the conversation -""" - -import os -from mic import Mic -import g2p -from music import * -import stt - - -class MusicMode: - - def __init__(self, PERSONA, mic): - self.persona = PERSONA - # self.mic - we're actually going to ignore the mic they passed in - self.music = Music() - - # index spotify playlists into new dictionary and language models - original = self.music.get_soup_playlist( - ) + ["STOP", "CLOSE", "PLAY", "PAUSE", - "NEXT", "PREVIOUS", "LOUDER", "SOFTER", "LOWER", "HIGHER", "VOLUME", "PLAYLIST"] - pronounced = g2p.translateWords(original) - zipped = zip(original, pronounced) - lines = ["%s %s" % (x, y) for x, y in zipped] - - with open("dictionary_spotify.dic", "w") as f: - f.write("\n".join(lines) + "\n") - - with open("sentences_spotify.txt", "w") as f: - f.write("\n".join(original) + "\n") - f.write(" \n \n") - f.close() - - # make language model - os.system( - "text2idngram -vocab sentences_spotify.txt < sentences_spotify.txt -idngram spotify.idngram") - os.system( - "idngram2lm -idngram spotify.idngram -vocab sentences_spotify.txt -arpa languagemodel_spotify.lm") - - # create a new mic with the new music models - self.mic = Mic( - mic.speaker, - stt.PocketSphinxSTT(lmd_music="languagemodel_spotify.lm", dictd_music="dictionary_spotify.dic"), - stt.PocketSphinxSTT(lmd_music="languagemodel_spotify.lm", dictd_music="dictionary_spotify.dic") - ) - - def delegateInput(self, input): - - command = input.upper() - - # check if input is meant to start the music module - if "PLAYLIST" in command: - command = command.replace("PLAYLIST", "") - elif "STOP" in command: - self.mic.say("Stopping music") - self.music.stop() - return - elif "PLAY" in command: - self.mic.say("Playing %s" % self.music.current_song()) - self.music.play() - return - elif "PAUSE" in command: - self.mic.say("Pausing music") - # not pause because would need a way to keep track of pause/play - # state - self.music.stop() - return - elif any(ext in command for ext in ["LOUDER", "HIGHER"]): - self.mic.say("Louder") - self.music.volume(interval=10) - self.music.play() - return - elif any(ext in command for ext in ["SOFTER", "LOWER"]): - self.mic.say("Softer") - self.music.volume(interval=-10) - self.music.play() - return - elif "NEXT" in command: - self.mic.say("Next song") - self.music.play() # backwards necessary to get mopidy to work - self.music.next() - self.mic.say("Playing %s" % self.music.current_song()) - return - elif "PREVIOUS" in command: - self.mic.say("Previous song") - self.music.play() # backwards necessary to get mopidy to work - self.music.previous() - self.mic.say("Playing %s" % self.music.current_song()) - return - - # SONG SELECTION... requires long-loading dictionary and language model - # songs = self.music.fuzzy_songs(query = command.replace("PLAY", "")) - # if songs: - # self.mic.say("Found songs") - # self.music.play(songs = songs) - - # print "SONG RESULTS" - # print "============" - # for song in songs: - # print "Song: %s Artist: %s" % (song.title, song.artist) - - # self.mic.say("Playing %s" % self.music.current_song()) - - # else: - # self.mic.say("No songs found. Resuming current song.") - # self.music.play() - - # PLAYLIST SELECTION - playlists = self.music.fuzzy_playlists(query=command) - if playlists: - self.mic.say("Loading playlist %s" % playlists[0]) - self.music.play(playlist_name=playlists[0]) - self.mic.say("Playing %s" % self.music.current_song()) - else: - self.mic.say("No playlists found. Resuming current song.") - self.music.play() - - return - - def handleForever(self): - - self.music.play() - self.mic.say("Playing %s" % self.music.current_song()) - - while True: - - try: - threshold, transcribed = self.mic.passiveListen(self.persona) - except: - continue - - if threshold: - - self.music.pause() - - input = self.mic.activeListen(MUSIC=True) - - if "close" in input.lower(): - self.mic.say("Closing Spotify") - return - - if input: - self.delegateInput(input) - else: - self.mic.say("Pardon?") - self.music.play() - -if __name__ == "__main__": - """ - Indexes the Spotify music library to dictionary_spotify.dic and languagemodel_spotify.lm - """ - - musicmode = MusicMode("JASPER", None) - music = musicmode.music - - original = music.get_soup() + ["STOP", "CLOSE", "PLAY", - "PAUSE", "NEXT", "PREVIOUS", "LOUDER", "SOFTER"] - pronounced = g2p.translateWords(original) - zipped = zip(original, pronounced) - lines = ["%s %s" % (x, y) for x, y in zipped] - - with open("dictionary_spotify.dic", "w") as f: - f.write("\n".join(lines) + "\n") - - with open("sentences_spotify.txt", "w") as f: - f.write("\n".join(original) + "\n") - f.write(" \n \n") - f.close() - - with open("sentences_spotify_separated.txt", "w") as f: - f.write("\n".join(music.get_soup_separated()) + "\n") - f.write(" \n \n") - f.close() - - # make language model - os.system( - "text2idngram -vocab sentences_spotify.txt < sentences_spotify_separated.txt -idngram spotify.idngram") - os.system( - "idngram2lm -idngram spotify.idngram -vocab sentences_spotify.txt -arpa languagemodel_spotify.lm") - - print "Language Model and Dictionary Done" diff --git a/client/vocabcompiler.py b/client/vocabcompiler.py index aba85ce..1ca0d26 100644 --- a/client/vocabcompiler.py +++ b/client/vocabcompiler.py @@ -35,8 +35,6 @@ def compile(sentences, dictionary, languagemodel): for module in modules: words.extend(module.WORDS) - # for spotify module - words.extend(["MUSIC", "SPOTIFY"]) words = list(set(words)) # create the dictionary -- cgit v1.3.1