From 090b2808efb7ef90d7d98a97a01040c777c689bb Mon Sep 17 00:00:00 2001 From: Mike Lowis Date: Thu, 21 Dec 2023 10:23:31 -0500 Subject: [PATCH 1/1] initial commit --- .gitignore | 1 + index.html | 79 ++++++++++++++++++++++++++++++++++++++++++++++ play-videos | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ play.html | 79 ++++++++++++++++++++++++++++++++++++++++++++++ scan-videos | 49 +++++++++++++++++++++++++++++ serve | 10 ++++++ serve-videos | 26 +++++++++++++++ 7 files changed, 333 insertions(+) create mode 100644 .gitignore create mode 100644 index.html create mode 100755 play-videos create mode 100644 play.html create mode 100755 scan-videos create mode 100755 serve create mode 100755 serve-videos diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..94a2dd1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.json \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..a08ba8c --- /dev/null +++ b/index.html @@ -0,0 +1,79 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/play-videos b/play-videos new file mode 100755 index 0000000..37e9361 --- /dev/null +++ b/play-videos @@ -0,0 +1,89 @@ +#!/bin/env ruby + +require 'json' +require 'fileutils' + +# reload the database +$db = JSON.parse(File.read("index.json")) +$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() + data = { "curr" => 1, "channels" => $channels.map{|c| c[:play] } } + pp data + File.open("program.json.temp", "wb") do |f| + f.write JSON.dump(data) + end + FileUtils.mv("program.json.temp", "program.json") +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 + +# load up the channels and generate the initial program +populate_channels() +update_program() + +# wake up once a second to see if a program has finished and pick the next program +while 1 + if program_changed() + update_program() + end + sleep 1 +end + diff --git a/play.html b/play.html new file mode 100644 index 0000000..a08ba8c --- /dev/null +++ b/play.html @@ -0,0 +1,79 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/scan-videos b/scan-videos new file mode 100755 index 0000000..de8a402 --- /dev/null +++ b/scan-videos @@ -0,0 +1,49 @@ +#!/bin/env ruby + +require 'json' +require 'fileutils' + +CMD="ffprobe -show_entries format=duration -v quiet -of csv=\"p=0\" -i" + +# reload the database +$db = {} +if File.exist?("index.json") + $db = JSON.parse(File.read("index.json")) +end + +def cleanup_files() + $db.keys.each do |f| + if not File.exist? f then + $db.delete(f) + end + end +end + +def scan_pictures(root_path) +end + +#def scan_shows(root_path) +#end + +def scan_videos(root_path) + Dir.glob("#{root_path}/**/*.{mp4,webm,ogg}").each do |f| + next if $db[f] + puts f + duration = `#{CMD} \"#{f}\"`.chomp.to_f + $db[f] = { "duration" => duration } + end +end + +# scan for pictures and videos +cleanup_files() +scan_pictures("Pictures") +scan_videos("Christmas") +scan_videos("Movies") +scan_videos("Shorts") +scan_videos("Shows") + +# write the database to disk +File.open("index.json.temp", "wb") do |f| + f.write JSON.dump($db) +end +FileUtils.mv("index.json.temp", "index.json") diff --git a/serve b/serve new file mode 100755 index 0000000..db6a7cb --- /dev/null +++ b/serve @@ -0,0 +1,10 @@ +#!/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 new file mode 100755 index 0000000..cc02160 --- /dev/null +++ b/serve-videos @@ -0,0 +1,26 @@ +#!/bin/env ruby + +require 'iodine' +require 'fileutils' + +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 +end + + +# static file service +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 +Iodine.start -- 2.52.0