can't capture keyboard strokes with cvWaitKey() - keyboard

I have a problem here and need your help. I've been trying to capture keyboard strokes using cvWaitKey() function.
cvWaitKey(10) should return the keyboard stroke pressed every 10ms.
But in my case, I'm getting every 18 seconds, all the keys that I've pressed during this period of 18 seconds, at once.
And the window that should normally close when I press 'esc' (see the code) is still open.
In console I get this:
VIDIOC_QUERYMENU:Invalid argument
VIDIOC_QUERYMENU:Invalid argument
VIDIOC_QUERYMENU:Invalid argument
-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-11536870939-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-111536870939-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1
With:
1536870939 corresponds to when I pressed 'esc'
-1 correspond to when no key was pressed
Thanks for help.
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include "iostream"
using namespace std;
int main()
{
IplImage *src=cvCreateImage(cvSize(640,480), 8, 3);
CvCapture* capture =cvCaptureFromCAM(CV_CAP_ANY);
int key;
while(1){
src = cvRetrieveFrame( capture );
cvNamedWindow( "out", CV_WINDOW_AUTOSIZE );
cvShowImage( "out", src );
key = cvWaitKey(10);
cout<<key;
if( key == 1536870939 ) break; //if 'esc' is pressed (in ubuntu 10.04)
cvGrabFrame( capture );
}
cvDestroyAllWindows();
cvReleaseCapture( &capture );
return 0;
}
I'm using: Opencv 2.2.0 , ubuntu 10.04 LTS , CodeBlocks 8.02

try using a 0xff mask to return 27 on an ESC key press:
if( (cvWaitKey(10)&0xff) == 27 ) break;
Alternatively, you can cast to a character:
if( (char)cvWaitKey(10) == 27 ) break;

The cause of the problem is the way cout works: it buffers characters and only sends them to the console if you send a newline character or if you explicitly ask it to do so. (Third case: the buffer gets full... but that's what you have to wait 18 seconds for.)
So put either cout << '\n'; or cout.flush(); after your current cout statement.
(By the way: VIDIOC_QUERYMENU:Invalid argument is from the v4l (webcam) driver... and I have no idea where 1536870939 comes from, ESC should be 27 :))

Related

proper way of catching control+key in ncurses

What is the proper way of catching a control+key in ncurses?
current im doing it defining control like this:
#define ctl(x) ((x) & 0x1f)
it works ok, but the problem is that i cannot catch C-j and ENTER at the same time, and this is because:
j = 106 = 1101010
0x1f = 31 = 0011111
1101010 & 0011111 = 0001010 = 10 = ENTER key..
So.. how shall I catch it?
Thanks!
--
Edit:
If i try the code below,
I am not able to catch the enter key correctly, not even in the numeric keyboard. Enter gets catched as ctrl-j.
#include <stdio.h>
#include <ncurses.h>
#define ctrl(x) ((x) & 0x1f)
int main(void) {
initscr();
int c = getch();
nonl();
switch (c) {
case KEY_ENTER:
printw("key: %c", c);
break;
case ctrl('j'):
printw("key: ctrl j");
break;
}
getch();
endwin();
return;
}
New code:
#include <stdio.h>
#include <ncurses.h>
#define ctrl(x) ((x) & 0x1f)
int main(void) {
initscr();
int l = -1;
int c = getch();
cbreak();
noecho();
nonl();
keypad(stdscr, TRUE);
switch (c) {
case KEY_ENTER:
printw("key: %c", c);
break;
case ctrl('j'):
printw("key: ctrl j");
break;
}
printw("\nnow press a key to end");
getch();
endwin();
return;
}
Try nonl:
The nl and nonl routines control whether the underlying display device
translates the return key into newline on input, and whether it translates newline into return and line-feed on output (in either case, the
call addch('\n') does the equivalent of return and line feed on the
virtual screen). Initially, these translations do occur. If you disable them using nonl, curses will be able to make better use of the
line-feed capability, resulting in faster cursor motion. Also, curses
will then be able to detect the return key.
Further reading: the Notes section of the getch manual page:
Generally, KEY_ENTER denotes the character(s) sent by the Enter key on
the numeric keypad:
the terminal description lists the most useful keys,
the Enter key on the regular keyboard is already handled by the
standard ASCII characters for carriage-return and line-feed,
depending on whether nl or nonl was called, pressing "Enter" on the
regular keyboard may return either a carriage-return or line-feed,
and finally
"Enter or send" is the standard description for this key.
That addresses the question about newline/carriage-return translation. A followup comment is a reminder to point out that the manual page gives basic advice in the Initialization section:
To get character-at-a-time input without echoing (most interactive,
screen oriented programs want this), the following sequence should be
used:
initscr(); cbreak(); noecho();
and that OP's sample program did not use cbreak (or raw). The manual page for cbreak says
Normally, the tty driver buffers typed characters until a newline or
carriage return is typed. The cbreak routine disables line buffering
and erase/kill character-processing (interrupt and flow control characters are unaffected), making characters typed by the user immediately
available to the program. The nocbreak routine returns the terminal to
normal (cooked) mode.
Initially the terminal may or may not be in cbreak mode, as the mode is
inherited; therefore, a program should call cbreak or nocbreak explicitly. Most interactive programs using curses set the cbreak mode.
Note that cbreak overrides raw. (See curs_getch(3x) for a discussion
of how these routines interact with echo and noecho.)
Also, in curs_getch you may read
If keypad is TRUE, and a function key is pressed, the token for that
function key is returned instead of the raw characters:
The predefined function keys are listed in <curses.h> as macros
with values outside the range of 8-bit characters. Their names begin with KEY_.
That is, curses will only return KEY_ENTER if the program calls keypad:
keypad(stdscr, TRUE);
For the sake of discussion, here is an example fixing some of the problems with your sample program as of May 17:
#include <stdio.h>
#include <ncurses.h>
#define ctrl(x) ((x) & 0x1f)
int
main(void)
{
int c;
initscr();
keypad(stdscr, TRUE);
cbreak();
noecho();
nonl();
c = getch();
switch (c) {
case KEY_ENTER:
printw("\nkey_enter: %d", c);
break;
case ctrl('j'):
printw("\nkey: ctrl j");
break;
default:
printw("\nkeyname: %d = %s\n", c, keyname(c));
break;
}
printw("\nnow press a key to end");
getch();
endwin();
return 0;
}
That is, you have to call keypad before getch, and the value returned for KEY_ENTER is not a character (it cannot be printed with %c).
Running on the Linux console with the usual terminal description, you will see only carriage return for the numeric keypad Enter, because that description does not use application mode. Linux console does support application mode, and a corresponding description could be written. As a quick check (there are differences...) you could set TERM=vt100 to see the KEY_ENTER.

