|
Posted: Mar 24, 2014 |
[ # 16 ]
|
|
Guru
Total posts: 1009
Joined: Jun 13, 2013
|
I understand the ChatScript solution too now. So basically popen() can activate any external program, with optional arguments merged into the command string beforehand.
In that case, should anyone else want a simple way of tying their ChatScript bot to the native Windows narrator, here’s some code for a visual basic file that you could activate by passing the following command string to popen():
talk.vbs "hello"
Code of the talk.vbs file (you can make this file in Notepad):
Set voice = CreateObject("sapi.spvoice") if(WScript.Arguments.Count = 1) then Dim text text = WScript.Arguments(0) voice.Speak text else voice.Speak "you must pass an argument" end if
|
|
|
|
|
Posted: Mar 24, 2014 |
[ # 17 ]
|
|
Moderator
Total posts: 2372
Joined: Jan 12, 2010
|
True, though popen does more than merely pass dynamic arguments over, it reads lines of responses from outside back into chatscript.
Cool, thanks for the code fragment.
|
|
|
|
|
Posted: Mar 24, 2014 |
[ # 18 ]
|
|
Moderator
Total posts: 2372
Joined: Jan 12, 2010
|
So I tried that (putting the talk.vbs script in chatscript home directory) and when CS called it, it opened the file and displayed it in notepad. What would I need to have done to make it run the script instead?
|
|
|
|
|
Posted: Mar 25, 2014 |
[ # 19 ]
|
|
Guru
Total posts: 1009
Joined: Jun 13, 2013
|
Oh, that’s easily overcome. popen() opens files in their default associated program, and apparently vbs files are set to open in Notepad on your computer. To change this, right-click the vbs file, select “open with” -> “choose default program” and change it to “Microsoft (R) Windows Based Script Host”, which is the program that normally runs the vbs script. As far as I know it comes installed with every Windows system. Make sure to V the checkbox for “use this program for all vbs files” or some such.
Let me know if it works out!
|
|
|
|
|
Posted: Mar 25, 2014 |
[ # 20 ]
|
|
Moderator
Total posts: 2372
Joined: Jan 12, 2010
|
Yup. I realized that as I went to sleep last night. Read your post just before I went to change it. Works now.
I had to make a few changes to CS to accommodate my uses of it so you’ll have to wait for next release (probably next week) for full utility. I added %os to know what os I was under, added $control_post = ~XPOSTPROCESS to bot definition, and then have this:
topic: ~xpostprocess system ()
t: (^query(direct_v ? chatoutput ? -1 ? @9 )) # get the sentences (why is the object)
loop()
{
$$tmp = ^last(@9subject) # note last output which is quoted string
if (!%server AND %os == windows)
{
$$tmp = join(talk " " $$tmp )
popen($$tmp null)
}
}
and eh voila, speech output from the bot. Engine changes include allowing a null function to popen (which wasn’t essential) and altering default storage of output facts from underscores to quoted string.
|
|
|
|
|
Posted: Mar 25, 2014 |
[ # 21 ]
|
|
Experienced member
Total posts: 69
Joined: Feb 6, 2014
|
I love you guys….but you still can’t have my beer. lol
|
|
|
|
|
Posted: Mar 25, 2014 |
[ # 22 ]
|
|
Guru
Total posts: 1009
Joined: Jun 13, 2013
|
Cool. I bet a lot of people are going to be happy with that.
I might as well ask, John, if you or anyone can see anything wrong this c++ code. This function copies my own program’s output text to the clipboard. Simultaneously I have a third party TTS program running that notices when the clipboard is used and starts reading the clipboard contents out loud. It works, but occasionally this crashes my program. Maybe I’m not locking memory where I should. No worries if you don’t know, I should probably be asking this on a c++ forum.
void copytoClipboard(const char* text) { const int textlength = strlen(text) +1; HGLOBAL copypaste = GlobalAlloc(GMEM_FIXED, textlength); if(copypaste != NULL) { memcpy(copypaste, text, textlength); if(OpenClipboard(GetDesktopWindow()) && EmptyClipboard() && SetClipboardData(CF_TEXT, copypaste) && CloseClipboard()) {;} } }
|
|
|
|
|
Posted: Mar 25, 2014 |
[ # 23 ]
|
|
Experienced member
Total posts: 69
Joined: Feb 6, 2014
|
Don,
To be honest, I dont know well enough to answer. I’ve never done anything like you’re doing there (clipboard and memcpy). My work has mostly been with SAPI and sending/recieving values through my com port to/from my microcontroller.
If the crashing is intermittent, though, I’d be inclined to agree that it’s probably a memory/pointer issue.
Wish I could be of more help.
|
|
|
|
|
Posted: Mar 25, 2014 |
[ # 24 ]
|
|
Guru
Total posts: 1297
Joined: Nov 3, 2009
|
I think every now and then you may be crashing by copying more text than you allocated memory for, Don.
This untested code is overkill, but you get the basic idea. Just brainstorming here.
HGLOBAL copypaste = GlobalAlloc(GMEM_FIXED, sizeof(text) + strlen(text)+2);
|
|
|
|
|
Posted: Mar 25, 2014 |
[ # 25 ]
|
|
Administrator
Total posts: 3111
Joined: Jun 14, 2010
|
I’m not conversant with any flavor of C, so please correct any wrong thinking here:
1.) It seems that you’re declaring a constant(?) (textlength) on each run of the above function. Is this common practice? Or is there a better way to declare it? I’m at least passingly familiar with several other programming/scripting languages, and I’ve never encountered a constant that only has local scope, so…
2.) I don’t think that 8Play’s suggestion of randomly insufficient memory allocation is the issue, unless the contents of the clipboard change at some point from the time textlength is set and the time the clipboard is utilized, but we’re talking about an insanely small amount of time here, so the likelihood of such a thing happening seems very small to me.
3.) The Windows clipboard is actually a collection of three completely different “objects” that happen to share the same memory space. There are text, image and file “objects”, and the random crash you’re experiencing may be a result of a conflict between them. I’m not sure of this, obviously, but it may be worth looking into.
|
|
|
|
|
Posted: Mar 26, 2014 |
[ # 26 ]
|
|
Guru
Total posts: 1009
Joined: Jun 13, 2013
|
Thanks for the thoughts, guys. I’ll try some alternatives like sizeof(), although the sizeof() value of string characters should be the same as the number of characters in the string (returned by strlen()). It’s supposed to allocate exactly enough memory for the string to fit into plus a null character (+1), and redo so every time a new text is passed to the function. I think 8pla’s code thus allocates memory for twice the length of the text. I could try a constant the size of Tokyo without dynamically allocating memory, see if that helps.
I’m setting the local variable ‘textlength’ just as a shortcut value so I don’t have to do strlen() twice (once to allocate the memory, once to copy exactly that length of memory, the string). I usually don’t set such variables constant, it’s probably unnecessary, I just saw this done in two examples.
I’m not doing anything else with the clipboard. The only theory I have is that maybe the TTS program on the other side is accessing the clipboard just as I’m writing to it.
|
|
|
|
|
Posted: Mar 26, 2014 |
[ # 27 ]
|
|
Administrator
Total posts: 3111
Joined: Jun 14, 2010
|
Maybe there’s a way to “lock” the memory for the clipboard fo everything else, set it, then release it? As I mentioned, I’m not familiar enough with C/C#/C++ to have more than a vague notion of things.
|
|
|
|
|
Posted: Mar 26, 2014 |
[ # 28 ]
|
|
Experienced member
Total posts: 69
Joined: Feb 6, 2014
|
One other thing I would check, Don, just to eliminate it… Once you find a sentence or phrase that crashes your program…can you test it by resending that exact same string? See if something that it crashed on once would make it crash again, consistently. If the same string doesn’t crash the second or third time, then you can probably eliminate bad input as the problem.
I’m wondering if there might not be a (hidden or control) character that some process doesn’t like. Either in your short code, or the TTS in the clipboard.
I know you’re working from MS to MS, but I’ve had to use Open Office many times to work with product information on my ecommerce website because MS puts all kinds of hidden crap in it’s output to my database that crashes my store.
ETA: I’m thinking there might be a /, “, or some other character from your generated input that’s killing the proces somewhere. In my store, I’ve now got it set to sanitize strings (ie: against sql injection attacks). You might want to find an example of how to sanitize a string, and run that on your generated output before sending it over to the clipboard. It’s only an additional line or two of code.
|
|
|
|
|
Posted: Mar 26, 2014 |
[ # 29 ]
|
|
Guru
Total posts: 1297
Joined: Nov 3, 2009
|
Don joked, “I could try a constant the size of Tokyo without dynamically allocating memory, see if that helps.”
Ha,ha… Ha! A good way to start the day, with a laugh. Of course I am exaggerating, throwing in the kitchen sink, in my code snippet. I’m just thinking, since it works most of the time, that maybe you’re sometimes writing just a tiny bit bigger than you allocated, and trashing something outside your block of memory allocated.
Oh, and I like what Dave said too. I don’t think my snippet used a constant either, but it is untested.
|
|
|
|
|
Posted: Mar 26, 2014 |
[ # 30 ]
|
|
Experienced member
Total posts: 69
Joined: Feb 6, 2014
|
Bruce Wilcox - Mar 25, 2014: Yup. I realized that as I went to sleep last night. Read your post just before I went to change it. Works now.
I had to make a few changes to CS to accommodate my uses of it so you’ll have to wait for next release (probably next week) for full utility. I added %os to know what os I was under, added $control_post = ~XPOSTPROCESS to bot definition, and then have this:
topic: ~xpostprocess system ()
t: (^query(direct_v ? chatoutput ? -1 ? @9 )) # get the sentences (why is the object)
loop()
{
$$tmp = ^last(@9subject) # note last output which is quoted string
if (!%server AND %os == windows)
{
$$tmp = join(talk " " $$tmp )
popen($$tmp null)
}
}
and eh voila, speech output from the bot. Engine changes include allowing a null function to popen (which wasn’t essential) and altering default storage of output facts from underscores to quoted string.
I’m trying to do some weird logging stuff. In simplecontrol.top, I want to log a custom file only for answers it cannot find and has to answer “I don’t know”. In order to do this, I need to know what the user typed. Is there a variable like “chatoutput” in your example above that will give me exactly what the user typed? Everything I’ve tried so far just gives me the count or the boolean, never their exact input.
|
|
|
|