From cb1c24186eb02c4d944fd332255d9e1fe4492bf5 Mon Sep 17 00:00:00 2001 From: jojohoch <joachim.hoch@iqb.hu-berlin.de> Date: Wed, 17 Nov 2021 09:18:30 +0100 Subject: [PATCH] [player] Play audios and videos depending on others --- .../element-components/audio.component.ts | 2 ++ .../control-bar/control-bar.component.html | 10 ++++----- .../control-bar/control-bar.component.ts | 22 +++++++++++++++---- .../element-components/video.component.ts | 2 ++ ...edia-player-element-component.directive.ts | 6 +++++ .../element-container.component.ts | 19 ++++++++++++---- .../src/app/services/media-player.service.ts | 15 ++++++++----- 7 files changed, 58 insertions(+), 18 deletions(-) diff --git a/projects/common/element-components/audio.component.ts b/projects/common/element-components/audio.component.ts index 93147b3a3..1d90d57f9 100644 --- a/projects/common/element-components/audio.component.ts +++ b/projects/common/element-components/audio.component.ts @@ -17,6 +17,8 @@ import { MediaPlayerElementComponent } from '../media-player-element-component.d [project]="project" [elementModel]="elementModel" [active]="active" + [dependencyDissolved]="dependencyDissolved" + (onMediaValidStatusChanged)="onMediaValidStatusChanged.emit($event)" (elementValueChanged)="elementValueChanged.emit($event)"> </app-control-bar> </div> diff --git a/projects/common/element-components/control-bar/control-bar.component.html b/projects/common/element-components/control-bar/control-bar.component.html index 89fc247b8..871462c72 100644 --- a/projects/common/element-components/control-bar/control-bar.component.html +++ b/projects/common/element-components/control-bar/control-bar.component.html @@ -4,9 +4,9 @@ <button *ngIf="!playing || !elementModel.pauseControl" mat-button class="control-button" - [class.enabled-control]="!disabled && active" + [class.enabled-control]="!disabled && active && dependencyDissolved" [class.active-control]="playing" - [disabled]="disabled || !active" + [disabled]="disabled || !active || !dependencyDissolved" (click)="play($event)"> <mat-icon>play_arrow</mat-icon> </button> @@ -15,9 +15,9 @@ <button *ngIf="playing" mat-button class="control-button" - [class.enabled-control]="!disabled && active" + [class.enabled-control]="!disabled && active && dependencyDissolved" [class.active-control]="pausing" - [disabled]="disabled || !active" + [disabled]="disabled || !active || !dependencyDissolved" (click)="pause($event)"> <mat-icon>pause</mat-icon> </button> @@ -33,7 +33,7 @@ step="1" [max]="player.duration" [value]="player.currentTime" - [disabled]="disabled || !elementModel.interactiveProgressbar || !active" + [disabled]="disabled || !elementModel.interactiveProgressbar || !active || !dependencyDissolved" (input)="onTimeChange($event)"> </mat-slider> </ng-container> diff --git a/projects/common/element-components/control-bar/control-bar.component.ts b/projects/common/element-components/control-bar/control-bar.component.ts index 5dc5dce8d..50c752a47 100644 --- a/projects/common/element-components/control-bar/control-bar.component.ts +++ b/projects/common/element-components/control-bar/control-bar.component.ts @@ -16,7 +16,10 @@ export class ControlBarComponent implements OnInit, OnChanges, OnDestroy { @Input() elementModel!: AudioElement | VideoElement; @Input() project!: 'player' | 'editor'; @Input() active!: boolean; + @Input() dependencyDissolved!: boolean; @Output() elementValueChanged = new EventEmitter<ValueChangeElement>(); + @Output() onMediaValidStatusChanged = new EventEmitter<string>(); + duration!: number; currentTime!: number; currentRestTime!: number; @@ -29,15 +32,15 @@ export class ControlBarComponent implements OnInit, OnChanges, OnDestroy { showHint!: boolean; disabled!: boolean; playbackTime!: number; + valid!: boolean; // TODO: // uninterruptible: boolean; // false kein Blättern; starten eines anderen Videos; .... // hideOtherPages: boolean; // false (Solange nicht vollständig gespielt, sind alle anderen Seiten verborgen) - // activeAfterID: string; // '' (andere Audio-id; Audio ist deaktiviert, solange anderes nicht vollständig abgespielt) // minRuns: number; // 1 ngOnInit(): void { - // Firefox has problems to get the duration + this.dependencyDissolved = !this.elementModel.activeAfterID; this.player.ondurationchange = () => this.initTimeValues(); this.player.ontimeupdate = () => { this.currentTime = this.player.currentTime / 60; @@ -55,12 +58,13 @@ export class ControlBarComponent implements OnInit, OnChanges, OnDestroy { this.showHint = false; }; this.player.onended = () => { - if (!this.checkStatus(this.runCounter + 1)) { + if (!this.checkDisabledState(this.runCounter + 1)) { this.runCounter += 1; if (this.elementModel.loop) { this._play(); } } + this.checkValidState(this.runCounter); }; this.player.onvolumechange = () => { this.player.muted = !this.player.volume; @@ -113,7 +117,15 @@ export class ControlBarComponent implements OnInit, OnChanges, OnDestroy { event.preventDefault(); } - private checkStatus(runCounter: number): boolean { + private checkValidState(runCounter: number): boolean { + this.valid = this.elementModel.minRuns === 0 ? true : runCounter >= this.elementModel.minRuns; + if (this.valid) { + this.onMediaValidStatusChanged.emit(this.elementModel.id); + } + return this.valid; + } + + private checkDisabledState(runCounter: number): boolean { this.disabled = !this.elementModel.maxRuns ? false : this.elementModel.maxRuns <= runCounter; return this.disabled; } @@ -167,6 +179,8 @@ export class ControlBarComponent implements OnInit, OnChanges, OnDestroy { this.currentRestTime = (this.player.duration - this.player.currentTime) / 60; this.runCounter = Math.floor(this.elementModel.playbackTime); this.player.currentTime = (this.elementModel.playbackTime - this.runCounter) * this.player.duration; + this.checkDisabledState(this.runCounter); + this.checkValidState(this.runCounter); } else { this.duration = 0; this.runCounter = 0; diff --git a/projects/common/element-components/video.component.ts b/projects/common/element-components/video.component.ts index 68b51dd8d..04edb4f0c 100644 --- a/projects/common/element-components/video.component.ts +++ b/projects/common/element-components/video.component.ts @@ -18,6 +18,8 @@ import { MediaPlayerElementComponent } from '../media-player-element-component.d [player]="player" [project]="project" [elementModel]="elementModel" + [dependencyDissolved]="dependencyDissolved" + (onMediaValidStatusChanged)="onMediaValidStatusChanged.emit($event)" (elementValueChanged)="elementValueChanged.emit($event)"> </app-control-bar> </div> diff --git a/projects/common/media-player-element-component.directive.ts b/projects/common/media-player-element-component.directive.ts index fc4201f8b..fa698c833 100644 --- a/projects/common/media-player-element-component.directive.ts +++ b/projects/common/media-player-element-component.directive.ts @@ -6,10 +6,16 @@ import { ElementComponent } from './element-component.directive'; export abstract class MediaPlayerElementComponent extends ElementComponent { @Output() elementValueChanged = new EventEmitter<ValueChangeElement>(); @Output() onMediaPlayStatusChanged = new EventEmitter<string | null>(); + @Output() onMediaValidStatusChanged = new EventEmitter<string>(); active: boolean = true; + dependencyDissolved!: boolean; setActualPlayingMediaId(id: string | null): void { this.active = !id || id === this.elementModel.id; } + + setActivatedAfterID(): void { + this.dependencyDissolved = true; + } } diff --git a/projects/player/src/app/components/element-container/element-container.component.ts b/projects/player/src/app/components/element-container/element-container.component.ts index dde763d43..98fcfcf3d 100644 --- a/projects/player/src/app/components/element-container/element-container.component.ts +++ b/projects/player/src/app/components/element-container/element-container.component.ts @@ -66,11 +66,12 @@ export class ElementContainerComponent implements OnInit { } else if (elementComponent instanceof CompoundElementComponent) { this.initCompoundElement(elementComponent); } else if (elementComponent instanceof MediaPlayerElementComponent) { - this.mediaPlayerService.registerMediaElement(elementComponent); + this.mediaPlayerService.registerMediaElement(elementComponent, this.elementModel.activeAfterID as string); } this.subscribeStartSelection(elementComponent); this.subscribeApplySelection(elementComponent); - this.subscribeMediaStatusChanged(elementComponent); + this.subscribeMediaPlayStatusChanged(elementComponent); + this.subscribeMediaValidStatusChanged(elementComponent); this.subscribeNavigationRequested(elementComponent); this.subscribeElementValueChanged(elementComponent); this.subscribeForKeyboardEvents(elementComponent); @@ -167,12 +168,22 @@ export class ElementContainerComponent implements OnInit { } } - private subscribeMediaStatusChanged(elementComponent: any): void { + private subscribeMediaPlayStatusChanged(elementComponent: any): void { if (elementComponent.onMediaPlayStatusChanged) { elementComponent.onMediaPlayStatusChanged .pipe(takeUntil(this.ngUnsubscribe)) .subscribe((playStatus: string | null) => { - this.mediaPlayerService.broadCastPlayChanges(playStatus); + this.mediaPlayerService.broadcastPlayStatusChanged(playStatus); + }); + } + } + + private subscribeMediaValidStatusChanged(elementComponent: any): void { + if (elementComponent.onMediaValidStatusChanged) { + elementComponent.onMediaValidStatusChanged + .pipe(takeUntil(this.ngUnsubscribe)) + .subscribe((validId: string) => { + this.mediaPlayerService.broadcastValidStatusChanged(validId); }); } } diff --git a/projects/player/src/app/services/media-player.service.ts b/projects/player/src/app/services/media-player.service.ts index ff0df1433..a1da319d2 100644 --- a/projects/player/src/app/services/media-player.service.ts +++ b/projects/player/src/app/services/media-player.service.ts @@ -5,13 +5,18 @@ import { MediaPlayerElementComponent } from '../../../../common/media-player-ele providedIn: 'root' }) export class MediaPlayerService { - mediaElements: MediaPlayerElementComponent[] = []; + mediaElements: { mediaElement: MediaPlayerElementComponent; dependOn: string }[] = []; - registerMediaElement(mediaElement: MediaPlayerElementComponent): void { - this.mediaElements.push(mediaElement); + registerMediaElement(mediaElement: MediaPlayerElementComponent, dependOn: string): void { + this.mediaElements.push({ mediaElement, dependOn }); } - broadCastPlayChanges(actualId: string | null): void { - this.mediaElements.forEach(mediaElement => mediaElement.setActualPlayingMediaId(actualId)); + broadcastPlayStatusChanged(actualId: string | null): void { + this.mediaElements.forEach(mediaElement => mediaElement.mediaElement.setActualPlayingMediaId(actualId)); + } + + broadcastValidStatusChanged(validId: string): void { + const validMediaElements = this.mediaElements.filter(mediaElement => mediaElement.dependOn === validId); + validMediaElements.forEach(mediaElement => mediaElement.mediaElement.setActivatedAfterID()); } } -- GitLab