cvWaitKey() is not working? - c

I'm reading a book. The author explains the function clearly. The problem is that my program doesn't detect any key that is pressed, so I can't terminate the window or stop a loop. This is the part of the problem.
while(1)
{
frame = cvQueryFrame( capture );
if ( !frame )
break;
cvShowImage("Example2", frame);
char c = cvWaitKey(33);
if ( c == 27 )
{
printf("Yes");
break; // 27 == escape button
}
}
I'm using Mac (I'm running the program from the terminal).

There might be 2 possibilities ,
The focus is not on the cv window when you press the key.
Try using just, cvWaitKey().

Related

xevent.xkey.keycode not working for me (X11)

So I have this piece of code which works well
while(1) {
XNextEvent(dpy,&e);
paint(cs,g);
if(e.xbutton.button == 1) {
evolue(g,gc,cycleG);
paint(cs,g);
printf("test");
}else if(e.xbutton.button==3) break ;
}
here xbutton.button == 1 is the left click.
I want to change the code so that it does the function with a keyboard press by changing it to
while(1) {
XNextEvent(dpy,&e);
paint(cs,g);
if(e.xkey.keycode == 54) {
evolue(g,gc,cycleG);
paint(cs,g);
printf("test");
}else if(e.xbutton.button==3) break ;
}
I got the keycode 54 by running xev on the terminal
so anyways logically the second piece of code should work but it just doesn't run the code inside the if statement unlike when it took mouse input. So..what gives? And how to fix it taking keyboard input?
Edit:
for further testing I wrote this code
while(1) {
XNextEvent(dpy,&e);
if(e.type == KeyPress){
paint(cs,g);
evolue(g,gc,cycleG);
}
if(e.type == ButtonPress){
paint(cs,g);
evolue(g,gc,cycleG);
}
}
so that it executes the program no matter what mouse button is pressed and no matter what keyboard key is pressed, but again, only mouse buttons execute the program while keyboard keys dont.
The problem was in a function above that chooses the input type it was this
XSelectInput(dpy, win, ExposureMask|ButtonPressMask);
I changed it to this
XSelectInput(dpy, win, ExposureMask|ButtonPressMask|KeyPressMask);
and this fixed it.

How can I have getch() just in some cases in C?

I don't really know how to type the Title so I came up with this. So basically I am trying to make some sort of a snake in C. But I don't know how to make the controls. Lets say you have pressed left arrow and the snake has to move left till another key is pressed but I can't come up with the code for that its always stopping and waiting for me to press the key.
I was thinking for something like this:
for ( i = 0; i < 10 ; i++ ) {
if( next_move = getch() ) break;
else Sleep(10);
}
if(!next_move)
next_move = prev_move;
if( move ( next_move, bite_cord ) ) {
prev_move = next_move;
next_move = 0;
Sleep(300);
system("CLS");
printf("You lost. ");
}
My idea was to wait one second and if theres no key pressed to continue with the previous one but if its pressed to save the pressed now.
Do you have any ideas of how to do it?
You can use kbhit()
The code would be something like
if (kbhit())
input = getch(); //Or something like that

Can anyone suggest a way of coding captureing keystrokes without waiting for keys to be pressed?

I'm coding a snake game in C and my compiler is turbo C.
I've got a problem with moving the snake. I need a function or a way of coding so that I can move my snake without the keyboard waiting for a key to be pressed. but if a key is pressed some specific actions are to be done. I used the structure below but it doesn't work as I explained above:
while (gameStatus == CONTINUE)
{
if(kbhit)
{
char c = getch();
.....
}
.....
}
can anyone help?
kbhit is a function. When you write if(kbhit) you are testing if the function exists. Instead call the function by writing if(kbhit()).
while (gameStatus == CONTINUE)
{
if (kbhit())
{
char c = '\0';
/*a keystroke return 0*/
if ((c=getch())!=0)
{
c=getch(); /*then you capture the actual directional key*/
......conditionals
}
//else if not was a directional, you Can Pause or Something
.....
}
.....
}

How do i stop the blocking?

