From f7bfc5011e5c9122235b14fc4133591ffe671173 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sun, 22 Oct 2017 21:26:07 +0200 Subject: [PATCH] Add some support in the client for reading key events from a non-core IPv6 Buddy. --- client/Makefile | 2 +- client/event_device.cpp | 175 ++++++++++++++++++++++++++++++++++++++++ client/event_device.h | 26 ++++++ client/mainwindow.cpp | 16 ++++ client/mainwindow.h | 3 + client/mainwindow.ui | 21 +++++ 6 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 client/event_device.cpp create mode 100644 client/event_device.h diff --git a/client/Makefile b/client/Makefile index e76e5b8..e17047e 100644 --- a/client/Makefile +++ b/client/Makefile @@ -8,7 +8,7 @@ CXXFLAGS += -std=gnu++11 -fPIC $(shell pkg-config --cflags $(PKG_MODULES)) -pthr LDLIBS=$(shell pkg-config --libs $(PKG_MODULES)) -pthread OBJS_WITH_MOC = mainwindow.o -OBJS += $(OBJS_WITH_MOC) main.o acmp_client.o +OBJS += $(OBJS_WITH_MOC) main.o acmp_client.o event_device.o OBJS += $(OBJS_WITH_MOC:.o=.moc.o) %.o: %.cpp diff --git a/client/event_device.cpp b/client/event_device.cpp new file mode 100644 index 0000000..26ac820 --- /dev/null +++ b/client/event_device.cpp @@ -0,0 +1,175 @@ +#include "event_device.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace std; + +using std::set; +using std::pair; + +EventDevice::EventDevice(const std::set> &accepted_usb_ids, QObject *receiver) + : accepted_usb_ids(accepted_usb_ids), receiver(receiver) +{ + init(); +} + +void EventDevice::init() +{ + /* scan /dev/input for event devices */ + DIR *dir = opendir("/dev/input"); + struct dirent *de; + bool found = false; + struct input_id found_id; + char path[PATH_MAX]; + + if (dir == NULL) { + perror("/dev/input"); + exit(1); + } + + while ((de = readdir(dir))) { + if (strncmp(de->d_name, "event", 5) != 0) + continue; + + sprintf(path, "/dev/input/%s", de->d_name); + fd = open(path, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "Warning, skipping %s: %s\n", + path, strerror(errno)); + } else { + struct input_id id; + if (ioctl(fd, EVIOCGID, &id) == -1) { + fprintf(stderr, "ioctl on %s: %s\n", + path, strerror(errno)); + exit(1); + } + + if (accepted_usb_ids.count({ id.vendor, id.product }) != 0) { + found = true; + found_id = id; + break; + } + + close(fd); + } + } + + closedir(dir); + + if (found) { + char name[256]; + ioctl(fd, EVIOCGNAME(255), name); + + fprintf(stderr, "Found device (%04x,%04x) at %s: \"%s\"\n", + found_id.vendor, found_id.product, path, name); + } else { + fprintf(stderr, "Could not find the USB device\n"); + } +} + +void EventDevice::start_thread() +{ + thr = thread(&EventDevice::thread_func, this); + thr.detach(); +} + +void EventDevice::thread_func() +{ + struct input_event iev; + int ret; + + for ( ;; ) { + if (fd != -1) { + ret = read(fd, &iev, sizeof(iev)); + if (ret != sizeof(iev)) { + perror("read"); + fd = -1; + } + } + if (fd == -1) { + sleep(5); + init(); + continue; + } + + if (iev.type != EV_KEY) + continue; + if (iev.value != 1) + continue; + + QEvent *event = nullptr; + switch (iev.code) { + case 11: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_0, Qt::NoModifier, "0"); + break; + case 2: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier, "1"); + break; + case 3: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_2, Qt::NoModifier, "2"); + break; + case 4: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_3, Qt::NoModifier, "3"); + break; + case 5: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_4, Qt::NoModifier, "4"); + break; + case 6: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_5, Qt::NoModifier, "5"); + break; + case 7: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_6, Qt::NoModifier, "6"); + break; + case 8: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_7, Qt::NoModifier, "7"); + break; + case 9: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_8, Qt::NoModifier, "8"); + break; + case 10: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_9, Qt::NoModifier, "9"); + break; + case 30: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::ShiftModifier, "A"); + break; + case 48: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_B, Qt::ShiftModifier, "B"); + break; + case 46: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_C, Qt::ShiftModifier, "C"); + break; + case 32: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_D, Qt::ShiftModifier, "D"); + break; + case 18: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_E, Qt::ShiftModifier, "E"); + break; + case 33: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_F, Qt::ShiftModifier, "F"); + break; + case 14: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier); + break; + case 28: + event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier); + break; + } + if (event) { + QApplication::postEvent(receiver, event); + } + // printf("iev.type=%d iev.value=%d iev.code=%d\n", iev.type, iev.value, iev.code); + } +} + diff --git a/client/event_device.h b/client/event_device.h new file mode 100644 index 0000000..134a547 --- /dev/null +++ b/client/event_device.h @@ -0,0 +1,26 @@ +#ifndef _EVENTDEVICE_H +#define _EVENTDEVICE_H 1 + +#include +#include +#include +#include + +class QObject; + +class EventDevice { +private: + int fd; + std::set> accepted_usb_ids; + std::thread thr; + QObject *receiver; + + void init(); + void thread_func(); + +public: + EventDevice(const std::set> &accepted_usb_ids, QObject *receiver); + void start_thread(); +}; + +#endif /* !defined(_EVENTDEVICE_H) */ diff --git a/client/mainwindow.cpp b/client/mainwindow.cpp index 3dd3715..af7ee4b 100644 --- a/client/mainwindow.cpp +++ b/client/mainwindow.cpp @@ -120,7 +120,14 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->show_lower_third_btn, &QPushButton::clicked, this, &MainWindow::show_lower_third_clicked); connect(ui->hide_lower_third_btn, &QPushButton::clicked, this, &MainWindow::hide_lower_third_clicked); + connect(ui->quick_lower_third_edit, &QLineEdit::returnPressed, this, &MainWindow::quick_lower_third_activate); + connect(ui->show_quick_lower_third_btn, &QPushButton::clicked, this, &MainWindow::quick_lower_third_activate); + autocomment_update(); + + const set> usb{{ 0x0e8f, 0x0041 }}; + event_device = new EventDevice(usb, ui->quick_lower_third_edit); + event_device->start_thread(); } MainWindow::~MainWindow() @@ -244,6 +251,15 @@ void MainWindow::hide_lower_third_clicked() acmp->send_command("cg 1 invoke 1 hidelowerthird"); } +void MainWindow::quick_lower_third_activate() +{ + map param; + param["code"] = ui->quick_lower_third_edit->text().toStdString(); + acmp->send_command("cg 1 update 1 \"" + escape_quotes(serialize_as_json(param)) + "\""); + acmp->send_command("cg 1 invoke 1 quicklowerthird"); + ui->quick_lower_third_edit->clear(); +} + void MainWindow::autocomment_update() { int score1 = ui->score_1_box->value(); diff --git a/client/mainwindow.h b/client/mainwindow.h index f2b0a67..8a51790 100644 --- a/client/mainwindow.h +++ b/client/mainwindow.h @@ -4,6 +4,7 @@ #include #include "acmp_client.h" +#include "event_device.h" namespace Ui { class MainWindow; @@ -37,10 +38,12 @@ private: void set_and_show_autocomment_clicked(); void show_lower_third_clicked(); void hide_lower_third_clicked(); + void quick_lower_third_activate(); void autocomment_update(); Ui::MainWindow *ui; ACMPClient *acmp; + EventDevice *event_device; }; #endif // MAINWINDOW_H diff --git a/client/mainwindow.ui b/client/mainwindow.ui index c3194a4..507e31a 100644 --- a/client/mainwindow.ui +++ b/client/mainwindow.ui @@ -463,6 +463,27 @@ + + + + + + Quick lower third (A<num>/B<num> = players, C<num> = code): + + + + + + + + + + Show + + + + + -- 2.39.2