How to capture key presses in linux two applications - linux

I have two applications running on an embedded linux platform. I want to have the main application have focus with the keypad but I want another application in the background that can monitor key presses for the KEY_POWER to signal the system to shutdown.
We want to make this separate from the main app because turning the system off is important if the main app has crashed or hung.
Capturing Keystrokes in GNU/Linux in C This doesn't seem to nicley if there are two apps reading from it. I think, i know evtest won't work with our main app up.
We do not have a window manager. Our only graphical app is Qt5, the other one is a background daemon.

Related

Separated process and GUI -- how to start the application in the correct way

I have a separate process and GUI for my application. Details below. Now I am ready to bring the application "in production". Although there are likely only 2 users on this planet I want to handle the startup of the application correctly. That is, adhering to the correct Unix philosophy. Although the application might be able to run in Windows, I am not interested.
I think I have 2 options:
Starting both the player process and the GUI from their own init.d scripts. And have a third script to call both. Usually placed in an autostart directory. Or just have both the process and the gui startup script in the correct rcX.d
Start the player process from an init.d script and fork the GUI from within the process. I could pass parameters to the process to tell whether or not it should start the GUI. This does not preclude starting a GUI process manually elsewhere.
Both options have variations, but the difference between the two is fundamental.
More info on the application
The application is an internet radio player. But with the special feature it can play back previously recorded streams, introducing a time shift to compensate for time differences if the player and transmitter are in different time zones.
The recorder is part of the same project, but not part of the application.
The application consists of the player which is able to play headless, and fully controlled through configuration files. The player can also be controlled by a GUI which communicates with the player through TCP/IP. The application gracefully handles if the player runs without GUI a single GUI, or with multiple GUI's. The GUI gracefully handles the absence or re-connection of the player.
If the player runs headless I want to connect from any PC with a GUI. In some situations I want to use the application and GUI on the same laptop or PC. The main application is a dedicated RasPI player with touch screen. This RasPI should launch both the player and GUI simultaneously when I start the application. Optionally I can start another GUI from another PC to control settings I cannot access thru the touch screen.
I don't think it is relevant, but both parts are written in Tcl/Tk. The player has an extension which interfaces to the libmpv API, part of the mpv media player.
So the player and the GUI are so far independent nothing breaks if one runs without the other, and recover gracefully when they both run. The question is how to start both processes. Independent init.d scripts or forking.
Assuming both the player and the GUI are implemented as Tcl scripts, you can use the source command to load one from the other. For example, when starting the GUI, it can detect that the player is not running (because the socket connection fails). In that case it can do source player.tcl. To avoid name conflicts you can use different namespaces, or load the player in a separate interpreter. I don't expect either of the components to do any blocking actions. But if they do, you can even load the player in an interpreter in another thread.
set dir [file dirname [file normalize [info script]]]
interp create player
player eval [list source [file join $dir player.tcl]]
There are other possibilities for deciding between starting one or both components, like passing a command line option to either of the components to also load the other component.
Since you are specifically interested in linux, another strategy would be to make use of dbus. Your player could publish a dbus interface (using dbif). The GUI can then call a method of that interface, with the "-autostart" option on (the default). When set up correctly, that would cause the player to start, if it isn't already running.
In player.tcl:
package require dbif
dbif connect tk.tcl.mpvplayer
dbif method / Version {} version {return $::version}
You can add more methods, and signals and properties. But since you already have a TCP/IP interface, you don't need to implement a full API via dbus.
In your GUI application:
package require dbus
dbus connect
# Auto-start the player, if necessary
dbus call -dest tk.tcl.mpvplayer / tk.tcl.mpvplayer Version
To enable auto-starting the player, create a file ~/.local/share/dbus-1/services/tk.tcl.mpvplayer.service:
[D-BUS Service]
Name=tk.tcl.mpvplayer
Exec=/home/pi/mpvplayer/player.tcl
The examples above use the session bus, which is normally associated with the display (:0). To make it work when the player runs headless, you may need to set the DISPLAY variable for it to connect to the correct session bus. Alternatively you can use the system bus. But that will require some adjustments.

Making a GUI in Linux without booting the OS's GUI

Sorry if I'm using wrong terminology here.
I'd like to make an appliance for users that's running from a Raspberry Pi. When it's booted, I'd like users to see my own GUI that I'll design (hopefully in PyQT but I'm not sure about that yet.)
The thing I don't know how to do: I don't want the users to see the Linux operating system on the screen at all. I don't want them to see the desktop and launch my app. I want my app to be automatically launched on startup. I want it to be the only thing accessible and visible to the users. i.e. it should be full-screen and a user wouldn't be able to exit it or interact with the OS in any way.
How can I do that?

