c# - Smart Way to Handle Voice Commands in Code to Action a Command -
rather using switch/case or if boolean checks can long , awfully tedious, wonder if better way can sought handling , processing commands.
e.g:
if(settings.getname == command) { speak("i here"); } if("get news feed" == command) { myrssfeed rssnewsfeed = new myrssfeed(); rssnewsfeed.getfeed(); }
the if commands go on... here snippet of switch statement:
switch (command) { #region <-- time command --> case "time please": case "whats time": case "what time it": getcurrenttime(); break; #endregion <-- time command --> #region <-- date command --> case "whats date": case "what date it": case "whats date today": case "what date today": getcurrentdate(); break; #endregion <-- date command --> #region <-- media player commands --> case "play bamboo forest": data.musicplayer.play(@"\bamboo forest play list.wpl"); break; case "next song": data.musicplayer.next(); break; case "previous song": data.musicplayer.previous(); break; case "stop music": data.musicplayer.stop(); break; case "pause music": data.musicplayer.pause(); break; case "resume music": data.musicplayer.resume(); break; case "mute music": data.musicplayer.mute(); break; case "volume up": data.musicplayer.volumeup(); break; case "volume down": data.musicplayer.volumedown(); break; #endregion <-- media player commands --> #region <-- voice recognition control commands --> case "stop listening": audio.listen.newcommandrecognitionengine.recognizeasynccancel(); audio.voice.speak("ok"); audio.listen.initialise(main); break; #endregion <-- voice recognition control commands --> #region <-- application commands --> case "quiet": audio.voice.stop(); break; case "download": audio.voice.speak("opening download window."); main.dlinterface.showbitsjobs(); break; case "settings": audio.voice.speak("opening settings window."); main.settings.show(); break; case "close": if (main.dlinterface.visable == true) { main.dlinterface.hide(); audio.voice.speak("closing download window."); } if (main.settings.visible == true) { main.settings.hide(); audio.voice.speak("closing settings window."); } break; case "out of way": if (main.windowstate == system.windows.forms.formwindowstate.normal) { main.windowstate = system.windows.forms.formwindowstate.minimized; audio.voice.speak("my apologies"); } break; case "where you": if (main.windowstate == system.windows.forms.formwindowstate.minimized) { main.windowstate = system.windows.forms.formwindowstate.normal; audio.voice.speak("here"); } break; default: // nothing here... break; }
i have sql database contains commands. load commands need. has command name colum , value colum. can change these add change or delete columns needed.
currently, once command recognised, use combination of if statements , switch/case catch catch recognised command.
i have thought somehow dropping dll's folder , how scanning on app load. if add command somehow use value field action command in dll.
i realise rather complex situation feel better solution can found make process more simple.
edit: have looked @ already: http://social.msdn.microsoft.com/forums/en-us/4f962dc0-aec2-4191-9fe2-e1dfeb1da5dd/voice-command-api
please ask if need more information.
[edit] paqogomez has answered question. see working example below:
using system; using system.linq; using myapp.appcommands; using system.reflection; using system.collections.generic; namespace myapp { class program { static void main(string[] args) { methodinfo mymethod; var methods = new commands(); mymethod = commandfactory.getcommandmethods("time please"); mymethod.invoke(methods, null); mymethod = commandfactory.getcommandmethods("volume down"); mymethod.invoke(methods, null); mymethod = commandfactory.getcommandmethods("volume up"); mymethod.invoke(methods, null); console.readline(); } } public static class commandfactory { private static dictionary<string, methodinfo> commandmethods = new dictionary<string, methodinfo>(); public static methodinfo getcommandmethods(string command) { methodinfo methodinfo; var mycommandmethods = new commands(); if (commandmethods.count == 0) { var methodnames = typeof(commands).getmethods(bindingflags.public | bindingflags.declaredonly | bindingflags.instance); var speechattributemethods = methodnames.where(y => y.getcustomattributes().oftype<commandattribute>().any()); foreach (var speechattributemethod in speechattributemethods) { foreach (var attribute in speechattributemethod.getcustomattributes(true)) { commandmethods.add(((commandattribute)attribute).commandvalue, speechattributemethod); } } methodinfo = commandmethods[command]; } else { methodinfo = commandmethods[command]; } return methodinfo; } } } namespace myapp.appcommands { public class commands { [command("time please")] [command("whats time")] [command("what time it")] public void gettime() { console.writeline(datetime.now.tolocaltime()); } [command("volume down")] public void volumedown() { console.writeline("volume down 1"); } [command("volume up")] public void volumeup() { console.writeline("volume 1"); } } [system.attributeusage(system.attributetargets.method, allowmultiple = true)] public class commandattribute : system.attribute { public string commandvalue { get; set; } public commandattribute(string textvalue) { this.commandvalue = textvalue; } } }
beautiful work paqogomez , thank sharing! fast , elegant!.
in case, need call code is:
private static void commandrecognized(object sender, speechrecognizedeventargs e) { methodinfo mymethod; var methods = new commands(); mymethod = commandfactory.getcommandmethods(e.result.text); mymethod.invoke(methods, null); }
which event handler of speech recognition engine:
commandrecognitionengine.speechrecognized += new eventhandler<speechrecognizedeventargs>(commandrecognized);
you looking strategy pattern defined here.
this allow handle multiple if statements easily.
a factory pattern might suit you. factory use reflection determine command create.
you dump commands dictionary.
edit:
given last bit of code example factory need. i've put 1 below.
the factory reflects on methods in myspeechmethods
, looks ones speechattributes
, sends methodinfo
invoke. if need return values methods can either set methods return same type (like string) or generics, i'll leave you. :)
using system; using system.collections.generic; using system.linq; using system.reflection; using myapp.speechmethods; namespace myapp { class program { static void main(string[] args) { var methods = new myspeechmethods(); methodinfo mymethod; mymethod = speechfactory.getspeechmethod("time please"); mymethod.invoke(methods, null); mymethod = speechfactory.getspeechmethod("volume down"); mymethod.invoke(methods, null); mymethod = speechfactory.getspeechmethod("volume up"); mymethod.invoke(methods, null); } } public static class speechfactory { private static dictionary<string, methodinfo> speechmethods = new dictionary<string, methodinfo>(); public static methodinfo getspeechmethod(string speechtext) { methodinfo methodinfo; var myspeechmethods = new myspeechmethods(); if (speechmethods.count == 0) { var methodnames = typeof (myspeechmethods).getmethods(bindingflags.public | bindingflags.declaredonly | bindingflags.instance); var speechattributemethods = methodnames.where(y => y.getcustomattributes().oftype<speechattribute>().any()); foreach (var speechattributemethod in speechattributemethods) { foreach (var attribute in speechattributemethod.getcustomattributes(true)) { speechmethods.add(((speechattribute)attribute).speechvalue, speechattributemethod); } } methodinfo = speechmethods[speechtext]; } else { methodinfo = speechmethods[speechtext]; } return methodinfo; } } } namespace myapp.speechmethods { public class myspeechmethods { [speech("time please")] [speech("whats time")] [speech("what time it")] public void gettime() { console.writeline(datetime.now.tolocaltime()); } [speech("volume down")] public void volumedown() { console.writeline("volume down 1"); } [speech("volume up")] public void volumeup() { console.writeline("volume 1"); } } [system.attributeusage(system.attributetargets.method, allowmultiple = true)] public class speechattribute : system.attribute { public string speechvalue { get; set; } public speechattribute(string textvalue) { this.speechvalue = textvalue; } } }
Comments
Post a Comment