Add media controls (#229)

This commit is contained in:
Matt Hensman
2022-08-24 02:17:35 +01:00
committed by GitHub
parent cbc039a355
commit ac46802431
37 changed files with 1694 additions and 432 deletions

View File

@@ -19,7 +19,8 @@ import {
MediaStatus,
ReceiverMediaMessage,
SenderMediaMessage,
SenderMessage
SenderMessage,
_MediaCommand
} from "./types";
import { SessionStatus } from "./enums";
@@ -29,16 +30,6 @@ import { MediaCommand } from "./media/enums";
import { LoadRequest, QueueLoadRequest, QueueItem } from "./media/classes";
import Media, { NS_MEDIA } from "./media/Media";
/** supportedMediaCommands bitflag returned in MEDIA_STATUS messages */
enum _MediaCommand {
PAUSE = 1,
SEEK = 2,
STREAM_VOLUME = 4,
STREAM_MUTE = 8,
QUEUE_NEXT = 64,
QUEUE_PREV = 128
}
/**
* Takes a media object and a media status object and merges the status
* with the existing media object, updating it with new properties.

View File

@@ -15,16 +15,6 @@ import {
UserAction
} from "./enums";
export class AudiobookChapterMediaMetadata {
bookTitle?: string;
chapterNumber?: number;
chapterTitle?: string;
images?: Image[];
subtitle?: string;
title?: string;
type = MetadataType.AUDIOBOOK_CHAPTER;
}
export class AudiobookContainerMetadata {
authors?: string[];
narrators?: string[];
@@ -71,7 +61,7 @@ export class BreakStatus {
export class ContainerMetadata {
containerDuration?: number;
containerImages?: Image[];
sections?: MediaMetadata[];
sections?: Metadata[];
title?: string;
constructor(
@@ -88,16 +78,6 @@ export class EditTracksInfoRequest {
) {}
}
export class GenericMediaMetadata {
images?: Image[];
metadataType = MetadataType.GENERIC;
releaseDate?: string;
releaseYear?: number;
subtitle?: string;
title?: string;
type = MetadataType.GENERIC;
}
export class GetStatusRequest {
customData: unknown = null;
}
@@ -129,6 +109,7 @@ export class LoadRequest {
}
export type Metadata =
| AudiobookChapterMediaMetadata
| GenericMediaMetadata
| MovieMediaMetadata
| MusicTrackMediaMetadata
@@ -156,33 +137,60 @@ export class MediaInfo {
constructor(public contentId: string, public contentType: string) {}
}
export class MediaMetadata {
export abstract class MediaMetadata<T extends MetadataType> {
queueItemId?: number;
sectionDuration?: number;
sectionStartAbsoluteTime?: number;
sectionStartTimeInContainer?: number;
sectionStartTimeInMedia?: number;
type: MetadataType;
metadataType: MetadataType;
type: T;
metadataType: T;
constructor(type: MetadataType) {
constructor(type: T) {
this.type = type;
this.metadataType = type;
}
}
export class MovieMediaMetadata {
export class AudiobookChapterMediaMetadata extends MediaMetadata<MetadataType.AUDIOBOOK_CHAPTER> {
bookTitle?: string;
chapterNumber?: number;
chapterTitle?: string;
images?: Image[];
subtitle?: string;
title?: string;
constructor() {
super(MetadataType.AUDIOBOOK_CHAPTER);
}
}
export class GenericMediaMetadata extends MediaMetadata<MetadataType.GENERIC> {
images?: Image[];
releaseDate?: string;
releaseYear?: number;
subtitle?: string;
title?: string;
constructor() {
super(MetadataType.GENERIC);
}
}
export class MovieMediaMetadata extends MediaMetadata<MetadataType.MOVIE> {
images?: Image[];
metadataType = MetadataType.MOVIE;
releaseDate?: string;
releaseYear?: number;
studio?: string;
subtitle?: string;
title?: string;
type = MetadataType.MOVIE;
constructor() {
super(MetadataType.MOVIE);
}
}
export class MusicTrackMediaMetadata {
export class MusicTrackMediaMetadata extends MediaMetadata<MetadataType.MUSIC_TRACK> {
albumArtist?: string;
albumName?: string;
artist?: string;
@@ -190,20 +198,18 @@ export class MusicTrackMediaMetadata {
composer?: string;
discNumber?: number;
images?: Image[];
metadataType = MetadataType.MUSIC_TRACK;
releaseDate?: string;
releaseYear?: number;
songName?: string;
title?: string;
trackNumber?: number;
type = MetadataType.MUSIC_TRACK;
constructor() {
super(MetadataType.MUSIC_TRACK);
}
}
export class PauseRequest {
customData: unknown = null;
}
export class PhotoMediaMetadata {
export class PhotoMediaMetadata extends MediaMetadata<MetadataType.PHOTO> {
artist?: string;
creationDateTime?: string;
height?: number;
@@ -211,10 +217,33 @@ export class PhotoMediaMetadata {
latitude?: number;
location?: string;
longitude?: number;
metadataType = MetadataType.PHOTO;
title?: string;
type = MetadataType.PHOTO;
width?: number;
constructor() {
super(MetadataType.PHOTO);
}
}
export class TvShowMediaMetadata extends MediaMetadata<MetadataType.TV_SHOW> {
episode?: number;
episodeNumber?: number;
episodeTitle?: string;
images?: Image[];
originalAirdate?: string;
releaseYear?: number;
season?: number;
seasonNumber?: number;
seriesTitle?: string;
title?: string;
constructor() {
super(MetadataType.TV_SHOW);
}
}
export class PauseRequest {
customData: unknown = null;
}
export class PlayRequest {
@@ -339,21 +368,6 @@ export class Track {
constructor(public trackId: number, public type: TrackType) {}
}
export class TvShowMediaMetadata {
episode?: number;
episodeNumber?: number;
episodeTitle?: string;
images?: Image[];
metadataType: number = MetadataType.TV_SHOW;
originalAirdate?: string;
releaseYear?: number;
season?: number;
seasonNumber?: number;
seriesTitle?: string;
title?: string;
type = MetadataType.TV_SHOW;
}
export class UserActionState {
customData: unknown = null;

View File

@@ -15,15 +15,17 @@ import {
} from "./media/enums";
export interface MediaStatus {
activeTrackIds?: number[];
currentItemId?: number;
mediaSessionId: number;
media?: MediaInfo;
playbackRate: number;
playerState: PlayerState;
idleReason?: IdleReason;
items?: QueueItem[];
currentTime: number;
currentTime: Nullable<number>;
supportedMediaCommands: number;
repeatMode: RepeatMode;
repeatMode?: RepeatMode;
volume: Volume;
customData: unknown;
}
@@ -66,6 +68,23 @@ export interface CastSessionCreatedDetails extends CastSessionUpdatedDetails {
transportId: string;
}
/** supportedMediaCommands bitflag returned in MEDIA_STATUS messages */
export enum _MediaCommand {
PAUSE = 1,
SEEK = 2,
STREAM_VOLUME = 4,
STREAM_MUTE = 8,
QUEUE_NEXT = 64,
QUEUE_PREV = 128,
QUEUE_SHUFFLE = 256,
QUEUE_SKIP_AD = 512,
QUEUE_REPEAT_ALL = 1024,
QUEUE_REPEAT_ONE = 2048,
QUEUE_REPEAT = 3072,
EDIT_TRACKS = 4096,
PLAYBACK_RATE = 8192
}
interface ReqBase {
requestId: number;
}
@@ -91,77 +110,89 @@ interface MediaReqBase extends ReqBase {
export type SenderMediaMessage =
| (MediaReqBase & { type: "PLAY" })
| (MediaReqBase & { type: "PAUSE" })
| (MediaReqBase & { type: "MEDIA_GET_STATUS" })
| {
type: "MEDIA_GET_STATUS";
mediaSessionId?: number;
customData?: unknown;
requestId: number;
}
| {
type: "GET_STATUS";
mediaSessionId?: number;
customData?: unknown;
requestId: number;
}
| (MediaReqBase & { type: "STOP" })
| (MediaReqBase & { type: "MEDIA_SET_VOLUME"; volume: Partial<Volume> })
| (MediaReqBase & { type: "MEDIA_SET_VOLUME"; volume: Volume })
| (MediaReqBase & { type: "SET_VOLUME"; volume: Volume })
| (MediaReqBase & { type: "SET_PLAYBACK_RATE"; playbackRate: number })
| (ReqBase & {
type: "LOAD";
activeTrackIds: Nullable<number[]>;
activeTrackIds?: Nullable<number[]>;
atvCredentials?: string;
atvCredentialsType?: string;
autoplay: Nullable<boolean>;
currentTime: Nullable<number>;
autoplay?: Nullable<boolean>;
currentTime?: Nullable<number>;
customData?: unknown;
media: MediaInfo;
sessionId: Nullable<string>;
sessionId?: Nullable<string>;
})
| (MediaReqBase & {
type: "SEEK";
resumeState: Nullable<ResumeState>;
currentTime: Nullable<number>;
resumeState?: Nullable<ResumeState>;
currentTime?: Nullable<number>;
})
| (MediaReqBase & {
type: "EDIT_TRACKS_INFO";
activeTrackIds: Nullable<number[]>;
textTrackStyle: Nullable<string>;
activeTrackIds?: Nullable<number[]>;
textTrackStyle?: Nullable<string>;
})
// QueueLoadRequest
| (ReqBase & {
| (MediaReqBase & {
type: "QUEUE_LOAD";
items: QueueItem[];
startIndex: number;
repeatMode: string;
sessionId: Nullable<string>;
sessionId?: Nullable<string>;
})
// QueueInsertItemsRequest
| (MediaReqBase & {
type: "QUEUE_INSERT";
items: QueueItem[];
insertBefore: Nullable<number>;
sessionId: Nullable<string>;
insertBefore?: Nullable<number>;
sessionId?: Nullable<string>;
})
// QueueUpdateItemsRequest
| (MediaReqBase & {
type: "QUEUE_UPDATE";
items: QueueItem[];
sessionId: Nullable<string>;
sessionId?: Nullable<string>;
})
// QueueJumpRequest
| (MediaReqBase & {
type: "QUEUE_UPDATE";
jump: Nullable<number>;
currentItemId: Nullable<number>;
sessionId: Nullable<string>;
jump?: Nullable<number>;
currentItemId?: Nullable<number>;
sessionId?: Nullable<string>;
})
// QueueRemoveItemsRequest
| (MediaReqBase & {
type: "QUEUE_REMOVE";
itemIds: number[];
sessionId: Nullable<string>;
sessionId?: Nullable<string>;
})
// QueueReorderItemsRequest
| (MediaReqBase & {
type: "QUEUE_REORDER";
itemIds: number[];
insertBefore: Nullable<number>;
sessionId: Nullable<string>;
insertBefore?: Nullable<number>;
sessionId?: Nullable<string>;
})
// QueueSetPropertiesRequest
| (MediaReqBase & {
type: "QUEUE_UPDATE";
repeatMode: Nullable<string>;
sessionId: Nullable<string>;
repeatMode?: Nullable<string>;
sessionId?: Nullable<string>;
});
export type ReceiverMediaMessage =