]> git.sesse.net Git - pkanalytics/commitdiff
Initial commit; really only a (bad) video player.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 30 Apr 2023 10:27:27 +0000 (12:27 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 30 Apr 2023 10:28:05 +0000 (12:28 +0200)
mainwindow.h [new file with mode: 0644]
mainwindow.ui [new file with mode: 0644]
meson.build [new file with mode: 0644]
stats.cpp [new file with mode: 0644]

diff --git a/mainwindow.h b/mainwindow.h
new file mode 100644 (file)
index 0000000..052e15d
--- /dev/null
@@ -0,0 +1,21 @@
+#include <QMediaPlayer>
+#include <QMainWindow>
+#include <QApplication>
+#include <stdint.h>
+#include <optional>
+
+class MainWindow : public QMainWindow
+{
+       Q_OBJECT
+
+public:
+       MainWindow();
+
+       QMediaPlayer *player;
+
+private:
+       void seek(int64_t delta_ms);
+       bool seeking = false;
+       bool playing = true;
+       std::optional<uint64_t> buffered_seek;
+};
diff --git a/mainwindow.ui b/mainwindow.ui
new file mode 100644 (file)
index 0000000..a64b1e3
--- /dev/null
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>800</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QGridLayout" name="gridLayout_2">
+    <item row="0" column="0">
+     <layout class="QGridLayout" name="gridLayout" rowstretch="1,0,0">
+      <item row="1" column="0">
+       <widget class="QLabel" name="timestamp">
+        <property name="text">
+         <string>1:02:03</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="0">
+       <widget class="QVideoWidget" name="video" native="true">
+        <property name="minimumSize">
+         <size>
+          <width>320</width>
+          <height>240</height>
+         </size>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QTableView" name="tableView"/>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>800</width>
+     <height>23</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QVideoWidget</class>
+   <extends>QWidget</extends>
+   <header location="global">QVideoWidget</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/meson.build b/meson.build
new file mode 100644 (file)
index 0000000..4df5b37
--- /dev/null
@@ -0,0 +1,10 @@
+project('stats', 'cpp', default_options: ['buildtype=debugoptimized'], version: '0.0.1')
+
+qt6 = import('qt6')
+qt6deps = dependency('qt6', modules: ['Core', 'Gui', 'Widgets', 'Multimedia', 'MultimediaWidgets'])
+qt_files = qt6.preprocess(
+        moc_headers: ['mainwindow.h'],
+       ui_files: ['mainwindow.ui'],
+        dependencies: qt6deps)
+
+executable('stats', 'stats.cpp', qt_files, dependencies: [qt6deps])
diff --git a/stats.cpp b/stats.cpp
new file mode 100644 (file)
index 0000000..7bce2a2
--- /dev/null
+++ b/stats.cpp
@@ -0,0 +1,95 @@
+#include <QMediaPlayer>
+#include <QMainWindow>
+#include <QApplication>
+#include <QGridLayout>
+#include <QVideoWidget>
+#include <QShortcut>
+#include <iostream>
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+MainWindow::MainWindow()
+{
+       player = new QMediaPlayer;
+       //player->setSource(QUrl::fromLocalFile("/home/sesse/dev/stats/ultimate.mkv"));
+       player->setSource(QUrl::fromLocalFile("/home/sesse/dev/stats/ultimate-prores.mkv"));
+       player->play();
+
+       Ui::MainWindow *ui = new Ui::MainWindow;
+       ui->setupUi(this);
+
+       connect(player, &QMediaPlayer::positionChanged, [ui, this](uint64_t pos) {
+               int ms = pos % 1000;
+               pos /= 1000;
+               int sec = pos % 60;
+               pos /= 60;
+               int min = pos % 60;
+               int hour = pos / 60;
+
+               char buf[256];
+               snprintf(buf, sizeof(buf), "%d:%02d:%02d.%03d", hour, min, sec, ms);
+               ui->timestamp->setText(buf);
+               if (buffered_seek) {
+                       player->setPosition(*buffered_seek);
+                       buffered_seek.reset();
+               }
+               if (!playing) {
+                       player->pause();  // We only played to get a picture.
+               }
+       });
+
+       player->setVideoOutput(ui->video);
+
+       QShortcut *key_k = new QShortcut(QKeySequence(Qt::Key_K), this);
+       connect(key_k, &QShortcut::activated, [this]() { seek(-10000); });
+
+       QShortcut *key_l = new QShortcut(QKeySequence(Qt::Key_L), this);
+       connect(key_l, &QShortcut::activated, [this]() { seek(10000); });
+
+       QShortcut *key_left = new QShortcut(QKeySequence(Qt::Key_Left), this);
+       connect(key_left, &QShortcut::activated, [this]() { seek(-1000); });
+
+       QShortcut *key_right = new QShortcut(QKeySequence(Qt::Key_Right), this);
+       connect(key_right, &QShortcut::activated, [this]() { seek(1000); });
+
+       // TODO: Would be nice to actually have a frame...
+       QShortcut *key_comma = new QShortcut(QKeySequence(Qt::Key_Comma), this);
+       connect(key_comma, &QShortcut::activated, [this]() { seek(-20); });
+
+       QShortcut *key_period = new QShortcut(QKeySequence(Qt::Key_Period), this);
+       connect(key_period, &QShortcut::activated, [this]() { seek(20); });
+
+       QShortcut *key_space = new QShortcut(QKeySequence(Qt::Key_Space), this);
+       connect(key_space, &QShortcut::activated, [this]() {
+               if (playing) {
+                       player->pause();
+               } else {
+                       player->setPlaybackRate(1.0);
+                       player->play();
+               }
+               playing = !playing;
+       });
+}
+
+void MainWindow::seek(int64_t delta_ms)
+{
+       int64_t current_pos = buffered_seek ? *buffered_seek : player->position();
+       uint64_t pos = std::max<int64_t>(current_pos + delta_ms, 0);
+       buffered_seek = pos;
+       if (!playing) {
+               player->setPlaybackRate(0.01);
+               player->play();  // Or Qt won't show the seek.
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       QApplication app(argc, argv);
+
+       MainWindow mainWindow;
+       mainWindow.resize(QSize(1280, 720));
+       mainWindow.show();
+
+       return app.exec();
+
+}