diff --git a/test-wsplay/ws.html b/test-wsplay/ws.html new file mode 100644 index 0000000..b81ae00 --- /dev/null +++ b/test-wsplay/ws.html @@ -0,0 +1,55 @@ + + + + + +IntroQ/http + + + + + +

PUSH PUSH PUSH

+ + +

Team(1から6): +

+ +

+ +

+

+ +

+ + + + +

+ +
+ + + diff --git a/test-wsplay/ws.js b/test-wsplay/ws.js new file mode 100644 index 0000000..fd495b0 --- /dev/null +++ b/test-wsplay/ws.js @@ -0,0 +1,132 @@ +// 例 +// https://www.codespeedy.com/change-html5-audio-player-src-file-in-javascript/ +function intro() { + var team = document.getElementById("tm"), + button = document.getElementById("push"), + info = document.getElementById("info"), + music = document.getElementById("music"), + play = document.getElementById("play"), + msrc = document.getElementById("msrc"); + var conn, PORT=8804, server = location.hostname; + server = "wss://www.iekei.org/hayaoshi/" + function sendmsg(str) { + conn.send(JSON.stringify({team: team.value, state: str})); + } + function initConn() { + alert(music.volume); + try { + conn = new WebSocket(server); + conn.onopen = function() {}; // Nothing special + conn.onerror = function(err) { + alert('WebSocket failure: ' + err) + }; + conn.onmessage = function(ev) { + info.textContent = ev.data; + console.log("data: "+ev.data); + if (ev.data.match(/\.(mp3|ogg)/)) { + music.setAttribute("src", ev.data); + info.textContent = "Loading..."; + //info.textContent = "Playing "+music.getAttribute("src"); + music.volume = 0.1; + music.load(); + if (team.value == "admin") + info.textContent += ev.data; + else + info.textContent += "Done."; + sendmsg("loading done"); + button.disabled = false; + } else if (ev.data.match(/PING/)) { + sendmsg("PONG"); + } else if (ev.data.match(/LOAD: (\d+)\/(\d+)/)) { + if (team.value == "admin") { + var a=parseInt(RegExp.$1), b=parseInt(RegExp.$2); + // alert(a+"..."+b); + if (a>=b) { + play.textContent = " PLAYxxx "; + info.textContent = music.getAttribute("src"); + play.disabled = false; + } else { + play.textContent = (" PLAY "+a+"/"+b); + play.disabled = true; + } + } + } else if (ev.data.match(/(PLAY|STOP): ([0-9.]+) ([0-9.]+)/)) { + var delay = RegExp.$2*2000, + ct = parseFloat(RegExp.$3), + start = (RegExp.$1.match(/PLAY/)) + delay = Math.round(delay*100)/100; + info.textContent = "PUSH!!!"+delay; + if (ct>0) { + console.log("StartPos="+ct); + music.currentTime = ct; + } + setTimeout(function() { + (start) ? music.play() : music.pause(); + }, delay); + // music.resume().play(); + // music.play(); + } else if (ev.data.match(/RESET/)) { + console.log("Got RESET!!!!!"); + music.currentTime = 0; + info.textContent = "Ready..."; + button.disabled = false; + } else if (ev.data.match(new RegExp(team.value))) { + // alert(new RegExp(team.value)); + music.pause(); + button.disabled = true; + } else { + music.pause(); + } + }; + conn.onclose = function(ev) { + info.textContent = "接続断: 頃合を見てPUSHを押してください。"; + button.disabled = false; + conn = null; + }; + info.textContent = "Ready..."; + } catch (err) { + alert("Socket Creation Error\n\ +Firefoxですか? URLウィンドウに about:config と入れて\n\ +Search: 窓に websocket と入れて、\n\ +network..websocket.allowInsecureFromHTTP\n\ +の行をダブルクリックして true に変えてください。\n" + err); + } + } + function push(ev) { + music.pause(); + if (!conn) { + initConn(); + } else if (team.value == "") { + alert("Teamに1から6のどれかを入れてね!"); + } else { + var info = {team: team.value, state: "PUSH: "+music.currentTime}, + str = JSON.stringify(info); + conn.send(str); + } + } + document.getElementById("prev").addEventListener("click", function() { + sendmsg("prev"); + }, false); + document.getElementById("next").addEventListener("click", function() { + sendmsg("next"); + }, false); + document.getElementById("play").addEventListener("click", function() { + sendmsg("PLAY"); + }, false); + document.getElementById("stop").addEventListener("click", function() { + sendmsg("STOP: "+music.currentTime); + }, false); + document.getElementById("reset").addEventListener("click", function() { + sendmsg("RESET"); + }, false); + function catchClick() { + info.setAttribute("pre-caution", ""); + info.textContent = "Ready..."; + music.play(); music.pause(); + document.removeEventListener("click", catchClick); + } + document.addEventListener("click", catchClick, false); + button.addEventListener("mousedown", push, false); + initConn(); +} +document.addEventListener("DOMContentLoaded", intro, false); diff --git a/test-wsplay/ws.rb b/test-wsplay/ws.rb new file mode 100755 index 0000000..e84543d --- /dev/null +++ b/test-wsplay/ws.rb @@ -0,0 +1,120 @@ +#!/usr/bin/env ruby +# -*- coding: utf-8 -*- +# EM Intro. - http://keijinsonyaban.blogspot.jp/2010/12/eventmachine.html + +require 'em-websocket' +require 'json' +PORT = 8804 + +clients = {} +ans = {} +readiness = {} + +@musiclist = ["aiai.ogg", "u-mebius.mp3", "u-tarou.ogg", "u-tiga-b.ogg", + "music-video.mp3"] +@musicpos = 0 +@rediness = {} +@admin = nil +@stoptime = nil + +print("No clients yet...") +EM::WebSocket.start({:host => "0.0.0.0", :port => PORT}) do |ws_conn| + ws_conn.onopen do + # p "hello"+ws_conn.inspect + clients[ws_conn] = a = {} # Start from NO NAME + printf("%d guest(s)\n", clients.keys.length) + a["ping"] = Time.now.to_f + ws_conn.send("PING") + end + ws_conn.onmessage do |message| + jv = JSON.parse(message) + team, st = jv['team'], jv['state'] + if team > '' + clients[ws_conn]["name"] = team + if /PUSH: ([0-9.]+)/ =~ st + ans[team] = true + @stoptime = $1.to_f + STDERR.printf("Stopped at client %.3fs\n", @stoptime) + end + end + # clients.each{|conn| conn.send(resp) } + if team=="admin" + @admin = ws_conn + case st + when "prev" + @musicpos = [0, @musicpos-1].max + ans = {}; @rediness = {}; msg = @musiclist[@musicpos] + @stoptime = nil + when "next" + @musicpos = [@musiclist.length-1, @musicpos+1].min + ans = {}; @rediness = {}; msg = @musiclist[@musicpos] + @stoptime = nil + when "RESET" + ans = {}; msg="RESET" + @stoptime = nil + when "PLAY", /STOP: ([0-9.]+)/ + cmd = (/PLAY/=~st ? "PLAY" : "STOP") + @stoptime = $1 + maxdelay = clients.keys.collect{|x|clients[x]["delay"]}.max + clients.keys.each{|c| + d = maxdelay-clients[c]["delay"] + c.send("#{cmd}: #{d} #{@stoptime||0}") + } + msg="" + else + msg = ans.keys.select{|x|x!="admin"}.join(", ") + end + #if false && /prev|next/ =~ st + # STDERR.printf("Set pos @ %d -> %s\n", @musicpos, @musiclist[@musicpos]) + # @rediness = {} + # clients.keys.each{|conn| + # conn.send(msg) # if conn!=ws_conn; + # } + if msg>"" + clients.keys.each{|conn| conn.send(msg)} + end + end + resp = ans.keys.select{|x|x!="admin"}.join(", ") + case st + when /PONG/i + a = clients[ws_conn] + a["pong"] = Time.now.to_f + a["delay"] = a["pong"]-a["ping"] + p clients.values.collect{|v| v['delay']}.join(", ") + when /loading done/i + @rediness[ws_conn] = true + msg = "RESET" + STDERR.printf("%d/%d\n", @rediness.keys.length, clients.keys.length) + # clients.keys.each{|conn| conn.send("RESET")} + @admin.send(sprintf("LOAD: %d/%d\n", @rediness.keys.length, clients.keys.length)) + if @rediness.keys.length == clients.keys.length then + clients.keys.each {|conn| + if conn != @admin + STDERR.puts("Sending RESET to #{conn}") + conn.send("RESET") + end + } + end + end + if /PLAY|STOP|RESET|loading/ !~ st + clients.keys.each{|conn| conn.send(resp);} + # clients.each{|conn| conn.send(@musiclist[@musicpos])} + end + end + ws_conn.onclose do + clients.delete(ws_conn) + @rediness + # p "bye"+ws_conn.inspect + printf("%d GUEST(s)\n", clients.keys.length) + end + EM::defer do + puts "..captured!" + loop do + print("Hit Return to Reset client messages...") + line = gets + puts("Resetting") + clients.keys.each{|conn| conn.send("Ready..") } + ans = {}; + end + end +end