Skip to content

Commit 49cd2d5

Browse files
committed
1 parent ddf8871 commit 49cd2d5

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

packages/project-editor/flow/components/actions/index.tsx

+105
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path from "path";
12
import React from "react";
23
import {
34
observable,
@@ -126,6 +127,7 @@ import {
126127
LANGUAGE_ICON,
127128
LOG_ICON,
128129
PALETTE_ICON,
130+
PLAY_AUDIO_ICON,
129131
PRINT_TO_PDF_ICON
130132
} from "project-editor/ui-components/icons";
131133
import { humanize } from "eez-studio-shared/string";
@@ -2077,6 +2079,107 @@ export class LogActionComponent extends ActionComponent {
20772079

20782080
////////////////////////////////////////////////////////////////////////////////
20792081

2082+
export class PlayAudioActionComponent extends ActionComponent {
2083+
static classInfo = makeDerivedClassInfo(ActionComponent.classInfo, {
2084+
enabledInComponentPalette: (projectType: ProjectType) =>
2085+
projectType === ProjectType.DASHBOARD,
2086+
2087+
properties: [
2088+
makeExpressionProperty(
2089+
{
2090+
name: "audioFile",
2091+
type: PropertyType.MultilineText,
2092+
propertyGridGroup: specificGroup
2093+
},
2094+
"string"
2095+
)
2096+
],
2097+
defaultValue: {},
2098+
icon: PLAY_AUDIO_ICON,
2099+
componentHeaderColor: "#C9E9D2",
2100+
execute: (context: IDashboardComponentContext) => {
2101+
const audioFile = context.evalProperty<string>("audioFile");
2102+
if (audioFile == undefined) {
2103+
context.throwError(`Invalid Audio file property`);
2104+
return;
2105+
}
2106+
2107+
// Create an AudioContext
2108+
const audioContext = new window.AudioContext();
2109+
2110+
// Function to play audio
2111+
function playAudio(url: string) {
2112+
fetch(url)
2113+
.then(response => response.arrayBuffer())
2114+
.then(arrayBuffer =>
2115+
audioContext.decodeAudioData(arrayBuffer)
2116+
)
2117+
.then(audioBuffer => {
2118+
const source = audioContext.createBufferSource();
2119+
source.buffer = audioBuffer;
2120+
source.connect(audioContext.destination);
2121+
source.start(0);
2122+
})
2123+
.catch(error =>
2124+
console.error("Error loading audio:", error)
2125+
);
2126+
}
2127+
2128+
playAudio(audioFile);
2129+
2130+
context.propagateValueThroughSeqout();
2131+
}
2132+
});
2133+
2134+
audioFile: string;
2135+
2136+
override makeEditable() {
2137+
super.makeEditable();
2138+
2139+
makeObservable(this, {
2140+
audioFile: observable
2141+
});
2142+
}
2143+
2144+
getInputs() {
2145+
return [
2146+
{
2147+
name: "@seqin",
2148+
type: "any" as ValueType,
2149+
isSequenceInput: true,
2150+
isOptionalInput: true
2151+
},
2152+
...super.getInputs()
2153+
];
2154+
}
2155+
2156+
getOutputs() {
2157+
return [
2158+
{
2159+
name: "@seqout",
2160+
type: "null" as ValueType,
2161+
isSequenceOutput: true,
2162+
isOptionalOutput: true
2163+
},
2164+
...super.getOutputs()
2165+
];
2166+
}
2167+
2168+
getBody(flowContext: IFlowContext): React.ReactNode {
2169+
if (!this.audioFile) {
2170+
return null;
2171+
}
2172+
2173+
return (
2174+
<div className="body">
2175+
<pre>{path.basename(this.audioFile)}</pre>
2176+
</div>
2177+
);
2178+
}
2179+
}
2180+
2181+
////////////////////////////////////////////////////////////////////////////////
2182+
20802183
export class CallActionActionComponent extends ActionComponent {
20812184
static classInfo = makeDerivedClassInfo(ActionComponent.classInfo, {
20822185
flowComponentId: COMPONENT_TYPE_CALL_ACTION_ACTION,
@@ -4969,6 +5072,8 @@ registerClass("SortArrayActionComponent", SortArrayActionComponent);
49695072

49705073
registerClass("LogActionComponent", LogActionComponent);
49715074

5075+
registerClass("PlayAudioActionComponent", PlayAudioActionComponent);
5076+
49725077
registerClass("ReadSettingActionComponent", ReadSettingActionComponent);
49735078
registerClass("WriteSettingsActionComponent", WriteSettingsActionComponent);
49745079

packages/project-editor/ui-components/icons.tsx

+9
Original file line numberDiff line numberDiff line change
@@ -3558,3 +3558,12 @@ export const FOCUS_WIDGET_ICON: any = (
35583558
/>
35593559
</svg>
35603560
);
3561+
3562+
export const PLAY_AUDIO_ICON = (
3563+
<svg fill="currentcolor" viewBox="-100 -100 2120 2120">
3564+
<path
3565+
d="M1129.432 113v1694.148H903.545l-451.772-451.773V564.773L903.545 113h225.887Zm542.545 248.057C1832.017 521.097 1920 733.882 1920 960.107c0 226.226-87.983 438.898-248.023 598.938l-79.851-79.85c138.694-138.582 214.93-323.018 214.93-519.087 0-196.183-76.236-380.506-214.93-519.2ZM338.83 564.773v790.602H169.415C75.672 1355.375 0 1279.703 0 1185.96V734.187c0-93.742 75.672-169.414 169.415-169.414H338.83Zm1093.922 36.085c95.776 97.018 148.407 224.644 148.407 359.16 0 134.628-52.631 262.253-148.407 359.272l-80.303-79.174c74.656-75.897 115.767-175.4 115.767-280.099 0-104.585-41.111-204.088-115.767-279.986Z"
3566+
fillRule="evenodd"
3567+
/>
3568+
</svg>
3569+
);

0 commit comments

Comments
 (0)