From 33411c23b3ce174df8d4f6b881921d7944be0e2c Mon Sep 17 00:00:00 2001 From: Sara Joiner Date: Tue, 30 Oct 2018 14:54:56 -0700 Subject: [PATCH 1/7] Add basic structure for Sound library Adds the basic structure for the Sound library, and populates it with the first couple (not yet implemented) methods. --- src/compiler/runtime/libraries-metadata.ts | 12 ++++++++++++ src/compiler/runtime/libraries/sound.ts | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/compiler/runtime/libraries/sound.ts diff --git a/src/compiler/runtime/libraries-metadata.ts b/src/compiler/runtime/libraries-metadata.ts index e2583eb..7ac682a 100644 --- a/src/compiler/runtime/libraries-metadata.ts +++ b/src/compiler/runtime/libraries-metadata.ts @@ -187,6 +187,18 @@ export class LibrariesMetadata { // No Events }); + public readonly Sound: TypeMetadata = new TypeMetadata("Sound", + { + PlayClick: new MethodMetadata("Sound", "PlayClick", false, []), + PlayClickAndWait: new MethodMetadata("Sound", "PlayClickAndWait", false, []) + }, + { + // No Properties + }, + { + // No Events + }); + public readonly Stack: TypeMetadata = new TypeMetadata("Stack", { PushValue: new MethodMetadata("Stack", "PushValue", false, ["StackName", "Value"]), diff --git a/src/compiler/runtime/libraries/sound.ts b/src/compiler/runtime/libraries/sound.ts new file mode 100644 index 0000000..0097cff --- /dev/null +++ b/src/compiler/runtime/libraries/sound.ts @@ -0,0 +1,18 @@ +import { ExecutionEngine } from "../../execution-engine"; +import { LibraryTypeInstance, LibraryMethodInstance, LibraryPropertyInstance, LibraryEventInstance } from "../libraries"; + +export class SoundLibrary implements LibraryTypeInstance { + + private executePlayStockSound(engine: ExecutionEngine, soundName: string, sync: boolean): void { + + } + + public readonly methods: { readonly [name: string]: LibraryMethodInstance } = { + PlayClick: { execute: this.executePlayStockSound.bind(this, "Click.wav", false) }, + PlayClickAndWait: { execute: this.executePlayStockSound.bind(this, "Click.wav", true) }, + }; + + public readonly properties: { readonly [name: string]: LibraryPropertyInstance } = {}; + + public readonly events: { readonly [name: string]: LibraryEventInstance } = {}; +} From e955419d293115c2a69035345f13f7d22ff316db Mon Sep 17 00:00:00 2001 From: Sara Joiner Date: Tue, 30 Oct 2018 19:58:12 -0700 Subject: [PATCH 2/7] Implementation of Sound.PlayClick Implemented Sound.PlayClick and manually verified that it works! --- build/webpack.config.ts | 2 +- src/app/content/sounds/Click.wav | Bin 0 -> 2476 bytes src/compiler/runtime/libraries-metadata.ts | 3 +-- src/compiler/runtime/libraries.ts | 2 ++ src/compiler/runtime/libraries/sound.ts | 23 +++++++++++++++++---- 5 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 src/app/content/sounds/Click.wav diff --git a/build/webpack.config.ts b/build/webpack.config.ts index faa288f..3da07a2 100644 --- a/build/webpack.config.ts +++ b/build/webpack.config.ts @@ -61,7 +61,7 @@ export function factory(params: IFactoryParams): webpack.Configuration { ] }, { - test: /\.(png|gif)$/, + test: /\.(png|gif|wav)$/, use: [ { loader: "file-loader", diff --git a/src/app/content/sounds/Click.wav b/src/app/content/sounds/Click.wav new file mode 100644 index 0000000000000000000000000000000000000000..f9b5f08992cff2cba9678962c8e92411a72bd85d GIT binary patch literal 2476 zcmbVNOK%e~5Z>P4MvvV16Pzm!v~c917I7&>RV7de5`^Zp>-8(UO(+l{gn9sllyHTg z!cXBRl$o)|>unZNa8-Le^L^ipAMxJ3y}7x#oFqFpwr?Ih>s-5%B*_~5{n}3Ge=WI` z?C*8?j#OdqyzfnCp2MxE192!h; z$OeZmp10er)@bpi-)e3bLIE|uh z0-xJK-{XJ**h?3IaPBT03|d1R3Fu|MKRp%#H{bw>Dkw)CddVO(9u6gOTug;X2X#K* zdtk&RNs3l_s7(T-fhO}}i-i&F(PX(=*o7zupalj5Zk}5-x;PtaB8ix_H883ou!pdb zN-%lXNSJv%M(d1)Fu9*YmD<~ZM2G3hBUSFsNstO~S&3osNY|orEGv+R2Veov+$7%rT@Sj@wH4QYa0FeqPzW%0mZ2aga~MpLjxsZE&6BM5|eY;(LCu}o~}36v_l z%4(`K=y|fc=s3ZuFp1AsTj+9fxM#$nokoz*JiYLJD9Qr95gI-a*yy=5))<5D z3%u{p@ae}#l-^PJK>*5o0EJGU-j_v#OHOZALv>IwHjI!#ljeH=&x_)5yTBH?LSj;7 Z`&eDGy4n>mw*Dr_I98 Date: Tue, 30 Oct 2018 20:02:15 -0700 Subject: [PATCH 3/7] Add documentation for PlayClick Adds the documentation for PlayClick. --- build/strings/en/documentation.json | 2 ++ src/strings/documentation.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/build/strings/en/documentation.json b/build/strings/en/documentation.json index 323b409..6970a16 100644 --- a/build/strings/en/documentation.json +++ b/build/strings/en/documentation.json @@ -159,6 +159,8 @@ "Shapes_HideShape_ShapeName": "The name of the shape.", "Shapes_ShowShape": "Shows a previously hidden shape.", "Shapes_ShowShape_ShapeName": "The name of the shape.", + "Sound": "The Sound object provides operations that allow the playback of sounds. Some sample sounds are provided along with the library.", + "Sound_PlayClick" : "Plays the Click Sound.", "Stack": "This object provides a way of storing values just like stacking up a plate. You can push a value to the top of the stack and pop it off. You can only pop the values one by one off the stack and the last pushed value will be the first one to pop out.", "Stack_PushValue": "Pushes a value to the specified stack.", "Stack_PushValue_StackName": "The name of the stack.", diff --git a/src/strings/documentation.ts b/src/strings/documentation.ts index dfc5cd5..6403dbb 100644 --- a/src/strings/documentation.ts +++ b/src/strings/documentation.ts @@ -161,6 +161,8 @@ export module DocumentationResources { export const Shapes_HideShape_ShapeName = "The name of the shape."; export const Shapes_ShowShape = "Shows a previously hidden shape."; export const Shapes_ShowShape_ShapeName = "The name of the shape."; + export const Sound = "The Sound object provides operations that allow the playback of sounds. Some sample sounds are provided along with the library."; + export const Sound_PlayClick = "Plays the Click Sound."; export const Stack = "This object provides a way of storing values just like stacking up a plate. You can push a value to the top of the stack and pop it off. You can only pop the values one by one off the stack and the last pushed value will be the first one to pop out."; export const Stack_PushValue = "Pushes a value to the specified stack."; export const Stack_PushValue_StackName = "The name of the stack."; From 4afcdcb6653f7a495278f76d211e3f92ceac3a03 Mon Sep 17 00:00:00 2001 From: Sara Joiner Date: Wed, 31 Oct 2018 14:52:40 -0700 Subject: [PATCH 4/7] Add strings for the rest of the Sound APIs Adds the strings for the rest of the Sound APIs, as copied from SmallBasic.Web\Content\js\json\generated-output.json --- build/strings/en/documentation.json | 17 +++++++++++++++++ src/strings/documentation.ts | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/build/strings/en/documentation.json b/build/strings/en/documentation.json index 6970a16..9fdcb83 100644 --- a/build/strings/en/documentation.json +++ b/build/strings/en/documentation.json @@ -161,6 +161,23 @@ "Shapes_ShowShape_ShapeName": "The name of the shape.", "Sound": "The Sound object provides operations that allow the playback of sounds. Some sample sounds are provided along with the library.", "Sound_PlayClick" : "Plays the Click Sound.", + "Sound_PlayClickAndWait" : "Plays the Click Sound and waits for it to finish.", + "Sound_PlayChime" : "Plays the Chime Sound. ", + "Sound_PlayChimeAndWait" : "Plays the Chime Sound and waits for it to finish.", + "Sound_PlayChimes" : "Plays the Chimes Sound.", + "Sound_PlayChimesAndWait" : "Plays the Chimes Sound and waits for it to finish.", + "Sound_PlayBellRing" : "Plays the Bell Ring Sound.", + "Sound_PlayBellRingAndWait" : "Plays the Bell Ring Sound and waits for it to finish.", + "Sound_PlayMusic" : "Plays musical notes.", + "Sound_PlayMusic_Notes" : "A set of musical notes to play. The format is a subset of the Music Macro Language supported by QBasic.", + "Sound_Play" : "Plays the Click Sound.", + "Sound_Play_FilePath" : "", + "Sound_PlayAndWait" : "Plays an audio file and waits until it is finished playing. This could be an mp3, wav, or wma file. Other file formats may or may not play depending on the audio codecs installed on the user's computer. If the file was already paused, this operation will resume from the position where the playback was paused.", + "Sound_PlayAndWait_FilePath" : "The path for the audio file. This could either be a local file (e.g.: c:\\music\\track1.mp3) or a file on the network (e.g.: http://contoso.com/track01.wma).", + "Sound_Pause" : "Pauses playback of an audio file. If the file was not already playing, this operation will not do anything.", + "Sound_Pause_FilePath" : "The path for the audio file. This could either be a local file (e.g.: c:\\music\\track1.mp3) or a file on the network (e.g.: http://contoso.com/track01.wma).", + "Sound_Stop" : "Stops playback of an audio file. If the file was not already playing, this operation will not do anything.", + "Sound_Stop_FilePath" : "The path for the audio file. This could either be a local file (e.g.: c:\\music\\track1.mp3) or a file on the network (e.g.: http://contoso.com/track01.wma).", "Stack": "This object provides a way of storing values just like stacking up a plate. You can push a value to the top of the stack and pop it off. You can only pop the values one by one off the stack and the last pushed value will be the first one to pop out.", "Stack_PushValue": "Pushes a value to the specified stack.", "Stack_PushValue_StackName": "The name of the stack.", diff --git a/src/strings/documentation.ts b/src/strings/documentation.ts index 6403dbb..3c667bc 100644 --- a/src/strings/documentation.ts +++ b/src/strings/documentation.ts @@ -163,6 +163,23 @@ export module DocumentationResources { export const Shapes_ShowShape_ShapeName = "The name of the shape."; export const Sound = "The Sound object provides operations that allow the playback of sounds. Some sample sounds are provided along with the library."; export const Sound_PlayClick = "Plays the Click Sound."; + export const Sound_PlayClickAndWait = "Plays the Click Sound and waits for it to finish."; + export const Sound_PlayChime = "Plays the Chime Sound. "; + export const Sound_PlayChimeAndWait = "Plays the Chime Sound and waits for it to finish."; + export const Sound_PlayChimes = "Plays the Chimes Sound."; + export const Sound_PlayChimesAndWait = "Plays the Chimes Sound and waits for it to finish."; + export const Sound_PlayBellRing = "Plays the Bell Ring Sound."; + export const Sound_PlayBellRingAndWait = "Plays the Bell Ring Sound and waits for it to finish."; + export const Sound_PlayMusic = "Plays musical notes."; + export const Sound_PlayMusic_Notes = "A set of musical notes to play. The format is a subset of the Music Macro Language supported by QBasic."; + export const Sound_Play = "Plays the Click Sound."; + export const Sound_Play_FilePath = ""; + export const Sound_PlayAndWait = "Plays an audio file and waits until it is finished playing. This could be an mp3, wav, or wma file. Other file formats may or may not play depending on the audio codecs installed on the user's computer. If the file was already paused, this operation will resume from the position where the playback was paused."; + export const Sound_PlayAndWait_FilePath = "The path for the audio file. This could either be a local file (e.g.: c:\music\track1.mp3) or a file on the network (e.g.: http://contoso.com/track01.wma)."; + export const Sound_Pause = "Pauses playback of an audio file. If the file was not already playing, this operation will not do anything."; + export const Sound_Pause_FilePath = "The path for the audio file. This could either be a local file (e.g.: c:\music\track1.mp3) or a file on the network (e.g.: http://contoso.com/track01.wma)."; + export const Sound_Stop = "Stops playback of an audio file. If the file was not already playing, this operation will not do anything."; + export const Sound_Stop_FilePath = "The path for the audio file. This could either be a local file (e.g.: c:\music\track1.mp3) or a file on the network (e.g.: http://contoso.com/track01.wma)."; export const Stack = "This object provides a way of storing values just like stacking up a plate. You can push a value to the top of the stack and pop it off. You can only pop the values one by one off the stack and the last pushed value will be the first one to pop out."; export const Stack_PushValue = "Pushes a value to the specified stack."; export const Stack_PushValue_StackName = "The name of the stack."; From 26b41007ef48f7868cd7489425964dbdfb4a12fd Mon Sep 17 00:00:00 2001 From: Sara Joiner Date: Wed, 31 Oct 2018 14:54:43 -0700 Subject: [PATCH 5/7] Fix Sound.Play strings Copy better strings into Sound.Play and Sound.Play.FilePath, per the actual documentation headers in the original code. --- build/strings/en/documentation.json | 4 ++-- src/strings/documentation.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/strings/en/documentation.json b/build/strings/en/documentation.json index 9fdcb83..5041657 100644 --- a/build/strings/en/documentation.json +++ b/build/strings/en/documentation.json @@ -170,8 +170,8 @@ "Sound_PlayBellRingAndWait" : "Plays the Bell Ring Sound and waits for it to finish.", "Sound_PlayMusic" : "Plays musical notes.", "Sound_PlayMusic_Notes" : "A set of musical notes to play. The format is a subset of the Music Macro Language supported by QBasic.", - "Sound_Play" : "Plays the Click Sound.", - "Sound_Play_FilePath" : "", + "Sound_Play" : "Plays an audio file. This could be an mp3 or wav or wma file. Other file formats may or may not play depending on the audio codecs installed on the user's computer. If the file was already paused, this operation will resume from the position where the playback was paused.", + "Sound_Play_FilePath" : "The path for the audio file. This could either be a local file (e.g.: c:\\music\\track1.mp3) or a file on the network (e.g.: http://contoso.com/track01.wma).", "Sound_PlayAndWait" : "Plays an audio file and waits until it is finished playing. This could be an mp3, wav, or wma file. Other file formats may or may not play depending on the audio codecs installed on the user's computer. If the file was already paused, this operation will resume from the position where the playback was paused.", "Sound_PlayAndWait_FilePath" : "The path for the audio file. This could either be a local file (e.g.: c:\\music\\track1.mp3) or a file on the network (e.g.: http://contoso.com/track01.wma).", "Sound_Pause" : "Pauses playback of an audio file. If the file was not already playing, this operation will not do anything.", diff --git a/src/strings/documentation.ts b/src/strings/documentation.ts index 3c667bc..724606f 100644 --- a/src/strings/documentation.ts +++ b/src/strings/documentation.ts @@ -172,8 +172,8 @@ export module DocumentationResources { export const Sound_PlayBellRingAndWait = "Plays the Bell Ring Sound and waits for it to finish."; export const Sound_PlayMusic = "Plays musical notes."; export const Sound_PlayMusic_Notes = "A set of musical notes to play. The format is a subset of the Music Macro Language supported by QBasic."; - export const Sound_Play = "Plays the Click Sound."; - export const Sound_Play_FilePath = ""; + export const Sound_Play = "Plays an audio file. This could be an mp3 or wav or wma file. Other file formats may or may not play depending on the audio codecs installed on the user's computer. If the file was already paused, this operation will resume from the position where the playback was paused."; + export const Sound_Play_FilePath = "The path for the audio file. This could either be a local file (e.g.: c:\music\track1.mp3) or a file on the network (e.g.: http://contoso.com/track01.wma)."; export const Sound_PlayAndWait = "Plays an audio file and waits until it is finished playing. This could be an mp3, wav, or wma file. Other file formats may or may not play depending on the audio codecs installed on the user's computer. If the file was already paused, this operation will resume from the position where the playback was paused."; export const Sound_PlayAndWait_FilePath = "The path for the audio file. This could either be a local file (e.g.: c:\music\track1.mp3) or a file on the network (e.g.: http://contoso.com/track01.wma)."; export const Sound_Pause = "Pauses playback of an audio file. If the file was not already playing, this operation will not do anything."; From 6bcc162a727b4a62554be5cba814ee4e380f17e5 Mon Sep 17 00:00:00 2001 From: Sara Joiner Date: Wed, 31 Oct 2018 15:27:15 -0700 Subject: [PATCH 6/7] Add structure for the rest of the Sound APIs Implement the structure of the rest of the Sound APIs, + actually implement the three easy ones (playing sound files like what was already implemented for Click) --- src/app/content/sounds/BellRing.wav | Bin 0 -> 40502 bytes src/app/content/sounds/Chime.wav | Bin 0 -> 29558 bytes src/app/content/sounds/Pause.wav | Bin 0 -> 8006 bytes src/compiler/runtime/libraries-metadata.ts | 14 +++++++++- src/compiler/runtime/libraries/sound.ts | 31 +++++++++++++++++++-- 5 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 src/app/content/sounds/BellRing.wav create mode 100644 src/app/content/sounds/Chime.wav create mode 100644 src/app/content/sounds/Pause.wav diff --git a/src/app/content/sounds/BellRing.wav b/src/app/content/sounds/BellRing.wav new file mode 100644 index 0000000000000000000000000000000000000000..8c310fb2e132c1eff72fd7d5a360523892d2620f GIT binary patch literal 40502 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 literal 0 HcmV?d00001 diff --git a/src/compiler/runtime/libraries-metadata.ts b/src/compiler/runtime/libraries-metadata.ts index 19cc779..c664197 100644 --- a/src/compiler/runtime/libraries-metadata.ts +++ b/src/compiler/runtime/libraries-metadata.ts @@ -189,7 +189,19 @@ export class LibrariesMetadata { public readonly Sound: TypeMetadata = new TypeMetadata("Sound", { - PlayClick: new MethodMetadata("Sound", "PlayClick", false, []) + PlayClick: new MethodMetadata("Sound", "PlayClick", false, []), + PlayClickAndWait: new MethodMetadata("Sound", "PlayClickAndWait", false, []), + PlayChime: new MethodMetadata("Sound", "PlayChime", false, []), + PlayChimeAndWait: new MethodMetadata("Sound", "PlayChimeAndWait", false, []), + PlayChimes: new MethodMetadata("Sound", "PlayChimes", false, []), + PlayChimesAndWait: new MethodMetadata("Sound", "PlayChimesAndWait", false, []), + PlayBellRing: new MethodMetadata("Sound", "PlayBellRing", false, []), + PlayBellRingAndWait: new MethodMetadata("Sound", "PlayBellRingAndWait", false, []), + PlayMusic: new MethodMetadata("Sound", "PlayMusic", false, ["Notes"]), + Play: new MethodMetadata("Sound", "Play", false, ["FilePath"]), + PlayAndWait: new MethodMetadata("Sound", "PlayAndWait", false, ["FilePath"]), + Pause: new MethodMetadata("Sound", "Pause", false, ["FilePath"]), + Stop: new MethodMetadata("Sound", "Stop", false, ["FilePath"]) }, { // No Properties diff --git a/src/compiler/runtime/libraries/sound.ts b/src/compiler/runtime/libraries/sound.ts index 478c580..b2b4047 100644 --- a/src/compiler/runtime/libraries/sound.ts +++ b/src/compiler/runtime/libraries/sound.ts @@ -1,9 +1,15 @@ import { LibraryTypeInstance, LibraryMethodInstance, LibraryPropertyInstance, LibraryEventInstance } from "../libraries"; const ClickSound = require("../../../app/content/sounds/click.wav"); +const ChimeSound = require("../../../app/content/sounds/chime.wav"); +const ChimesSound = require("../../../app/content/sounds/pause.wav"); +const BellRingSound = require("../../../app/content/sounds/bellring.wav"); enum Sound { - Click + Click, + Chime, + Chimes, + BellRing } export class SoundLibrary implements LibraryTypeInstance { @@ -14,6 +20,15 @@ export class SoundLibrary implements LibraryTypeInstance { case Sound.Click: audioFile = ClickSound; break; + case Sound.Chime: + audioFile = ChimeSound; + break; + case Sound.Chimes: + audioFile = ChimesSound; + break; + case Sound.BellRing: + audioFile = BellRingSound; + break; } if (audioFile !== "") @@ -24,7 +39,19 @@ export class SoundLibrary implements LibraryTypeInstance { } public readonly methods: { readonly [name: string]: LibraryMethodInstance } = { - PlayClick: { execute: this.executePlayStockSound.bind(this, Sound.Click) } + PlayClick: { execute: this.executePlayStockSound.bind(this, Sound.Click) }, + PlayClickAndWait: { execute: () => { throw new Error("Not Implemented yet."); } }, + PlayChime: { execute: this.executePlayStockSound.bind(this, Sound.Chime) }, + PlayChimeAndWait: { execute: () => { throw new Error("Not Implemented yet."); } }, + PlayChimes: { execute: this.executePlayStockSound.bind(this, Sound.Chimes) }, + PlayChimesAndWait: { execute: () => { throw new Error("Not Implemented yet."); } }, + PlayBellRing: { execute: this.executePlayStockSound.bind(this, Sound.BellRing) }, + PlayBellRingAndWait: { execute: () => { throw new Error("Not Implemented yet."); } }, + PlayMusic: { execute: () => { throw new Error("Not Implemented yet."); } }, + Play: { execute: () => { throw new Error("Not Implemented yet."); } }, + PlayAndWait: { execute: () => { throw new Error("Not Implemented yet."); } }, + Pause: { execute: () => { throw new Error("Not Implemented yet."); } }, + Stop: { execute: () => { throw new Error("Not Implemented yet."); } } }; public readonly properties: { readonly [name: string]: LibraryPropertyInstance } = {}; From 8e65ba26dd33c7d6e4ae416a9156c3649fed4312 Mon Sep 17 00:00:00 2001 From: Sara Joiner Date: Wed, 31 Oct 2018 18:00:07 -0700 Subject: [PATCH 7/7] Add unit tests for the Sound library Refactor the Sound library to make it more unit testable, and add some basic tests. --- src/app/components/common/sound-plugin.ts | 12 ++++ src/compiler/runtime/libraries/sound.ts | 34 ++++++++---- tests/compiler/helpers.ts | 14 +++++ tests/compiler/runtime/libraries/sound.ts | 67 +++++++++++++++++++++++ tests/compiler/tests-list.ts | 1 + 5 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 src/app/components/common/sound-plugin.ts create mode 100644 tests/compiler/runtime/libraries/sound.ts diff --git a/src/app/components/common/sound-plugin.ts b/src/app/components/common/sound-plugin.ts new file mode 100644 index 0000000..b27e2f6 --- /dev/null +++ b/src/app/components/common/sound-plugin.ts @@ -0,0 +1,12 @@ +import { ISoundLibraryPlugin } from "../../../compiler/runtime/libraries/sound"; + +export class SoundLibraryPlugin implements ISoundLibraryPlugin { + + public playAudio(audioFile: string): void { + if (audioFile !== "") + { + let audio = new Audio(audioFile); + audio.play(); + } + } +} diff --git a/src/compiler/runtime/libraries/sound.ts b/src/compiler/runtime/libraries/sound.ts index b2b4047..60e005b 100644 --- a/src/compiler/runtime/libraries/sound.ts +++ b/src/compiler/runtime/libraries/sound.ts @@ -1,9 +1,10 @@ import { LibraryTypeInstance, LibraryMethodInstance, LibraryPropertyInstance, LibraryEventInstance } from "../libraries"; +import { SoundLibraryPlugin } from "../../../app/components/common/sound-plugin"; -const ClickSound = require("../../../app/content/sounds/click.wav"); -const ChimeSound = require("../../../app/content/sounds/chime.wav"); -const ChimesSound = require("../../../app/content/sounds/pause.wav"); -const BellRingSound = require("../../../app/content/sounds/bellring.wav"); +export const ClickSound = require("../../../app/content/sounds/click.wav"); +export const ChimeSound = require("../../../app/content/sounds/chime.wav"); +export const ChimesSound = require("../../../app/content/sounds/pause.wav"); +export const BellRingSound = require("../../../app/content/sounds/bellring.wav"); enum Sound { Click, @@ -12,8 +13,25 @@ enum Sound { BellRing } +export interface ISoundLibraryPlugin { + playAudio(audioFile : string): void; +} + export class SoundLibrary implements LibraryTypeInstance { - + private _pluginInstance: ISoundLibraryPlugin | undefined; + + public get plugin(): ISoundLibraryPlugin { + if (!this._pluginInstance) { + this._pluginInstance = new SoundLibraryPlugin(); + } + + return this._pluginInstance; + } + + public set plugin(plugin: ISoundLibraryPlugin) { + this._pluginInstance = plugin; + } + private executePlayStockSound(soundName: Sound): void { let audioFile : string = ""; switch (soundName) { @@ -31,11 +49,7 @@ export class SoundLibrary implements LibraryTypeInstance { break; } - if (audioFile !== "") - { - let audio = new Audio(audioFile); - audio.play(); - } + this.plugin.playAudio(audioFile); } public readonly methods: { readonly [name: string]: LibraryMethodInstance } = { diff --git a/tests/compiler/helpers.ts b/tests/compiler/helpers.ts index d319f95..783c919 100644 --- a/tests/compiler/helpers.ts +++ b/tests/compiler/helpers.ts @@ -8,6 +8,7 @@ import { CompilerPosition, CompilerRange } from "../../src/compiler/syntax/range import { TokenKind } from "../../src/compiler/syntax/tokens"; import { ITextWindowLibraryPlugin, TextWindowColor } from "../../src/compiler/runtime/libraries/text-window"; import { BaseValue } from "../../src/compiler/runtime/values/base-value"; +import { ISoundLibraryPlugin } from "../../src/compiler/runtime/libraries/sound"; export function getMarkerPosition(text: string, marker: string): CompilerPosition { expect(marker.length).toBe(1); @@ -162,3 +163,16 @@ export class TextWindowTestBuffer implements ITextWindowLibraryPlugin { } } } + +export class TestSoundLibraryPlugin implements ISoundLibraryPlugin { + + private lastAudioPlayed : string = ""; + + public getLastAudioPlayed() : string { + return this.lastAudioPlayed; + } + + public playAudio(audioFile: string): void { + this.lastAudioPlayed = audioFile; + } +} diff --git a/tests/compiler/runtime/libraries/sound.ts b/tests/compiler/runtime/libraries/sound.ts new file mode 100644 index 0000000..c00adf7 --- /dev/null +++ b/tests/compiler/runtime/libraries/sound.ts @@ -0,0 +1,67 @@ +import "jasmine"; +import { Compilation } from "../../../../src/compiler/compilation"; +import { ExecutionEngine, ExecutionMode, ExecutionState } from "../../../../src/compiler/execution-engine"; +import { TestSoundLibraryPlugin } from "../../helpers"; +import { ClickSound, ChimeSound, ChimesSound, BellRingSound } from "../../../../src/compiler/runtime/libraries/sound"; + +describe("Compiler.Runtime.Libraries.Sound", () => { + it("plays a clicking sound", () => { + const compilation = new Compilation(` +Sound.PlayClick()`); + + const plugin = new TestSoundLibraryPlugin(); + const engine = new ExecutionEngine(compilation); + + engine.libraries.Sound.plugin = plugin; + engine.execute(ExecutionMode.RunToEnd); + + expect(plugin.getLastAudioPlayed()).toBe(ClickSound); + expect(engine.state).toBe(ExecutionState.Terminated); + expect(engine.exception).toBeUndefined(); + }); + + it("plays a chiming sound", () => { + const compilation = new Compilation(` +Sound.PlayChime()`); + + const plugin = new TestSoundLibraryPlugin(); + const engine = new ExecutionEngine(compilation); + + engine.libraries.Sound.plugin = plugin; + engine.execute(ExecutionMode.RunToEnd); + + expect(plugin.getLastAudioPlayed()).toBe(ChimeSound); + expect(engine.state).toBe(ExecutionState.Terminated); + expect(engine.exception).toBeUndefined(); + }); + + it("plays the chimes sound", () => { + const compilation = new Compilation(` +Sound.PlayChimes()`); + + const plugin = new TestSoundLibraryPlugin(); + const engine = new ExecutionEngine(compilation); + + engine.libraries.Sound.plugin = plugin; + engine.execute(ExecutionMode.RunToEnd); + + expect(plugin.getLastAudioPlayed()).toBe(ChimesSound); + expect(engine.state).toBe(ExecutionState.Terminated); + expect(engine.exception).toBeUndefined(); + }); + + it("plays a ringing bell sound", () => { + const compilation = new Compilation(` +Sound.PlayBellRing()`); + + const plugin = new TestSoundLibraryPlugin(); + const engine = new ExecutionEngine(compilation); + + engine.libraries.Sound.plugin = plugin; + engine.execute(ExecutionMode.RunToEnd); + + expect(plugin.getLastAudioPlayed()).toBe(BellRingSound); + expect(engine.state).toBe(ExecutionState.Terminated); + expect(engine.exception).toBeUndefined(); + }); +}); diff --git a/tests/compiler/tests-list.ts b/tests/compiler/tests-list.ts index dcd909f..178d76b 100644 --- a/tests/compiler/tests-list.ts +++ b/tests/compiler/tests-list.ts @@ -27,6 +27,7 @@ import "./runtime/libraries/array"; import "./runtime/libraries/clock"; import "./runtime/libraries/math"; import "./runtime/libraries/program"; +import "./runtime/libraries/sound"; import "./runtime/libraries/stack"; import "./runtime/libraries/text-window";