Uinput - Mouse events were not working - linux

I was finding a problem in emulating the mouse events via uinput device event files.
I could write the event with 'struct input_event' structure format for keyboard/mouse events but only key events were working fine and mouse events were not working
I enabled all the bits required for uinput
UI_SET_EVBIT - EV_KEY (keyboard/mouse), EV_REP (Repeating events), EV_SYN (Sync report events), EV_REL (Mouse)
UI_SET_RELBIT - REL_X, REL_Y (Mouse)
UI_SET_KEYBIT - All the keys in keyboard, BTN_MOUSE, BTN_LEFT, BTN_RIGHT, BTN_MIDDLE
I triggered the events with the below code
gettimeofday(&ev.time,0);
ev.type = EV_KEY;
ev.code = BTN_LEFT;
ev.value = <MOUSE PRESS/RELEASE>; // tbhis wil lbe either 0 or 1
if(write(uinputfd, &ev, sizeof(ev)) < 0)
{
return false;
}
// Then send the X
gettimeofday(&ev.time,0);
ev.type = EV_REL;
ev.code = REL_X;
ev.value = x;
if(write(uinputfd, &ev, sizeof(ev)) < 0)
{
return false;
}
// Then send the Y
gettimeofday(&ev.time,0);
ev.type = EV_REL;
ev.code = REL_Y;
ev.value = y;
if(write(uinputfd, &ev, sizeof(ev)) < 0)
{
return false;
}
// Finally send the SYN
gettimeofday(&ev.time,0);
ev.type = EV_SYN;
ev.code = SYN_REPORT;
ev.value = 0;
if(write(uinputfd, &ev, sizeof(ev)) < 0)
{
return false;
}
Also, I could read/print the Keyboard/Mouse events from the corresponding uinput device input files.
Does anybody have any idea why only mouse events were not working?

I do not have an answer why, but I have noticed that I had to separate keys, absolute, and relative into separate devices. I was hoping somebody else had the answer of how to combine them into one device.
Edit1: Key and relative events are able to be on the same device. If you would still like help for this, I would suggest posting the code used to set up the struct uinput_user_dev, and writing the SET_EVBIT and SET_RELBIT. The sending of events looks fine, so it is probably the initialization, or closing.

Related

Video call using PJSUA