Does a window need a graphical environment to exist?

This one is a pretty strange question of mine so I'll try to explain the best I can.
On a DOS Linux distribution, without having installed any graphical environment, if I start an application which is supposed to have a GUI, will I be able to interact with that window via code?
What I thought is that if KDE/GNOME's role is to graphically represent an existing GUI, I should be able to interact with it but if these graphical environments have an active role in the window creation there is nothing I can do.
You won't be able to run a graphical program without a window manager.
The reason is that the window manager is doing a lot more than just allowing the window to be shown to the user. It comes with libraries and services for constructing windows and components and interacting with them. Without these libraries and services, the program won't be able to start.
The only exception would be if a program contained all the graphical code built into it, and didn't rely on a window manager. Realistically this would only happen for a fairly simple program and in special cases; for instance, Raspbian includes OMXPlayer, which shows full screen video without relying on any window manager.
Quoting (with some adaptation) from https://raspberrypi.stackexchange.com/a/3974 which answers how to start mplayer in X11 without a window manager:
The X server is really usually called X and you can just start it. You can set the DISPLAY number as an argument along with some other things.
You might want to have some sort of session, though, and still go through xinit or such and start X with startx. You can use .xinitrc or such as a script and simply not start a window manager there. You will need a "magic client" as the last command that stays running so X doesn't terminate immediately. In a traditional "failsafe" session, that was an xterm. If you know what to launch and launch once only, it could be that program or any UI/wrapper that does the launching for you. When the last ("magic") client in the init script terminates, X terminates.
If all you want to do is play video, you might see if you can run mplayer with directfb instead and skip using X11 entirely.

Two applications using framebuffer

I'm writing a set of Linux framebuffer applications for embedded hardware. The main application runs on tty1 from /etc/inittab (for now it's just a touchscreen test) and is supposed to run permanently. The second application is executed from acpid when the power button is pressed, and it's supposed to ask user if he really want to shut the device down, and read user answer from a touchscreen. What I want is that the second application would takeover framebuffer while it runs, and then release it and restore the state of screen, so the main application can continue without restart.
Is this scenario possible with 2 different applications, and how should they interact ? Now the second application just can't draw anything while the main application is running.
I know I can kill and restart main application, or move poweroff notification to the main application and have acpid just sending a signal to it, but those solutions don't seem to be optimal.
One solution would of course be to have THREE applications, one that does the actual framebuffer interaction, and the other two just sends messages (in some form, e.g. through a pipe, socket or similar). This is how "window managers" and similar usually works (but much more complicated, of course)

How to start a gtk application after booting up without logging in?

I have got a gtk application. I want it to start automatically when I boot up the system, such that instead of getting usual login screen, my application greets the user.
My application is a sort of cash dispensing application. So user should not even see the login screen of linux. Whenever machine in boot up, after loading services and all that, my application should appear on the screen. One should not have to put any password or login in anyway to start that application.
Now so far I have tried the following but all in vain.
I put the command in my /etc/rc.local file
/home/EXE/cashier
Then rebooted machine in run level 5. But nothing happens. I get the usual login screen. Other programs that do not involve any gui or gtk, they are automatically started in this manner but not the gtk application.
Then I put
xint /home/EXE/cahier
and later
xint /home/EXE/./cashier
But they too didn't work. When I looked into details, I found out that "An Xserver is already running on screen 0, cannot open other server" or something like that.
Then I tried booting into run level 3, this time it worked.
xint /home/EXE/.cachier
But in run level 3, the font and icon sizes are smaller. Moreover some windows do not cover the whole screen.
Now I will really appreciate a way to run my application in run level 5, without showing login screen automatically.
Regards
Edit
Currently, the application is running on fedora core 2
This is more a question about linux distribution startup than it is about Gtk applications. The specifics are going to depend on your distribution, but the essence is:
Disable the gdm facility, which is normally responsible for spawning your X server.
Run xinit (not "xint") to start the server manually. This takes a client as its argument. It may work to run your Gtk application directly (it needs to be smart enough to position and size itself instead of relying on a window manager), but more likely you will want to pick a window manager to run it in. The easiest way to do this is via script that you pass to xinit.

Resources