Skip to content

Commit

Permalink
Persist last scene (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusandra committed May 9, 2024
1 parent 795c5da commit 46f3ce9
Show file tree
Hide file tree
Showing 9 changed files with 342 additions and 144 deletions.
409 changes: 283 additions & 126 deletions backend/app/codegen/scene_nim.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion backend/app/models/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def new_frame(name: str, frame_host: str, server_host: str, device: Optional[str
rotate=0,
background_color="#ffffff",
device=device or "web_only",
log_to_file=None, # save the SSD by default
log_to_file=None, # spare the SD card from load
)
db.session.add(frame)
db.session.commit()
Expand Down
4 changes: 2 additions & 2 deletions e2e/generated/scenes.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is autogenerated

import frameos/types
import tables
import tables, options
import scenes/scene_color as scene_color
import scenes/scene_gradient as scene_gradient
import scenes/scene_ifElse as scene_ifElse
Expand All @@ -11,7 +11,7 @@ import scenes/scene_qr as scene_qr
import scenes/scene_split as scene_split
import scenes/scene_text as scene_text

let defaultSceneId* = "color".SceneId
let defaultSceneId* = some("color".SceneId)

const sceneOptions* = [
("color".SceneId, "Test Color"),
Expand Down
2 changes: 2 additions & 0 deletions e2e/state/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# This changes too unpredictably in CI
scene.json
26 changes: 25 additions & 1 deletion frameos/src/frameos/runner.nim
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var
lastPublicStates {.guard: lastPublicStatesLock.} = %*{}
lastPublicSceneId {.guard: lastPublicStatesLock.} = "".SceneId
lastPersistedStates = %*{}
lastPersistedSceneId: Option[SceneId] = none(SceneId)

proc setLastImage(image: Image) =
withLock lastImageLock:
Expand Down Expand Up @@ -91,13 +92,25 @@ proc updateLastPersistedState*(self: FrameScene) =
if hasChanges:
writeFile(&"{SCENE_STATE_JSON_FOLDER}/scene-{sanitizePathString(self.id.string)}.json", $persistedState)
self.lastPersistedStateUpdate = epochTime()
if lastPersistedSceneId.isNone() or lastPersistedSceneId.get() != self.id:
writeFile(&"{SCENE_STATE_JSON_FOLDER}/scene.json", $(%*{"sceneId": self.id.string}))
lastPersistedSceneId = some(self.id)

proc loadPersistedState*(sceneId: SceneId): JsonNode =
try:
return parseJson(readFile(&"{SCENE_STATE_JSON_FOLDER}/scene-{sanitizePathString(sceneId.string)}.json"))
except IOError:
return %*{}

proc loadLastScene*(): Option[SceneId] =
try:
let json = parseJson(readFile(&"{SCENE_STATE_JSON_FOLDER}/scene.json"))
if json.hasKey("sceneId"):
result = some(SceneId(json["sceneId"].getStr()))
lastPersistedSceneId = result
except IOError:
return none(SceneId)

proc renderSceneImage*(self: RunnerThread, exportedScene: ExportedScene, scene: FrameScene): Image =
let sceneTimer = epochTime()
let requiredWidth = self.frameConfig.renderWidth()
Expand Down Expand Up @@ -301,12 +314,23 @@ proc startMessageLoop*(self: RunnerThread): Future[void] {.async.} =
if waitTime < 200:
waitTime += 5

proc getFirstSceneId*(): SceneId =
if defaultSceneId.isSome():
return defaultSceneId.get()
let lastSceneId = loadLastScene()
if lastSceneId.isSome():
return lastSceneId.get()
if len(exportedScenes) > 0:
for key in keys(exportedScenes):
return key
return "".SceneId

proc createRunnerThread*(args: (FrameConfig, Logger)) =
{.cast(gcsafe).}:
var runnerThread = RunnerThread(
frameConfig: args[0],
scenes: initTable[SceneId, FrameScene](),
currentSceneId: defaultSceneId,
currentSceneId: getFirstSceneId(),
lastRenderAt: 0,
sleepFuture: none(Future[void]),
isRendering: false,
Expand Down
6 changes: 3 additions & 3 deletions frameos/src/scenes/scenes.nim
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import default as defaultScene
import frameos/types
import tables
import tables, options

let defaultSceneId* = "default".SceneId
let defaultSceneId* = some("default".SceneId)

const sceneOptions* = [
("753d9439-8470-4834-8c5d-73264875c5b1".SceneId, "Default Scene"),
]

proc getExportedScenes*(): Table[SceneId, ExportedScene] =
result = initTable[SceneId, ExportedScene]()
result[defaultSceneId] = defaultScene.exportedScene
result["default".SceneId] = defaultScene.exportedScene

# TODO Scene options:
# - start at boot / start when requested
Expand Down
23 changes: 13 additions & 10 deletions frontend/src/scenes/frame/panels/Scenes/SceneDropDown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function SceneDropDown({ sceneId, context }: SceneDropDownProps) {
const { frameId } = useValues(frameLogic)
const { editScene, editSceneJSON } = useActions(panelsLogic)
const { scenes } = useValues(scenesLogic({ frameId }))
const { toggleSettings, renameScene, duplicateScene, deleteScene, setAsDefault } = useActions(
const { toggleSettings, renameScene, duplicateScene, deleteScene, setAsDefault, removeDefault } = useActions(
scenesLogic({ frameId })
)
const { saveAsTemplate, saveAsZip } = useActions(templatesLogic({ frameId }))
Expand Down Expand Up @@ -79,15 +79,18 @@ export function SceneDropDown({ sceneId, context }: SceneDropDownProps) {
onClick: () => renameScene(scene.id),
icon: <PencilSquareIcon className="w-5 h-5" />,
},
...(!scene.default
? [
{
label: 'Set as default',
onClick: () => setAsDefault(scene.id),
icon: <FlagIcon className="w-5 h-5" />,
},
]
: []),

scene.default
? {
label: 'Remove "start on boot"',
onClick: () => removeDefault(),
icon: <FlagIcon className="w-5 h-5" />,
}
: {
label: 'Set to start on boot',
onClick: () => setAsDefault(scene.id),
icon: <FlagIcon className="w-5 h-5" />,
},
{
label: 'Delete scene',
confirm: 'Are you sure you want to delete this scene?',
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/frame/panels/Scenes/Scenes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export function Scenes() {
</span>
{scene.default ? (
<Tag className="ml-2" color="primary">
default
start on boot
</Tag>
) : null}
{scene?.settings?.refreshInterval && Number.isFinite(scene.settings.refreshInterval) ? (
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/scenes/frame/panels/Scenes/scenesLogic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const scenesLogic = kea<scenesLogicType>([
actions({
toggleSettings: (sceneId: string) => ({ sceneId }),
setAsDefault: (sceneId: string) => ({ sceneId }),
removeDefault: true,
deleteScene: (sceneId: string) => ({ sceneId }),
renameScene: (sceneId: string) => ({ sceneId }),
duplicateScene: (sceneId: string) => ({ sceneId }),
Expand Down Expand Up @@ -87,6 +88,17 @@ export const scenesLogic = kea<scenesLogicType>([
),
})
},
removeDefault: () => {
frameLogic({ frameId: props.frameId }).actions.setFrameFormValues({
scenes: values.scenes.map((scene) => {
if ('default' in scene) {
const { default: _, ...rest } = scene
return rest
}
return scene
}),
})
},
duplicateScene: ({ sceneId }) => {
const scene = values.scenes.find((s) => s.id === sceneId)
if (!scene) {
Expand Down

0 comments on commit 46f3ce9

Please sign in to comment.