I'm using pjsua to create a video call from a monitor to a phone. I'm able to establish an audio call without problem, but if I try to establish a video call (vid_cnt=1), I'm getting an error.
My purpose is to get and save the audio and video of the phone.
This is my configuration:
void hard_account_config(pjsua_acc_config& acc_cfg, pjsua_transport_id transport_tcp) {
pjsua_acc_config_default(&acc_cfg);
acc_cfg.ka_interval = 15;
// VIDEO
acc_cfg.vid_in_auto_show = PJ_TRUE;
acc_cfg.vid_out_auto_transmit = PJ_TRUE;
acc_cfg.vid_cap_dev = VideoCaptureDeviceId();
acc_cfg.vid_wnd_flags = PJMEDIA_VID_DEV_WND_BORDER | PJMEDIA_VID_DEV_WND_RESIZABLE;
acc_cfg.reg_timeout = 300;
acc_cfg.use_srtp = PJMEDIA_SRTP_DISABLED;
pjsua_srtp_opt_default(&acc_cfg.srtp_opt);
acc_cfg.ice_cfg_use = PJSUA_ICE_CONFIG_USE_CUSTOM;
acc_cfg.ice_cfg.enable_ice = PJ_FALSE;
acc_cfg.allow_via_rewrite = PJ_FALSE;
acc_cfg.allow_sdp_nat_rewrite = acc_cfg.allow_via_rewrite;
acc_cfg.allow_contact_rewrite = acc_cfg.allow_via_rewrite ? 2 : PJ_FALSE;
acc_cfg.publish_enabled = PJ_TRUE;
acc_cfg.transport_id = transport_tcp;
acc_cfg.cred_count = 1;
acc_cfg.cred_info[0].username = pj_string(USER);
acc_cfg.cred_info[0].realm = pj_string("*");
acc_cfg.cred_info[0].scheme = pj_string("Digest");
acc_cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
acc_cfg.cred_info[0].data = pj_string(PASS);
}
Once registration is completed, I run the following code:
prn("=== Test Call ===");
pj_str_t uri = pj_string("sip:" + call_target + "#" + SERVER);
pjsua_call_id call_id;
pjsua_call_setting call_setting;
pjsua_call_setting_default(&call_setting);
call_setting.flag = 0;
call_setting.vid_cnt = PJMEDIA_HAS_VIDEO ? 1 : 0;
pjsua_msg_data msg_data;
pjsua_msg_data_init(&msg_data);
pj_status_t status = pjsua_call_make_call(acc_id, &uri, &call_setting, NULL, &msg_data, &call_id);
if (status != PJ_SUCCESS) {
prn("Error trying: pjsua_call_make_call");
return;
}
I know that PJMEDIA_HAS_VIDEO is equal to 1 on the conf_site.h and pjsua_call_make_call return PJ_SUCCESS.
I've seen that if I have headphones connected, there is no problem. But if I disconnect them, the following error is shown:
#pjsua_aud.c ..Error retrieving default audio device parameters: Unable to find default audio device (PJMEDIA_EAUD_NODEFDEV) [status=420006]
If I connect the headphones, I enable the video and run my code, the following error is shown:
#pjsua_media.c ......pjsua_vid_channel_update() failed for call_id 0 media 1: Unable to find default video device (PJMEDIA_EVID_NODEFDEV)
So, using PJSUA it is necessary to have audio and video devices on the monitor and phone? Should I create virtual ports if I don't have the devices?
You can use the following code to get a list of audio/video devices in PJSUA, which will most likely provide you with a loopback device (among others).
pjmedia_aud_dev_info audio_device[64];
unsigned int audio_device_cnt = 64;
status = pjsua_enum_aud_devs(audio_device, &audio_device_cnt);
printf("There are %d audio devices\n", audio_device_cnt);
for (int i = 0; i < audio_device_cnt; i++) {
printf("%d: %s\n", i, audio_device[i].name);
}
pjmedia_vid_dev_info video_device[64];
unsigned int video_device_cnt = 64;
status = pjsua_vid_enum_devs(video_device, &video_device_cnt);
printf("There are %d video devices\n", video_device_cnt);
for (int i = 0; i < video_device_cnt; i++) {
printf("%d: %s\n", i, video_device[i].name);
}
I have not personally tried capturing a loopback audio device but for video, PJSUA provides an internal colorbar generator (Colorbar generator in this list), which you can use.
Once you find the indices of loopback or dummy audio/video devices you want to use, you can set them by using
pjsua_set_snd_dev(<YOUR DUMMY CAPTURE DEVICE>, <YOUR DUMMY PLAYBACK DEVICE>);
acc_cfg.vid_cap_dev = <YOUR VIDEO CAPTURE DEVICE>;

My code doesn't receive a message from xserver

I want to receive a message from xserver when I close my window.
(when I hit the 'X' button')
For example, I have a list of windows that are currently opened. (can be referred by dayRecord.)
I want to print that "window closed!" when I click the x button on a terminal.
But though I clicked it, I couldn't get any message from xserver.
Also, that XNextEvent is blocking.
I've test this exact same logic with a window generated in my code using XCreateSimpleWindow,
and it worked perfectly.
I can even close an existing window I created manualy by XDestroyWindow.
So, I think there is no difference between a window that is created by the code
and created before the code starts once if I have a window id.
But somehow, I cannot get any message from a former one.
This is my code.
It is trying to get a list of windows that are opened.
And within them, when I close a terminal it should print "window closed!"
void windowManager() {
// getting a text viewer to be traced
char **textViewers = getTextViewers();
// retreiving new record of a day
DayRecord *dayRecord = getNewDayRecord();
// save an x11 display, and currently opened windows into the day record
Display *display = recordInit(dayRecord);
Window whatToClose;
for (int i = 0; i < dayRecord->recordCnt; ++i) {
printf("currently opened: %s %lu\n", dayRecord->record[i].name, dayRecord->record[i].window);
// for example: i want to know when a terminal is closed. (before the program starts, it should be opened, or it crashes.)
if (strcmp(dayRecord->record[i].name, "gnome-terminal-server") == 0)
whatToClose = dayRecord->record[i].window;
addInfoSpace(display, dayRecord->record + i, textViewers);
}
printf("let's close %lu: %s\n", whatToClose, getWindowName(display, whatToClose));
// window close detecting logic down here...
Atom wmDelete = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, whatToClose, &wmDelete, 1);
XEvent xEvent;
printf("I am listening!\n");
while (True) {
XNextEvent(display, &xEvent);
if (xEvent.type == ClientMessage && xEvent.xclient.data.l[0] == wmDelete) {
printf("window closed!\n");
break;
}
}
char *json = (char *)malloc(sizeof(char) * 100000);
dayRecordToJSON(dayRecord, json);
printf("%s", json);
// freeing memories
free2dArray((void **)textViewers, MAX_FILE_COUNT);
freeDayRecord(dayRecord);
XCloseDisplay(display);
}
Thank you.
I've tried many things and this worked.
If you're trying to do the same thing, please check the code.
But, I am not sure if this is a right way to do.
Maybe there can be a safer and right way to do this but this works anyway.
// ...
Atom wmDelete = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, whatToClose, &wmDelete, 1);
XSelectInput(display, whatToClose, SubstructureNotifyMask);
XEvent xEvent;
printf("I am listening!\n");
while (1) {
XNextEvent(display, &xEvent);
if (xEvent.type == DestroyNotify) {
printf("window closed!\n");
break;
}
}
// ...

