From 9c8a9a894ac1436b1b5f7ef9ed8c2e163ba8eb88 Mon Sep 17 00:00:00 2001
From: ben <ben@nagy.contact>
Date: Sun, 5 Jan 2025 21:41:48 -0800
Subject: added action-gesturing-state cycling logic

---
 lua/sleep.lua | 150 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 116 insertions(+), 34 deletions(-)

(limited to 'lua')

diff --git a/lua/sleep.lua b/lua/sleep.lua
index 931c21e..3a48469 100644
--- a/lua/sleep.lua
+++ b/lua/sleep.lua
@@ -1,4 +1,7 @@
-local config_file = "../sleep.json" -- TODO: update path to . (since sleep.json should be in is.xyz.mpv)
+local mp = require 'mp'
+--local socket = require("socket") -- not portable
+
+local config_file = "/storage/emulated/0/Android/media/is.xyz.mpv/scripts/sleep.json"
 
 local time = {
 	minutes = 25,
@@ -11,13 +14,28 @@ local time = {
 		remaining = nil,
 		was_active = false,
 		last_update = "", -- ISO 8601
+		-- file_name = ""
 	},
 }
 
 local gesture_state = {
-	last_trigger_sec = 0,
-	trigger_count = 0,
-	latency = 3, -- seconds
+	triggers = {
+		count = 0,
+		last_action_time = 0,
+	},
+	actions = {
+		pending = false,
+		confirm_timeout = 5, -- seconds
+		timer = nil,
+		callback = nil,
+	}
+}
+
+local ActionType = {
+    SET_TIMER = 1,
+    REMOVE_TIMER = 2,
+    REINSTATE = 3,
+    RESET = 4
 }
 
 
@@ -34,7 +52,7 @@ local function read_jsonkey_value(file_str, json_obj, obj_key)
 	local e_obj = string.find(file_str, "}", b_obj)
 
 	if not (b_obj or e_obj) then
-		print(json_obj .. "does not exist or " .. config_file "is formatted incorrectly")
+		mp.msg.error("[sleep.lua]" .. json_obj .. "does not exist or " .. config_file "is formatted incorrectly")
 		return nil
 	end
 
@@ -42,7 +60,7 @@ local function read_jsonkey_value(file_str, json_obj, obj_key)
 	local key_val = string.match(substr, obj_key)
 
 	if not key_val then
-		print("could not extract \"" .. string.match(obj_key, "\"([^\"]+)\"") .. "\"" .. " from " .. file)
+		mp.msg.error("[sleep.lua]: could not extract \"" .. string.match(obj_key, "\"([^\"]+)\"") .. "\"" .. " from " .. config_file)
 		return nil
 	end
 
@@ -50,39 +68,37 @@ local function read_jsonkey_value(file_str, json_obj, obj_key)
 end
 
 local function read_config()
-	print("opening", config_file .. "...")
+	mp.msg.info("[sleep.lua]: opening", config_file .. "...")
 
 	local openf = io.input(config_file)
 	if openf == nil then
-		print("failed to open", config_file .. "!")
+		mp.msg.error("[sleep.lua]: failed to open", config_file .. "!")
 		-- TODO: we should make sure it exists, otherwise should create it
 	end
 
+
 	local file_str = openf:read("*all")
 	if file_str == nil or file_str == "" then
-		print("failed to read config_file into string or config_file is empty")
+		mp.msg.error("[sleep.lua]: Failed to read config_file into string or config_file is empty", config_file .. "!")
 	end
 
+	mp.msg.info("[sleep.lua]: closing", config_file .. ".")
+	io.close(openf)
+
 	local default_time = read_jsonkey_value(file_str, "\"config\"", "\"default_time\"%s*:%s*(%d+)")
 	local prevstate_tstamp = read_jsonkey_value(file_str, "\"previous_state\"", "\"timestamp\"%s*:%s*\"(.-)\"")
 	local prevstate_lastup = read_jsonkey_value(file_str, "\"previous_state\"", "\"last_updated\"%s*:%s*\"(.-)\"")
 	local prevstate_active = read_jsonkey_value(file_str, "\"previous_state\"", "\"was_active\"%s*:%s*([a-zA-Z]+)")
 
-	if (default_time and prevstate_tstamp and prevstate_lastup and prevstate_active) then
-		--[[ print("default_time: " .. default_time)
-		print("prevstate_tstamp: " .. prevstate_tstamp)
-		print("prevstate_lastup: " .. prevstate_lastup)
-		print("prevstate_active: " .. prevstate_active) ]]
-	else
-		-- print("something went wrong")
-	end
-
-	print("closing", config_file .. ".")
-	io.close(openf)
+	mp.msg.info("default_time: " .. default_time or "[sleep.lua]: could not extract default_time from")
+	mp.msg.info("prevstate_tstamp: " .. prevstate_tstamp)
+	mp.msg.info("prevstate_lastup: " .. prevstate_lastup)
+	mp.msg.info("prevstate_active: " .. prevstate_active)
 end
 
 local function reinstate_tstamp(time)
 	-- according to a gesture, this should be called, and seek to @param in file
+	-- we also need to verify that we're in the correct file.
 end
 
 local function export_time()
@@ -93,33 +109,99 @@ end
 local function stop_timer()
 end
 
-local function reset_timer()
+local function remove_timer()
 end
 
 local function set_timer()
-	timer.minutes = read_config() or timer.minutes
-	timer.active = true
-	mp.osd_message("Timer has been set for " .. timer.minutes .. " minutes.", 3)
 end
 
 local function display_time()
 end
 
+local function cancel_pending_action()
+    if gesture_state.actions.timer then
+        gesture_state.actions.timer:kill()
+        gesture_state.actions.timer = nil
+        gesture_state.actions.callback = nil
+        gesture_state.actions.pending = false
+        mp.osd_message("Action cancelled")
+    end
+end
+
+local function confirm_action(action_t)
+	cancel_pending_action()
+	gesture_state.actions.pending = true
+
+	local messages = {
+		[ActionType.SET_TIMER] = "Timer will be set for " .. time.minutes .. " minutes in " .. gesture_state.actions.confirm_timeout .. " seconds.\nGesture again to cancel",
+		[ActionType.REMOVE_TIMER] = "Timer will be removed in " .. gesture_state.actions.confirm_timeout .. " seconds.\nGesture again to cancel",
+		[ActionType.REINSTATE] = "Timer will be reinstated in " .. gesture_state.actions.confirm_timeout .. " seconds.\nGesture again to cancel",
+		[ActionType.RESET] = "Timer will be reset in " .. gesture_state.actions.confirm_timeout .. " seconds.\nGesture again to cancel"
+	}
+
+	mp.osd_message(messages[action_t], gesture_state.actions.confirm_timeout)
+
+	gesture_state.actions.timer = mp.add_timeout(gesture_state.actions.confirm_timeout, function()
+		if gesture_state.actions.callback then
+			gesture_state.actions.callback()
+		end
+
+		gesture_state.actions.timer = nil
+		gesture_state.actions.callback = nil
+		gesture_state.actions.pending = false
+	end)
+
+	return true
+end
+
 -- user calls this
 local function handle_gesture()
-	    mp.osd_message("Gesture Received.", 3)
-		set_timer()
-
-		-- TODO:
-		-- the firs time handle_gestures() is called, timer should be set
-		-- if handle_gestures() is called a second time within a short period, then we should cycle timer off
-		-- if handle_gestures() is called again a third time within a short period, then we should reinstate the last time export
-		-- should include debouncing logic for clean gesture input (eg. ignore calls made within some tiny time before each other)
+	mp.osd_message("Gesture Received. (" .. gesture_state.triggers.count .. ")", 3)
+	gesture_state.triggers.count = gesture_state.triggers.count + 1
+
+	local current_time = mp.get_time()
+	gesture_state.triggers.last_action_time = current_time
+
+	if gesture_state.actions.pending then
+		cancel_pending_action()
+		return
+	end
+
+	if gesture_state.triggers.count == ActionType.SET_TIMER then
+		local confirmed = confirm_action(ActionType.SET_TIMER)
+		if confirmed then
+			gesture_state.actions.callback = function()
+				--set_timer()
+				mp.osd_message("Timer has been set!")
+			end
+		end
+	elseif gesture_state.triggers.count == ActionType.REMOVE_TIMER then
+		local confirmed = confirm_action(ActionType.REMOVE_TIMER)
+		if confirmed then
+			gesture_state.actions.callback = function()
+				--remove_timer()
+				mp.osd_message("Timer has been removed.")
+			end
+		end
+	elseif gesture_state.triggers.count == ActionType.REINSTATE then
+		local confirmed = confirm_action(ActionType.REINSTATE)
+		if confirmed then
+			gesture_state.actions.callback = function()
+				-- reinstate_timer(t)
+				mp.osd_message("Reinstating [time stamp] from [FILE].")
+			end
+		end
+	else
+		gesture_state.triggers.count = 0
+	end
 end
 
 -- called immediately upon opening a media config_file
-function main()
-	    mp.osd_message("Sleep timer script initialized!", 3)
+local function main()
+	mp.msg.info("[sleep.lua]: script has been loaded")
+	mp.osd_message("script has been loaded")
+
+	--read_config()
 end
 
 mp.add_key_binding(nil, "sleep", handle_gesture) -- the user invokes this by gesturing (user-set in input.conf)
-- 
cgit v1.2.3