@cycle-robot-drivers/sound
Advanced tools
Comparing version 1.0.2 to 1.0.3
@@ -1,2 +0,2 @@ | ||
import { ActionSources, ActionSinks, EventSource } from '@cycle-robot-drivers/action'; | ||
import { ActionSources, ActionSinks, EventSource } from "@cycle-robot-drivers/action"; | ||
export interface Sources extends ActionSources { | ||
@@ -3,0 +3,0 @@ AudioPlayer: EventSource; |
@@ -34,16 +34,19 @@ "use strict"; | ||
function input(goal$, cancel$, audioPlayerEndedEvent$, audioPlayerPausedEvent$) { | ||
return xstream_1.default.merge(goal$.filter(function (g) { return typeof g !== 'undefined' && g !== null; }) | ||
return xstream_1.default.merge(goal$ | ||
.filter(function (g) { return typeof g !== "undefined" && g !== null; }) | ||
.map(function (g) { return action_1.initGoal(g); }) | ||
.map(function (goal) { return ({ | ||
type: InputType.GOAL, | ||
value: typeof goal.goal === 'string' ? { | ||
goal_id: goal.goal_id, | ||
goal: { src: goal.goal }, | ||
} : goal, | ||
value: typeof goal.goal === "string" | ||
? { | ||
goal_id: goal.goal_id, | ||
goal: { src: goal.goal } | ||
} | ||
: goal | ||
}); }), cancel$.map(function (val) { return ({ type: InputType.CANCEL, value: val }); }), audioPlayerEndedEvent$.mapTo({ | ||
type: InputType.ENDED, | ||
value: null, | ||
value: null | ||
}), audioPlayerPausedEvent$.mapTo({ | ||
type: InputType.PAUSE, | ||
value: null, | ||
value: null | ||
})); | ||
@@ -57,5 +60,5 @@ } | ||
goal_id: goal.goal_id, | ||
newGoal: null, | ||
newGoal: null | ||
}, outputs: { | ||
AudioPlayer: goal.goal, | ||
AudioPlayer: goal.goal | ||
} }); | ||
@@ -65,7 +68,8 @@ } | ||
else if (prev.state === State.RUN) { | ||
if (input.type === InputType.GOAL || input.type === InputType.CANCEL | ||
&& (input.value === null || | ||
action_1.isEqualGoalID(input.value, prev.variables.goal_id))) { | ||
if (input.type === InputType.GOAL || | ||
(input.type === InputType.CANCEL && | ||
(input.value === null || | ||
action_1.isEqualGoalID(input.value, prev.variables.goal_id)))) { | ||
return __assign({}, prev, { state: State.PREEMPT, variables: __assign({}, prev.variables, { newGoal: input.type === InputType.GOAL ? input.value : null }), outputs: { | ||
AudioPlayer: null, | ||
AudioPlayer: null | ||
} }); | ||
@@ -76,3 +80,3 @@ } | ||
goal_id: null, | ||
newGoal: null, | ||
newGoal: null | ||
}, outputs: { | ||
@@ -82,6 +86,6 @@ result: { | ||
goal_id: prev.variables.goal_id, | ||
status: action_1.Status.SUCCEEDED, | ||
status: action_1.Status.SUCCEEDED | ||
}, | ||
result: input.value, | ||
}, | ||
result: input.value | ||
} | ||
} }); | ||
@@ -95,3 +99,3 @@ } | ||
goal_id: !!newGoal ? newGoal.goal_id : null, | ||
newGoal: null, | ||
newGoal: null | ||
}, outputs: { | ||
@@ -102,6 +106,6 @@ AudioPlayer: !!newGoal ? newGoal.goal : undefined, | ||
goal_id: prev.variables.goal_id, | ||
status: action_1.Status.PREEMPTED, | ||
status: action_1.Status.PREEMPTED | ||
}, | ||
result: input.value, | ||
}, | ||
result: input.value | ||
} | ||
} }); | ||
@@ -118,11 +122,12 @@ } | ||
goal_id: null, | ||
newGoal: null, | ||
newGoal: null | ||
}, | ||
outputs: null, | ||
outputs: null | ||
}; | ||
}); | ||
var inputReducer$ = input$ | ||
.map(function (input) { return function inputReducer(prev) { | ||
return transition(prev, input); | ||
}; }); | ||
var inputReducer$ = input$.map(function (input) { | ||
return function inputReducer(prev) { | ||
return transition(prev, input); | ||
}; | ||
}); | ||
return xstream_1.default.merge(initReducer$, inputReducer$); | ||
@@ -138,3 +143,4 @@ } | ||
var initGoalStatus = action_1.generateGoalStatus({ status: action_1.Status.SUCCEEDED }); | ||
return xstream_1.default.merge(done$, active$) | ||
return xstream_1.default | ||
.merge(done$, active$) | ||
.compose(dropRepeats_1.default(action_1.isEqualGoalStatus)) | ||
@@ -148,11 +154,8 @@ .startWith(initGoalStatus); | ||
return { | ||
result: outputs$ | ||
.filter(function (o) { return !!o.result; }) | ||
.map(function (o) { return o.result; }), | ||
result: outputs$.filter(function (o) { return !!o.result; }).map(function (o) { return o.result; }), | ||
AudioPlayer: outputs$ | ||
.filter(function (o) { return typeof o.AudioPlayer !== 'undefined'; }) | ||
.map(function (o) { return o.AudioPlayer; }), | ||
.filter(function (o) { return typeof o.AudioPlayer !== "undefined"; }) | ||
.map(function (o) { return o.AudioPlayer; }) | ||
}; | ||
} | ||
; | ||
/** | ||
@@ -177,5 +180,4 @@ * AudioPlayerAction action component. | ||
function AudioPlayerAction(sources) { | ||
var input$ = input(sources.goal || xstream_1.default.never(), sources.cancel || xstream_1.default.never(), sources.AudioPlayer.events('ended'), sources.AudioPlayer.events('pause')); | ||
var input$ = input(sources.goal || xstream_1.default.never(), sources.cancel || xstream_1.default.never(), sources.AudioPlayer.events("ended"), sources.AudioPlayer.events("pause")); | ||
var reducer = transitionReducer(input$); | ||
; | ||
var status$ = status(sources.state.stream); | ||
@@ -182,0 +184,0 @@ var outputs = output(sources.state.stream); |
@@ -1,2 +0,2 @@ | ||
export { makeAudioPlayerDriver } from './makeAudioPlayerDriver'; | ||
export { Sources as AudioPlayerActionSources, Sinks as AudioPlayerActionSinks, AudioPlayerAction, } from './AudioPlayerAction'; | ||
export { makeAudioPlayerDriver } from "./makeAudioPlayerDriver"; | ||
export { Sources as AudioPlayerActionSources, Sinks as AudioPlayerActionSinks, AudioPlayerAction } from "./AudioPlayerAction"; |
@@ -1,2 +0,2 @@ | ||
import { EventSource } from '@cycle-robot-drivers/action'; | ||
import { EventSource } from "@cycle-robot-drivers/action"; | ||
export declare function makeAudioPlayerDriver(): (sink$: any) => EventSource; |
@@ -40,3 +40,3 @@ "use strict"; | ||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement | ||
['src', 'volume', 'loop'].map(function (arg) { | ||
["src", "volume", "loop"].map(function (arg) { | ||
if (arg in args) { | ||
@@ -46,3 +46,7 @@ audio[arg] = args[arg]; | ||
}); | ||
audio.play(); | ||
// https://developers.google.com/web/updates/2017/09/autoplay-policy-changes | ||
audio.play().catch(function (err) { | ||
console.warn("audio.play() error", err); | ||
audio.dispatchEvent(new Event("ended")); | ||
}); | ||
} | ||
@@ -49,0 +53,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { ActionSources, ActionSinks, EventSource } from '@cycle-robot-drivers/action'; | ||
import { ActionSources, ActionSinks, EventSource } from "@cycle-robot-drivers/action"; | ||
export interface Sources extends ActionSources { | ||
@@ -3,0 +3,0 @@ AudioPlayer: EventSource; |
@@ -12,5 +12,5 @@ var __assign = (this && this.__assign) || function () { | ||
}; | ||
import xs from 'xstream'; | ||
import dropRepeats from 'xstream/extra/dropRepeats'; | ||
import { Status, initGoal, generateGoalStatus, isEqualGoalStatus, isEqualGoalID, } from '@cycle-robot-drivers/action'; | ||
import xs from "xstream"; | ||
import dropRepeats from "xstream/extra/dropRepeats"; | ||
import { Status, initGoal, generateGoalStatus, isEqualGoalStatus, isEqualGoalID } from "@cycle-robot-drivers/action"; | ||
var State; | ||
@@ -30,16 +30,19 @@ (function (State) { | ||
function input(goal$, cancel$, audioPlayerEndedEvent$, audioPlayerPausedEvent$) { | ||
return xs.merge(goal$.filter(function (g) { return typeof g !== 'undefined' && g !== null; }) | ||
return xs.merge(goal$ | ||
.filter(function (g) { return typeof g !== "undefined" && g !== null; }) | ||
.map(function (g) { return initGoal(g); }) | ||
.map(function (goal) { return ({ | ||
type: InputType.GOAL, | ||
value: typeof goal.goal === 'string' ? { | ||
goal_id: goal.goal_id, | ||
goal: { src: goal.goal }, | ||
} : goal, | ||
value: typeof goal.goal === "string" | ||
? { | ||
goal_id: goal.goal_id, | ||
goal: { src: goal.goal } | ||
} | ||
: goal | ||
}); }), cancel$.map(function (val) { return ({ type: InputType.CANCEL, value: val }); }), audioPlayerEndedEvent$.mapTo({ | ||
type: InputType.ENDED, | ||
value: null, | ||
value: null | ||
}), audioPlayerPausedEvent$.mapTo({ | ||
type: InputType.PAUSE, | ||
value: null, | ||
value: null | ||
})); | ||
@@ -53,5 +56,5 @@ } | ||
goal_id: goal.goal_id, | ||
newGoal: null, | ||
newGoal: null | ||
}, outputs: { | ||
AudioPlayer: goal.goal, | ||
AudioPlayer: goal.goal | ||
} }); | ||
@@ -61,7 +64,8 @@ } | ||
else if (prev.state === State.RUN) { | ||
if (input.type === InputType.GOAL || input.type === InputType.CANCEL | ||
&& (input.value === null || | ||
isEqualGoalID(input.value, prev.variables.goal_id))) { | ||
if (input.type === InputType.GOAL || | ||
(input.type === InputType.CANCEL && | ||
(input.value === null || | ||
isEqualGoalID(input.value, prev.variables.goal_id)))) { | ||
return __assign({}, prev, { state: State.PREEMPT, variables: __assign({}, prev.variables, { newGoal: input.type === InputType.GOAL ? input.value : null }), outputs: { | ||
AudioPlayer: null, | ||
AudioPlayer: null | ||
} }); | ||
@@ -72,3 +76,3 @@ } | ||
goal_id: null, | ||
newGoal: null, | ||
newGoal: null | ||
}, outputs: { | ||
@@ -78,6 +82,6 @@ result: { | ||
goal_id: prev.variables.goal_id, | ||
status: Status.SUCCEEDED, | ||
status: Status.SUCCEEDED | ||
}, | ||
result: input.value, | ||
}, | ||
result: input.value | ||
} | ||
} }); | ||
@@ -91,3 +95,3 @@ } | ||
goal_id: !!newGoal ? newGoal.goal_id : null, | ||
newGoal: null, | ||
newGoal: null | ||
}, outputs: { | ||
@@ -98,6 +102,6 @@ AudioPlayer: !!newGoal ? newGoal.goal : undefined, | ||
goal_id: prev.variables.goal_id, | ||
status: Status.PREEMPTED, | ||
status: Status.PREEMPTED | ||
}, | ||
result: input.value, | ||
}, | ||
result: input.value | ||
} | ||
} }); | ||
@@ -114,11 +118,12 @@ } | ||
goal_id: null, | ||
newGoal: null, | ||
newGoal: null | ||
}, | ||
outputs: null, | ||
outputs: null | ||
}; | ||
}); | ||
var inputReducer$ = input$ | ||
.map(function (input) { return function inputReducer(prev) { | ||
return transition(prev, input); | ||
}; }); | ||
var inputReducer$ = input$.map(function (input) { | ||
return function inputReducer(prev) { | ||
return transition(prev, input); | ||
}; | ||
}); | ||
return xs.merge(initReducer$, inputReducer$); | ||
@@ -134,3 +139,4 @@ } | ||
var initGoalStatus = generateGoalStatus({ status: Status.SUCCEEDED }); | ||
return xs.merge(done$, active$) | ||
return xs | ||
.merge(done$, active$) | ||
.compose(dropRepeats(isEqualGoalStatus)) | ||
@@ -144,11 +150,8 @@ .startWith(initGoalStatus); | ||
return { | ||
result: outputs$ | ||
.filter(function (o) { return !!o.result; }) | ||
.map(function (o) { return o.result; }), | ||
result: outputs$.filter(function (o) { return !!o.result; }).map(function (o) { return o.result; }), | ||
AudioPlayer: outputs$ | ||
.filter(function (o) { return typeof o.AudioPlayer !== 'undefined'; }) | ||
.map(function (o) { return o.AudioPlayer; }), | ||
.filter(function (o) { return typeof o.AudioPlayer !== "undefined"; }) | ||
.map(function (o) { return o.AudioPlayer; }) | ||
}; | ||
} | ||
; | ||
/** | ||
@@ -173,5 +176,4 @@ * AudioPlayerAction action component. | ||
export function AudioPlayerAction(sources) { | ||
var input$ = input(sources.goal || xs.never(), sources.cancel || xs.never(), sources.AudioPlayer.events('ended'), sources.AudioPlayer.events('pause')); | ||
var input$ = input(sources.goal || xs.never(), sources.cancel || xs.never(), sources.AudioPlayer.events("ended"), sources.AudioPlayer.events("pause")); | ||
var reducer = transitionReducer(input$); | ||
; | ||
var status$ = status(sources.state.stream); | ||
@@ -178,0 +180,0 @@ var outputs = output(sources.state.stream); |
@@ -1,2 +0,2 @@ | ||
export { makeAudioPlayerDriver } from './makeAudioPlayerDriver'; | ||
export { Sources as AudioPlayerActionSources, Sinks as AudioPlayerActionSinks, AudioPlayerAction, } from './AudioPlayerAction'; | ||
export { makeAudioPlayerDriver } from "./makeAudioPlayerDriver"; | ||
export { Sources as AudioPlayerActionSources, Sinks as AudioPlayerActionSinks, AudioPlayerAction } from "./AudioPlayerAction"; |
@@ -1,3 +0,3 @@ | ||
export { makeAudioPlayerDriver } from './makeAudioPlayerDriver'; | ||
export { AudioPlayerAction, } from './AudioPlayerAction'; | ||
export { makeAudioPlayerDriver } from "./makeAudioPlayerDriver"; | ||
export { AudioPlayerAction } from "./AudioPlayerAction"; | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,2 @@ | ||
import { EventSource } from '@cycle-robot-drivers/action'; | ||
import { EventSource } from "@cycle-robot-drivers/action"; | ||
export declare function makeAudioPlayerDriver(): (sink$: any) => EventSource; |
@@ -1,4 +0,4 @@ | ||
import xs from 'xstream'; | ||
import fromEvent from 'xstream/extra/fromEvent'; | ||
import { adapt } from '@cycle/run/lib/adapt'; | ||
import xs from "xstream"; | ||
import fromEvent from "xstream/extra/fromEvent"; | ||
import { adapt } from "@cycle/run/lib/adapt"; | ||
/** | ||
@@ -35,3 +35,3 @@ * [HTML Audio](https://www.w3schools.com/tags/ref_av_dom.asp) | ||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement | ||
['src', 'volume', 'loop'].map(function (arg) { | ||
["src", "volume", "loop"].map(function (arg) { | ||
if (arg in args) { | ||
@@ -41,3 +41,7 @@ audio[arg] = args[arg]; | ||
}); | ||
audio.play(); | ||
// https://developers.google.com/web/updates/2017/09/autoplay-policy-changes | ||
audio.play().catch(function (err) { | ||
console.warn("audio.play() error", err); | ||
audio.dispatchEvent(new Event("ended")); | ||
}); | ||
} | ||
@@ -44,0 +48,0 @@ } |
{ | ||
"name": "@cycle-robot-drivers/sound", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"description": "A Cycle.js driver for playing sounds using HTMLAudioElement", | ||
@@ -5,0 +5,0 @@ "author": "Michael Jae-Yoon Chung", |
@@ -1,30 +0,38 @@ | ||
import xs, {Stream} from 'xstream'; | ||
import dropRepeats from 'xstream/extra/dropRepeats'; | ||
import xs, { Stream } from "xstream"; | ||
import dropRepeats from "xstream/extra/dropRepeats"; | ||
import { | ||
GoalID, Goal, GoalStatus, Status, Result, | ||
ActionSources, ActionSinks, | ||
GoalID, | ||
Goal, | ||
GoalStatus, | ||
Status, | ||
Result, | ||
ActionSources, | ||
ActionSinks, | ||
EventSource, | ||
initGoal, generateGoalStatus, isEqualGoalStatus, isEqualGoalID, | ||
} from '@cycle-robot-drivers/action'; | ||
initGoal, | ||
generateGoalStatus, | ||
isEqualGoalStatus, | ||
isEqualGoalID | ||
} from "@cycle-robot-drivers/action"; | ||
enum State { | ||
WAIT = 'WAIT', | ||
RUN = 'RUN', | ||
PREEMPT = 'PREEMPT', | ||
WAIT = "WAIT", | ||
RUN = "RUN", | ||
PREEMPT = "PREEMPT" | ||
} | ||
type Variables = { | ||
goal_id: GoalID, | ||
newGoal: Goal, | ||
goal_id: GoalID; | ||
newGoal: Goal; | ||
}; | ||
type Outputs = { | ||
AudioPlayer?: any, | ||
result?: Result, | ||
AudioPlayer?: any; | ||
result?: Result; | ||
}; | ||
type ReducerState = { | ||
state: State, | ||
variables: Variables, | ||
outputs: Outputs, | ||
state: State; | ||
variables: Variables; | ||
outputs: Outputs; | ||
}; | ||
@@ -35,14 +43,13 @@ | ||
enum InputType { | ||
GOAL = 'GOAL', | ||
CANCEL = 'CANCEL', | ||
ENDED = 'ENDED', | ||
PAUSE = 'PAUSE', | ||
GOAL = "GOAL", | ||
CANCEL = "CANCEL", | ||
ENDED = "ENDED", | ||
PAUSE = "PAUSE" | ||
} | ||
type Input = { | ||
type: InputType, | ||
value: Goal | GoalID | string, | ||
type: InputType; | ||
value: Goal | GoalID | string; | ||
}; | ||
function input( | ||
@@ -52,23 +59,27 @@ goal$: Stream<Goal | string>, | ||
audioPlayerEndedEvent$: Stream<GoalID>, | ||
audioPlayerPausedEvent$: Stream<GoalID>, | ||
audioPlayerPausedEvent$: Stream<GoalID> | ||
): Stream<Input> { | ||
return xs.merge( | ||
goal$.filter(g => typeof g !== 'undefined' && g !== null) | ||
goal$ | ||
.filter(g => typeof g !== "undefined" && g !== null) | ||
.map(g => initGoal(g)) | ||
.map(goal => ({ | ||
type: InputType.GOAL, | ||
value: typeof goal.goal === 'string' ? { | ||
goal_id: goal.goal_id, | ||
goal: {src: goal.goal}, | ||
} : goal, | ||
value: | ||
typeof goal.goal === "string" | ||
? { | ||
goal_id: goal.goal_id, | ||
goal: { src: goal.goal } | ||
} | ||
: goal | ||
})), | ||
cancel$.map(val => ({type: InputType.CANCEL, value: val})), | ||
cancel$.map(val => ({ type: InputType.CANCEL, value: val })), | ||
audioPlayerEndedEvent$.mapTo({ | ||
type: InputType.ENDED, | ||
value: null, | ||
value: null | ||
}), | ||
audioPlayerPausedEvent$.mapTo({ | ||
type: InputType.PAUSE, | ||
value: null, | ||
}), | ||
value: null | ||
}) | ||
); | ||
@@ -80,3 +91,3 @@ } | ||
if (input.type === InputType.GOAL) { | ||
const goal = (input.value as Goal); | ||
const goal = input.value as Goal; | ||
return { | ||
@@ -87,13 +98,16 @@ ...prev, | ||
goal_id: goal.goal_id, | ||
newGoal: null, | ||
newGoal: null | ||
}, | ||
outputs: { | ||
AudioPlayer: goal.goal, | ||
}, | ||
AudioPlayer: goal.goal | ||
} | ||
}; | ||
} | ||
} else if (prev.state === State.RUN) { | ||
if (input.type === InputType.GOAL || input.type === InputType.CANCEL | ||
&& (input.value === null || | ||
isEqualGoalID(input.value as GoalID, prev.variables.goal_id))) { | ||
if ( | ||
input.type === InputType.GOAL || | ||
(input.type === InputType.CANCEL && | ||
(input.value === null || | ||
isEqualGoalID(input.value as GoalID, prev.variables.goal_id))) | ||
) { | ||
return { | ||
@@ -104,7 +118,7 @@ ...prev, | ||
...prev.variables, | ||
newGoal: input.type === InputType.GOAL ? (input.value as Goal) : null, | ||
newGoal: input.type === InputType.GOAL ? (input.value as Goal) : null | ||
}, | ||
outputs: { | ||
AudioPlayer: null, | ||
}, | ||
AudioPlayer: null | ||
} | ||
}; | ||
@@ -117,3 +131,3 @@ } else if (input.type === InputType.ENDED) { | ||
goal_id: null, | ||
newGoal: null, | ||
newGoal: null | ||
}, | ||
@@ -124,7 +138,7 @@ outputs: { | ||
goal_id: prev.variables.goal_id, | ||
status: Status.SUCCEEDED, | ||
status: Status.SUCCEEDED | ||
}, | ||
result: input.value, | ||
}, | ||
}, | ||
result: input.value | ||
} | ||
} | ||
}; | ||
@@ -140,3 +154,3 @@ } | ||
goal_id: !!newGoal ? newGoal.goal_id : null, | ||
newGoal: null, | ||
newGoal: null | ||
}, | ||
@@ -148,7 +162,7 @@ outputs: { | ||
goal_id: prev.variables.goal_id, | ||
status: Status.PREEMPTED, | ||
status: Status.PREEMPTED | ||
}, | ||
result: input.value, | ||
}, | ||
}, | ||
result: input.value | ||
} | ||
} | ||
}; | ||
@@ -161,20 +175,22 @@ } | ||
function transitionReducer(input$: Stream<Input>): Stream<Reducer> { | ||
const initReducer$: Stream<Reducer> = xs.of( | ||
function initReducer(prev: ReducerState): ReducerState { | ||
return { | ||
state: State.WAIT, | ||
variables: { | ||
goal_id: null, | ||
newGoal: null, | ||
}, | ||
outputs: null, | ||
const initReducer$: Stream<Reducer> = xs.of(function initReducer( | ||
prev: ReducerState | ||
): ReducerState { | ||
return { | ||
state: State.WAIT, | ||
variables: { | ||
goal_id: null, | ||
newGoal: null | ||
}, | ||
outputs: null | ||
}; | ||
}); | ||
const inputReducer$: Stream<Reducer> = input$.map( | ||
input => | ||
function inputReducer(prev: ReducerState): ReducerState { | ||
return transition(prev, input); | ||
} | ||
} | ||
); | ||
const inputReducer$: Stream<Reducer> = input$ | ||
.map(input => function inputReducer(prev: ReducerState): ReducerState { | ||
return transition(prev, input); | ||
}); | ||
return xs.merge(initReducer$, inputReducer$); | ||
@@ -189,5 +205,6 @@ } | ||
.filter(rs => rs.state === State.RUN) | ||
.map(rs => ({goal_id: rs.variables.goal_id, status: Status.ACTIVE})); | ||
const initGoalStatus = generateGoalStatus({status: Status.SUCCEEDED}); | ||
return xs.merge(done$, active$) | ||
.map(rs => ({ goal_id: rs.variables.goal_id, status: Status.ACTIVE })); | ||
const initGoalStatus = generateGoalStatus({ status: Status.SUCCEEDED }); | ||
return xs | ||
.merge(done$, active$) | ||
.compose(dropRepeats(isEqualGoalStatus)) | ||
@@ -202,17 +219,15 @@ .startWith(initGoalStatus); | ||
return { | ||
result: outputs$ | ||
.filter(o => !!o.result) | ||
.map(o => o.result), | ||
result: outputs$.filter(o => !!o.result).map(o => o.result), | ||
AudioPlayer: outputs$ | ||
.filter(o => typeof o.AudioPlayer !== 'undefined') | ||
.map(o => o.AudioPlayer), | ||
.filter(o => typeof o.AudioPlayer !== "undefined") | ||
.map(o => o.AudioPlayer) | ||
}; | ||
}; | ||
} | ||
export interface Sources extends ActionSources { | ||
AudioPlayer: EventSource, | ||
AudioPlayer: EventSource; | ||
} | ||
export interface Sinks extends ActionSinks { | ||
AudioPlayer: any, | ||
AudioPlayer: any; | ||
} | ||
@@ -242,6 +257,6 @@ | ||
sources.cancel || xs.never(), | ||
sources.AudioPlayer.events('ended'), | ||
sources.AudioPlayer.events('pause'), | ||
sources.AudioPlayer.events("ended"), | ||
sources.AudioPlayer.events("pause") | ||
); | ||
const reducer = transitionReducer(input$);; | ||
const reducer = transitionReducer(input$); | ||
const status$ = status(sources.state.stream); | ||
@@ -248,0 +263,0 @@ const outputs = output(sources.state.stream); |
@@ -1,6 +0,6 @@ | ||
export {makeAudioPlayerDriver} from './makeAudioPlayerDriver'; | ||
export { makeAudioPlayerDriver } from "./makeAudioPlayerDriver"; | ||
export { | ||
Sources as AudioPlayerActionSources, | ||
Sinks as AudioPlayerActionSinks, | ||
AudioPlayerAction, | ||
} from './AudioPlayerAction'; | ||
AudioPlayerAction | ||
} from "./AudioPlayerAction"; |
@@ -1,7 +0,6 @@ | ||
import xs from 'xstream'; | ||
import fromEvent from 'xstream/extra/fromEvent'; | ||
import {adapt} from '@cycle/run/lib/adapt'; | ||
import {EventSource} from '@cycle-robot-drivers/action'; | ||
import xs from "xstream"; | ||
import fromEvent from "xstream/extra/fromEvent"; | ||
import { adapt } from "@cycle/run/lib/adapt"; | ||
import { EventSource } from "@cycle-robot-drivers/action"; | ||
/** | ||
@@ -19,5 +18,3 @@ * [HTML Audio](https://www.w3schools.com/tags/ref_av_dom.asp) | ||
class AudioSource implements EventSource { | ||
constructor( | ||
private _audio: HTMLAudioElement, | ||
) {} | ||
constructor(private _audio: HTMLAudioElement) {} | ||
@@ -34,3 +31,3 @@ events(eventName: string) { | ||
xs.fromObservable(sink$).addListener({ | ||
next: (args) => { | ||
next: args => { | ||
if (!args) { | ||
@@ -41,3 +38,3 @@ audio.pause(); | ||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement | ||
['src', 'volume', 'loop'].map(arg => { | ||
["src", "volume", "loop"].map(arg => { | ||
if (arg in args) { | ||
@@ -47,3 +44,7 @@ audio[arg] = args[arg]; | ||
}); | ||
audio.play(); | ||
// https://developers.google.com/web/updates/2017/09/autoplay-policy-changes | ||
audio.play().catch(err => { | ||
console.warn("audio.play() error", err); | ||
audio.dispatchEvent(new Event("ended")); | ||
}); | ||
} | ||
@@ -54,3 +55,3 @@ } | ||
return new AudioSource(audio) as EventSource; | ||
} | ||
}; | ||
} |
@@ -1,47 +0,47 @@ | ||
import xs from 'xstream' | ||
import {mockTimeSource} from '@cycle/time'; | ||
import {withState} from '@cycle/state'; | ||
import xs from "xstream"; | ||
import { mockTimeSource } from "@cycle/time"; | ||
import { withState } from "@cycle/state"; | ||
import { | ||
GoalID, GoalStatus, Status, | ||
generateGoalID, | ||
} from '@cycle-robot-drivers/action' | ||
import {AudioPlayerAction as Action} from '../src/AudioPlayerAction'; | ||
GoalID, | ||
GoalStatus, | ||
Status, | ||
generateGoalID | ||
} from "@cycle-robot-drivers/action"; | ||
import { AudioPlayerAction as Action } from "../src/AudioPlayerAction"; | ||
console.debug = jest.fn(); // hide debug outputs | ||
console.debug = jest.fn(); // hide debug outputs | ||
function createToStatusFnc(goal_id: GoalID) { | ||
return function (str: string): GoalStatus { | ||
return function(str: string): GoalStatus { | ||
switch (str) { | ||
case 'a': | ||
case "a": | ||
return { | ||
goal_id, | ||
status: Status.ACTIVE, | ||
status: Status.ACTIVE | ||
}; | ||
case 'p': | ||
case "p": | ||
return { | ||
goal_id, | ||
status: Status.PREEMPTED, | ||
status: Status.PREEMPTED | ||
}; | ||
case 's': | ||
case "s": | ||
return { | ||
goal_id, | ||
status: Status.SUCCEEDED, | ||
status: Status.SUCCEEDED | ||
}; | ||
} | ||
}; | ||
}; | ||
} | ||
describe('AudioPlayerAction', () => { | ||
it('walks through "happy path"', (done) => { | ||
describe("AudioPlayerAction", () => { | ||
it('walks through "happy path"', done => { | ||
const Time = mockTimeSource(); | ||
// Create test input streams with time | ||
const goalStr$ = Time.diagram(`-x---|`); | ||
const goalStr$ = Time.diagram(`-x---|`); | ||
const events = { | ||
ended: Time.diagram(`---x-|`), | ||
pause: Time.diagram(`-----|`), | ||
} | ||
const expectedValueStr$ = Time.diagram(`-x`); | ||
ended: Time.diagram(`---x-|`), | ||
pause: Time.diagram(`-----|`) | ||
}; | ||
const expectedValueStr$ = Time.diagram(`-x`); | ||
const expectedStatusStr$ = Time.diagram(`-a-s`); | ||
@@ -51,7 +51,7 @@ const expectedResultStr$ = Time.diagram(`---s`); | ||
// Create the action to test | ||
const goal = {src: 'dummy.ogg'}; | ||
const goal = { src: "dummy.ogg" }; | ||
const goal_id = generateGoalID(); | ||
const goal$ = goalStr$.mapTo({ | ||
goal_id, | ||
goal, | ||
goal | ||
}); | ||
@@ -63,3 +63,3 @@ const sinks = withState((sources: any) => { | ||
AudioPlayer: { | ||
events: (eventName) => { | ||
events: eventName => { | ||
return events[eventName]; | ||
@@ -76,3 +76,3 @@ } | ||
status: toStatus(str), | ||
result: null, | ||
result: null | ||
})); | ||
@@ -88,13 +88,13 @@ | ||
it('cancels a running goal on cancel"', (done) => { | ||
it('cancels a running goal on cancel"', done => { | ||
const Time = mockTimeSource(); | ||
// Create test input streams with time | ||
const goalMark$ = Time.diagram(`-x----|`); | ||
const cancel$ = Time.diagram(`---x--|`); | ||
const goalMark$ = Time.diagram(`-x----|`); | ||
const cancel$ = Time.diagram(`---x--|`); | ||
const events = { | ||
ended: Time.diagram(`----x-|`), | ||
pause: Time.diagram(`------|`), | ||
} | ||
const expectedValueNum$ = Time.diagram(`-0-1`); | ||
ended: Time.diagram(`----x-|`), | ||
pause: Time.diagram(`------|`) | ||
}; | ||
const expectedValueNum$ = Time.diagram(`-0-1`); | ||
const expectedStatusStr$ = Time.diagram(`-a--p`); | ||
@@ -104,7 +104,7 @@ const expectedResultStr$ = Time.diagram(`----p`); | ||
// update strings to proper inputs | ||
const goal = {src: 'dummy.ogg'}; | ||
const goal = { src: "dummy.ogg" }; | ||
const goal_id = generateGoalID(); | ||
const goal$ = goalMark$.mapTo({ | ||
goal_id, | ||
goal, | ||
goal | ||
}); | ||
@@ -117,3 +117,3 @@ const sinks = withState((sources: any) => { | ||
AudioPlayer: { | ||
events: (eventName) => { | ||
events: eventName => { | ||
return events[eventName]; | ||
@@ -131,3 +131,3 @@ } | ||
status: toStatus(str), | ||
result: null, | ||
result: null | ||
})); | ||
@@ -143,12 +143,12 @@ | ||
it('does nothing on initial cancel', (done) => { | ||
it("does nothing on initial cancel", done => { | ||
const Time = mockTimeSource(); | ||
// Create test input streams with time | ||
const cancel$ = Time.diagram(`-x-|`); | ||
const cancel$ = Time.diagram(`-x-|`); | ||
const events = { | ||
ended: Time.diagram(`---|`), | ||
pause: Time.diagram(`---|`), | ||
} | ||
const expectedValue$ = Time.diagram(``); | ||
ended: Time.diagram(`---|`), | ||
pause: Time.diagram(`---|`) | ||
}; | ||
const expectedValue$ = Time.diagram(``); | ||
const expectedStatus$ = Time.diagram(``); | ||
@@ -164,3 +164,3 @@ const expectedResult$ = Time.diagram(``); | ||
AudioPlayer: { | ||
events: (eventName) => { | ||
events: eventName => { | ||
return events[eventName]; | ||
@@ -179,13 +179,13 @@ } | ||
it('does nothing on cancel after succeeded', (done) => { | ||
it("does nothing on cancel after succeeded", done => { | ||
const Time = mockTimeSource(); | ||
// Create test input streams with time | ||
const goalMark$ = Time.diagram(`-x----|`); | ||
const cancel$ = Time.diagram(`----x-|`); | ||
const goalMark$ = Time.diagram(`-x----|`); | ||
const cancel$ = Time.diagram(`----x-|`); | ||
const events = { | ||
ended: Time.diagram(`---x--|`), | ||
pause: Time.diagram(`------|`), | ||
} | ||
const expectedValueNum$ = Time.diagram(`-0`); | ||
ended: Time.diagram(`---x--|`), | ||
pause: Time.diagram(`------|`) | ||
}; | ||
const expectedValueNum$ = Time.diagram(`-0`); | ||
const expectedStatusStr$ = Time.diagram(`-a-s`); | ||
@@ -195,7 +195,7 @@ const expectedResultStr$ = Time.diagram(`---s`); | ||
// Create the action to test | ||
const goal = {src: 'dummy.ogg'}; | ||
const goal = { src: "dummy.ogg" }; | ||
const goal_id = generateGoalID(); | ||
const goal$ = goalMark$.mapTo({ | ||
goal_id, | ||
goal, | ||
goal | ||
}); | ||
@@ -208,3 +208,3 @@ const sinks = withState((sources: any) => { | ||
AudioPlayer: { | ||
events: (eventName) => { | ||
events: eventName => { | ||
return events[eventName]; | ||
@@ -222,3 +222,3 @@ } | ||
status: toStatus(str), | ||
result: null, | ||
result: null | ||
})); | ||
@@ -234,13 +234,13 @@ | ||
it('does nothing on cancel after preempted', (done) => { | ||
it("does nothing on cancel after preempted", done => { | ||
const Time = mockTimeSource(); | ||
// Create test input streams with time | ||
const goalMark$ = Time.diagram(`-x-----|`); | ||
const cancel$ = Time.diagram(`---x-x-|`); | ||
const goalMark$ = Time.diagram(`-x-----|`); | ||
const cancel$ = Time.diagram(`---x-x-|`); | ||
const events = { | ||
ended: Time.diagram(`----x--|`), | ||
pause: Time.diagram(`-------|`), | ||
} | ||
const expectedValueNum$ = Time.diagram(`-0-1`); | ||
ended: Time.diagram(`----x--|`), | ||
pause: Time.diagram(`-------|`) | ||
}; | ||
const expectedValueNum$ = Time.diagram(`-0-1`); | ||
const expectedStatusStr$ = Time.diagram(`-a--p`); | ||
@@ -250,7 +250,7 @@ const expectedResultStr$ = Time.diagram(`----p`); | ||
// Create the action to test | ||
const goal = {src: 'dummy.ogg'}; | ||
const goal = { src: "dummy.ogg" }; | ||
const goal_id = generateGoalID(); | ||
const goal$ = goalMark$.mapTo({ | ||
goal_id, | ||
goal, | ||
goal | ||
}); | ||
@@ -263,3 +263,3 @@ const sinks = withState((sources: any) => { | ||
AudioPlayer: { | ||
events: (eventName) => { | ||
events: eventName => { | ||
return events[eventName]; | ||
@@ -277,3 +277,3 @@ } | ||
status: toStatus(str), | ||
result: null, | ||
result: null | ||
})); | ||
@@ -289,27 +289,30 @@ | ||
it('cancels the first goal on receiving a second goal', (done) => { | ||
it("cancels the first goal on receiving a second goal", done => { | ||
const Time = mockTimeSource(); | ||
// Create test input streams with time | ||
const goalMark$ = Time.diagram(`-0--1----|`); | ||
const goalMark$ = Time.diagram(`-0--1----|`); | ||
const events = { | ||
ended: Time.diagram(`-------x-|`), | ||
pause: Time.diagram(`-----x---|`), | ||
ended: Time.diagram(`-------x-|`), | ||
pause: Time.diagram(`-----x---|`) | ||
}; | ||
const expecteds = [{ | ||
value: Time.diagram(`-0--x`), | ||
status: Time.diagram(`-a---p`), | ||
result: Time.diagram(`-----p`), | ||
}, { | ||
value: Time.diagram(`-----1`), | ||
status: Time.diagram(`-----a-s`), | ||
result: Time.diagram(`-------s`), | ||
}]; | ||
const expecteds = [ | ||
{ | ||
value: Time.diagram(`-0--x`), | ||
status: Time.diagram(`-a---p`), | ||
result: Time.diagram(`-----p`) | ||
}, | ||
{ | ||
value: Time.diagram(`-----1`), | ||
status: Time.diagram(`-----a-s`), | ||
result: Time.diagram(`-------s`) | ||
} | ||
]; | ||
// Create the action to test | ||
const goal_ids = [generateGoalID(), generateGoalID()]; | ||
const goals = [{src: 'dummy.org'}, {text: 'genius.ogg'}]; | ||
const goals = [{ src: "dummy.org" }, { text: "genius.ogg" }]; | ||
const goal$ = goalMark$.map(i => ({ | ||
goal_id: goal_ids[i], | ||
goal: goals[i], | ||
goal: goals[i] | ||
})); | ||
@@ -321,3 +324,3 @@ const sinks = withState((sources: any) => { | ||
AudioPlayer: { | ||
events: (eventName) => { | ||
events: eventName => { | ||
return events[eventName]; | ||
@@ -330,3 +333,3 @@ } | ||
expecteds.map((expected, i) => { | ||
expected.value = expected.value.map(j => goals[j] ? goals[j] : null); | ||
expected.value = expected.value.map(j => (goals[j] ? goals[j] : null)); | ||
const toStatus = createToStatusFnc(goal_ids[i]); | ||
@@ -336,3 +339,3 @@ expected.status = expected.status.map(str => toStatus(str)); | ||
status: toStatus(str), | ||
result: null, | ||
result: null | ||
})); | ||
@@ -339,0 +342,0 @@ }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
55737
1117