Fix app and media type detection for non-app triggered receiver selector

This commit is contained in:
hensm
2022-09-01 13:43:59 +01:00
parent 314a1d2031
commit 78e936195c
4 changed files with 74 additions and 25 deletions

View File

@@ -20,6 +20,7 @@ import {
import type { ApiConfig } from "../cast/sdk/classes";
import { ReceiverAction } from "../cast/sdk/enums";
import { DEFAULT_MEDIA_RECEIVER_APP_ID } from "../cast/sdk/media";
import { createReceiver } from "../cast/utils";
import deviceManager from "./deviceManager";
@@ -301,10 +302,10 @@ const castManager = new (class {
if (
receiverSelector?.isOpen &&
// If selector context is the same as the instance context
receiverSelector.pageInfo?.tabId ===
instance.contentContext?.tabId &&
receiverSelector.pageInfo?.frameId ===
instance.contentContext?.frameId &&
isSameContext(
receiverSelector.pageInfo,
instance.contentContext
) &&
// If selector is supposed to close
(await options.get("receiverSelectorWaitForConnection"))
) {
@@ -566,17 +567,48 @@ async function getReceiverSelection(selectionOpts: {
let availableMediaTypes = ReceiverSelectorMediaType.None;
// Default frame ID
if (!selectionOpts.frameId) selectionOpts.frameId = 0;
if (selectionOpts.frameId === undefined) selectionOpts.frameId = 0;
// Fallback to instance context
if (!selectionOpts.tabId && selectionOpts.castInstance?.contentContext) {
if (
selectionOpts.tabId === undefined &&
selectionOpts.castInstance?.contentContext
) {
selectionOpts.tabId = selectionOpts.castInstance.contentContext.tabId;
selectionOpts.frameId =
selectionOpts.castInstance.contentContext.frameId;
}
const opts = await options.getAll();
/**
* If context supplied, but no instance, check for an instance at
* that context.
*/
if (
!selectionOpts.castInstance &&
selectionOpts.tabId !== undefined &&
selectionOpts.frameId !== undefined
) {
const contextInstance = castManager.getInstanceAt(
selectionOpts.tabId,
selectionOpts.frameId
);
/**
* If the app in that context is the extension mirroring app or
* the default receiver, just ignore it.
*/
const contextAppId = contextInstance?.apiConfig?.sessionRequest.appId;
if (
contextAppId !== opts.mirroringAppId &&
contextAppId !== DEFAULT_MEDIA_RECEIVER_APP_ID
) {
selectionOpts.castInstance = contextInstance;
}
}
let pageInfo: Optional<ReceiverSelectorPageInfo>;
if (selectionOpts.tabId) {
if (selectionOpts.tabId !== undefined) {
try {
pageInfo = {
tabId: selectionOpts.tabId,
@@ -603,8 +635,6 @@ async function getReceiverSelection(selectionOpts: {
availableMediaTypes |= ReceiverSelectorMediaType.App;
}
const opts = await options.getAll();
// Disable mirroring media types if mirroring is not enabled
if (!opts.mirroringEnabled) {
availableMediaTypes &= ~(

View File

@@ -5,10 +5,10 @@ import type { Message } from "../../messaging";
// Cast types
import { Capability, ReceiverAvailability } from "../sdk/enums";
import { Media, PlayerState } from "../sdk/media";
import type Session from "../sdk/Session";
import cast, { ensureInit, CastPort } from "../export";
import { Media, PlayerState } from "../sdk/media";
const logger = new Logger("fx_cast [media sender]");

View File

@@ -5,9 +5,10 @@ import { Logger } from "../../lib/logger";
import { ReceiverDevice, ReceiverSelectorMediaType } from "../../types";
import type Session from "../sdk/Session";
import cast, { ensureInit } from "../export";
import type { ReceiverAvailability } from "../sdk/enums";
import type Session from "../sdk/Session";
import cast, { ensureInit } from "../export";
const logger = new Logger("fx_cast [mirroring sender]");
@@ -49,7 +50,7 @@ class MirroringSender {
private async init() {
try {
ensureInit({
await ensureInit({
contextTabId: this.contextTabId,
receiverDevice: this.receiverDevice
});

View File

@@ -67,19 +67,37 @@
* Checks if device is compatible with the requested app and
* capabilities.
*/
function isDeviceCompatible(device: ReceiverDevice) {
// If device is audio-only, check app's audio support flag
if (
!(device.capabilities & ReceiverDeviceCapabilities.VIDEO_OUT) &&
appInfo?.isRequestAppAudioCompatible === false
) {
return false;
function isDeviceCompatible(
mediaType: ReceiverSelectorMediaType,
device: ReceiverDevice
) {
switch (mediaType) {
case ReceiverSelectorMediaType.App:
// If device is audio-only, check app's audio support flag
if (
!(
device.capabilities &
ReceiverDeviceCapabilities.VIDEO_OUT
) &&
appInfo?.isRequestAppAudioCompatible === false
) {
return false;
}
return hasRequiredCapabilities(
device,
appInfo?.sessionRequest?.capabilities
);
/** Mirroring requires video output capability. */
case ReceiverSelectorMediaType.Tab:
case ReceiverSelectorMediaType.Screen:
return !!(
device.capabilities & ReceiverDeviceCapabilities.VIDEO_OUT
);
}
return hasRequiredCapabilities(
device,
appInfo?.sessionRequest?.capabilities
);
return false;
}
let port: Nullable<Port> = null;
@@ -365,7 +383,7 @@
{isMediaTypeAvailable}
isAnyMediaTypeAvailable={availableMediaTypes !==
ReceiverSelectorMediaType.None &&
isDeviceCompatible(device)}
isDeviceCompatible(mediaType, device)}
isAnyConnecting={isConnecting}
bind:lastMenuShownDeviceId
on:cast={ev => onReceiverCast(ev.detail.device)}