Console app input

BlitzMax Forums/BlitzMax Beginners Area/Console app input

spacerat(Posted 2007) [#1]
Hey, a quick question concerning consoles. I am making a server app, which (as a server does) needs to be constantly executing it's code. I ALSO need it to take input without pausing the code execution so the input command is out of the question. Polled input (if KeyDown, etc) does not seem to work with console apps, and I don't want to have to create another app just to act as input for the server.

Any help would be appreciated :D

EDIT: I did some sniffing around and found that the input() function simply reads from the stream connecting blitz to the console using readline(). I also found that the function that tells the console to accept input at all, is that readline() function. The reason it pauses (I think) is that readline pauses if you call it and there is nothing to read. So if there is a way of asking the console for input without having the pausiness of readline, that is what I need.


Perturbatio(Posted 2007) [#2]
this might help (win32 only):

?Win32
Extern 
	Function getch() = "getch"
EndExtern
?
a = getch()
While a <> 13 
	Print Chr(a)
	a = getch()
Wend


Press return to quit


spacerat(Posted 2007) [#3]
Awesome, thanks perturbatio, it does just what I wanted. However I might also need this for linux too, so if someone could find out a similar function for linux or point me in the right direction that would put the icing on the cake.

Edit: Someone suggest it should work with wine, so I am not particularly in need of a linux solution.


TaskMaster(Posted 2007) [#4]
Windows apps running under wine kinda suck. So, if you can make a Linux version, that is way better.


spacerat(Posted 2007) [#5]
Obviously I fail at testing, the function you gave doesn't do what I want; it still pauses to wait for the string when you call getch. I need it to be asynchronus, I need to be able to type into the console and read from it, while still executing code.


tonyg(Posted 2007) [#6]
Does it have to be the console window of a console App or can it be a graphics window?
This might help.


spacerat(Posted 2007) [#7]
It has to be a console window, I cannot use the graphics window since this may get used on a text only linux server. Also that link didn't help since that uses graphics.


WendellM(Posted 2007) [#8]
This issue has been in the back of my mind a bit, too, so I poked around the web and found GetAsynchKeyState, and searching for that on these forums led to: http://www.blitzbasic.com/Community/posts.php?topic=68096

Here's a quick & dirty example showing that the program executes continuously in the console:
Extern "win32"
	Function GetAsyncKeyState:Short( key:Int )
End Extern

Local typed$
Repeat
	For c = KEY_BACKSPACE To KEY_Z
		If KeyHit(c) Then typed :+ Chr(c)
	Next
	If Rand(100) = 100 Then Print "I rolled 100! So far, you've typed: " + typed
	Delay 10
Forever

Function KeyHit:Int(key:Int)
	Select GetAsyncKeyState(key)
		Case 32767,-32767
			Return True
		Default
			Return False
	EndSelect
EndFunction

Function KeyDown:Int(key:Int)
	Select GetAsyncKeyState(key)
		Case 32767,32768,-32767,-32768
			Return True
		Default
			Return False
	EndSelect
EndFunction

Const KEY_BACKSPACE=$08
Const KEY_TAB=$09
Const KEY_CLEAR=$10
Const KEY_ENTER=$0D
Const KEY_SHIFT=$10
Const KEY_CTRL=$11
Const KEY_ALT=$12
Const KEY_PAUSE=$13
Const KEY_CAPSLOCK=$14
Const KEY_ESCAPE=$1B
Const KEY_SPACE=$20
Const KEY_PAGEUP=$21
Const KEY_PAGEDOWN=$22
Const KEY_END=$23
Const KEY_HOME=$24
Const KEY_LEFT=$25
Const KEY_UP=$26
Const KEY_RIGHT=$27
Const KEY_DOWN=$28
Const KEY_SELECT=$29
Const KEY_PRINT=$2A
Const KEY_EXECUTE=$2B
Const KEY_PRTSCRN=$2C
Const KEY_INSERT=$2D
Const KEY_DELETE=$2E
Const KEY_HELP=$2F
Const KEY_0=$30
Const KEY_1=$31
Const KEY_2=$32
Const KEY_3=$33
Const KEY_4=$34
Const KEY_5=$35
Const KEY_6=$36
Const KEY_7=$37
Const KEY_8=$38
Const KEY_9=$39
Const KEY_A=$41
Const KEY_B=$42
Const KEY_C=$43
Const KEY_D=$44
Const KEY_E=$45
Const KEY_F=$46
Const KEY_G=$47
Const KEY_H=$48
Const KEY_I=$49
Const KEY_J=$4A
Const KEY_K=$4B
Const KEY_L=$4C
Const KEY_M=$4D
Const KEY_N=$4E
Const KEY_O=$4F
Const KEY_P=$50
Const KEY_Q=$51
Const KEY_R=$52
Const KEY_S=$53
Const KEY_T=$54
Const KEY_U=$55
Const KEY_V=$56
Const KEY_W=$57
Const KEY_X=$58
Const KEY_Y=$59
Const KEY_Z=$5A
Crude, but it's a start. You'll need to handle special keys (e.g. Enter, Shift) and keep track of capitalization yourself if that's important. Also note that this gets what's typed whether the console has the focus or not, so it sees all input.


ziggy(Posted 2007) [#9]
I suggestyou to run the console environment as a service, and connect the two applications (the server itself, and the console app) using pipes. The same way MaxIDE does with the running BlitzMax program. This is the best choice, as the user-console will run on a separate thread, and the server won't stop execution


Picklesworth(Posted 2007) [#10]
Since I'm too lazy to sort out Pipes myself, can anyone share an example of using those in BlitzMax?
I've never used pipes before, and my search here revealed one thread called "Pipes" which seems to have disappeared :(


Brucey(Posted 2007) [#11]
Pickles, perhaps an investigation into "popen" might be of interest. (try "man popen" in Linux for help).
Perhaps not what you want, but it's one way... ;-)


SebHoll(Posted 2007) [#12]
Brucey is currently developing a cross-platform Curses module that should allow for better console UIs - check out his worklog for more information. And as it is event driven, it should allow you to execute code while waiting for input.

LOL, Brucey beat my post by 35 seconds!


Brucey(Posted 2007) [#13]
Aye, but I'm not sure that's what spacerat is after.

But spacerat, if it is the sort of thing you're planning, it's working great so far. "true" event driven console apps with UI components.
There was a small windows demo exe that showed a clock ticking while you could input in the text box - working on all three supported platforms. (I code primarily on Linux then port to Mac/Windows).


Picklesworth(Posted 2007) [#14]
Yep, popen sounds like the right track.
I'm pondering separating the GUI and the core for a program (as well as allow for some kind of fancy cross-platform extendibility), and i/o seems a nice and simple way to do it. Just need to know how to link one program's i/o with another!
From the looks of it, the IDE is a good place to start learning. (Only problem being that its source code is scary).
A quick search gave me
		process=CreateProcess(cmd$,HIDECONSOLE)

		If Not process Notify "Process Failure with "+cmd;Return

		If Not process.status() Notify "Process Failed to start "+cmd;process=Null;Return		

		pipe=TTextStream.Create(Process.pipe,TTextStream.UTF8)
...Which looks like the right thing!


As for your stuff, spaceRat, I believe readstdin will read your input without a pause. Only thing then is getting processes to find yours, which can be done a number of ways. It is common for server processes to run as daemon processes, with other programs that you can then run to send them data through some means that the user needn't think about.
Reading up on mutexes may help. I don't understand them very well myself, but everyone else seems to, and apparently they do something for identifying / finding running processes. I would suggest dbus if you were using Linux (a global interface to pass all kinds of messages between processes without needing a specific target), but there has been absolutely no mention of it here so it could be a pain to get going.