visual c++ Serialport class handling data very slow

I'm trying to handle data recieved at about 1Hz from a robot through a serialport (bluetooth connection). I will recieve data with different headers determining what data will be recieved and what the expected length of the message is.
for example:
Header: sensorvalues (0x32) -> expected length 11 incl. header.
First i want to check if the byte is a header and if thats the case extract the expected length (in bytes).
I am using vc++ and the serialport class in the GUI.
The "seirialport->read(buffer, 0, expected length)" is very slow and not very reliable. I found some tips at http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport but the buffer still builds up to the point where I have about 200 bytes in the buffer, which is not very good when i need live sensorvalues displayed on the GUI.
The key parts of my code are:
System::Void MyForm::serialPort1_DataReceived_1(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e) {
if (serialPort1->BytesToRead > 0){
if (write_position == 0){
serialPort1->BaseStream->ReadAsync(data_recieved_buffer, 0, 1);
header = data_recieved_buffer[0];
if (this->InvokeRequired){
myrecievedata_delegate^ d = gcnew myrecievedata_delegate(&myrecievedata);
this->Invoke(d, gcnew array < Object^ > {'h'});
}
else
{
myrecievedata('h');
}
}
else if (this->serialPort1->BytesToRead > expected_length - 1)
{
serialPort1->BaseStream->ReadAsync(data_recieved_buffer, 0, expected_length - 1);
if (this->InvokeRequired){
myrecievedata_delegate^ d = gcnew myrecievedata_delegate(&myrecievedata);
this->Invoke(d, gcnew array < Object^ > {'b'});
}
else
{
myrecievedata('b');
}
}
else{
return;
}
}
and the recieved data is sent to
System::Void MyForm::myrecievedata(char status){
if (status == 'h'){
handleheader(header);
}
else if (status == 'b'){
handlebyte();
}
Is the problem at the serialport_datarecieved event? I can only think of invoke (which I have very little knowledge about) being the problem, still keeping the work in the serialport thread.
If that is the case how would I make sure that the data is handled in a different thread?
Thanks in advance!

How to monitor playback on ALSA via asoundlib?

I'm building an application that allows for ALSA configuration and in the GUI there is a peek meter that allows the client to see playback levels in realtime. I'm having a hard time determining what device to connect to because I don't know if ALSA has a default "loopback" or not and what it's called. I am also having trouble converting the read data into a sample, then finding said sample's amplitude. Here is what I have built so far:
Grab device and set hardware params
if (0 == snd_pcm_open(&pPcm, "default", SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK))
{
if (0 == snd_pcm_set_params(pPcm, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 96000, 1, 1)) // This last argument confuses me because I'm not given a unit of measurement (second, millisecond, mircosecond, etc.)
{
return snd_pcm_start(pPcm);
}
}
pPcm = nullptr;
return -1;
Read from device and return the peek of the audio signal
int iRtn = -1;
if (nullptr == pPcm)
{
if (-1 == SetupListener())
{
return iRtn;
}
}
// Check to make the state is sane for reading.
if (SND_PCM_STATE_PREPARED == snd_pcm_state(pPcm) ||
SND_PCM_STATE_RUNNING == snd_pcm_state(pPcm))
{
snd_pcm_resume(pPcm); // This might be superfluous.
// The state is sane, read from the stream.
signed short iBuffer = 0;
int iNumRead = snd_pcm_readi(pPcm, &iBuffer, 1);
if (0 < iNumRead)
{
// This calculates an approximation.
// We have some audio data, acquire it's peek in dB. (decibels)
float nSample = static_cast<float>(iBuffer);
float nAmplitude = nSample / MAX_AMPLITUDE_S16; // MAX_AMPLITUDE_S16 is defined as "32767"
float nDecibels = (0 < nAmplitude) ? 20 * log10(nAmplitude) : 0;
iRtn = static_cast<int>(nDecibels); // Cast to integer for GUI element.
}
}
return iRtn;
The ALSA documentation seems very barren and so I apologize if I'm misusing the API.

Windows + SetCommState how to set RTS?

I have an application that has been ported up from VC++ 6 where it worked fine. The code in question uses the WinAPI for a serial device driver. When ported to VS2012, the same code behaves rather differently.
Create a DCB, set SetCommState and go. CTS was set high, RTS was set high and you were on your way.
Since ported up to VS2012 Pro MFC, I am finding that it sets up SetCommState the same with or without hardware flow control:
memset(&dcb, 0x00, sizeof(dcb));
dcb.DCBlength = sizeof(DCB);
// Must be TRUE, only binary mode in Windows
dcb.fBinary = TRUE;
dcb.fParity = FALSE;
// XOn/XOff disabled
dcb.fTXContinueOnXoff = TRUE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.XonLim = 0;
dcb.XoffLim = 0;
dcb.XonChar = 0;
dcb.XoffChar = 0;
// Misc Stuff
dcb.EofChar = 0;
dcb.EvtChar = 0;
dcb.ErrorChar = 0;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
dcb.fAbortOnError = FALSE;
// 8N1 Setup
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
// Baud Rate
if (dwBaudRate == BAUD_115200)
{
dcb.BaudRate = CBR_115200;
}
else
{
dcb.BaudRate = CBR_38400;
}
// setup hardware flow control
if (bHardware == eYesHardwareFlowControl)
{
// ================ FLOW CONTROL ON ================
switch (bIgnoreCTS)
{
case eIgnoreCTS:
dcb.fOutxCtsFlow = FALSE;
break;
case eEnableCTS:
dcb.fOutxCtsFlow = TRUE;
break;
default:
case eCTSDecideLater:
dcb.fOutxCtsFlow = TRUE;
break;
}
// DSR Flow Control
dcb.fDsrSensitivity = FALSE;
dcb.fOutxDsrFlow = FALSE;
// <<Hardware flow control On(TRUE) Off(FALSE)>>
dcb.fDtrControl = DTR_CONTROL_ENABLE;
// <<Hardware flow control On(_HANDSHAKE) Off(_ENBLE)>>
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
}
else
{
// ================ FLOW CONTROL OFF ================
switch (bIgnoreCTS)
{
case eIgnoreCTS:
dcb.fOutxCtsFlow = FALSE;
break;
case eEnableCTS:
dcb.fOutxCtsFlow = TRUE;
break;
default:
case eCTSDecideLater:
dcb.fOutxCtsFlow = FALSE;
break;
}
// DSR Flow Control
dcb.fDsrSensitivity = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
}
if (SetCommState(m_hIdComDev, &dcb) == WINDOWS_API_ZERO_IS_BAD)
{
dwLastError = GetLastError();
}
At this point, I have set up the DCB, cleared it. I don't read in the previous state is I don't want to trust any garbage of anyone that previously used the port. Then I set up every field with Baud, Flow Control and CTS Ignore being the only optional items.
So, what I've noticed is that I can create situation where the Device and the PC don't communicate. Now, mind you, they always did before and they always work with Hyperterminal, ProComm, TeraTerm and so on. What I can see is that when these comm programs start (and the old VC++ 6 App), when the device is created and set up, RTS is immediately set high.
Now, my App, once the DCB is set up, SetCommState called; RTS is always LOW. And when this happens, communications is toast.
I want to FORCE RTS to be high and thought I could do it like this:
if (EscapeCommFunction(m_hIdComDev, CLRRTS) == WINDOWS_API_ZERO_IS_BAD)
{
dwLastError = GetLastError();
}
if (EscapeCommFunction(m_hIdComDev, SETRTS) == WINDOWS_API_ZERO_IS_BAD)
{
dwLastError = GetLastError();
}
But this fails, it gives an error 87 (parameter error). And I cannot quite figure it out. Even if I just SETRTS high only, it fails.
Any ideas on how I can force Windows to set RTS high after I setup the comm parameters in the DCB?
Well it turned out to be a device problem and not a windows problem at all.

Resources