import {Injectable} from '@angular/core'; import {Constants, PreloaderOxService, SettingsService} from 'ox-core'; // import {ScreenOxService} from './screen-ox.service'; import {AudiOX} from '../models/audio-ox'; import {Subscription, timer} from 'rxjs'; import {ScreenTypeOx} from 'ox-types'; @Injectable({ providedIn: 'root' }) export class SoundOxService { private audios: AudiOX[]; private musics: AudiOX[]; private _currentScreen: ScreenTypeOx; get currentScreen(): ScreenTypeOx { return this._currentScreen; } set currentScreen(value: ScreenTypeOx) { this._currentScreen = value; this.checkAudiosByScreen(); this.checkMusicByScreen(); } private playingMultipleAudioData: { subscription: Subscription, screen: ScreenTypeOx, callBack?: () => void, playCallbackOnCancel: boolean, id: number }; private multipleCancelIds: number[]; constructor(private preloader: PreloaderOxService, private settingsService: SettingsService) { this.audios = []; this.musics = []; this.multipleCancelIds = []; } public setSoundOn(on: boolean) { this.settingsService.setSound(on); this.checkAudiosByScreen(); } soundOn(): boolean { return this.settingsService.getSound(); } musicOn(): boolean { return this.settingsService.getMusic(); } public setMusicOn(on: boolean) { this.settingsService.setMusic(on); this.checkMusicByScreen(); } public playMusic(url: string, askingScreen: ScreenTypeOx) { const aux = this.preloader.resources.get(url); if (!aux || aux.error) { console.log('The music ' + url + ' can not be played, ', aux ? 'error: ' + aux.error : 'the resource is not loaded.'); return; } const musicOx = new AudiOX(aux.data, askingScreen); this.addAsLastScreenMusic(musicOx); musicOx.audio.loop(true); if (this.isCurrentScreen(askingScreen) && this.musicOn()) { this.playHowl(musicOx); } } public pauseMusic(askingScreen: ScreenTypeOx) { const music = this.musics.find(x => x.askedFor === askingScreen); if (music) { music.audio.pause(); } } public playCurrentMusic(askingScreen: ScreenTypeOx) { const music = this.musics.find(x => x.askedFor === askingScreen); if (music && this.isCurrentScreen(askingScreen)) { music.audio.play(); } } public playSoundEffect(url: string, askingScreen: ScreenTypeOx, duplicateIfIsTheSame: boolean = false, playAnyWay: boolean = false, callBack?: (x?) => void, fromMultiple?: boolean) { this.checkMultiple(askingScreen, fromMultiple); const aux = this.preloader.resources.get(url); if (!aux || aux.error) { console.log('The audio ' + url + ' can not be played, ', aux ? 'error: ' + aux.error : 'the resource is not loaded.'); return; } const howlerData = aux.data; if (!duplicateIfIsTheSame && howlerData.playing) { howlerData.stop(); } const audiOX = new AudiOX(howlerData, askingScreen); this.addAsLastScreenAudio(audiOX, duplicateIfIsTheSame); audiOX.audio.mute(!this.isCurrentScreen(askingScreen) || (!this.soundOn() && !playAnyWay)); audiOX.audio.once('end', () => { this.audios = this.audios.filter(x => x.audio !== audiOX.audio); if (callBack) { callBack(); } }); this.playHowl(audiOX); } playMultipleSound(soundPath: string[], inBetweenTime: number, fromIndex: number, fromScreen: ScreenTypeOx, callBack?: () => void, playCallbackOnCancel?: boolean, carryId?: number) { // const sounds = ; const id = carryId === undefined ? (Math.max(...this.multipleCancelIds, this.playingMultipleAudioData ? this.playingMultipleAudioData.id : 0) + 1) : carryId; if (this.playingMultipleAudioData && this.playingMultipleAudioData.id !== id) { this.cancelMultiple(); } if (!this.playingMultipleAudioData && fromIndex !== 0) { return; } this.playingMultipleAudioData = { screen: fromScreen, callBack, playCallbackOnCancel, subscription: undefined, id }; this.playSoundEffect(soundPath[fromIndex], fromScreen, false, true, () => { if (this.multipleCancelIds.includes(id)) { this.multipleCancelIds = this.multipleCancelIds.filter(x => x !== id); return; } if (this.playingMultipleAudioData) { if (soundPath[fromIndex + 1] !== undefined) { this.playingMultipleAudioData.subscription = timer(inBetweenTime).subscribe(x => { this.playMultipleSound(soundPath, inBetweenTime, fromIndex + 1, fromScreen, callBack, playCallbackOnCancel, carryId === undefined ? id : carryId); }); } else { this.multipleFinish(); } } }, true); } private isCurrentScreen(askingScreen: ScreenTypeOx) { return this.currentScreen === askingScreen; // return this.screenOx.isShowingScreen(askingScreen); } private addAsLastScreenAudio(sound: AudiOX, duplicateIfIsTheSame: boolean) { this.audios.filter(x => x.askedFor === sound.askedFor).forEach(x => x.audio.mute(true)); this.audios = this.audios.filter(x => x.askedFor !== sound.askedFor || (duplicateIfIsTheSame && sound.audio === x.audio)); this.audios.push(sound); } private addAsLastScreenMusic(musicOx: AudiOX) { this.musics.filter(x => x.askedFor === musicOx.askedFor).forEach(x => x.audio.stop()); this.musics = this.musics.filter(x => x.askedFor !== musicOx.askedFor); this.musics.push(musicOx); } private checkMusicByScreen() { this.musics.forEach(x => { if (this.isCurrentScreen(x.askedFor) && this.musicOn()) { this.playHowl(x); } else { x.audio.pause(); } }); } private checkAudiosByScreen() { this.audios.forEach(x => { x.audio.mute(!this.isCurrentScreen(x.askedFor) || !this.soundOn()); }); } private playHowl(audiOX: AudiOX) { audiOX.audio.play(); } playClick(fromScreen: ScreenTypeOx) { this.playSoundEffect(Constants.clickSoundPath, fromScreen); } playBubble(fromScreen: ScreenTypeOx) { this.playSoundEffect(Constants.bubble, fromScreen); } playWoosh(fromScreen: ScreenTypeOx) { this.playSoundEffect(Constants.woosh, fromScreen); } playRightSound(fromScreen: ScreenTypeOx) { this.playSoundEffect(Constants.correctAnswerSoundPath, fromScreen); } playWrongSound(fromScreen: ScreenTypeOx) { this.playSoundEffect(Constants.wrongAnswerSoundPath, fromScreen); } playGameCompleteSound(fromScreen: ScreenTypeOx) { this.playSoundEffect(Constants.gameCompleteAnswerSoundPath, fromScreen); } playCantClickSound(fromScreen: ScreenTypeOx) { this.playSoundEffect(Constants.cantClickSoundPath, fromScreen); } private checkMultiple(askingScreen: ScreenTypeOx, fromMultiple: boolean) { if (!fromMultiple && this.playingMultipleAudioData !== undefined && this.playingMultipleAudioData.screen === askingScreen) { this.cancelMultiple(); } } private cancelMultiple() { this.multipleCancelIds.push(this.playingMultipleAudioData.id); if (this.playingMultipleAudioData.subscription) { this.playingMultipleAudioData.subscription.unsubscribe(); this.playingMultipleAudioData.subscription = undefined; } if (this.playingMultipleAudioData.playCallbackOnCancel && this.playingMultipleAudioData.callBack) { this.playingMultipleAudioData.callBack(); } this.playingMultipleAudioData = undefined; } private multipleFinish() { if (this.playingMultipleAudioData.subscription) { this.playingMultipleAudioData.subscription.unsubscribe(); this.playingMultipleAudioData.subscription = undefined; } if (this.playingMultipleAudioData.callBack) { this.playingMultipleAudioData.callBack(); } this.playingMultipleAudioData = undefined; } }