1
+
/*
2
+
* FXGL - JavaFX Game Library. The MIT License (MIT).
3
+
* Copyright (c) AlmasB (almaslvl@gmail.com).
4
+
* See LICENSE for details.
5
+
*/
6
+
7
+
package com.almasb.fxgl.gesturerecog
8
+
9
+
import com.almasb.fxgl.core.EngineService
10
+
import com.almasb.fxgl.core.concurrent.Async
11
+
import com.almasb.fxgl.intelligence.WebAPI
12
+
import com.almasb.fxgl.logging.Logger
13
+
import com.almasb.fxgl.speechrecog.SpeechRecognitionService
14
+
import com.almasb.fxgl.ws.LocalWebSocketServer
15
+
import javafx.geometry.Point3D
16
+
import org.openqa.selenium.WebDriver
17
+
import org.openqa.selenium.chrome.ChromeDriver
18
+
import org.openqa.selenium.chrome.ChromeOptions
19
+
import java.util.function.Consumer
20
+
21
+
/**
22
+
* TODO: remove duplicate code
23
+
*
24
+
* @author Almas Baim (https://github.com/AlmasB)
25
+
*/
26
+
class HandTrackingService : EngineService() {
27
+
28
+
private val log = Logger.get(SpeechRecognitionService::class.java)
29
+
private val server = LocalWebSocketServer("HandTrackingServer", WebAPI.GESTURE_RECOGNITION_PORT)
30
+
31
+
private var webDriver: WebDriver? = null
32
+
33
+
private val handDataHandlers = arrayListOf<Consumer<Hand>>()
34
+
35
+
override fun onInit() {
36
+
server.addMessageHandler { message ->
37
+
try {
38
+
val rawData = message.split(",").filter { it.isNotEmpty() }
39
+
40
+
val id = rawData[0].toInt()
41
+
val points = ArrayList<Point3D>()
42
+
43
+
var i = 1
44
+
while (i < rawData.size) {
45
+
val x = rawData[i + 0].toDouble()
46
+
val y = rawData[i + 1].toDouble()
47
+
val z = rawData[i + 2].toDouble()
48
+
49
+
points.add(Point3D(x, y, z))
50
+
51
+
i += 3
52
+
}
53
+
54
+
Async.startAsyncFX {
55
+
handDataHandlers.forEach { it.accept(Hand(id, points)) }
56
+
}
57
+
58
+
} catch (e: Exception) {
59
+
log.warning("Failed to parse message.", e)
60
+
}
61
+
}
62
+
63
+
server.start()
64
+
}
65
+
66
+
/**
67
+
* Starts this service in a background thread.
68
+
* Can be called after stop() to restart the service.
69
+
* If the service has already started, then calls stop() and restarts it.
70
+
*/
71
+
fun start() {
72
+
Async.startAsync {
73
+
try {
74
+
if (webDriver != null) {
75
+
stop()
76
+
}
77
+
78
+
val options = ChromeOptions()
79
+
options.addArguments("--headless=new")
80
+
options.addArguments("--use-fake-ui-for-media-stream")
81
+
82
+
webDriver = ChromeDriver(options)
83
+
webDriver!!.get(WebAPI.GESTURE_RECOGNITION_API)
84
+
85
+
// we are ready to use the web api service
86
+
} catch (e: Exception) {
87
+
log.warning("Failed to start Chrome web driver. Ensure Chrome is installed in default location")
88
+
log.warning("Error data", e)
89
+
}
90
+
}
91
+
}
92
+
93
+
/**
94
+
* Stops this service.
95
+
* No-op if it has not started via start() before.
96
+
*/
97
+
fun stop() {
98
+
try {
99
+
if (webDriver != null) {
100
+
webDriver!!.quit()
101
+
webDriver = null
102
+
}
103
+
} catch (e: Exception) {
104
+
log.warning("Failed to quit web driver", e)
105
+
}
106
+
}
107
+
108
+
fun addInputHandler(handler: Consumer<Hand>) {
109
+
handDataHandlers += handler
110
+
}
111
+
112
+
fun removeInputHandler(handler: Consumer<Hand>) {
113
+
handDataHandlers -= handler
114
+
}
115
+
116
+
override fun onExit() {
117
+
stop()
118
+
server.stop()
119
+
}
120
+
}
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4