From e80309933050a8f52c18c249f218f0c1ae5af1f8 Mon Sep 17 00:00:00 2001 From: Mike Lowis Date: Thu, 21 Dec 2023 12:08:49 -0500 Subject: [PATCH] simple ruby websocket works except for starting video midstream. Need to try tunneling through nginx to solve that... --- index.html | 73 +++++++++++++------------------ serve | 10 ----- serve-videos | 120 ++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 139 insertions(+), 64 deletions(-) delete mode 100755 serve diff --git a/index.html b/index.html index a08ba8c..dfc85f9 100644 --- a/index.html +++ b/index.html @@ -19,61 +19,48 @@ - +(()=>{ connect(); })(); + \ No newline at end of file diff --git a/serve b/serve deleted file mode 100755 index db6a7cb..0000000 --- a/serve +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -play_videos(){ - while [ 1 ]; do - ./play-videos - done -} - -play_videos & -websocketd -staticdir . -port 8080 cat diff --git a/serve-videos b/serve-videos index cc02160..f05f097 100755 --- a/serve-videos +++ b/serve-videos @@ -1,26 +1,124 @@ #!/bin/env ruby require 'iodine' +require 'json' require 'fileutils' +# reload the database +$db = JSON.parse(File.read("index.json")) +$now_playing = nil +$channel = 0 +$channels = [ + { include: ["Christmas"] }, + { include: ["Movies", "Shorts", "Shows"] }, + { include: ["Movies"] }, + { include: ["Shorts"] }, + { include: ["Shows"] }, + { include: ["Pictures"] }, +] + +def secs_since_midnight() + now = Time.now + midnight = Time.new(now.year, now.month, now.day, 0, 0, 0) + (now - midnight) +end + +def next_show(channel) + cfg = $channels[channel] + path = cfg[:files][cfg[:curr]] + cfg[:curr] += 1 + if cfg[:curr] >= cfg[:files].length + cfg[:files].shuffle + cfg[:curr] = 0 + end + (path ? $db[path].merge({"path"=>path}) : nil) +end + +def populate_channels() + files = $db.keys + start_time = secs_since_midnight() + $channels.each_with_index do |cfg, i| + cfg[:files] = files.select{|f| cfg[:include].select{|prefix| f.start_with? prefix}.length > 0 }.shuffle + cfg[:curr] = 0 + cfg[:play] = { + chan: i, + start_time: start_time, + } + cfg[:play][:curr] = next_show(i) + cfg[:play][:next] = next_show(i) + end +end + +def update_program() + $now_playing = $channels[$channel][:play] + Iodine.publish(:atv, JSON.dump($now_playing.merge({ "cmd" => "play" }))) +end + +def program_changed() + changed = false + time = secs_since_midnight +# time = $channels[0][:play][:start_time] + $channels[0][:play][:curr]["duration"] + $channels.each_with_index do |chan, i| + next if not chan[:play][:curr] + end_time = chan[:play][:start_time] + chan[:play][:curr]["duration"] + if end_time <= time then + changed = true + chan[:play][:chan] = i + chan[:play][:curr] = chan[:play][:next] + chan[:play][:next] = next_show(i) + chan[:play][:start_time] = time +# pp chan[:play] + end +# puts "Chan #{i} time remaining #{end_time - time}" + end + changed +end + +module ATV + def on_open(client) + puts "connect: #{client}" + client.subscribe :atv + send(client, $now_playing.merge({ "cmd" => "play" })) + end + + def on_close(client) + puts "disconnect: #{client}" + end + + def on_message(client, data) + # nothing to do, we are stream only + end + + def send(client, data) + client.write JSON.dump(data) + end + + extend self +end + APP = Proc.new do |env| -# if env['rack.upgrade?'.freeze] == :websocket -# env['rack.upgrade'.freeze] = SystemTrace -# [0,{}, []] # It's possible to set cookies for the response. -# else -# data = PAGE_HTML -# [200, {"Content-Length" => "#{data.length}", "Content-Type" => "text/html"}, [data]] -# end + if env['rack.upgrade?'.freeze] == :websocket + env['rack.upgrade'.freeze] = ATV + [0,{}, []] # It's possible to set cookies for the response. + end end +# load up the channels and generate the initial program +populate_channels() +update_program() -# static file service +# setup the websocket and static file server Iodine.listen( service: :http, - public: Dir.getwd(), handler: APP ) -# for static file service, we only need a single thread and a single worker. -Iodine.threads = 1 +# Every second check for a video change and send it out if needed +Iodine.run_every(1000) do + if program_changed() + update_program() + end +end + +# start the server now Iodine.start -- 2.52.0