]> git.sesse.net Git - ultimatescore/commitdiff
Add some support in the client for reading key events from a non-core IPv6 Buddy.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 22 Oct 2017 19:26:07 +0000 (21:26 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 22 Oct 2017 19:26:07 +0000 (21:26 +0200)
client/Makefile
client/event_device.cpp [new file with mode: 0644]
client/event_device.h [new file with mode: 0644]
client/mainwindow.cpp
client/mainwindow.h
client/mainwindow.ui

index e76e5b82b94cf3eba8d6bc6bc251d69de48995ab..e17047e8d25a9ae4252a28174f7373ab6cf49c20 100644 (file)
@@ -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 (file)
index 0000000..26ac820
--- /dev/null
@@ -0,0 +1,175 @@
+#include "event_device.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <linux/input.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <QApplication>
+#include <QKeyEvent>
+
+using namespace std;
+
+using std::set;
+using std::pair;
+
+EventDevice::EventDevice(const std::set<std::pair<unsigned, unsigned>> &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 (file)
index 0000000..134a547
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _EVENTDEVICE_H
+#define _EVENTDEVICE_H 1
+
+#include <string>
+#include <set>
+#include <thread>
+#include <utility>
+
+class QObject;
+
+class EventDevice {
+private:
+       int fd;
+       std::set<std::pair<unsigned, unsigned>> accepted_usb_ids;
+       std::thread thr;
+       QObject *receiver;
+
+       void init();
+       void thread_func();
+
+public:
+       EventDevice(const std::set<std::pair<unsigned, unsigned>> &accepted_usb_ids, QObject *receiver);
+       void start_thread();
+};
+
+#endif /* !defined(_EVENTDEVICE_H) */
index 3dd371516f8d6c13e2202bdc4de352569263a2d8..af7ee4b05695f616f533047c43b9b4348b70174a 100644 (file)
@@ -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<pair<unsigned, unsigned>> 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<string, string> 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();
index f2b0a6748482abe0a1789d92d7c50e6e5ad58a0f..8a517901b669e3499120943d0fbeab9a47b8272d 100644 (file)
@@ -4,6 +4,7 @@
 #include <QMainWindow>
 
 #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
index c3194a43766e76e2d0d5e8799901e8c898a3fcdf..507e31a400afaaebaaaebeeac97deccdb5de0141 100644 (file)
         </item>
        </layout>
       </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_12">
+        <item>
+         <widget class="QLabel" name="label_13">
+          <property name="text">
+           <string>Quick lower third (A&lt;num&gt;/B&lt;num&gt; = players, C&lt;num&gt; = code):</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="quick_lower_third_edit"/>
+        </item>
+        <item>
+         <widget class="QPushButton" name="show_quick_lower_third_btn">
+          <property name="text">
+           <string>Show</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
      </layout>
     </item>
    </layout>