-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1506 from bartbutenaers/ui-audio-widget
New Widget: Audio
- Loading branch information
Showing
10 changed files
with
457 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
--- | ||
description: "Play dynamically audio files with ui-audio in Node-RED Dashboard 2.0." | ||
props: | ||
Group: Defines which group of the UI Dashboard this widget will render in. | ||
Size: Controls the width of the button with respect to the parent group. Maximum value is the width of the group. | ||
Source: | ||
description: The source is the url where the audio file can be fetched.. | ||
dynamic: true | ||
Autoplay: | ||
description: Specify whether the audio file will start playing automatically. | ||
dynamic: true | ||
Loop: | ||
description: Specify whether the audio should be looping, i.e. start playing automatically again when ended. | ||
dynamic: true | ||
Muted: | ||
description: Specify whether the audio should be muted. | ||
dynamic: true | ||
controls: | ||
enabled: | ||
example: true | false | ||
description: Allow control over whether or not the button is clickable. | ||
dynamic: | ||
Source: | ||
payload: msg.ui_update.source | ||
structure: ["String"] | ||
Autoplay: | ||
payload: msg.ui_update.autoplay | ||
structure: ["'on' | 'off'"] | ||
Loop: | ||
payload: msg.ui_update.loop | ||
structure: ["'on' | 'off'"] | ||
Muted: | ||
payload: msg.ui_update.muted | ||
structure: ["'on' | 'off'"] | ||
--- | ||
|
||
<script setup> | ||
import { ref } from 'vue' | ||
|
||
import ExampleButtonHold from '../../examples/ui-button-hold.json' | ||
|
||
import TryDemo from "./../../components/TryDemo.vue" | ||
import FlowViewer from '../../components/FlowViewer.vue' | ||
|
||
const examples = ref({ | ||
'hold': ExampleButtonHold | ||
}) | ||
</script> | ||
|
||
|
||
<TryDemo href="button-example"> | ||
|
||
# Audio `ui-audio` | ||
|
||
</TryDemo> | ||
|
||
Adds a clickable button to your dashboard. | ||
|
||
## Properties | ||
|
||
<PropsTable/> | ||
|
||
## Dynamic Properties | ||
|
||
<DynamicPropsTable/> | ||
|
||
## Controls | ||
|
||
<ControlsTable/> | ||
|
||
## Example | ||
|
||
### Simple Button | ||
|
||
![Example of a Button](/images/node-examples/ui-button.png "Example of a Button"){data-zoomable} | ||
*Example of a rendered button in a Dashboard.* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<script type="text/html" data-help-name="ui-audio"> | ||
<p> | ||
Plays an audio file in the dashboard. | ||
</p> | ||
<p> | ||
Each received <code>msg.payload</code> will contain a new source, i.e. a new audio file url. | ||
</p> | ||
<h3>Properties</h3> | ||
<dl class="message-properties"> | ||
<dt>Source <span class="property-type">string</span></dt> | ||
<dd>The source is the url where the audio file can be fetched.</dd> | ||
<dt>Autoplay <span class="property-type">list</span></dt> | ||
<dd>Specify whether the audio file will start playing automatically.</dd> | ||
<dt>Loop <span class="property-type">list</span></dt> | ||
<dd>Specify whether the audio should be looping, i.e. start playing automatically again when ended.</dd> | ||
<dt>Muted <span class="property-type">list</span></dt> | ||
<dd>Specify whether the audio should be muted.</dd> | ||
</dl> | ||
<h3>Dynamic Properties (Inputs)</h3> | ||
<p>Any of the following can be appended to a <code>msg.ui_update</code> in order to override or set properties on this node at runtime.</p> | ||
<dl class="message-properties"> | ||
<dt class="optional">src<span class="property-type">string</span></dt> | ||
<dd>Override the configured audio source.</dd> | ||
<dt class="optional">autoplay<span class="property-type">'on' | 'off'</span></dt> | ||
<dd>Override the configured autoplay setting .</dd> | ||
<dt class="optional">loop<span class="property-type">'on' | 'off'</span></dt> | ||
<dd>Override the configured looping behaviour.</dd> | ||
<dt class="optional">muted<span class="property-type">'on' | 'off'</span></dt> | ||
<dd>Override the configured muted setting.</dd> | ||
</dl> | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"ui-audio": { | ||
"label": { | ||
"group": "Group", | ||
"size": "Size", | ||
"icon": "Icon", | ||
"source": "Source", | ||
"autoplay": "Autoplay", | ||
"loop": "Loop", | ||
"muted": "Muted" | ||
}, | ||
"option": { | ||
"on": "On", | ||
"off": "Off" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
<script type="text/javascript"> | ||
(function () { | ||
RED.nodes.registerType('ui-audio', { | ||
category: RED._('@flowfuse/node-red-dashboard/ui-base:ui-base.label.category'), | ||
color: RED._('@flowfuse/node-red-dashboard/ui-base:ui-base.colors.medium'), | ||
defaults: { | ||
group: { type: 'ui-group', required: true }, | ||
name: { value: '' }, | ||
order: { value: 0 }, | ||
width: { | ||
value: 0, | ||
validate: function (v) { | ||
const width = v || 0 | ||
const currentGroup = $('#node-input-group').val() || this.group | ||
const groupNode = RED.nodes.node(currentGroup) | ||
const valid = !groupNode || +width >= 0 | ||
$('#node-input-size').toggleClass('input-error', !valid) | ||
return valid | ||
} | ||
}, | ||
height: { value: 0 }, | ||
src: { value: ''}, | ||
autoplay: { value: 'off' }, | ||
loop: { value: 'off' }, | ||
muted: { value: 'off' } | ||
}, | ||
inputs: 1, | ||
outputs: 1, | ||
align: 'right', | ||
icon: 'font-awesome/fa-volume-up', | ||
paletteLabel: 'audio', | ||
label: function () { return this.name }, | ||
labelStyle: function () { return this.name ? 'node_label_italic' : '' }, | ||
oneditprepare: function () { | ||
// if this groups parent is a subflow template, set the node-config-input-width and node-config-input-height up | ||
// as typedInputs and hide the elementSizer (as it doesn't make sense for subflow templates) | ||
if (RED.nodes.subflow(this.z)) { | ||
// change inputs from hidden to text & display them | ||
$('#node-input-width').attr('type', 'text') | ||
$('#node-input-height').attr('type', 'text') | ||
$('div.form-row.nr-db-ui-element-sizer-row').hide() | ||
$('div.form-row.nr-db-ui-manual-size-row').show() | ||
} else { | ||
// not in a subflow, use the elementSizer | ||
$('div.form-row.nr-db-ui-element-sizer-row').show() | ||
$('div.form-row.nr-db-ui-manual-size-row').hide() | ||
$('#node-input-size').elementSizer({ | ||
width: '#node-input-width', | ||
height: '#node-input-height', | ||
group: '#node-input-group' | ||
}) | ||
} | ||
|
||
// use jQuery UI tooltip to convert the plain old title attribute to a nice tooltip | ||
$('.ui-node-popover-title').tooltip({ | ||
show: { | ||
effect: 'slideDown', | ||
delay: 150 | ||
} | ||
}) | ||
} | ||
}) | ||
})() | ||
</script> | ||
|
||
<script type="text/html" data-template-name="ui-audio"> | ||
<div class="form-row"> | ||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></label> | ||
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name"> | ||
</div> | ||
<div class="form-row"> | ||
<label for="node-input-group"><i class="fa fa-table"></i> <span data-i18n="ui-audio.label.group"></label> | ||
<input type="text" id="node-input-group"> | ||
</div> | ||
<div class="form-row nr-db-ui-element-sizer-row"> | ||
<label><i class="fa fa-object-group"></i> <span data-i18n="ui-audio.label.size"></label> | ||
<button class="editor-button" id="node-input-size"></button> | ||
</div> | ||
<div class="form-row nr-db-ui-manual-size-row"> | ||
<label><i class="fa fa-arrows-h"></i> <span data-i18n="ui-audio.label.width">Width</label> | ||
<input type="hidden" id="node-input-width"> | ||
</div> | ||
<div class="form-row nr-db-ui-manual-size-row"> | ||
<label><i class="fa fa-arrows-v"></i> <span data-i18n="ui-audio.label.height">Height</label> | ||
<input type="hidden" id="node-input-height"> | ||
</div> | ||
<div class="form-row"> | ||
<label for="node-input-src"><i class="fa fa-globe"></i> <span data-i18n="ui-audio.label.source"></label> | ||
<input type="text" id="node-input-src"> | ||
</div> | ||
<div class="form-row"> | ||
<label for="node-input-autoplay"><i class="fa fa-play-circle"></i> <span data-i18n="ui-audio.label.autoplay"></label> | ||
<select id="node-input-autoplay" style="width:70%;"> | ||
<option value="on" data-i18n="ui-audio.option.on"></option> | ||
<option value="off" data-i18n="ui-audio.option.off"></option> | ||
</select> | ||
</div> | ||
<div class="form-row"> | ||
<label for="node-input-loop"><i class="fa fa-retweet"></i> <span data-i18n="ui-audio.label.loop"></label> | ||
<select id="node-input-loop" style="width:70%;"> | ||
<option value="on" data-i18n="ui-audio.option.on"></option> | ||
<option value="off" data-i18n="ui-audio.option.off"></option> | ||
</select> | ||
</div> | ||
<div class="form-row"> | ||
<label for="node-input-muted"><i class="fa fa-volume-up"></i> <span data-i18n="ui-audio.label.muted"></label> | ||
<select id="node-input-muted" style="width:70%;"> | ||
<option value="on" data-i18n="ui-audio.option.on"></option> | ||
<option value="off" data-i18n="ui-audio.option.off"></option> | ||
</select> | ||
</div> | ||
<div class="form-tips"><b>Note</b>: Autoplay will only work after a user gesture (e.g. click on the dashboard).</span></div> | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
const datastore = require('../store/data.js') | ||
const statestore = require('../store/state.js') | ||
|
||
module.exports = function (RED) { | ||
function AudioNode (config) { | ||
const node = this | ||
|
||
RED.nodes.createNode(this, config) | ||
|
||
// which group are we rendering this widget | ||
const group = RED.nodes.getNode(config.group) | ||
|
||
const evts = { | ||
onAction: true, | ||
onInput: function (msg, send) { | ||
// store the latest msg passed to node, only if a source is supplied in the payload | ||
if (typeof msg.payload === 'string') { | ||
datastore.save(group.getBase(), node, msg) | ||
} | ||
// only send msg on if we have passthru enabled | ||
if (config.passthru) { | ||
send(msg) | ||
} | ||
}, | ||
beforeSend: function (msg) { | ||
if (msg.playback === 'play') { | ||
const lastMsg = datastore.get(node.id) | ||
// TODO zou eigenlijk de last message met een payload moeten zijn. | ||
const src = lastMsg?.payload || config.src | ||
if (typeof src !== 'string' || src.trim() === '') { | ||
node.warn('Cannot play audio when no source has been specified') | ||
} | ||
} | ||
|
||
if (msg.ui_update) { | ||
const updates = msg.ui_update | ||
|
||
if (updates) { | ||
if (typeof updates.src !== 'undefined') { | ||
// dynamically set "src" property | ||
statestore.set(group.getBase(), node, msg, 'src', updates.src) | ||
} | ||
if (typeof updates.autoplay !== 'undefined') { | ||
if (['on', 'off'].includes(updates.autoplay)) { | ||
// dynamically set "autoplay" property | ||
statestore.set(group.getBase(), node, msg, 'autoplay', updates.autoplay) | ||
} else { | ||
node.error('Property msg.ui_update.autoplay should be "on" or "off"') | ||
} | ||
} | ||
if (typeof updates.loop !== 'undefined') { | ||
if (['on', 'off'].includes(updates.loop)) { | ||
// dynamically set "loop" property | ||
statestore.set(group.getBase(), node, msg, 'loop', updates.loop) | ||
} else { | ||
node.error('Property msg.ui_update.loop should be "on" or "off"') | ||
} | ||
} | ||
if (typeof updates.muted !== 'undefined') { | ||
if (['on', 'off'].includes(updates.muted)) { | ||
// dynamically set "muted" property | ||
statestore.set(group.getBase(), node, msg, 'muted', updates.muted) | ||
} else { | ||
node.error('Property msg.ui_update.muted should be "on" or "off"') | ||
} | ||
} | ||
} | ||
} | ||
return msg | ||
} | ||
} | ||
|
||
// inform the dashboard UI that we are adding this node | ||
if (group) { | ||
group.register(node, config, evts) | ||
} else { | ||
node.error('No group configured') | ||
} | ||
} | ||
RED.nodes.registerType('ui-audio', AudioNode) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.