-- Info-Beamer script with streaming channel support gl.setup(NATIVE_WIDTH, NATIVE_HEIGHT) local json = require "json" local font = resource.load_font "roboto.ttf" local server_url = CONFIG.server_url or "http://192.168.1.22" local player_id = CONFIG.player_id or "default_player" local refresh_interval = CONFIG.refresh_interval or 30 local default_duration = CONFIG.default_duration or 10 local touch_enabled = CONFIG.touch_enabled ~= false -- Default to true local swipe_threshold = CONFIG.swipe_threshold or 100 local manual_override_duration = CONFIG.manual_override_duration or 10 local playlist = {} local current_item = 1 local item_start_time = 0 local last_update = 0 local channel_info = {} -- Touch and swipe variables local touch_start_x = 0 local touch_start_y = 0 local touch_start_time = 0 local is_touching = false local swipe_time_limit = 1.0 -- Maximum time for swipe (seconds) local manual_override = false local manual_override_time = 0 function update_playlist() -- Fetch channel content from server local url = server_url .. "/api/player/" .. player_id .. "/content" util.post_and_wait(url, "", function(response) if response.success then local data = json.decode(response.content) if data and data.content then playlist = data.content print("Updated channel content: " .. #playlist .. " items") -- Load assets for i, item in ipairs(playlist) do if item.type == "image" then item.resource = resource.load_image(server_url .. "/uploads/" .. item.filename) elseif item.type == "video" then item.resource = resource.load_video(server_url .. "/uploads/" .. item.filename) end end end end end) -- Also fetch channel information local channel_url = server_url .. "/api/player/" .. player_id .. "/channel" util.post_and_wait(channel_url, "", function(response) if response.success then channel_info = json.decode(response.content) or {} end end) last_update = sys.now() end -- Touch event handlers function node.on_touch(touches) for touch in touches() do if touch.type == "start" then -- Touch started touch_start_x = touch.x touch_start_y = touch.y touch_start_time = sys.now() is_touching = true elseif touch.type == "end" and is_touching then -- Touch ended - check for swipe local touch_end_x = touch.x local touch_end_y = touch.y local touch_duration = sys.now() - touch_start_time -- Calculate swipe distance and direction local dx = touch_end_x - touch_start_x local dy = touch_end_y - touch_start_y local distance = math.sqrt(dx * dx + dy * dy) -- Check if it's a valid swipe (horizontal, sufficient distance, quick enough) if distance > swipe_threshold and touch_duration < swipe_time_limit and math.abs(dx) > math.abs(dy) * 2 then -- More horizontal than vertical if #playlist > 1 then -- Only allow swipe if there's content to switch to if dx > 0 then -- Swipe right - next item next_content() else -- Swipe left - previous item previous_content() end -- Enable manual override mode manual_override = true manual_override_time = sys.now() print("Swipe detected: " .. (dx > 0 and "right (next)" or "left (previous)")) end end is_touching = false end end end -- Function to go to next content item function next_content() if #playlist > 0 then current_item = current_item + 1 if current_item > #playlist then current_item = 1 end item_start_time = sys.now() end end -- Function to go to previous content item function previous_content() if #playlist > 0 then current_item = current_item - 1 if current_item < 1 then current_item = #playlist end item_start_time = sys.now() end end function node.render() -- Update playlist periodically if sys.now() - last_update > refresh_interval then update_playlist() end -- Check if manual override has expired if manual_override and sys.now() - manual_override_time > manual_override_duration then manual_override = false item_start_time = sys.now() -- Reset automatic timing end -- If no playlist items, show waiting message if #playlist == 0 then font:write(100, 100, "Waiting for channel content...", 50, 1, 1, 1, 1) font:write(100, 200, "Server: " .. server_url, 30, 0.7, 0.7, 0.7, 1) font:write(100, 250, "Player ID: " .. player_id, 30, 0.7, 0.7, 0.7, 1) font:write(100, 300, "Swipe left/right to navigate when content is available", 20, 0.5, 0.5, 0.5, 1) return end local item = playlist[current_item] if not item then current_item = 1 item = playlist[current_item] if not item then return end end local duration = item.duration or default_duration -- Only advance automatically if not in manual override mode if not manual_override and sys.now() - item_start_time > duration then next_content() end -- Display current item if item and item.resource then if item.type == "image" then item.resource:draw(0, 0, WIDTH, HEIGHT) elseif item.type == "video" then item.resource:draw(0, 0, WIDTH, HEIGHT) end -- Show channel info overlay if channel_info.name then font:write(10, HEIGHT - 80, "Channel: " .. channel_info.name, 20, 1, 1, 1, 0.8) if channel_info.description then font:write(10, HEIGHT - 50, channel_info.description, 18, 1, 1, 1, 0.7) end end -- Show content navigation info if #playlist > 1 then local nav_text = string.format("%d / %d", current_item, #playlist) font:write(10, HEIGHT - 20, nav_text, 16, 1, 1, 1, 0.6) -- Show swipe instructions (fade in/out) local instructions_alpha = 0.4 + 0.2 * math.sin(sys.now() * 2) font:write(10, 30, "◀ Swipe to navigate ▶", 18, 1, 1, 1, instructions_alpha) end -- Show manual override indicator if manual_override then local remaining = manual_override_duration - (sys.now() - manual_override_time) font:write(WIDTH - 150, HEIGHT - 20, string.format("Manual: %.1fs", remaining), 16, 1, 1, 0, 0.8) end end -- Show current time local current_time = os.date("%H:%M") font:write(WIDTH - 100, 20, current_time, 24, 1, 1, 1, 0.9) end -- Initial load update_playlist()