Closed BawdyInkSlinger closed 4 years ago
No offense taken, The dragonfly framework is written in Python. However dragonfly can be used to to create a grammar for any programming language.
To answer your specific question, print("Voice command spoken.")
print a message to the natlink messages window or command prompt window.
def _process_recognition(self, node, extras): # Callback when command is spoken.
print("Voice command spoken.")
If you spoke do something computer
the following would be printed out to the natlink messages window or command prompt window.
Recognized: do something computer
Voice command spoken.
Basically _process_recognition
callback tells the user when a command was recognized Recognized: do something computer
. You could change print("Voice command spoken.")
to Text("Voice command spoken.").execute()
. Then every time any command is recognized, the phrase Voice command spoken
would be typed out as if you use the keyboard. If you're using the example verbatim you'll need to change the imports to from dragonfly import Grammar, CompoundRule, Text
to include Text
.
While the following wouldn't be included in the readme as it's too large, this might be helpful to you. The readme could be clarified.
To run the following grammar
python -m dragonfly load --engine natlink _sample.py
in the same directory as _sample.py
# These lines that start with the # are called comments. They don't affect the way the code runs.
# In this tutorial file, I put comments above the relevant lines.
# Before we begin, it's worth noting that the name of this file, sample.py, will cause it to never run.
# You will have to rename it to "_sample.py".
# Putting an underscore as the first character of a grammar Python file will tell dragonfly
# that you want this file to run all the time. Grammars that run all the time are good way to start.
# The alternative is making grammars for specific programs that only trigger when the programs are active.
# You can skip down to the next comment, none of this stuff is really important...
from dragonfly import (BringApp, Key, Function, Grammar, Playback,
IntegerRef, Dictation, Choice, WaitWindow, MappingRule, Text)
def my_function(n, text):
print("put some Python logic here: "+str(text))
class MainRule(MappingRule):
mapping = {
# it is this section that you want to fiddle around with if you're new: mapping, extras, and defaults
# in the next line, there are two things to observe:
# the first is the use of parentheses and the pipe symbol (|)
# --this lets me use either "lock dragon" or "deactivate" to trigger that command.
# The next is the playback action, which lets me tell Dragon to simulate me speaking some words.
'(lock Dragon | deactivate)': Playback([(["go", "to", "sleep"], 0.0)]),
# Here I'm using BringApp-- this is the same as typing what goes in between the parentheses
# into the Windows command prompt, without the quotes and commas, like:
# explorer C:\NatLink\NatLink\MacroSystem
# -- (which would open Windows Explorer at the specified location). Anything you can do with the command line can be done this way
"open natlink folder": BringApp("explorer", r"C:\NatLink\NatLink\MacroSystem"),
# here I'm using the Key action to press some keys -- see the documentation here: https://dragonfly2.readthedocs.io/en/latest/actions.html?highlight=key#module-dragonfly.actions.action_key
"remax": Key("a-space/10,r/10,a-space/10,x"),
# here I'm chaining a bunch of different actions together to do a complex task
"(show | open) documentation": BringApp('C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe') + WaitWindow(executable="chrome.exe") + Key('c-t') + WaitWindow(title="New Tab") + Text('https://dragonfly2.readthedocs.io/en/latest') + Key('enter'),
# here I'm just saying one word to trigger some other words
"hotel": Text("hotels are not cheap"),
# If you need to do more complicated tasks, or use external resources, a function might be what you need.
# note that here, I'm using extras: "n" and "text"
# The angle brackets <> meaning I'm using an extra, and the square brackets [] mean that I don't have to speak that word, it's optional.
# Advice: if you use an optional extra, like I am with "text", you should set a default value in the defaults section down below.
# To trigger the following command, you would have to say the word "function" followed by a number between 1 and 1000.
'[use] function <n> [<text>]': Function(my_function, extra={'n', 'text'}),
}
extras = [
IntegerRef("n", 1, 1000),
Dictation("text"),
Choice("choice",
{"alarm": "alarm", "custom grid": "CustomGrid", "element": "e"
}),
]
defaults = {"n": 1,
"text": "",
}
# this stuff is required too-- where I have the word "sample" below, each grammar file should have external unique
grammar = Grammar('sample')
grammar.add_rule(MainRule())
grammar.load()
I hope this helps your understanding :)
Yeah that helps a lot. I think some of this should be added to the readme. Thanks
FYI, for just trying stuff out, it might be easier to use the Kaldi backend, which can be installed a bit more simply, or the portable distribution from https://github.com/daanzu/kaldi-active-grammar/releases.
@LexiconCode That is a great demo example grammar! And I don't think it is too big for the README at all, especially considering how useful it would be. Although if you are worried about how it looks, you can do something like https://gist.github.com/pierrejoubert73/902cc94d79424356a8d20be2b382e1ab.
Hello @AcademyOfF,
Thank you for your suggestions! No offence is taken by me either; issues like this can occur when software documentation in general is not written or reviewed with different perspectives in mind. As the maintainer of this project, this is something I will try to keep in mind in the future.
I agree that the usage example should be before the installation part and it should be more like what @LexiconCode has posted above.
@daanzu I like the idea of putting things in expandable <details>
sections. I'll make some changes to the README file soon and link to them in this issue.
@daanzu I appreciate the feedback and specially the gist with \
Perhaps a separate FAQ page would also be useful?
Perhaps a separate FAQ page would also be useful?
That would be one way to go about it and would probably work just fine.
Right off the bat, I think the readme should start with answering the question of, "what does this project do?" Dragonfly is a speech recognition framework.
Kind of answers that, but it can be interpreted many ways and it's kind of more about what it is than what it does. The next sentence of It is a Python package which offers a high-level object model and allows its users to easily write scripts, macros, and programs which use speech recognition.
is more about The technology used than what the technology does.
I think a better introduction paragraph would be this:
dragonfly is a framework that makes it convenient to create custom commands in dictation software. The problem with creating custom commands natively in a front end tool like Dragon Software is…
From there, you can describe how these dragonfly scripts can be reused regardless of the dictation software you're using and how inconvenient it is to create custom commands with the built-in front ends, etc.
@AcademyOfF Thank you for this! I will rewrite the README with these things in mind.
The README currently includes a link to Stack Overflow posts tagged with "python-dragonfly" as the FAQ. While those questions and answers are useful, many of them are related to issues that were fixed some time ago. We also have no control over what questions Stack Overflow lists and in which order. I'll start putting together a proper FAQ for Dragonfly, post a link to it here and in the Gitter chat channels for input on changes, additional questions, etc.
The README currently includes a link to Stack Overflow posts tagged with "python-dragonfly" as the FAQ. While those questions and answers are useful, many of them are related to issues that were fixed some time ago. We also have no control over what questions Stack Overflow lists and in which order. I'll start putting together a proper FAQ for Dragonfly, post a link to it here and in the Gitter chat channels for input on changes, additional questions, etc.
I agree. Creating a FAQ is something I can get behind, but it's unrelated to my original request. Could we create a separate issue for the FAQ?
Sure, good point. I'll create a separate issue for it.
great, thanks a lot
I mean no offense by what I'm saying, but it's challenging to figure out what dragonfly does. From what I can tell with the example at the bottom, it gives me a way to write some code in Python that will generate text. Like, I think it's an alternative way of creating commands in Dragon software (or other software).
do something computer
willprint("Voice command spoken.")
, But what it would mean to "print" that content. Doesprint
mean it gets typed out at the cursor? I'm not asking for you to explain an excessive amount of detail, but a high level explanation of what this macro does would really help.