diff --git a/libs/surfaces/websockets/globals.cc b/libs/surfaces/websockets/globals.cc index 3113fcfb3a..9db0bcfa98 100644 --- a/libs/surfaces/websockets/globals.cc +++ b/libs/surfaces/websockets/globals.cc @@ -49,7 +49,7 @@ ArdourGlobals::position_time () const bool ArdourGlobals::transport_roll () const { - return static_cast(basic_ui ().transport_rolling ()); + return basic_ui ().transport_rolling (); } void @@ -57,14 +57,14 @@ ArdourGlobals::set_transport_roll (bool value) { if ((value && !transport_roll ()) || (!value && transport_roll ())) { // this call is equivalent to hitting the spacebar - basic_ui ().toggle_roll (); + basic_ui ().toggle_roll (false); } } bool ArdourGlobals::record_state () const { - return static_cast(session ().get_record_enabled ()); + return session ().get_record_enabled (); } void diff --git a/share/web_surfaces/builtin/transport/img/expand.svg b/share/web_surfaces/builtin/transport/img/expand.svg new file mode 100644 index 0000000000..387024b95d --- /dev/null +++ b/share/web_surfaces/builtin/transport/img/expand.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + diff --git a/share/web_surfaces/builtin/transport/img/pause.svg b/share/web_surfaces/builtin/transport/img/pause.svg new file mode 100644 index 0000000000..6f65640439 --- /dev/null +++ b/share/web_surfaces/builtin/transport/img/pause.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/share/web_surfaces/builtin/transport/img/play.svg b/share/web_surfaces/builtin/transport/img/play.svg new file mode 100644 index 0000000000..76d1352dfb --- /dev/null +++ b/share/web_surfaces/builtin/transport/img/play.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/share/web_surfaces/builtin/transport/img/record-off.svg b/share/web_surfaces/builtin/transport/img/record-off.svg new file mode 100644 index 0000000000..7fb74068f3 --- /dev/null +++ b/share/web_surfaces/builtin/transport/img/record-off.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/share/web_surfaces/builtin/transport/img/record-on.svg b/share/web_surfaces/builtin/transport/img/record-on.svg new file mode 100644 index 0000000000..1cc4eeea31 --- /dev/null +++ b/share/web_surfaces/builtin/transport/img/record-on.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/share/web_surfaces/builtin/transport/index.html b/share/web_surfaces/builtin/transport/index.html index 9d1a40f24c..252ccba540 100644 --- a/share/web_surfaces/builtin/transport/index.html +++ b/share/web_surfaces/builtin/transport/index.html @@ -3,8 +3,20 @@ Ardour Transport + + -

Under Construction

+
+
+
+
+ + +
+
+
+ + diff --git a/share/web_surfaces/builtin/transport/main.css b/share/web_surfaces/builtin/transport/main.css new file mode 100644 index 0000000000..1cd9fddcf4 --- /dev/null +++ b/share/web_surfaces/builtin/transport/main.css @@ -0,0 +1,97 @@ +body { + margin: 0; + background: #000; + color: rgb(248,248,242); + font-family: Helvetica, Arial, sans-serif; +} + +button { + outline: none; + border: none; + background: none; + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +#main { + position: fixed; + height: 100%; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + background: rgb(62,61,61); +} + +#ui { + display: flex; + flex-direction: column; + width: 768px; + height: 384px; + max-width: 100%; + max-height: 100%; + background: rgba(0,0,0,0.1); + border-radius: 4px; + cursor: default; + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + -webkit-tap-highlight-color: rgba(0,0,0,0); +} + +#time { + display: flex; + flex: 1; + justify-content: center; + align-items: center; + font-family: monospace; + font-size: 64px; +} + +@media screen and (max-width: 320px) { + #time { + font-size: 32px; + } +} + +#buttons { + display: flex; + flex: 2; + justify-content: space-evenly; + align-items: center; +} + +#buttons > button { + height: 148px; + width: 148px; + max-height: 100%; + max-width: 100%; + border: solid 16px transparent; +} + +#fullscreen { + position: fixed; + top: 16px; + right: 12px; + width: 24px; + height: 24px; + opacity: 0.5; + background-image: url('img/expand.svg'); +} + +.pulse { + animation: pulse 1s infinite ease-out; +} + +@keyframes pulse { + 0% { + transform: scale(1); + } + 50% { + transform: scale(1.1); + } + 100% { + transform: scale(1); + } +} diff --git a/share/web_surfaces/builtin/transport/main.js b/share/web_surfaces/builtin/transport/main.js new file mode 100644 index 0000000000..fcfff6c561 --- /dev/null +++ b/share/web_surfaces/builtin/transport/main.js @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2020 Luciano Iam + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +import { ArdourClient } from '/shared/ardour.js'; + +(() => { + + const dom = { + main: document.getElementById('main'), + time: document.getElementById('time'), + roll: document.getElementById('roll'), + record: document.getElementById('record'), + fullscreen: document.getElementById('fullscreen') + }; + + const ardour = new ArdourClient(location.host); + + let _rolling = false; + let _record = false; + + function main () { + addDomEventListeners (); + + ardour.addCallbacks({ + onError: console.log, + onPositionTime: setPosition, + onTransportRoll: setRolling, + onRecordState: setRecord + }); + + ardour.connect(); + } + + function addDomEventListeners () { + // transport buttons + const touchOrClick = ('ontouchstart' in document.documentElement) ? 'touchstart' : 'click'; + + const roll = () => { + setRolling (!_rolling); + ardour.setTransportRoll (_rolling); + }; + + dom.roll.addEventListener(touchOrClick, roll); + + const record = () => { + setRecord (!_record); + ardour.setRecordState (_record); + }; + + dom.record.addEventListener(touchOrClick, record); + + // fullscreen button + let requestFullscreen = null, fullscreenChange = null; + + if ('requestFullscreen' in dom.main) { + requestFullscreen = dom.main.requestFullscreen.bind(dom.main); + fullscreenChange = 'fullscreenchange'; + } else if ('webkitRequestFullscreen' in dom.main) { + requestFullscreen = dom.main.webkitRequestFullscreen.bind(dom.main); + fullscreenChange = 'webkitfullscreenchange'; + } + + if (requestFullscreen && fullscreenChange) { + dom.fullscreen.addEventListener(touchOrClick, requestFullscreen); + + document.addEventListener(fullscreenChange, (e) => { + const fullscreen = document.fullScreen || document.webkitIsFullScreen; + dom.fullscreen.style.display = fullscreen ? 'none' : 'inline'; + }); + } else { + dom.fullscreen.style.display = 'none'; + } + + // keyboard actions + document.addEventListener('keydown', (e) => { + const key = e.key.toLowerCase(); + + if (key == ' ') { + roll(); + } else if (key == 'r') { + record(); + } else if (key == 'f') { + requestFullscreen(); + } + }); + } + + function setPosition (seconds) { + const h = Math.floor(seconds / 3600), + m = Math.floor((seconds - 3600 * h) / 60), + s = Math.floor(seconds - 3600 * h - 60 * m), + ms = Math.round(1000 * (seconds % 1)), + time = (h < 10 ? '0' + h : h) + + ':' + (m < 10 ? '0' + m : m) + + ':' + (s < 10 ? '0' + s : s) + + '.' + (ms < 100 ? (ms < 10 ? '00' + ms : '0' + ms) : ms); + dom.time.innerHTML = time; + } + + function setRolling (rolling) { + _rolling = rolling + const image = _rolling ? 'img/pause.svg' : 'img/play.svg'; + dom.roll.style.backgroundImage = `url(${image})`; + } + + function setRecord (record) { + _record = record; + + if (_record) { + dom.record.style.backgroundImage = 'url(img/record-on.svg)'; + dom.record.classList.add('pulse'); + } else { + dom.record.style.backgroundImage = 'url(img/record-off.svg)'; + dom.record.classList.remove('pulse'); + } + } + + main(); + +})(); diff --git a/share/web_surfaces/builtin/transport/manifest.xml b/share/web_surfaces/builtin/transport/manifest.xml index aef70440cc..1d8c664f10 100644 --- a/share/web_surfaces/builtin/transport/manifest.xml +++ b/share/web_surfaces/builtin/transport/manifest.xml @@ -1,6 +1,6 @@ - + diff --git a/share/web_surfaces/index.html b/share/web_surfaces/index.html index 692481d682..e2ee4d3134 100644 --- a/share/web_surfaces/index.html +++ b/share/web_surfaces/index.html @@ -3,6 +3,7 @@ Ardour Web Surfaces + diff --git a/share/web_surfaces/index/main.css b/share/web_surfaces/index/main.css index 5129f8ddd5..3dff44ab57 100644 --- a/share/web_surfaces/index/main.css +++ b/share/web_surfaces/index/main.css @@ -76,6 +76,12 @@ h2 { list-style-type: none; } +@media screen and (max-width: 320px) { + .surface-list > ul { + padding: 0; + } +} + .surface-list > ul > li { margin: 4ex 0; } @@ -89,4 +95,5 @@ h2 { font-family: Monaco, monospace; font-size: 0.9em; color: #444; + word-wrap: break-word; }