Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
deskscreen
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
1
Issues
1
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Package Registry
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
kowis-projects
deskscreen
Commits
302bde05
Commit
302bde05
authored
Apr 03, 2019
by
David
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Works on the desktop!
parent
f48e1e16
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
159 additions
and
26 deletions
+159
-26
src/main/kotlin/is/kow/deskscreen/camera/CameraController.kt
src/main/kotlin/is/kow/deskscreen/camera/CameraController.kt
+66
-11
src/main/kotlin/is/kow/deskscreen/camera/CameraView.kt
src/main/kotlin/is/kow/deskscreen/camera/CameraView.kt
+92
-14
src/main/kotlin/is/kow/deskscreen/wx/WeatherController.kt
src/main/kotlin/is/kow/deskscreen/wx/WeatherController.kt
+1
-1
src/main/resources/imagery/MaineCoon-cropped.jpeg
src/main/resources/imagery/MaineCoon-cropped.jpeg
+0
-0
No files found.
src/main/kotlin/is/kow/deskscreen/camera/CameraController.kt
View file @
302bde05
package
`is`.kow.deskscreen.camera
import
`is`.kow.deskscreen.MainController
import
`is`.kow.deskscreen.TransitionsController
import
com.github.thomasnield.rxkotlinfx.doOnNextFx
import
com.github.thomasnield.rxkotlinfx.observeOnFx
import
com.hopding.jrpicam.RPiCamera
import
io.reactivex.Observable
import
io.reactivex.schedulers.Schedulers
import
javafx.embed.swing.SwingFXUtils
import
javafx.event.ActionEvent
import
javafx.scene.image.Image
import
mu.KotlinLogging
import
tornadofx.*
import
java.nio.file.Paths
import
java.util.concurrent.TimeUnit
class
CameraController
:
Controller
()
{
...
...
@@ -19,6 +23,7 @@ class CameraController : Controller() {
private
val
mainController
:
MainController
by
inject
()
private
val
cameraStateModel
:
CameraStateModel
by
inject
()
private
val
transitionsController
:
TransitionsController
by
inject
()
init
{
//Only care that the folders exist
...
...
@@ -50,35 +55,85 @@ class CameraController : Controller() {
val
timeout
=
5
//Handles the timer countdown
Observable
.
range
(
timeout
,
0
)
//TODO: why did this never show up?
logger
.
debug
(
"Right before starting range timeout"
)
Observable
.
intervalRange
(
0
,
timeout
.
toLong
()
+
1
,
0
,
1
,
TimeUnit
.
SECONDS
)
.
map
{
timeout
-
it
}
.
observeOnFx
()
.
map
{
logger
.
debug
(
"COUNTING: $it"
)
cameraStateModel
.
countdownPercentage
.
value
=
it
/
timeout
.
toDouble
()
}
.
subscribe
()
//The camera blocks things. need to also start the countdown observable for the thing.
//TODO: when it's not the pi, just use some image with the same dimensions!
camera
?.
setRotation
(
270
)
?.
setDateTimeOn
()
?.
setTimeout
(
timeout
)
?.
setFullPreviewOn
()
?.
takeBufferedStill
()
if
(
mainController
.
isPi
)
{
//Camera won't be null if it's pi!
val
bf
=
camera
?.
setRotation
(
270
)
?.
setDateTimeOn
()
?.
setTimeout
(
timeout
)
?.
setFullPreviewOn
()
?.
takeBufferedStill
()
!!
//lets just convert it directly
SwingFXUtils
.
toFXImage
(
bf
,
null
)
}
else
{
//load the cat picture WHY WON'T YOU LOAD MY KITTY
val
stream
=
this
.
javaClass
.
getResourceAsStream
(
"/imagery/MaineCoon-cropped.jpeg"
)
val
img
=
Image
(
stream
)
Thread
.
sleep
((
timeout
*
1000
).
toLong
())
img
}
}
.
doOnNextFx
{
cameraStateModel
.
image
.
value
=
it
logger
.
debug
(
"SETTING IMAGE IN THE MODEL AND CHANGING STATE"
)
cameraStateModel
.
image
.
set
(
it
)
cameraStateModel
.
state
.
set
(
PictureTakingState
.
PREVIEWING
)
}
.
doOnError
{
logger
.
error
(
"Error during taking picture!"
,
it
)
}
.
subscribe
()
}
fun
keepPicture
()
{
fun
keepPicture
(
actionEvents
:
Observable
<
ActionEvent
>)
{
actionEvents
.
doOnNext
{
logger
.
error
(
"SHARE PICTURE OR SOMETHING!"
)
}
.
observeOnFx
()
.
map
{
cameraStateModel
.
image
.
value
=
null
cameraStateModel
.
state
.
set
(
PictureTakingState
.
READY
)
//TODO: would set state to sharing or something to display what to do with the picture
//Until then, just return them to the main frame
transitionsController
.
showDefaultView
()
}
.
subscribe
()
}
fun
rejectPicture
(
actionEvents
:
Observable
<
ActionEvent
>)
{
actionEvents
.
observeOnFx
()
.
map
{
cameraStateModel
.
image
.
value
=
null
cameraStateModel
.
state
.
set
(
PictureTakingState
.
READY
)
}
.
subscribe
()
}
fun
rejectPicture
()
{
fun
cancelPictureTaking
(
actionEvents
:
Observable
<
ActionEvent
>)
{
actionEvents
.
observeOnFx
()
.
doOnNext
{
cameraStateModel
.
image
.
value
=
null
cameraStateModel
.
state
.
set
(
PictureTakingState
.
READY
)
transitionsController
.
showDefaultView
()
}
.
subscribe
()
}
}
\ No newline at end of file
src/main/kotlin/is/kow/deskscreen/camera/CameraView.kt
View file @
302bde05
package
`is`.kow.deskscreen.camera
import
com.github.thomasnield.rxkotlinfx.actionEvents
import
com.github.thomasnield.rxkotlinfx.toObservableChanges
import
com.github.thomasnield.rxkotlinfx.toObservableChangesNonNull
import
javafx.beans.binding.Bindings
import
javafx.beans.binding.BooleanBinding
import
javafx.beans.property.SimpleDoubleProperty
import
javafx.beans.property.SimpleObjectProperty
import
javafx.geometry.Pos
import
javafx.scene.control.ProgressBar
import
javafx.scene.image.Image
import
javafx.scene.layout.Priority
import
mu.KotlinLogging
import
org.kordamp.ikonli.fontawesome5.FontAwesomeSolid
import
org.kordamp.ikonli.javafx.FontIcon
import
tornadofx.*
import
java.
awt.image.BufferedImag
e
import
java.
util.concurrent.atomic.AtomicReferenc
e
enum
class
PictureTakingState
{
READY
,
TAKING
,
PREVIEWING
,
GOOD
}
class
CameraState
{
val
imageProperty
=
SimpleObjectProperty
<
Buffered
Image
>(
this
,
"image"
,
null
)
val
imageProperty
=
SimpleObjectProperty
<
Image
>(
this
,
"image"
,
null
)
var
image
by
imageProperty
val
stateProperty
=
SimpleObjectProperty
<
PictureTakingState
>(
this
,
"state"
,
PictureTakingState
.
READY
)
...
...
@@ -32,34 +35,50 @@ class CameraState {
class
CameraStateModel
:
ItemViewModel
<
CameraState
>()
{
private
val
logger
=
KotlinLogging
.
logger
{}
val
image
:
SimpleObjectProperty
<
Buffered
Image
>
=
bind
(
CameraState
::
imageProperty
)
val
image
:
SimpleObjectProperty
<
Image
>
=
bind
(
CameraState
::
imageProperty
)
val
state
:
SimpleObjectProperty
<
PictureTakingState
>
=
bind
(
CameraState
::
stateProperty
)
val
countdownPercentage
=
bind
(
CameraState
::
countdownPercentageProperty
)
val
previewing
:
BooleanBinding
=
Bindings
.
equal
(
PictureTakingState
.
PREVIEWING
,
state
)
val
readyToTake
:
BooleanBinding
=
Bindings
.
equal
(
PictureTakingState
.
READY
,
state
)
val
taking
:
BooleanBinding
=
Bindings
.
equal
(
PictureTakingState
.
TAKING
,
state
)
}
class
CameraView
:
View
()
{
private
val
logger
=
KotlinLogging
.
logger
{}
private
val
cameraLoadingView
:
CameraLoadingView
by
inject
()
private
val
cameraImagePreviewView
:
CameraImagePreviewView
by
inject
()
private
val
cameraStateModel
:
CameraStateModel
by
inject
()
private
val
cameraController
:
CameraController
by
inject
()
private
val
currentView
=
AtomicReference
<
View
>()
init
{
//set up the state, it's weird that I even have to do this, the initial value doesn't work
cameraStateModel
.
state
.
set
(
PictureTakingState
.
READY
)
currentView
.
set
(
cameraLoadingView
)
}
override
fun
onDock
()
{
//Hook up an observable to the state to have it swap views when ready
cameraStateModel
.
state
.
toObservableChangesNonNull
()
.
map
{
change
->
val
to
=
change
.
newVal
to
}
.
map
{
when
(
it
)
{
PictureTakingState
.
PREVIEWING
->
currentView
.
getAndSet
(
cameraImagePreviewView
).
replaceWith
(
cameraImagePreviewView
)
else
->
currentView
.
getAndSet
(
cameraLoadingView
).
replaceWith
(
cameraLoadingView
)
}
}
.
subscribe
()
}
override
val
root
=
borderpane
{
//Left and right can be 160px max
center
=
c
ameraLoadingView
.
root
center
=
c
urrentView
.
get
()
.
root
right
=
vbox
{
prefWidth
=
160.0
...
...
@@ -67,44 +86,78 @@ class CameraView : View() {
alignment
=
Pos
.
CENTER
button
(
""
,
FontIcon
.
of
(
FontAwesomeSolid
.
CHECK_SQUARE
,
60
))
{
//WHYYYYY
style
{
baseColor
=
c
(
"black"
)
backgroundColor
+=
c
(
"green"
)
}
enableWhen
{
cameraStateModel
.
previewing
}
cameraController
.
take
Picture
(
actionEvents
())
cameraController
.
keep
Picture
(
actionEvents
())
//Picture is good, enabled only after a capture
//Make it green
}
}
//Kinda want a space in-between these two
button
(
"Take Picture!"
)
{
//Call the controller action that updates the model and starts the count down
enableWhen
(
cameraStateModel
.
readyToTake
)
hbox
{
alignment
=
Pos
.
CENTER
style
{
paddingTop
=
10.0
}
button
(
"Take Picture!"
)
{
//Call the controller action that updates the model and starts the count down
enableWhen
(
cameraStateModel
.
readyToTake
)
cameraController
.
takePicture
(
actionEvents
())
}
}
label
(
"Delay to take picture"
)
hbox
{
progressbar
{
bind
(
cameraStateModel
.
countdownPercentage
)
//Set max width to the same as something?
hgrow
=
Priority
.
ALWAYS
progressbar
(
cameraStateModel
.
countdownPercentage
)
{
useMaxWidth
=
true
prefWidthProperty
().
bind
(
this
@hbox
.
widthProperty
())
}
}
}
left
=
vbox
{
left
=
borderpane
{
prefWidth
=
160.0
hbox
{
top
=
hbox
{
alignment
=
Pos
.
CENTER
button
(
""
,
FontIcon
.
of
(
FontAwesomeSolid
.
WINDOW_CLOSE
,
60
))
{
cameraController
.
rejectPicture
(
actionEvents
())
style
{
baseColor
=
c
(
"black"
)
backgroundColor
+=
c
(
"red"
)
}
//Picture is no good, don't keep it
enableWhen
{
cameraStateModel
.
previewing
}
}
}
bottom
=
hbox
{
alignment
=
Pos
.
CENTER
button
(
""
,
FontIcon
.
of
(
FontAwesomeSolid
.
EJECT
,
60
))
{
cameraController
.
cancelPictureTaking
(
actionEvents
())
style
{
baseColor
=
c
(
"black"
)
}
disableWhen
{
cameraStateModel
.
taking
}
}
}
}
}
}
...
...
@@ -120,3 +173,28 @@ class CameraLoadingView : View() {
}
}
}
class
CameraImagePreviewView
:
View
()
{
private
val
cameraStateModel
:
CameraStateModel
by
inject
()
private
val
logger
=
KotlinLogging
.
logger
{}
override
val
root
=
hbox
{
//Put teh image here
imageview
{
this
.
fitHeight
=
480.0
this
.
fitWidth
=
480.0
this
.
image
=
cameraStateModel
.
image
.
get
()
//Why doesn't this get triggered, because first time through it's a race condition
cameraStateModel
.
image
.
toObservableChanges
()
.
map
{
if
(
it
.
newVal
!=
null
)
{
this
.
image
=
it
.
newVal
}
else
{
//Can this even work?
logger
.
debug
(
"NO IMAGE"
)
this
.
image
=
null
}
}
.
subscribe
()
}
}
}
src/main/kotlin/is/kow/deskscreen/wx/WeatherController.kt
View file @
302bde05
...
...
@@ -176,7 +176,7 @@ class WeatherController : Controller() {
//TODO: emit to the ticker the error to display it on the screen
logger
.
error
(
"Failed to acquire hourly forecast url"
,
throwable
)
}
.
retry
()
//TODO: should have some kind of backoff or whatever
.
retry
()
//TODO: should have some kind of backoff or whatever
yeah need that
.
subscribe
()
//EMIT!
...
...
src/main/resources/imagery/MaineCoon-cropped.jpeg
0 → 100644
View file @
302bde05
92.9 KB
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment