Option to send key presses from external app via named pipes

This commit is contained in:
Niellun
2025-11-03 19:09:27 +02:00
parent c83f00e7bf
commit 765a437f1d
5 changed files with 107 additions and 1 deletions
+12
View File
@@ -147,6 +147,18 @@
#key-back = 0
#key-home = 0
# Path for named pipe that keys are going to be listen on to.
# If empty pipe listening is disables.
# Example /tmp/fastcarplay_pipe
# Keys are bytes and defined directly as in protocol, examples:
# BTN_LEFT 100
# BTN_RIGHT 101
# BTN_SELECT_DOWN 104
# BTN_SELECT_UP 105
# BTN_BACK 106
# BTN_HOME 200
#key-pipe-path =
##############################################################################
# 4.Debug
##############################################################################
+4 -1
View File
@@ -20,6 +20,7 @@ extern "C"
#include "decoder.h"
#include "pcm_audio.h"
#include "interface.h"
#include "pipe_listener.h"
#define FRAME_DELAY_INACTIVE 200
@@ -102,7 +103,8 @@ void processKey(Protocol &protocol, SDL_Keysym key, RunParams &params)
else if (key.sym == Settings::keyHome)
{
protocol.sendKey(BTN_HOME);
} else
}
else
{
std::cout << "[Key] Unmapped key " << key.sym << std::endl;
}
@@ -228,6 +230,7 @@ void application()
audioAux.start(&protocol.audioStreamAux, &audioMain);
protocol.start(evtStatus, evtConnected);
Interface interface(renderer);
PipeListener pipeListener(protocol, (Settings::keyPipe.value.length() > 2) ? Settings::keyPipe.value.c_str() : nullptr);
std::cout << "[Main] Loop" << std::endl;
uint32_t latestid = 0;
+67
View File
@@ -0,0 +1,67 @@
#include "pipe_listener.h"
#include <cerrno>
#include <fcntl.h>
#include <iostream>
#include <sys/stat.h>
#include <unistd.h>
PipeListener::PipeListener(Protocol &protocol, const char *path)
: _protocol(protocol), _path(path), _active(false)
{
if(path == nullptr)
return;
unlink(_path);
if (mkfifo(_path, 0666) == -1)
if (errno != EEXIST)
{
std::cout << "[Pipe] Failed to create FIFO " << _path << ": " << std::strerror(errno) << std::endl;
return;
}
_active = true;
_thread = std::thread(&PipeListener::loop, this);
}
PipeListener::~PipeListener()
{
if (!_active)
return;
// Signal the listening thread to exit by setting the active flag first.
_active = false;
int tmp = open(_path, O_WRONLY | O_NONBLOCK);
if (tmp >= 0)
{
write(tmp, "\0", 1);
close(tmp);
}
if (_thread.joinable())
_thread.join();
unlink(_path);
}
void PipeListener::loop()
{
std::cout << "[Pipe] Listening on " << _path << std::endl;
while (_active)
{
int fd = open(_path, O_RDONLY);
if (fd == -1)
{
std::cout << "[Pipe] Failed to open " << _path << ": " << std::strerror(errno) << std::endl;
return;
}
char value;
while (_active && read(fd, &value, 1) > 0)
{
std::cout << "[Pipe] Received: " << (int)value << std::endl;
if (value != 0)
_protocol.sendKey(value);
}
if (fd >= 0)
close(fd);
}
std::cout << "[Pipe] Finished on " << _path << std::endl;
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef SRC_NAMED_PIPE_H
#define SRC_NAMED_PIPE_H
#include <thread>
#include <atomic>
#include "protocol.h"
class PipeListener {
public:
PipeListener(Protocol &protocol, const char *path);
~PipeListener();
private:
void loop();
Protocol &_protocol;
const char *_path;
bool _active;
std::thread _thread;
};
#endif // SRC_NAMED_PIPE_H
+2
View File
@@ -49,6 +49,8 @@ public:
static inline Setting<int> keyEnter{"key-enter", 0};
static inline Setting<int> keyBack{"key-back", 0};
static inline Setting<int> keyHome{"key-home", 0};
static inline Setting<std::string> keyPipe{"key-pipe-path", ""};
// Debug section
static inline Setting<int> protocolDebug{"protocol-debug", 0};