Skip to content

Commit

Permalink
feat(player): add setAudioGain method on player
Browse files Browse the repository at this point in the history
  • Loading branch information
mihar-22 committed Mar 28, 2024
1 parent a73a99a commit a4a7778
Show file tree
Hide file tree
Showing 17 changed files with 82 additions and 55 deletions.
2 changes: 1 addition & 1 deletion packages/react/src/components/player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface MediaPlayerProps extends Omit<ReactElementProps<MediaPlayerInst
/**
* The URL or object of the current media resource/s to be considered for playback.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#loading-source}
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#sources}
*/
src?: PlayerSrc;
aspectRatio?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface FullscreenButtonProps
* A button for toggling the fullscreen mode of the player.
*
* @docs {@link https://www.vidstack.io/docs/player/components/buttons/fullscreen-button}
* @see {@link https://www.vidstack.io/docs/player/core-concepts/fullscreen}
* @see {@link https://www.vidstack.io/docs/player/api/fullscreen}
* @example
* ```tsx
* const isActive = useMediaState('fullscreen');
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/components/ui/buttons/pip-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface PIPButtonProps extends ReactElementProps<PIPButtonInstance, HTM
* A button for toggling the picture-in-picture (PIP) mode of the player.
*
* @docs {@link https://www.vidstack.io/docs/player/components/buttons/pip-button}
* @see {@link https://www.vidstack.io/docs/player/core-concepts/picture-in-picture}
* @see {@link https://www.vidstack.io/docs/player/api/picture-in-picture}
* @example
* ```tsx
* const isActive = useMediaState('pictureInPicture');
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/hooks/use-media-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function useMediaState<T extends keyof MediaState>(
/**
* This hook is used to subscribe to the current media state on the nearest parent player.
*
* @docs {@link https://vidstack.io/docs/player/core-concepts/state#reading}
* @docs {@link https://vidstack.io/docs/player/core-concepts/state-management#reading}
*/
export function useMediaStore(
ref?: React.RefObject<MediaPlayerInstance | null>,
Expand Down
6 changes: 5 additions & 1 deletion packages/vidstack/player/styles/default/menus.css
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@
height: var(--size);
}

:where(.vds-menu-item-hint, .vds-menu-open-icon) {
:where(.vds-menu-item-hint, .vds-menu-open-icon, .vds-radio-hint) {
color: var(--text-hint-color);
font-size: var(--media-menu-hint-font-size, 13px);
font-weight: var(--media-menu-hint-font-weight, 400);
Expand Down Expand Up @@ -728,6 +728,10 @@
margin-left: 6px;
}

:where(.vds-radio-hint) {
margin-left: auto;
}

/*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Color Picker
Expand Down
32 changes: 20 additions & 12 deletions packages/vidstack/src/components/player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ export class MediaPlayer
/**
* A list of all `VideoQuality` objects representing the set of available video renditions.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/quality#quality-list}
* @see {@link https://vidstack.io/docs/player/api/video-quality}
*/
@prop
get qualities(): VideoQualityList {
Expand All @@ -444,7 +444,7 @@ export class MediaPlayer
/**
* A list of all `AudioTrack` objects representing the set of available audio tracks.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/audio-tracks}
* @see {@link https://vidstack.io/docs/player/api/audio-tracks}
*/
@prop
get audioTracks(): AudioTrackList {
Expand All @@ -454,7 +454,7 @@ export class MediaPlayer
/**
* A list of all `TextTrack` objects representing the set of available text tracks.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/text-tracks}
* @see {@link https://vidstack.io/docs/player/api/text-tracks}
*/
@prop
get textTracks(): TextTrackList {
Expand All @@ -464,8 +464,6 @@ export class MediaPlayer
/**
* Contains text renderers which are responsible for loading, parsing, and rendering text
* tracks.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/text-tracks#text-renderer}
*/
@prop
get textRenderers(): TextRenderers {
Expand Down Expand Up @@ -661,7 +659,7 @@ export class MediaPlayer
* Attempts to display the player in fullscreen. The promise will resolve if successful, and
* reject if not. This method will throw if any fullscreen API is _not_ currently available.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/fullscreen}
* @see {@link https://vidstack.io/docs/player/api/fullscreen}
*/
@method
async enterFullscreen(target?: MediaFullscreenRequestTarget, trigger?: Event) {
Expand All @@ -672,7 +670,7 @@ export class MediaPlayer
* Attempts to display the player inline by exiting fullscreen. This method will throw if any
* fullscreen API is _not_ currently available.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/fullscreen}
* @see {@link https://vidstack.io/docs/player/api/fullscreen}
*/
@method
async exitFullscreen(target?: MediaFullscreenRequestTarget, trigger?: Event) {
Expand All @@ -684,7 +682,7 @@ export class MediaPlayer
* not supported. This method will also return a `PictureInPictureWindow` if the current
* provider supports it.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/picture-in-picture}
* @see {@link https://vidstack.io/docs/player/api/picture-in-picture}
*/
@method
enterPictureInPicture(trigger?: Event) {
Expand All @@ -695,7 +693,7 @@ export class MediaPlayer
* Attempts to display the player in inline by exiting picture-in-picture mode. This method
* will throw if not supported.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/picture-in-picture}
* @see {@link https://vidstack.io/docs/player/api/picture-in-picture}
*/
@method
exitPictureInPicture(trigger?: Event) {
Expand All @@ -706,7 +704,7 @@ export class MediaPlayer
* Sets the current time to the live edge (i.e., `duration`). This is a no-op for non-live
* streams and will throw if called before media is ready for playback.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/live#live-edge}
* @see {@link https://vidstack.io/docs/player/api/live}
*/
@method
seekToLiveEdge(trigger?: Event): void {
Expand All @@ -717,7 +715,7 @@ export class MediaPlayer
* Called when media can begin loading. Calling this method will trigger the initial provider
* loading process. Calling it more than once has no effect.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#loading-strategies}
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#load-strategies}
*/
@method
startLoading(trigger?: Event): void {
Expand All @@ -727,7 +725,7 @@ export class MediaPlayer
/**
* Called when the poster image can begin loading. Calling it more than once has no effect.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#loading-strategies}
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#load-strategies}
*/
@method
startLoadingPoster(trigger?: Event) {
Expand All @@ -751,6 +749,16 @@ export class MediaPlayer
return this._requestMgr._requestGoogleCast(trigger);
}

/**
* Set the audio gain, amplifying volume and enabling a maximum volume above 100%.
*
* @see {@link https://vidstack.io/docs/player/api/audio-gain}
*/
@method
setAudioGain(gain: number, trigger?: Event) {
return this._requestMgr._setAudioGain(gain, trigger);
}

override destroy() {
this._media.remote.setPlayer(null);
this.dispatch('destroy');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface FullscreenButtonEvents
* @attr data-active - Whether fullscreen mode is active.
* @attr data-supported - Whether fullscreen mode is supported.
* @docs {@link https://www.vidstack.io/docs/player/components/buttons/fullscreen-button}
* @see {@link https://www.vidstack.io/docs/player/core-concepts/fullscreen}
* @see {@link https://www.vidstack.io/docs/player/api/fullscreen}
*/
export class FullscreenButton extends Component<FullscreenButtonProps, {}, FullscreenButtonEvents> {
static props: FullscreenButtonProps = {
Expand Down
2 changes: 1 addition & 1 deletion packages/vidstack/src/components/ui/buttons/pip-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface PIPButtonEvents
* @attr data-active - Whether picture-in-picture mode is active.
* @attr data-supported - Whether picture-in-picture mode is available.
* @docs {@link https://www.vidstack.io/docs/player/components/buttons/pip-button}
* @see {@link https://www.vidstack.io/docs/player/core-concepts/picture-in-picture}
* @see {@link https://www.vidstack.io/docs/player/api/picture-in-picture}
*/
export class PIPButton extends Component<PIPButtonProps, {}, PIPButtonEvents> {
static props: PIPButtonProps = ToggleButtonController.props;
Expand Down
4 changes: 2 additions & 2 deletions packages/vidstack/src/core/api/media-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,15 @@ export interface MediaAutoPlayEvent extends MediaEvent<MediaAutoPlayEventDetail>
* Fired when the player can begin loading the current provider and media. This depends on the
* `load` player prop.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#loading-strategies}
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#load-strategies}
*/
export interface MediaCanLoadEvent extends MediaEvent<void> {}

/**
* Fired when the player can begin loading the poster image. This depends on the `posterLoad`
* player prop.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#loading-strategies}
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#load-strategies}
*/
export interface MediaCanLoadPosterEvent extends MediaEvent<void> {}

Expand Down
6 changes: 3 additions & 3 deletions packages/vidstack/src/core/api/player-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export interface MediaPlayerProps
/**
* The URL and optionally type of the current media resource/s to be considered for playback.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#loading-source}
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#sources}
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/src}
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/srcObject}
*/
Expand All @@ -120,7 +120,7 @@ export interface MediaPlayerProps
* - `custom`: media will wait for the `startLoading()` method or `media-start-loading` event.
* - `play`: media will delay loading until there is a play request.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#loading-strategies}
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#load-strategies}
*/
load: MediaLoadingStrategy;
/**
Expand All @@ -131,7 +131,7 @@ export interface MediaPlayerProps
* - `visible`: poster will delay loading until the provider has entered the viewport.
* - `custom`: poster will wait for the `startLoadingPoster()` method or `media-poster-start-loading` event.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#loading-strategies}
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#load-strategies}
*/
posterLoad: MediaPosterLoadingStrategy;
/**
Expand Down
4 changes: 2 additions & 2 deletions packages/vidstack/src/core/api/player-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,14 +362,14 @@ export interface MediaState {
/**
* Whether media is allowed to begin loading. This depends on the `load` player prop.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#loading-strategies}
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#load-strategies}
*/
canLoad: boolean;
/**
* Whether the media poster is allowed to begin loading. This depends on the `posterLoad`
* player prop.
*
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#loading-strategies}
* @see {@link https://vidstack.io/docs/player/core-concepts/loading#load-strategies}
*/
canLoadPoster: boolean;
/**
Expand Down
4 changes: 2 additions & 2 deletions packages/vidstack/src/core/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ export type MediaViewType = 'unknown' | 'audio' | 'video';
/**
* Indicates the type of strategy that should be used to initiate the loading process.
*
* @docs {@see https://www.vidstack.io/docs/player/core-concepts/loading#loading-strategies}
* @docs {@see https://www.vidstack.io/docs/player/core-concepts/loading#load-strategies}
*/
export type MediaLoadingStrategy = 'eager' | 'idle' | 'visible' | 'custom' | 'play';

/**
* Indicates the type of strategy that should be used to initiate the poster loading process.
*
* @docs {@see https://www.vidstack.io/docs/player/core-concepts/loading#loading-strategies}
* @docs {@see https://www.vidstack.io/docs/player/core-concepts/loading#load-strategies}
*/
export type MediaPosterLoadingStrategy = 'eager' | 'idle' | 'visible' | 'custom';

Expand Down
2 changes: 1 addition & 1 deletion packages/vidstack/src/core/quality/video-quality.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ListSymbol } from '../../foundation/list/symbols';
import { QualitySymbol } from './symbols';

/**
* @see {@link https://vidstack.io/docs/player/core-concepts/quality#quality-list}
* @see {@link https://vidstack.io/docs/player/core-concepts/video-quality#quality-list}
*/
export class VideoQualityList extends SelectList<VideoQuality, VideoQualityListEvents> {
private _auto = false;
Expand Down
31 changes: 23 additions & 8 deletions packages/vidstack/src/core/state/media-request-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,24 @@ export class MediaRequestManager extends MediaPlayerController implements MediaR
}
}

_setAudioGain(gain: number, trigger?: Event) {
const { audioGain, canSetAudioGain } = this.$state;

if (audioGain() === gain) return;

const provider = this._$provider();

if (!provider?.audioGain || !canSetAudioGain()) {
throw Error('[vidstack] audio gain api not available');
}

if (trigger) {
this._request._queue._enqueue('media-audio-gain-change-request', trigger);
}

provider.audioGain.setGain(gain);
}

_seekToLiveEdge(trigger?: Event) {
if (__SERVER__) return;

Expand Down Expand Up @@ -633,14 +651,11 @@ export class MediaRequestManager extends MediaPlayerController implements MediaR
}

['media-audio-gain-change-request'](event: RE.MediaAudioGainChangeRequestEvent) {
const { audioGain, canSetAudioGain } = this.$state;
if (audioGain() === event.detail || !canSetAudioGain()) return;

const provider = this._$provider();
if (!provider?.audioGain) return;

this._request._queue._enqueue('media-audio-gain-change-request', event);
provider.audioGain.setGain(event.detail);
try {
this._setAudioGain(event.detail, event);
} catch (e) {
// no-op
}
}

['media-quality-change-request'](event: RE.MediaQualityChangeRequestEvent) {
Expand Down
Loading

0 comments on commit a4a7778

Please sign in to comment.