Get the char that would be typed on `XKB_KEY_dead_circumflex` and normal key

Is there a way to determine in which character it would resolv e.g. if I would type XKB_KEY_dead_circumflex and char a? The result here would be â, but how can I detect this programmatically?
This not only applies to XKB_KEY_dead_circumflex, but e.g. also to XKB_KEY_dead_greek to type the greek alphabet.
In X, this particular behaviour is determined by the Input Method (IM). X is very flexible; you could write an input method that combines XKB_KEY_dead_circumflex and a into Japanes キ if you like. Or output an è, if you want to confuse your users...
You could try XmbLookupString or Xutf8LookupString to simulate keypresses and return the correct character:
XIM im= XOpenIM(display, NULL, NULL, NULL);
XIC ic = XCreateIC(im);
char buf[8];
KeySym symbol;
Status status;
XKeyPressedEvent event;
event.type = XKeyPressEvent;
event.display = display;
event.window = window;
event.state = 0; // optionally add Shift, Ctrl, Meta
event.keycode = XBK_KEY_dead_circumflex;
Xutf8LookupString(ic, &event, buf, 8, symbol, status); // send dead key
event.keycode = XBK_KEY_a;
Xutf8LookupString(ic, &event, buf, 8, symbol, status); // send real key
buf should now contain the UTF8 code for â, but check status to see if the transformation succeeded.
Note that you have to pass the keycode for 'a', not the ASCII code for 'a' (I don't think there is any X function that takes a dead key and a character and returns the combination). You must also simulate only KeyPresses (see the manual page for Xutf8LookupString).

XKeysymToKeycode, XTestFakeKeyEvent and mapping

I have the following problem:
I'm trying to send fake key events to the X server.
To do this, I'm aware of two methods:
XSendEvent - I tried this tutorial with the XK_Z instead of XK_Down
Does not work with GTK3
XTestFakeKeyEvent - See my code below
My problem is, None of this method takes account of the keyboard mapping. I mean, when I select AZERTY mapping I have a "z" character as I expect, when I select the QWERTY mapping I get a "w" and with my beloved BÉPO mapping I get an "é".
How can I get the same character independently of the keyboard mapping??
I'm using Ubuntu 12.10 under Unity.
Here, my code for XTestFakeKeyEvent:
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>
#include <iostream>
// The key code to be sent.
// A full list of available codes can be found in /usr/include/X11/keysymdef.h
/* g++ -o XFakeKey tst.c -L/usr/X11R6/lib -lX11 -lXtst */
char *text = "z";
main()
{
// Obtain the X11 display.
Display *display = XOpenDisplay(0);
if(display == NULL)
return -1;
Window focusWindow;
int revert;
XGetInputFocus(display, &focusWindow, &revert);
KeyCode code = XKeysymToKeycode(display, XStringToKeysym(text));
XTestFakeKeyEvent(display, code, True, CurrentTime);
XTestFakeKeyEvent(display, code, False, CurrentTime);
XCloseDisplay(display);
return 0;
}
Use the XChangeKeyboardMapping API to bind a unicode Keysym to an unused Keycode.
Then, you send the remapped Keycode (using XTestFakeKeyEvent or XSendEvent) and applications that use XKeycodeToKeysym will get your intended symbol, independent of the current keyboard/IME.
Not tested, but seems to work according to this comment.

Ncurses: F1-F5 keys

I have a Probclem with functions keys in curses.h.
I have this littel programm seen on different websites/tutorials
#include <ncurses.h>
int main()
{ int ch;
initscr(); /* Start curses mode */
raw(); /* Line buffering disabled */
keypad(stdscr, TRUE); /* We get F1, F2 etc.. */
noecho(); /* Don't echo() while we do getch */
printw("Type any character to see it in bold\n");
ch = getch();
while (ch != KEY_F(1))
{
if(ch == KEY_F(1))
printw("F1 Key pressed: Ending program.\n");
else
{ printw("The pressed key is ");
attron(A_BOLD);
printw("%c\n", ch);
attroff(A_BOLD);
}
refresh();
ch = getch();
}
printw("end\n");
endwin(); /* End curses mode */
return 0;
}
The keys F6-F12 works fine and the code which is returned is also fine (for example: 270 if F6 ist pressed). But if I press F5 not 269 is returned, like it would be supposed to be, instead the following is happening (only by pressing F5 once):
Type any character to see it in bold
The pressed key is ^[
27
The pressed key is [
91
The pressed key is 1
49
The pressed key is 5
53
The pressed key is ~
126
So I think the whole Escape Sequence ist returned. I read on the internet about this problem and two times there was a hint which describes to change the TERM variable to xterm or vt100. So I tried to change TERM to vt 220 and also xterm, but nothing change. When i changed it to vt100 also F6-F12 didn't work.
Can anybody help me how I can recognize if the user presses F1-F5? Keys like enter, Backspace, up, down, etc. are recognized fine.
best regards
Sounds like a disagreement between what terminfo says your terminal sends and what it actually does. May be the result of an incorrect terminfo file on the target machine, or the wrong $TERM setting, or any number of things.
I'd start by comparing what
$ infocmp -L
says on the target machine, as compared what the terminal actually sends when running, say, cat.
If you are running xterm, maybe you have a ~/.Xresources file translating your function keys. VMS users often would remap F1 - F5 keys that way. Also many terminal emulators (like Putty) have options to remap these keys.

getch() of ncurses doesn't work

I need to create a mainloop for my program and wrote the following function:
void menu(){
int ch;
cbreak();
noecho();
initscr();
refresh();
while (ch != KEY_F(9)){
ch = getch();
cout << ch << endl;
switch (ch){
case KEY_F(1): add();
break;
case KEY_F(2): edit();
break;
case KEY_F(3):
break;
case KEY_F(4):
break;
}
}
endwin();
}
But getch() doesn't work and print -1 in loop. how i do?
May i set special attr or call special func?
You need to call keypad() e.g. keypad(stdscr, TRUE). But beyond that the function keys may not work on your terminal. Check your ncurses.h file for a has_key() function and you can use that to determine if they are available on your terminal.
First, every ncurses function should be used only after initscr() has been called. In your code cbreak() and noecho() are probably ignored.
Second, if you want to use function keys, you have to tell that to ncurses, by calling keypad(stdscr, TRUE). However, since not every computer has got function keys, you should always check if the system support that functionality, using has_key() (same for has_colors() that checks if current terminal supports colors).
Yes, my loop is here:
initscr();
clear();
noecho();
cbreak(); /* Line buffering disabled. pass on everything */
startx = (80 - WIDTH) / 2;
starty = (24 - HEIGHT) / 2;
menu_win = newwin(HEIGHT, WIDTH, starty, startx);
keypad(menu_win, TRUE);
mvprintw(0, 0, "Name of my program");
refresh();
print_menu(menu_win, highlight);
while (true)
{ c = wgetch(menu_win);
switch(c){
TYPE OF KEYS;
}//END OF SWITCH
}//END OF LOOP

Resources