diff --git a/demos/MoodTagger/Angry.db b/demos/MoodTagger/Angry.db deleted file mode 100644 index a5e64d3..0000000 Binary files a/demos/MoodTagger/Angry.db and /dev/null differ diff --git a/demos/MoodTagger/Happy.db b/demos/MoodTagger/Happy.db deleted file mode 100644 index fc06143..0000000 Binary files a/demos/MoodTagger/Happy.db and /dev/null differ diff --git a/demos/MoodTagger/Peaceful.db b/demos/MoodTagger/Peaceful.db deleted file mode 100644 index 5447ccb..0000000 Binary files a/demos/MoodTagger/Peaceful.db and /dev/null differ diff --git a/demos/MoodTagger/Sad.db b/demos/MoodTagger/Sad.db deleted file mode 100644 index 64814e7..0000000 Binary files a/demos/MoodTagger/Sad.db and /dev/null differ diff --git a/demos/MoodTagger/classifier_SVM.py b/demos/MoodTagger/classifier_SVM.py deleted file mode 100644 index 2056266..0000000 --- a/demos/MoodTagger/classifier_SVM.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra -# -# This file is part of Gaia -# -# Gaia is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the Free -# Software Foundation (FSF), either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the Affero GNU General Public License -# version 3 along with this program. If not, see http://www.gnu.org/licenses/ - - - -from gaia2 import * - -def train_SVM(dataset): - # recreate a copy of the given dataset without history - ds = dataset.copy() - ds.forgetHistory() - ds = transform(ds, 'remove', {'descriptorNames':['*metadata*','*mfcc*', '*hpcp*', '*tristimulus*', 'beats_position', 'bpm_estimates', 'bpm_intervals', 'onset_times', 'rubato_start', 'rubato_stop', 'chords_key']}) - ds = transform(ds, 'FixLength') - ds = transform(ds, 'cleaner') - ds = transform(ds, 'normalize', { 'independent': True }) - ds = transform(ds, 'enumerate', {'descriptorNames': ds.layout().descriptorNames(StringType), 'except':'emotion_tags'}) - ds = transform(ds, 'svmtrain', { 'className': 'emotion_tags' }) - h = ds.history() - return h - - diff --git a/demos/MoodTagger/emotionSVM.py b/demos/MoodTagger/emotionSVM.py deleted file mode 100644 index 5161ea0..0000000 --- a/demos/MoodTagger/emotionSVM.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra -# -# This file is part of Gaia -# -# Gaia is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the Free -# Software Foundation (FSF), either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the Affero GNU General Public License -# version 3 along with this program. If not, see http://www.gnu.org/licenses/ - -#emotionSVM.py - -#trains SVMs based on binary training sets -#and applies them to songs to predict emotions - -from gaia2 import * -from songlib import * -from classifier_SVM import * - -class emotionSVM: - def __init__(self): - self.happyTraining = DataSet() - self.happyTraining.load('Happy.db') - self.sadTraining = DataSet() - self.sadTraining.load('Sad.db') - self.angryTraining = DataSet() - self.angryTraining.load('Angry.db') - self.peacefulTraining = DataSet() - self.peacefulTraining.load('Peaceful.db') - self.happySVM = TransfoChain() - self.sadSVM = TransfoChain() - self.angrySVM = TransfoChain() - self.peacefulSVM = TransfoChain() - try: - self.happySVM.load('HappySVM') - except: - self.happySVM = train_SVM(self.happyTraining) - self.happySVM.save('HappySVM') - try: - self.sadSVM.load('SadSVM') - except: - self.sadSVM = train_SVM(self.sadTraining) - self.sadSVM.save('SadSVM') - try: - self.angrySVM.load('AngrySVM') - except: - self.angrySVM = train_SVM(self.angryTraining) - self.angrySVM.save('AngrySVM') - try: - self.peacefulSVM.load('PeacefulSVM') - except: - self.peacefulSVM = train_SVM(self.peacefulTraining) - self.peacefulSVM.save('PeacefulSVM') - - def predictEmotions(self, testPoint): - emotions = [] - happyPredict = self.happySVM.mapPoint(testPoint) - sadPredict = self.sadSVM.mapPoint(testPoint) - angryPredict = self.angrySVM.mapPoint(testPoint) - peacefulPredict = self.peacefulSVM.mapPoint(testPoint) - - if(happyPredict['emotion_tags']=='Happy'): - emotions.append('Happy') - - if(sadPredict['emotion_tags']=='Sad'): - emotions.append('Sad') - - if(angryPredict['emotion_tags']=='Angry'): - emotions.append('Angry') - - if(peacefulPredict['emotion_tags']=='Peaceful'): - emotions.append('Peaceful') - - return emotions - - def retrainSVM(self, newPoint, emotion): - p = newPoint - emotion = str(emotion) - if("Happy" in emotion): - if(self.happyTraining.contains(p.name())): - self.happyTraining.removePoint(p.name()) - self.happyTraining.addPoint(p) - self.happyTraining.point(p.name())['emotion_tags']=emotion - self.happyTraining.save('Happy.db') - happySVM = train_SVM(self.happyTraining) - happySVM.save('HappySVM') - elif("Sad" in emotion): - if(self.sadTraining.contains(p.name())): - self.sadTraining.removePoint(p.name()) - self.sadTraining.addPoint(p) - self.sadTraining.point(p.name())['emotion_tags']=emotion - self.sadTraining.save('Sad.db') - sadSVM = train_SVM(self.sadTraining) - sadSVM.save('SadSVM') - elif("Angry" in emotion): - if(self.angryTraining.contains(p.name())): - self.angryTraining.removePoint(p.name()) - self.angryTraining.addPoint(p) - self.angryTraining.point(p.name())['emotion_tags']=emotion - self.angryTraining.save('Angry.db') - angrySVM = train_SVM(self.angryTraining) - angrySVM.save('AngrySVM') - elif("Peaceful" in emotion): - if(self.peacefulTraining.contains(p.name())): - self.peacefulTraining.removePoint(p.name()) - self.peacefulTraining.addPoint(p) - self.peacefulTraining.point(p.name())['emotion_tags']=emotion - self.peacefulTraining.save('Peaceful.db') - peacefulSVM = train_SVM(self.peacefulTraining) - peacefulSVM.save('PeacefulSVM') - - - diff --git a/demos/MoodTagger/mainapp.py b/demos/MoodTagger/mainapp.py deleted file mode 100644 index bec3c57..0000000 --- a/demos/MoodTagger/mainapp.py +++ /dev/null @@ -1,393 +0,0 @@ -# Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra -# -# This file is part of Gaia -# -# Gaia is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the Free -# Software Foundation (FSF), either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the Affero GNU General Public License -# version 3 along with this program. If not, see http://www.gnu.org/licenses/ - -# File: mainapp.py -#Runs the main application -from Tkinter import * -from tkentrycomplete import * -import tkFileDialog -import win32com.client -from nowplayingfeatures import * -from winampnew import * -from player import * -from songlib import * -from gaia2 import * -from emotionSVM import * - - - -class App: - - def __init__(self, master): - self.songLibrary = SongLibrary() #user's song library (should be 'songlibrary.db' by default - self.emo = emotionSVM() #collection of SVM classifiers to predict the presence of the emotions Happy, Sad, Angry, and Peaceful - #self.userTags = DataSet() #collection of past user tags (not needed yet) - #self.userTagList = self.userTags.pointNames() - - self.label = Label(master,text="Hello! Please select tags for the following song.\n If you would like to change the music player you use, please us the Music Player menu.\n").grid(row=0) - - self.player = Player('iTunes') #interface to the current player (iTunes or winamp) - - self.title = Label(master, text="Title: "+self.player.getCurrentTitle()) - self.title.grid(row=1) - self.artist = Label(master, text="Artist: "+self.player.getCurrentArtist()) - self.artist.grid(row=2) - - self.tags=[] #tags the user has already selected - self.predictTags=[] #tags the system predicts - - if(self.songLibrary.library.contains(self.player.getCurrentTitle().encode('ascii', 'ignore'))): #if the current song is in the library already - currtags = str(self.songLibrary.getEmotions(self.songLibrary.library.point((self.player.getCurrentTitle().encode('ascii', 'ignore'))))) - self.tags=currtags.split(',') #retrieve the listed emotions(if any) - #then predict which emotions are there - self.predictTags = self.emo.predictEmotions(self.songLibrary.library.point((self.player.getCurrentTitle().encode('ascii', 'ignore')))) - print "Place: __init__:" - print "Current Tags: ", self.tags - print "Predicted Tags: ", self.predictTags - self.happyVar = StringVar() #variable for the "Happy" check box - if("Happy" in self.tags): #if the user has already tagged the song as Peaceful - self.happyVar.set("Happy") - self.happycolor = 'grey' - else: - if("Happy" in self.predictTags): #if the system predicts the song to be peaceful - self.happyVar.set("Happy") - self.happycolor = 'red' - else: - self.happyVar.set("not") - self.happycolor = 'grey' - self.happyCheck = Checkbutton(master, text="Happy", variable=self.happyVar, onvalue="Happy", offvalue="not", bg=self.happycolor) - self.happyCheck.grid(row=3, sticky=W) - - - self.sadVar = StringVar() #variable for the "Sad" checkbox - if("Sad" in self.tags): #if the user has already tagged the song as happy - self.sadVar.set("Sad") - self.sadcolor = 'grey' - else: - if("Sad" in self.predictTags): #if the system predicts the song to be happy (and the user hasn't tagged it that way already) - self.sadVar.set("Sad") - self.sadcolor = 'red' - else: - self.sadVar.set("not") - self.sadcolor = 'grey' - self.sadCheck = Checkbutton(master, text="Sad", variable=self.sadVar, onvalue="Sad", offvalue="not", bg=self.sadcolor) - self.sadCheck.grid(row=3, sticky=W, padx=100) - - - self.angryVar = StringVar() #variable for the "Angry" check box - if("Angry" in self.tags): #if the user has already tagged the song as angry - self.angryVar.set("Angry") - self.angrycolor = 'grey' - else: - if("Angry" in self.predictTags): #if the system predicts the song to be angry - self.angryVar.set("Angry") - self.angrycolor = 'red' - else: - self.angryVar.set("not") - self.angrycolor = 'grey' - self.angryCheck = Checkbutton(master, text="Angry", variable=self.angryVar, onvalue="Angry", offvalue="not", bg=self.angrycolor) - self.angryCheck.grid(row=4, sticky=W) - - - self.peacefulVar = StringVar() #variable for the "Peaceful" check box - if("Peaceful" in self.tags): #if the user has already tagged the song as Peaceful - self.peacefulVar.set("Peaceful") - self.peacefulcolor = 'grey' - else: - if("Peaceful" in self.predictTags): #if the system predicts the song to be peaceful - self.peacefulVar.set("Peaceful") - self.peacefulcolor = 'red' - else: - self.peacefulVar.set("not") - self.peacefulcolor = 'grey' - self.peacefulCheck = Checkbutton(master, text="Peaceful", variable=self.peacefulVar, onvalue="Peaceful", offvalue="not", bg=self.peacefulcolor) - self.peacefulCheck.grid(row=4, sticky=W, padx=100) - - self.openInstruction = Label(master, text="You may also enter your own tag").grid(row=5, sticky=W) - - self.openTagVar = StringVar() - self.openTagEntry = Entry(master, textvariable=self.openTagVar, text="").grid(row=5, sticky=W, padx=200) - - self.tags=[self.happyVar, self.sadVar, self.angryVar, self.peacefulVar] - - - self.button = Button(master, text="Submit", command=self.submit).grid(row=6, sticky=W) - self.quit = Button(master, text="Quit", command=root.destroy).grid(row=6, sticky=E) - directory = tkFileDialog.askdirectory() - self.songLibrary.analyzeLib(directory) - - self.refresher=Label(master) - self.refresher.after(1000, self.refreshWindow) - - - def isTag(self, tag): - if(tag.get()=="not"): - return False - else: - return True - - - def submit(self): - redTags = filter(self.isTag, self.tags) #the tags taken from the GUI (filtered by whether there is a "not" in the tag) - tagsToSend = redTags[0].get() #gets the first tag (this is done so that the correct number of commas are submitted in the next loop - for i in range(1, len(redTags)): - tagsToSend=tagsToSend+","+redTags[i].get() #go through the rest of the tags and add them on the the string - #Routine to go through the text box and add written tags to the sent tags - # if(self.openTagVar.get()!=""): - # tagsToSend=tagsToSend+","+self.openTagVar.get() - # userTags = self.openTagVar.get().split(",") - # for tag in userTags: - # p = Point() - # p.loadFromString(tag) - # p.setName(tag) - # if not self.userTags.contains(p): - # self.userTags.addPoint(p) - # self.userTags.save("usertags.db") - print "Tags to send: ", tagsToSend - point = self.songLibrary.library.point(self.player.getCurrentTitle().encode('ascii', 'ignore')) - self.songLibrary.setEmotions(point, tagsToSend) - print "Place: Submit" - print self.songLibrary.getEmotions(point) - for tag in redTags: - rtag = str(tag.get()) - #tag the user checks that the system misses - if(not rtag in self.predictTags): - print "Retraining: ", rtag - self.emo.retrainSVM(point, tag.get()) - for pTag in self.predictTags: - #tag the system selects that the user removes - if(not pTag in tagsToSend): - newTag = "not "+pTag - print "Retraining: ", newTag - self.emo.retrainSVM(point, newTag) - - - def refreshMenu(self, type): - self.player.changeType(type) - self.title.config(text="Title: "+self.player.getCurrentTitle()) - self.artist.config(text="Artist: "+self.player.getCurrentArtist()) - title = self.player.getCurrentTitle().encode('ascii', 'ignore') - if(self.songLibrary.library.contains(title)): - currtags = str(self.songLibrary.getEmotions(self.songLibrary.library.point(title))) - print currtags - tags=currtags.split(',') - self.predictTags = self.emo.predictEmotions(self.songLibrary.library.point(title)) - print "Place: refreshMenu" - print "Current Tags: ", tags - print "Predicted Tags: ", self.predictTags - if("Happy" in tags): - self.happyVar.set("Happy") - self.happycolor='grey' - else: - if("Happy" in self.predictTags): - self.happyVar.set("Happy") - self.happycolor='red' - else: - self.happyVar.set("not") - self.happycolor='grey' - if("Sad" in tags): - self.sadVar.set("Sad") - self.sadcolor='grey' - else: - if("Sad" in self.predictTags): - self.sadVar.set("Sad") - self.sadcolor='red' - else: - self.sadVar.set("not") - self.sadcolor='grey' - if("Angry" in tags): - self.angryVar.set("Angry") - self.angrycolor='grey' - else: - if("Angry" in self.predictTags): - self.angryVar.set("Angry") - self.angrycolor='red' - else: - self.angryVar.set("not") - self.angrycolor='red' - if("Peaceful" in tags): - self.peacefulVar.set("Peaceful") - self.peacefulcolor='grey' - else: - if("Peaceful" in self.predictTags): - self.peacefulVar.set("Peaceful") - self.peacefulcolor='red' - else: - self.peacefulVar.set("not") - self.peacefulcolor='grey' - else: - file = self.player.sendCurrentSongToEssentia() - try: - self.songLibrary.addSong(file) - self.predictTags = self.emo.predictEmotions(self.songLibrary.library.point(title)) - print "Place: refreshMenu (song not in library)" - print "PredictedTags: ", self.predictTags - if("Happy" in self.predictTags): - self.happyVar.set("Happy") - self.happycolor = 'red' - else: - self.happyVar.set("not") - self.happycolor='grey' - if("Sad" in self.predictTags): - self.sadVar.set("Sad") - self.sadcolor = 'red' - else: - self.sadVar.set("not") - self.sadcolor = 'grey' - if("Angry" in self.predictTags): - self.angryVar.set("Angry") - self.angrycolor = 'red' - else: - self.angryVar.set("not") - self.angrycolor = 'grey' - if("Peaceful" in self.predictTags): - self.peacefulVar.set("Peaceful") - self.peacefulcolor='red' - else: - self.peacefulVar.set("not") - self.peacefulcolor='grey' - except: - self.happyVar.set("not") - self.happycolor='grey' - self.sadVar.set("not") - self.sadcolor = 'grey' - self.angryVar.set("not") - self.angrycolor = 'grey' - self.peacefulVar.set("not") - self.peacefulcolor='grey' - self.happyCheck.config(bg=self.happycolor) - self.sadCheck.config(bg=self.sadcolor) - self.angryCheck.config(bg=self.angrycolor) - self.peacefulCheck.config(bg=self.peacefulcolor) - - def refreshWindow(self): - if(self.player.getCurrentPosition()==0): - self.title.config(text="Title: "+self.player.getCurrentTitle()) - self.artist.config(text="Artist: "+self.player.getCurrentArtist()) - if(self.songLibrary.library.contains(self.player.getCurrentTitle().encode('ascii', 'ignore'))): #if the current song is in the library - #get the emotions - currtags = str(self.songLibrary.getEmotions(self.songLibrary.library.point((self.player.getCurrentTitle().encode('ascii', 'ignore'))))) - tags=currtags.split(',') - #predict emotions - self.predictTags = self.emo.predictEmotions(self.songLibrary.library.point((self.player.getCurrentTitle().encode('ascii', 'ignore')))) - print "Place: refreshWindow" - print "Current Tags: ", tags - print "Predicted Tags: ", self.predictTags - #change display to reflect the current and predicted tags - if("Happy" in tags): - self.happyVar.set("Happy") - self.happycolor='grey' - else: - if("Happy" in self.predictTags): - self.happyVar.set("Happy") - self.happycolor='red' - else: - self.happyVar.set("not") - self.happycolor='grey' - if("Sad" in tags): - self.sadVar.set("Sad") - self.sadcolor='grey' - else: - if("Sad" in self.predictTags): - self.sadVar.set("Sad") - self.sadcolor='red' - else: - self.sadVar.set("not") - self.sadcolor='grey' - if("Angry" in tags): - self.angryVar.set("Angry") - self.angrycolor='grey' - else: - if("Angry" in self.predictTags): - self.angryVar.set("Angry") - self.angrycolor='red' - else: - self.angryVar.set("not") - self.angrycolor='grey' - if("Peaceful" in tags): - self.peacefulVar.set("Peaceful") - self.peacefulcolor='grey' - else: - if("Peaceful" in self.predictTags): - self.peacefulVar.set("Peaceful") - self.peacefulcolor='red' - else: - self.peacefulVar.set("not") - self.peacefulcolor='grey' - else: - file = self.player.sendCurrentSongToEssentia() - try: - self.songLibrary.addSong(file) - self.predictTags = self.emo.predictEmotions(self.songLibrary.library.point((self.player.getCurrentTitle().encode('ascii', 'ignore')))) - if("Happy" in self.predictTags): - self.happyVar.set("Happy") - self.happycolor = 'red' - else: - self.happyVar.set("not") - self.happycolor='grey' - if("Sad" in self.predictTags): - self.sadVar.set("Sad") - self.sadcolor = 'red' - else: - self.sadVar.set("not") - self.sadcolor = 'grey' - if("Angry" in self.predictTags): - self.angryVar.set("Angry") - self.angrycolor = 'red' - else: - self.angryVar.set("not") - self.angrycolor = 'grey' - if("Peaceful" in self.predictTags): - self.peacefulVar.set("Peaceful") - self.peacefulcolor='red' - else: - self.peacefulVar.set("not") - self.peacefulcolor='grey' - except: - self.happyVar.set("not") - self.happycolor='grey' - self.sadVar.set("not") - self.sadcolor = 'grey' - self.angryVar.set("not") - self.angrycolor = 'grey' - self.peacefulVar.set("not") - self.peacefulcolor='grey' - self.happyCheck.config(bg=self.happycolor) - self.sadCheck.config(bg=self.sadcolor) - self.angryCheck.config(bg=self.angrycolor) - self.peacefulCheck.config(bg=self.peacefulcolor) - self.refresher.after(1000, self.refreshWindow) - - - - -root = Tk() -app = App(root) -menu = Menu(root) -root.config(menu=menu) -settingsmenu=Menu(menu) -playermenu = Menu(menu) -settingsmenu.add_cascade(label="Music Player", menu=playermenu) -menu.add_cascade(label="Settings", menu=settingsmenu) -playermenu.add_radiobutton(label = 'Winamp', value = 'Winamp', command= lambda type='winamp': app.refreshMenu(type)) -playermenu.add_radiobutton(label = 'iTunes', value = 'iTunes', command= lambda type='iTunes': app.refreshMenu(type)) - - - - - -root.mainloop() diff --git a/demos/MoodTagger/nowplayingfeatures.py b/demos/MoodTagger/nowplayingfeatures.py deleted file mode 100644 index 3b07c25..0000000 --- a/demos/MoodTagger/nowplayingfeatures.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra -# -# This file is part of Gaia -# -# Gaia is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the Free -# Software Foundation (FSF), either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the Affero GNU General Public License -# version 3 along with this program. If not, see http://www.gnu.org/licenses/ - -import win32com.client -import os -import subprocess -import winampnew - -#iTunes = win32com.client.gencache.EnsureDispatch("iTunes.Application") - -def sendCurrentiTunesSongToEssentia(iTunes): - - current = win32com.client.CastTo(iTunes.CurrentTrack, "IITFileOrCDTrack") - songPath = current.Location - outputstr = current.Name + '.sig' - subprocess.call([ r'C:\Program Files\Essentia\extractors\streaming_extractor.exe', songPath, outputstr]) - return outputstr - - -def sendCurrentWinampSongToEssentia(winamp, index): - songPath = winamp.getPlaylistFile(index) - outputstr = winamp.getPlaylistTitle(index) + ".sig" - subprocess.call([ r'C:\Program Files\Essentia\extractors\streaming_extractor.exe', songPath, outputstr]) - return outputstr - - - - diff --git a/demos/MoodTagger/player.py b/demos/MoodTagger/player.py deleted file mode 100644 index e7a5961..0000000 --- a/demos/MoodTagger/player.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra -# -# This file is part of Gaia -# -# Gaia is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the Free -# Software Foundation (FSF), either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the Affero GNU General Public License -# version 3 along with this program. If not, see http://www.gnu.org/licenses/ - -import win32com.client -from nowplayingfeatures import * -from winampnew import * - -class Player: - - def __init__(self, ptype): - if(ptype=='iTunes'): - self.app = win32com.client.gencache.EnsureDispatch("iTunes.Application") - self.app.Play() - elif(ptype=='winamp'): - self.app = Winamp() - self.type = ptype - - def sendCurrentSongToEssentia(self): - if(self.type=='iTunes'): - return sendCurrentiTunesSongToEssentia(self.app) - elif(self.type=='winamp'): - return sendCurrentWinampSongToEssentia(self.app, self.app.getListPosition()) - - def changeType(self, newtype): - if(newtype != self.type): - if(newtype == 'iTunes'): - self.app = win32com.client.gencache.EnsureDispatch("iTunes.Application") - elif(newtype=='winamp'): - self.app = Winamp() - self.type = newtype - print self.type - - def getCurrentTitle(self): - if(self.type=='iTunes'): - return self.app.CurrentTrack.Name - elif(self.type=='winamp'): - filename = self.app.getCurrentPlayingTitle() - index = filename.find("-")+2 - title = filename[index:] - return title - else: - return "" - - def getCurrentArtist(self): - if(self.type=='iTunes'): - return self.app.CurrentTrack.Artist - elif(self.type=='winamp'): - filename=self.app.getCurrentPlayingTitle().split("-") - return filename[0] - else: - return "" - - def getCurrentLength(self): - if(self.type=='iTunes'): - time = self.app.CurrentTrack.Time - timearray = time.split(':') - seconds = int(timearray[0])*60+(int(timearray[1])) - return seconds - elif(self.type=='winamp'): - return self.app.getPlayingTrackLength() - - def getCurrentPosition(self): - if(self.type=='iTunes'): - return self.app.PlayerPosition - elif(self.type=='winamp'): - position = self.app.getPlayingTrackPosition()/1000 - return position - else: - return 0 - - - - - - - - diff --git a/demos/MoodTagger/songlib.py b/demos/MoodTagger/songlib.py deleted file mode 100644 index ff15fbb..0000000 --- a/demos/MoodTagger/songlib.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra -# -# This file is part of Gaia -# -# Gaia is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the Free -# Software Foundation (FSF), either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the Affero GNU General Public License -# version 3 along with this program. If not, see http://www.gnu.org/licenses/ - -#songlib.py - -from gaia2 import * -import os -import subprocess - - -class SongLibrary: - def __init__(self, name='songlibrary'): - self.library = DataSet() - self.library.setName(name) - self.saveFile = name+'.db' - self.loadLib() - - def analyzeLib(self, directory): - files=os.listdir(directory) - for song in files: - input = directory+'\\'+song - print input - if(".mp3" in input): - if(".sig" not in input): - outputstr = directory+'\\'+song+".sig" - if(os.path.exists(outputstr)==False): - subprocess.call([ r'C:\Program Files\Essentia\extractors\streaming_extractor.exe', input, outputstr]) - self.addSong(outputstr) - self.saveLib() - - def addSong(self, filename): - #adds song data as a data point, returns the added point - file = open(filename) - p = Point() - p.loadFromString(file.read()) - title = p.label('title') - p.setName(title.toString()) - if(not p in self.library): - p.layout().add('emotion_tags', StringType, VariableLength) - self.library.addPoint(p) - self.saveLib() - return p - - def saveLib(self): - self.library.save(self.saveFile) - - def loadLib(self): - try: - self.library.load(self.saveFile) - except: - pass - - def setEmotions(self, point, emotions): - self.library.point(point.name()).setLabel('emotion_tags', emotions) - print emotions - print self.library.point(point.name()).label('emotion_tags') - self.saveLib() - - def getEmotions(self, point): - return self.library.point(point.name()).label('emotion_tags') - - def createGroundTruth(self, directory, emotionTag): - files=os.listdir(directory) - for song in files: - input = directory+'\\'+song - print input - if(".mp3" in input): - if(".sig" not in input): - outputstr = directory+'\\'+song+".sig" - if(os.path.exists(outputstr)==False): - subprocess.call([ r'C:\Program Files\Essentia\extractors\streaming_extractor.exe', input, outputstr]) - p = self.addSong(outputstr) - self.setEmotions(p, emotionTag) - self.saveLib() - - - - - - - diff --git a/demos/MoodTagger/winampnew.py b/demos/MoodTagger/winampnew.py deleted file mode 100644 index bcb0a4e..0000000 --- a/demos/MoodTagger/winampnew.py +++ /dev/null @@ -1,512 +0,0 @@ -# Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra -# -# This file is part of Gaia -# -# Gaia is free software: you can redistribute it and/or modify it under -# the terms of the GNU Affero General Public License as published by the Free -# Software Foundation (FSF), either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the Affero GNU General Public License -# version 3 along with this program. If not, see http://www.gnu.org/licenses/ - -# Copyright (C) 2009 Yaron Inger, http://ingeration.blogspot.com -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# or download it from http://www.gnu.org/licenses/gpl.txt - -# Revision History: -# -# 11/05/2008 Version 0.1 -# - Initial release -# -# 31/12/2009 Version 0.2 -# - Added support for keyword queries (queryAsKeyword) - -from ctypes import * -import win32api, win32con, win32gui, win32process, pywintypes -import os -import random -import time - -class Winamp(object): - # Winamp main window IPC - WM_WA_IPC = win32con.WM_USER - # Winamp's media library IPC - WM_ML_IPC = WM_WA_IPC + 0x1000 - - # add item to playlist - IPC_ENQUEUEFILE = 100 - # playback status - IPC_ISPLAYING = 104 - # delete winamp's internal playlist - IPC_DELETE = 101 - # get output time - IPC_GETOUTPUTTIME = 105 - - #gets playlist position - IPC_GETLISTPOS = 125 - # sets playlist position - IPC_SETPLAYLISTPOS = 121 - # sets volume - IPC_SETVOLUME = 122 - # gets list length - IPC_GETLISTLENGTH = 124 - # gets given index playlist file - IPC_GETPLAYLISTFILE = 211 - # gets given index playlist title - IPC_GETPLAYLISTTITLE = 212 - - #get currently playng filename - IPC_GET_PLAYING_FILENAME = 3031 - - # next playlist track - IPC_GET_NEXT_PLITEM = 361 - # current playing title - IPC_GET_PLAYING_TITLE = 3034 - - # runs an ml query - ML_IPC_DB_RUNQUERY = 0x0700 - # runs an ml query as a string - ML_IPC_DB_RUNQUERY_SEARCH = 0x0701 - # frees ml query results from winamp's memory - ML_IPC_DB_FREEQUERYRESULTS = 0x0705 - - # playback possible options - PLAYBACK_NOT_PLAYING = 0 - PLAYBACK_PLAYING = 1 - PLAYBACK_PAUSE = 3 - - GET_TRACK_POSITION = 0 - GET_TRACK_LENGTH = 1 - - # winamp buttons commands - BUTTON_COMMAND_PREVIOUS = 40044 - BUTTON_COMMAND_PLAY = 40045 - BUTTON_COMMAND_PAUSE = 40046 - BUTTON_COMMAND_STOP = 40047 - BUTTON_COMMAND_NEXT = 40048 - - # sort playlist by path and filename - ID_PE_S_PATH = 40211 - - class COPYDATATYPE(Structure): - _fields_ = [("szData", c_char_p)] - - """ - typedef struct tagCOPYDATASTRUCT { - ULONG_PTR dwData; - DWORD cbData; - PVOID lpData; - } COPYDATASTRUCT, *PCOPYDATASTRUCT; - - dwData - Specifies data to be passed to the receiving application. - cbData - Specifies the size, in bytes, of the data pointed to by the lpData member. - lpData - Pointer to data to be passed to the receiving application. This member can be NULL. - """ - class COPYDATASTRUCT(Structure): - _fields_ = [("dwData", c_ulong), - ("cbData", c_ulong), - ("lpData", c_void_p)] - - """ - typedef struct - { - itemRecord *Items; - int Size; - int Alloc; - } itemRecordList; - """ - class itemRecordList(Structure): - _fields_ = [("Items", c_void_p), - ("Size", c_int), - ("Alloc", c_int)] - - """ - typedef struct - { - char *filename; - char *title; - char *album; - char *artist; - char *comment; - char *genre; - int year; - int track; - int length; - char **extended_info; - // currently defined extended columns (while they are stored internally as integers - // they are passed using extended_info as strings): - // use getRecordExtendedItem and setRecordExtendedItem to get/set. - // for your own internal use, you can set other things, but the following values - // are what we use at the moment. Note that setting other things will be ignored - // by ML_IPC_DB*. - // - //"RATING" file rating. can be 1-5, or 0 or empty for undefined - //"PLAYCOUNT" number of file plays. - //"LASTPLAY" last time played, in standard time_t format - //"LASTUPD" last time updated in library, in standard time_t format - //"FILETIME" last known file time of file, in standard time_t format - //"FILESIZE" last known file size, in kilobytes. - //"BITRATE" file bitrate, in kbps - //"TYPE" - "0" for audio, "1" for video - - } itemRecord; - """ - class itemRecord(Structure): - _fields_ = [("filename", c_char_p), - ("title", c_char_p), - ("album", c_char_p), - ("artist", c_char_p), - ("comment", c_char_p), - ("genre", c_char_p), - ("year", c_int), - ("track", c_int), - ("length", c_int), - ("extended_info", c_char_p)] - - """ - typedef struct - { - char *query; - int max_results; // can be 0 for unlimited - itemRecordList results; - } mlQueryStruct; - """ - class mlQueryStruct(Structure): - pass - - def __init__(self): - self.__initStructures() - - # get important Winamp's window handles - try: - self.__mainWindowHWND = self.__findWindow([("Winamp v1.x", None)]) - self.__playlistHWND = self.__findWindow([("BaseWindow_RootWnd", None), - ("BaseWindow_RootWnd", "Playlist Editor"), - ("Winamp PE", "Winamp Playlist Editor")]) - self.__mediaLibraryHWND = self.__findWindow([("BaseWindow_RootWnd", None), - ("BaseWindow_RootWnd", "Winamp Library"), - ("Winamp Gen", "Winamp Library"), (None, None)]) - except pywintypes.error, e: - raise RuntimeError("Cannot find Winamp windows. Is winamp started?") - - self.__processID = win32process.GetWindowThreadProcessId(self.__mainWindowHWND)[1] - - # open Winamp's process - self.__hProcess = windll.kernel32.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, self.__processID) - - def detach(self): - """Detaches from Winamp's process.""" - windll.kernel32.CloseHandle(self.__hProcess) - - def __initStructures(self): - # cannot be done statically, because mlQueryStruct doesn't know any self.itemRecordList - try: - self.mlQueryStruct._fields_ = [("query", c_char_p), - ("max_results", c_int), - ("itemRecordList", self.itemRecordList)] - except AttributeError: - # mlQueryStruct already initialized - pass - - def __findWindow(self, windowList): - """Gets a handle to the lowest window in the given windows hierarchy. - - The given list should be in format of [, ]. - """ - currentWindow = None - - for i in xrange(len(windowList)): - if currentWindow is None: - currentWindow = win32gui.FindWindow(windowList[i][0], windowList[i][1]) - else: - currentWindow = win32gui.FindWindowEx(currentWindow, 0, windowList[i][0], windowList[i][1]) - - return currentWindow - - def __setattr__(self, attr, value): - if attr == "playlist": - self.clearPlaylist() - - [self.enqueueFile(item.filename) for item in value] - else: - object.__setattr__(self, attr, value) - - def __getattr__(self, attr): - if attr == "playlist": - return self.getPlaylistFilenames() - else: - try: - return object.__getattr__(self, attr) - except AttributeError: - raise AttributeError, attr - - def __readStringFromMemory(self, address, isUnicode = False): - """Reads a string from Winamp's memory address space.""" - - if isUnicode: - bufferLength = win32con.MAX_PATH * 2 - buffer = create_unicode_buffer(bufferLength * 2) - else: - bufferLength = win32con.MAX_PATH - buffer = create_string_buffer(bufferLength) - - bytesRead = c_ulong(0) - - """Note: this is quite an ugly hack, because we assume the string will have a maximum - size of MAX_PATH (=260) and that we're not in an end of a page. - - A proper way to solve it would be: - 1. calling VirutalQuery. - 2. Reading one byte at a time. (?) - 3. Use CreateRemoteThread to run strlen on Winamp's process. - """ - windll.kernel32.ReadProcessMemory(self.__hProcess, address, buffer, bufferLength, byref(bytesRead)) - - return buffer.value - - def enqueueFile(self, filePath): - """Enqueues a file in Winamp's playlist. - - filePath is the given file path to enqueue. - """ - - # prepare copydata structure for sending data - cpyData = create_string_buffer(filePath) - cds = self.COPYDATASTRUCT(c_ulong(self.IPC_ENQUEUEFILE), - c_ulong(len(cpyData.raw)), - cast(cpyData, c_void_p)) - - # send copydata message - win32api.SendMessage(self.__mainWindowHWND, - win32con.WM_COPYDATA, - 0, - addressof(cds)) - - def query(self, queryString, queryType = ML_IPC_DB_RUNQUERY): - """Queries Winamp's media library and returns a list of items matching the query. - - The query should include filters like '?artist has \'alice\''. - For more information, consult your local Winamp forums or media library. - """ - queryStringAddr = self.__copyDataToWinamp(queryString) - - # create query structs and copy to winamp - recordList = self.itemRecordList(0, 0, 0) - queryStruct = self.mlQueryStruct(cast(queryStringAddr, c_char_p), 0, recordList) - queryStructAddr = self.__copyDataToWinamp(queryStruct) - - # run query - win32api.SendMessage(self.__mediaLibraryHWND, self.WM_ML_IPC, queryStructAddr, queryType) - - receivedQuery = self.__readDataFromWinamp(queryStructAddr, self.mlQueryStruct) - - items = [] - - buf = create_string_buffer(sizeof(self.itemRecord) * receivedQuery.itemRecordList.Size) - windll.kernel32.ReadProcessMemory(self.__hProcess, receivedQuery.itemRecordList.Items, buf, sizeof(buf), 0) - - for i in xrange(receivedQuery.itemRecordList.Size): - item = self.__readDataFromWinamp(receivedQuery.itemRecordList.Items + (sizeof(self.itemRecord) * i), self.itemRecord) - - self.__fixRemoteStruct(item) - - items.append(item) - - # free results - win32api.SendMessage(self.__mediaLibraryHWND, self.WM_ML_IPC, queryStructAddr, self.ML_IPC_DB_FREEQUERYRESULTS) - - return items - - def queryAsKeyword(self, queryString): - """Queries Winamp's media library and returns a list of items matching the query. - - The query should be a keyword, like 'alice' (then the query is then treated as a string query). - This makes Winamp search the requested keyword in every data field in the media library database - (such as Artist, Album, Track Name, ...). - """ - return self.query(queryString, self.ML_IPC_DB_RUNQUERY_SEARCH) - - def __copyDataToWinamp(self, data): - if type(data) is str: - dataToCopy = create_string_buffer(data) - else: - dataToCopy = data - - # allocate data in Winamp's address space - lpAddress = windll.kernel32.VirtualAllocEx(self.__hProcess, None, sizeof(dataToCopy), win32con.MEM_COMMIT, win32con.PAGE_READWRITE) - # write data to Winamp's memory - windll.kernel32.WriteProcessMemory(self.__hProcess, lpAddress, addressof(dataToCopy), sizeof(dataToCopy), None) - - return lpAddress - - def __readDataFromWinamp(self, address, ctypesType): - if ctypesType is c_char_p: - buffer = create_string_buffer(win32con.MAX_PATH) - else: - buffer = create_string_buffer(sizeof(ctypesType)) - - bytesRead = c_ulong(0) - if windll.kernel32.ReadProcessMemory(self.__hProcess, address, buffer, sizeof(buffer), byref(bytesRead)) == 0: - # we're in a new page - if address / 0x1000 != address + sizeof(buffer): - # possible got into an unpaged memory region, read until end of page - windll.kernel32.ReadProcessMemory(self.__hProcess, address, buffer, ((address + 0x1000) & 0xfffff000) - address, byref(bytesRead)) - else: - raise RuntimeError("ReadProcessMemory failed at 0x%08x." % address) - - if ctypesType is c_char_p: - return cast(buffer, c_char_p) - else: - return cast(buffer, POINTER(ctypesType))[0] - - def __fixRemoteStruct(self, structure): - offset = 0 - - for i in xrange(len(structure._fields_)): - (field_name, field_type) = structure._fields_[i] - - if field_type is c_char_p or field_type is c_void_p: - # get pointer address - address = cast(addressof(structure) + offset, POINTER(c_int))[0] - - # ignore null pointers - if address != 0x0: - structure.__setattr__(field_name, self.__readDataFromWinamp(address, field_type)) - - offset += sizeof(field_type) - - def __sendUserMessage(self, wParam, lParam, hwnd = None): - """Sends a user message to the given hwnd with the given wParam and lParam.""" - if hwnd is None: - targetHWND = self.__mainWindowHWND - else: - targetHWND = hwnd - - return win32api.SendMessage(targetHWND, self.WM_WA_IPC, wParam, lParam) - - def __sendCommandMessage(self, wParam, lParam, hwnd = None): - """Sends a command message to the given hwnd with the given wParam and lParam.""" - if hwnd is None: - targetHWND = self.__mainWindowHWND - else: - targetHWND = hwnd - - return win32api.SendMessage(targetHWND, win32con.WM_COMMAND, wParam, lParam) - - def getPlaybackStatus(self): - """Gets Winamp's playback status. Use the constants PLAYBACK_NOT_PLAYING, - PLAYBACK_PLAYING and PLAYBACK_PAUSE = 3 to resolve status.""" - return self.__sendUserMessage(0, self.IPC_ISPLAYING) - - def getPlayingTrackLength(self): - """Gets the length in second of the current playing track.""" - return self.__sendUserMessage(self.GET_TRACK_LENGTH, self.IPC_GETOUTPUTTIME) - - def getPlayingTrackPosition(self): - """Gets the position in milliseconds of the current playing track.""" - return self.__sendUserMessage(self.GET_TRACK_POSITION, self.IPC_GETOUTPUTTIME) - - def clearPlaylist(self): - """Clears the playlist.""" - return self.__sendUserMessage(0, self.IPC_DELETE) - - def setPlaylistPosition(self, position): - """Sets the playlist position in the given position number (zero based).""" - return self.__sendUserMessage(position, self.IPC_SETPLAYLISTPOS) - - def setVolume(self, volume): - """Sets the internal Winamp's volume meter. Will only accept values in the range 0-255.""" - assert volume >= 0 and volume <= 255 - - self.__sendUserMessage(volume, self.IPC_SETVOLUME) - - def getCurrentPlayingTitle(self): - """Returns the title of the current playing track""" - address = self.__sendUserMessage(0, self.IPC_GET_PLAYING_TITLE) - - return self.__readStringFromMemory(address, True) - - def getPlaylistFile(self, position): - """Returns the filename of the current selected file in the playlist.""" - address = self.__sendUserMessage(position, self.IPC_GETPLAYLISTFILE) - - return self.__readStringFromMemory(address) - - def getPlaylistTitle(self, position): - """Returns the title of the current selected file in the playlist.""" - address = self.__sendUserMessage(position, self.IPC_GETPLAYLISTTITLE) - - return self.__readStringFromMemory(address) - - def getListLength(self): - """Returns the length of the current playlist.""" - return self.__sendUserMessage(0, self.IPC_GETLISTLENGTH) - - def getListPosition(self): - """Returns the position of the playlist""" - return self.__sendUserMessage(0, self.IPC_GETLISTPOS) - - def getPlaylistFilenames(self): - """Retrieves a list of the current playlist song filenames.""" - return [self.getPlaylistFile(position) for position in range(self.getListLength())] - - def getPlaylistTitles(self): - """Retrieves a list of the current playlist song titles.""" - return [self.getPlaylistTitle(position) for position in range(self.getListLength())] - - def next(self): - """Sets playlist marker to next song.""" - self.__sendCommandMessage(self.BUTTON_COMMAND_NEXT, 0) - - def previous(self): - """Sets playlist marker to previous song.""" - self.__sendCommandMessage(self.BUTTON_COMMAND_PREVIOUS, 0) - - def pause(self): - """Pauses Winamp's playback.""" - self.__sendCommandMessage(self.BUTTON_COMMAND_PAUSE, 0) - - def play(self): - """Starts / resumes playing Winamp's playback, or restarts current playing song.""" - self.__sendCommandMessage(self.BUTTON_COMMAND_PLAY, 0) - - def stop(self): - """Stops Winamp's playback.""" - self.__sendCommandMessage(self.BUTTON_COMMAND_STOP, 0) - - def sortPlaylist(self): - """Sorts the current playlist alphabetically.""" - self.__sendCommandMessage(self.ID_PE_S_PATH, 0, self.__playlistHWND) - - def playAlbum(self, album): - """Plays a given album name.""" - self.playlist = self.query("album = \"%s\"" % album) - self.stop() - self.sortPlaylist() - self.setPlaylistPosition(0) - self.play() - -def printMediaLibraryItem(item): - print "Filename: %s\nTrack: %s, Album: %s, Artist: %s\nComment: %s, Genre: %s" % (item.filename, item.track, item.album, item.artist, item.comment, item.genre) \ No newline at end of file