diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2020-03-07 10:30:55 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2020-03-07 10:30:55 +0100 |
commit | 9d0136249cade3469ac70f71cef4a428fecc7a9c (patch) | |
tree | 4e808eb055a1bac608ca7bc08e9b3ec95c0bdd76 /video-ps3eye/module.cpp | |
parent | adb5f89b018da33ee7e3aa8a48e5b742129da161 (diff) |
video/ps3eye: prototype open driver impl
Diffstat (limited to 'video-ps3eye/module.cpp')
-rw-r--r-- | video-ps3eye/module.cpp | 156 |
1 files changed, 150 insertions, 6 deletions
diff --git a/video-ps3eye/module.cpp b/video-ps3eye/module.cpp index ac6d8807..26b771e2 100644 --- a/video-ps3eye/module.cpp +++ b/video-ps3eye/module.cpp @@ -1,7 +1,19 @@ #include "module.hpp" -#if 0 +#include "compat/library-path.hpp" +#include "compat/sleep.hpp" +#include "compat/run-in-thread.hpp" + +#include <cstddef> + +#include <QCoreApplication> +#include <QMessageBox> + #include <libusb.h> +#ifdef __GNUG__ +# pragma clang diagnostic ignored "-Wcast-qual" +#endif + int device_count() { libusb_context * ctx = nullptr; @@ -50,8 +62,6 @@ bool check_device_exists() static const QString camera_name = QStringLiteral("PS3 Eye open driver"); -namespace video::impl { - std::vector<QString> ps3eye_camera_::camera_names() const { if (check_device_exists()) @@ -66,16 +76,150 @@ std::unique_ptr<camera> ps3eye_camera_::make_camera(const QString& name) else return {}; } -bool ps3eye_camera_::show_dialog(const QString& camera_name) +bool ps3eye_camera_::show_dialog(const QString&) { // TODO return false; } -bool ps3eye_camera_::can_show_dialog(const QString& camera_name) +bool ps3eye_camera_::can_show_dialog(const QString&) { return false; } -} // ns video::impl +ps3eye_camera::ps3eye_camera() +{ + if (!shm.success()) + return; + + static const QString library_path(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH); + wrapper.setWorkingDirectory(library_path); +#ifdef _WIN32 + wrapper.setProgram("\"ps3eye-subprocess.exe\""); +#else + wrapper.setProgram("ps3eye-subprocess"); #endif +} + +ps3eye_camera::~ps3eye_camera() +{ + stop(); +} + +void ps3eye_camera::stop() +{ + open = false; + + if (wrapper.state() != QProcess::NotRunning) + { + if (shm.success()) + { + volatile auto& ptr = *(ps3eye::shm*)shm.ptr(); + ptr.in.do_exit = true; + if (!wrapper.waitForFinished(500)) + wrapper.kill(); + wrapper.waitForFinished(-1); + } + else + { + wrapper.kill(); + wrapper.waitForFinished(-1); + } + } +} + +bool ps3eye_camera::start(info& args) +{ + if (!shm.success()) + return false; + + volatile auto& ptr = *(ps3eye::shm*)shm.ptr(); + + using mode = ps3eye::shm_in::mode; + + open = false; + fr = {}; + fr.channels = 3; + fr.channel_size = 1; + + if (!args.width || args.width > 320) + { + ptr.in.resolution = mode::vga; + fr.width = 640; fr.height = 480; + } + else + { + ptr.in.resolution = mode::qvga; + fr.width = 320; fr.height = 240; + } + + ptr.in.framerate = (uint8_t)std::clamp(args.fps, 30, 187); + ptr.in.gain = (uint8_t)s.gain; + ptr.in.exposure = (uint8_t)s.exposure; + + wrapper.start(); + + constexpr int sleep_ms = 10, max_sleeps = 5000/sleep_ms; + + for (int i = 0; i < max_sleeps; i++) + { + if (ptr.out.timecode > 0) + goto ok; + portable::sleep(sleep_ms); + } + + run_in_thread_async(qApp, [&]() { + QString error; + if (ptr.out.error_string[0] == '\0') + error = "Unknown error"; + else + error = QString::fromLatin1((const char*)ptr.out.error_string, + strnlen((const char*)ptr.out.error_string, sizeof(ptr.out.error_string))); + + QMessageBox::critical(nullptr, "Can't open camera", "PS3 Eye driver error: " + error, QMessageBox::Close); + }); + + return false; + +ok: + open = true; + return true; +} + +std::tuple<const frame&, bool> ps3eye_camera::get_frame() +{ + volatile auto& ptr = *(ps3eye::shm*)shm.ptr(); + constexpr int sleep_ms = 10; + constexpr int max_sleeps = 2000/sleep_ms; + + if (!open) + goto fail; + + for (int i = 0; i < max_sleeps; i++) + { + unsigned new_timecode = ptr.out.timecode; + if (timecode != new_timecode) + { + timecode = new_timecode; + goto ok; + } + portable::sleep(sleep_ms); + } + +fail: + stop(); + return { fr, false }; + + static_assert(offsetof(decltype(ptr.out), data_640x480) == offsetof(decltype(ptr.out), data_320x240)); + +ok: + fr.data = (unsigned char*)ptr.out.data_640x480; + return { fr, true}; +} + +bool ps3eye_camera::show_dialog() +{ + return false; +} + +OTR_REGISTER_CAMERA(ps3eye_camera_) |