Commit e4bab3c8 authored by Jens-Christian Fischer's avatar Jens-Christian Fischer
Browse files

Added control of BPM via Conductor Page

parent d7d5c08a
defmodule Grains.Beat do
use GenServer
require Logger
@minute 60_000
......@@ -9,6 +10,7 @@ defmodule Grains.Beat do
def set_bpm(bpm), do: GenServer.cast(__MODULE__, {:set_bpm, bpm})
def get_bpm(), do: GenServer.call(__MODULE__, :get_bpm)
def init(bpm) do
millisec = round(@minute / bpm)
......@@ -22,6 +24,11 @@ defmodule Grains.Beat do
{:noreply, round(@minute / bpm) }
end
def handle_call(:get_bpm, _from, state) do
{:reply, round(@minute / state), state}
end
def handle_info(:tick, state) do
Grengine.Conductor.perform()
|> send_values
......@@ -32,6 +39,7 @@ defmodule Grains.Beat do
end
def send_values(values) do
Logger.info "sending performance values"
Grains.Endpoint.broadcast("osc", "performance", values)
end
......
defmodule Grains.ConductorChannel do
use Grains.Web, :channel
alias Grains.ValueView
def join("conductor:" <> slider_id, _params, socket) do
bpm = Grains.Beat.get_bpm()
# resp = %{values: Phoenix.View.render_many({}, ValueView, "value.json") }
{:ok, %{bpm: bpm}, socket}
end
def handle_in("master", params, socket) do
IO.puts socket.assigns.user_uuid
IO.puts "slider: #{params["slider"]} : #{params["value"]}"
slider = params["slider"]
value = round(params["value"])
uuid = socket.assigns.user_uuid
Grains.Beat.set_bpm(value)
push socket, "set_bpm", %{bpm: value}
{:reply, :ok, socket}
end
end
......@@ -7,6 +7,7 @@ defmodule Grains.UserSocket do
channel "slider:*", Grains.SliderChannel
channel "orientation:*", Grains.OrientationChannel
channel "conductor:*", Grains.ConductorChannel
channel "presence:*", Grains.PresenceChannel
channel "osc", Grains.OscChannel
......
defmodule Grains.ConductorController do
use Grains.Web, :controller
def index(conn, _params) do
bpm = Grains.Beat.get_bpm
render conn, "index.html", bpm: bpm
end
end
......@@ -19,6 +19,7 @@ defmodule Grains.Router do
get "/grains/:grain", GrainsController, :show
get "/", PageController, :index
get "/conductor", ConductorController, :index
end
# Other scopes may use custom stacks.
......
......@@ -4,3 +4,8 @@
display: block;
height: 300px;
}
.bpmPanel {
display: block;
height: 40px;
}
......@@ -19,11 +19,11 @@ import _ from "underscore"
import socket from "./socket"
import SliderPanel from "./slider";
import OrientationPanel from "./orientation";
import BpmPanel from "./bpm.js";
SliderPanel.init(socket, "sliderPanel", ["s1", "s2", "s3"]);
OrientationPanel.init(socket, "orientationPanel");
BpmPanel.init(socket, "bpmPanel");
// Presence
......@@ -43,7 +43,10 @@ let listBy = (user, {metas: metas}) => {
let userList = document.getElementById("UserList")
let userCounter = document.getElementById("UserCount")
let render = (presences) => {
if (userList) {
userList.innerHTML = Presence.list(presences, listBy)
.map(presence => `
<li>
......@@ -51,7 +54,12 @@ let render = (presences) => {
<br><small>online since ${presence.onlineAt}</small>
</li>
`)
.join("");
.join("");
}
if (userCounter) {
userCounter.innerHTML = Presence.list(presences).length;
}
}
let room = socket.channel("presence:lobby", {})
......
import Interface from "interface.js";
let BpmPanel = {
sliderChannel : null,
bpmLabel: null,
bpmSlider: null,
init(socket, domId) {
if (!document.getElementById(domId)) {
console.log("No element found: " + domId);
return;
}
let that = this;
socket.connect();
this.sliderChannel = socket.channel("conductor:" + domId);
this.sliderChannel.join()
.receive("ok", response => {
that.bpmLabel.setValue(response.bpm);
that.bpmSlider.setValue(response.bpm);
})
.receive("error", reason => console.log("join failed", reason));
this.sliderChannel.on("set_bpm", response =>{
that.bpmLabel.setValue(response.bpm);
console.log("set bpm", response.bpm);
});
let a = new Interface.Panel({
container:document.getElementById(domId)
});
this.bpmLabel = new Interface.Label({
bounds: [.8, .1, .2, .9],
hAlign: 'center',
value: '0',
size: 28,
style: 'bold'
});
this.bpmSlider = new Interface.Slider({
bounds: [.05, .05, .7, 0.9],
label: 'BPM',
min: 30,
max: 180,
isVertical: false,
onvaluechange: function() {
that.send_value(this.value);
}
});
a.add(this.bpmSlider, this.bpmLabel);
a.background = 'black';
console.log("initialized bpm");
},
send_value(value) {
let payload = {slider: 'bpm', value: value};
this.sliderChannel.push("master", payload)
.receive("error", e => console.log(e));
},
};
export default BpmPanel;
<h1>Grains Conductor</h1>
<div id="bpmPanel" class="bpmPanel"></div>
<div class="row">
<div class="col-md-8">
<ul id="UserList" class="list-unstyled">
<li>Loading online users</li>
</ul>
</div>
</div>
......@@ -15,6 +15,7 @@
<div class="container">
<header class="header">
<img src="/images/switch.png" alt="SWITCH" height="46" width="180" />
<p>Online players: <span id="UserCount"></span></p>
</header>
<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
......@@ -24,13 +25,6 @@
<%= render @view_module, @view_template, assigns %>
</main>
<div class="row">
<div class="col-md-8">
<ul id="UserList" class="list-unstyled">
<li>Loading online users</li>
</ul>
</div>
</div>
</div> <!-- /container -->
<script>window.userToken = "<%= assigns[:user_token] %>"</script>
<script src="<%= static_path(@conn, "/js/app.js") %>"></script>
......
defmodule Grains.ConductorView do
use Grains.Web, :view
end
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment