]> git.mdlowis.com Git - proto/atv.git/commitdiff
simple ruby websocket works except for starting video midstream. Need to try tunnelin...
authorMike Lowis <mike.lowis@gentex.com>
Thu, 21 Dec 2023 17:08:49 +0000 (12:08 -0500)
committerMike Lowis <mike.lowis@gentex.com>
Thu, 21 Dec 2023 17:08:49 +0000 (12:08 -0500)
index.html
serve [deleted file]
serve-videos

index a08ba8c25e4ebed5e228bf1805a89ab34b770791..dfc85f9707a996a1070e2eb8dd1a28a2e8021d54 100644 (file)
 <video id="Video" width="100%" height="100%" src="" autoplay muted playsinline>
 </video>
 
-  <script>
-    (()=>{
-    let program = {};
+<script>
 
-    const secondsSinceMidnight = ()=>{
-        const now = new Date();
-        const midnight = new Date(
-            now.getFullYear(),
-            now.getMonth(),
-            now.getDate(),
-            0,0,0);
-        return (now.getTime() - midnight.getTime()) / 1000;
-    };
+const secondsSinceMidnight = ()=>{
+    const now = new Date();
+    const midnight = new Date(
+        now.getFullYear(),
+        now.getMonth(),
+        now.getDate(),
+        0,0,0);
+    return (now.getTime() - midnight.getTime()) / 1000;
+};
 
-    const playNextItem = (force)=>{
-        const channel  = program["channels"][program["curr"]];
-        console.log(channel);
-        const duration = channel["curr"]["duration"];
+const Cmd = {
+    play: (data)=>{
+        console.log(data);
+        const duration = data["curr"]["duration"];
         const since_mn = secondsSinceMidnight();
-        const end_time = channel["start_time"] + duration;
+        const end_time = data["start_time"] + duration;
         const offset   = duration - (end_time - since_mn);
         console.log(offset);
-        if (force || (offset > 0 && offset < duration))
+        if (offset > 0 && offset < duration)
         {
-            Video.src = channel["curr"]["path"] + "#t=" + Math.floor(offset);
+            Video.src = data["curr"]["path"] + "#t=" + Math.floor(offset);
             console.log(Video.src);
         }
-    };
+    }
+};
 
-    const updateProgram = (onload)=>{
-        fetch("program.json")
-            .then((resp)=> resp.json() )
-            .then((json)=>{
-                let changed = (
-                    program["curr"] !== json["curr"]
-                );
-                program = json;
-                if (typeof onload === 'function') {
-                    onload();
-                } else if (changed) {
-                    playNextItem();
-                }
-            });
+const connect = ()=>{
+    let ws = new WebSocket("ws://" + window.location.host);
+    ws.onmessage = (event)=>{
+        const msg = JSON.parse(event.data);
+        Cmd[msg.cmd](msg);
     };
 
-    const updateCurrentItem = ()=>{
-        updateProgram(playNextItem);
+    ws.onclose = (event)=>{
+        connect();
     };
+};
+
 
-    /* start the program and setup listeners to keep it in sync */
-    updateCurrentItem();
-    Video.addEventListener("ended", updateCurrentItem);
-    document.addEventListener("visibilitychange", updateCurrentItem);
-    setInterval(updateProgram, 1000);
-})();
-  </script>
+(()=>{ connect(); })();
+</script>
 
 </body></html>
\ No newline at end of file
diff --git a/serve b/serve
deleted file mode 100755 (executable)
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
index cc021607e3f3797e647f17c91247e0e328779805..f05f097e8c56f50a89cc7589a872a941e24a2a6d 100755 (executable)
 #!/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