Hey all I've asked this question a few times in the past few days but I just don't get it...I basically want to have the while loop for the Beep command executed in the background while the user can interact with the available case statements (only one shown..there are others)....i keep getting blocked and everytime i want the beep to make a sound constantly i block the rest of my program...I have to use Beep so please don't suggest any other functionality..
here's a sample code...
while( keypress != 'q' || keypress != 'Q')
{
x = Beep(x);
while (x == 1)
Beep(350,300);
alarm_t current;
keypress = _getch();
switch(keypress){
case 'h':
sprintf_s(current.message,"high alarm");
current.timeOfEvent = time(NULL);
recordEvent(current);
break;
Now...my issue is with the while loop and the Beep command....here is what i call to Beep(x)
int Beep(int y)
{
return y;
}
So basically i am trying to call a function outside of my current cpp file to just compare x and y, and return y as being equivalent to x...i thought this might avoid blocking but it doesn't...
Your while loop around beep just won't work and _getch is blocking. So it will just block until there's a character.
Depending what platform you are on, you need something like kbhit (and if you google that you will find alternatives for other platforms). ie it's not standard C functionality and platform specific.
kbhit will return true or false depending if there is a character or not.
So you can do:
while(!key_is_quit(ch))
{
Beep();
if(kbhit())
{
ch = getch();
// switch....
}
}

Input bar at console bottom in C

Window bottom
Some applications like vim, mutt, aptitude contain
a top window section for output and
a bottom section for the user to type in or for status display.
(Suppose there is one child process to output and another one to take user input. The purpose is to allow for updated output at the same time as you are typing the input or viewing the status.)
Actions Undo Package Resolver Search Options Views Help
C-T: Menu ?: Help q: Quit u: Update g: Download/Install/Remove Pkgs
|
|
|
|
|
┌─────────────┐ |
│Loading cache│ |
└─────────────┘ |
|
|
|
|
|
|
|
--------------------------------------------------------------------------- |
Initialising package states 100% |
+-------------------------------------------------------+
| some output here |
| |
| |
| |
| |
| |
|-------------------------------------------------------+
|:input here |
+-------------------------------------------------------+
Ncurses tutorial does not mention this to be obviously possible.
A query on "c print to {window,screen,terminal,console} bottom" at StackOverflow or at a web search engine isn't helpful.
Can this be done in C programmatically?
Discarding input
While some of the solutions below can move character to a given position, there is the problem that it may be needed to discard user input rather than leaving it on screen. Like in vim's case, typing ":w" and pressing Enter does not leave a ":w" on the screen.
Update. This is found here: How to delete text after getstr() c++ ncurses
Window focus - the UNSOLVED PART OF THE PROBLEM
While you are typing the input at window bottom and the text at the top changes, we see the problem of moving the focus back to the bottom. This is absent in the solutions as of December 29.
Update 1. Just attempting to
remember the previous cursor position, then
display the output, and then
restore the position
is not an easy solution: as these are different processes, attempts to retrieve cursor position don't affect the changes that happened during the other process execution.
Eg if parent takes input then the child doesn't know how the cursor position changed and can't restore the cursor position after performing a line of output at another part of the console.
Implementing this would involve some inter process communication and if there are other solutions they could be preferable.
Related
Get Input from keyboard without waiting for input Related, but not specific enough.
How to make a chat like UI using Python Urwid? Urwid for Python which does the job (per J.F. Sebastian in the comment below). Unfortunately not in C.
Using the standard libraries, there's no way to do that; using ncurses, as you already suggest, it is easily possible; I think this tutorial explains it quite nicely.
Using ANSI escape sequence it's possible to control the position of the cursor:
void gotoxy(int x, int y) {
printf("\033[%d;%dH",x,y);
}
So once you figure out the terminal height and width then you can use that function to position the cursor wherever you like and print stuff.
This answer suggests a slightly different approach, but it avoids a lot of complication you'd introduce by using the current method. I hope it is possible to implement these simplifications.
Use termio to turn off canonical mode.
Sample code (here) will show you exactly how to set up such an input loop. This sample 'polls-and-sleeps' which could mean a delay unless you reduce the sleep. Also I think you can use termio to set a timeout (wait a second and return 'no input' or give me the input NOW if it comes earlier). But if you are really going to monitor another process, polling might be the more flexible option.. You can really poll 30x a second and live with the .00001% processor hit it is going to cause, but you will love the simplicity and bug prevention it gives.
Avoid multiple threads and processes like the plague
You don't need to use 2 processes/threads if the only problem you are trying to solve is the fact that getch() blocks. That would be required if it were impossible to prevent the input functions from blocking. 'Canonical' (rules based) means all sorts of handy 'rules' are in effect, like, 'don't give the input to the program until ENTER is hit'. For a full screen console app you want to turn off all the rules and do everything yourself.
Put the main thread in charge of the window...
... Then you can just use the ansi escape csi codes to position the cursor back to where you want it. Caveat: you can't write to the lower-right box in the screen. Everything will scroll.
There is an annoying thing in MS windows programming where only the thread that creates a window can safely update it. There is actually a reason for this. Whether you're talking console, or windowing system. sooner or later, if you have multiple threads/processing hitting one output device, you'll interrupt an escape sequence (or have to make extra code to manage this which is a bad thing), be fighting for the output 'port', etc. you need one thread to manage the output.
if you really care about what some other thread or process is doing, just check it in your main console management loop. For example of you have another process that you just want to report its progress, start it from your program and capture its stdouput and look at that; another thread, just lock something shared you can check in your polling routine. Heck if it's just a byte and it's only used for statuses, don't even lock the damn thing. You can throw in a couple of GOTO's too, just to show your individuality :-)
caveat I don't know that ncurses would play well with you if you are manually messing with termio? I would guess it wants to do that itself. Never tried mixing. If your app is simple you could go it alone without the help, especially if you can wrestle ncurses into doing what you want. I'm no expert on those apps you mention but I'd bet they are micromanaging everything.
I had a similar issue a few weeks ago while writing an IRC client that runs in the terminal. I wrote it using the Windows conio library, but I'm fairly sure this should be applicable to curses. The idea is that console output is handled by a single thread, and console input is handled in a separate thread. Basically, all you need is a loop that pushes the return of getch() onto a mutexed FIFO that runs for the duration of the program. In the display thread, you can pop the keypresses off the FIFO and handle them however you like. You can't use a standard function like fgets(), but it's a very solid solution to your problem. I can provide the full (messy) source on request.
Edit: alright, well here's the relevant code from the FIFO pushing:
bool keyqueuewriting = false;
std::deque<int> keyqueue;
void grabkey( void* in )
{
int t;
while( true ){
t = getch();
#ifdef _WIN32
if( t == 224 || t == 0 )
{
t += getch() << 8;
}
#else
int off = 8;
if( t == 27 ){
int e = getch();
t += e << off;
off += 8;
while( e ==91 || (e >= '0' && e <= '9') || e == ';' )
{
e = getch();
t += e << off;
off += 8;
}
}
#endif
while( keyqueuewriting ){}
keyqueuewriting = true;
keyqueue.push_back( t );
keyqueuewriting = false;
}
}
And Handling:
while( keyqueuewriting ){}
keyqueuewriting = true;
while( keyqueue.size() > 0 )
{
shouldsleep = false;
int t = keyqueue.front();
keyqueue.pop_front();
switch( t )
{
case K_BACKSPACE:
if( pos > 0 ){
for( int i = pos-1; input[i] != 0; i++ ){input[i] = input[i+1];}
movecursorback( 1 );
pos -= 1;
} break;
case K_LEFT: if( pos > 0 ){ movecursorback( 1 ); pos -= 1; } break;
case K_RIGHT: if( input[pos] != 0 ) {movecursorforward( 1 ); pos += 1;} break;
case K_HOME: { gotoxy(0,SCREENHIG-1); pos = 0; } break;
case K_END: { int a = strlen( input ); /*gotoxy( 79,39 );*/ pos = a;} break;
case 3: exit(3); break;
default: if( t >= 0x20 && t < 0x80 ){
int a = strlen( input );
if( a > 998 )
a = 998;
int deadcode = 1;
input[999] = 0;
for( int i = a+1; i > pos; i-- ){input[i] = input[i-1];}
input[ pos ] = t;
movecursorforward( 1 );
pos++;
} break;
}
change = bufpos[curroom] - bufprev;
if( pos > 998 ) pos = 998;
if( pos - mescroll < 1 ) {mescroll += (pos-mescroll-1); gotoxy( pos-mescroll, SCREENHIG-1 );}
if( pos - mescroll > 78 ) {mescroll += (pos-mescroll-78); gotoxy( pos-mescroll, SCREENHIG-1 );}
if( mescroll < 0 ) {mescroll = 0; gotoxy( 0, SCREENHIG-1 ); }
savexy();
gotoxy( 0, SCREENHIG-1 );
char y = (input+mescroll)[79];
(input+mescroll)[79] = 0;
printf( "%s ", input+mescroll );
(input+mescroll)[79] = y;
returntosaved();
change2 = change;
bufprev = bufpos[curroom];
}
keyqueuewriting = false;
Yes, it uses std::deque. That should be the only C++ specific thing though. Just replace it with a C compatible FIFO.
The entire client can be found here.
Yes, it DOES compile in Linux, but it doesn't work. I never bothered to figure out how ncurses should be used before I started work on it.

Resources