mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-08 08:39:59 +00:00
Add availableMediaTypes bitmask to receiver selector open method
This commit is contained in:
@@ -66,14 +66,43 @@ class ViewController : NSViewController {
|
||||
|
||||
|
||||
self.mediaTypePopUpButton = NSPopUpButton()
|
||||
self.mediaTypePopUpButton.autoenablesItems = false
|
||||
self.mediaTypePopUpButton.addItems(withTitles: [
|
||||
initData.i18n_mediaTypeApp
|
||||
, initData.i18n_mediaTypeTab
|
||||
, initData.i18n_mediaTypeScreen
|
||||
])
|
||||
|
||||
let appItem = self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeApp)!
|
||||
let tabItem = self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeTab)!
|
||||
let screenItem = self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeScreen)!
|
||||
|
||||
// Set tags to enum value
|
||||
appItem.tag = MediaType.app.rawValue
|
||||
tabItem.tag = MediaType.tab.rawValue
|
||||
screenItem.tag = MediaType.screen.rawValue
|
||||
|
||||
if (initData.availableMediaTypes & appItem.tag) == 0 {
|
||||
self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeApp)?
|
||||
.isEnabled = false
|
||||
}
|
||||
if (initData.availableMediaTypes & tabItem.tag) == 0 {
|
||||
self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeTab)?
|
||||
.isEnabled = false
|
||||
}
|
||||
if (initData.availableMediaTypes & screenItem.tag) == 0 {
|
||||
self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeScreen)?
|
||||
.isEnabled = false
|
||||
}
|
||||
|
||||
self.mediaTypePopUpButton.selectItem(
|
||||
at: initData.defaultMediaType.rawValue)
|
||||
withTag: initData.defaultMediaType.rawValue)
|
||||
|
||||
|
||||
let mediaTypeStackView = NSStackView(views: [
|
||||
@@ -140,7 +169,7 @@ extension ViewController : ReceiverViewDelegate {
|
||||
|
||||
do {
|
||||
let mediaType = MediaType(
|
||||
rawValue: self.mediaTypePopUpButton.indexOfSelectedItem)!
|
||||
rawValue: self.mediaTypePopUpButton.selectedItem!.tag)!
|
||||
|
||||
let selection = ReceiverSelection(
|
||||
receiver: receiver
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
struct InitData : Codable {
|
||||
let receivers: [Receiver]
|
||||
let defaultMediaType: MediaType
|
||||
let availableMediaTypes: Int
|
||||
|
||||
let i18n_extensionName: String
|
||||
let i18n_castButtonTitle: String
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
enum MediaType : Int, Codable {
|
||||
case app, tab, screen
|
||||
import Foundation
|
||||
|
||||
|
||||
enum MediaType: Int, Codable {
|
||||
case app = 1
|
||||
case tab = 2
|
||||
case screen = 4
|
||||
}
|
||||
|
||||
3
ext/src/global.d.ts
vendored
3
ext/src/global.d.ts
vendored
@@ -37,7 +37,8 @@ declare interface RTCPeerConnection {
|
||||
}
|
||||
|
||||
declare interface MediaDevices {
|
||||
getDisplayMedia(constraints: MediaStreamConstraints): Promise<MediaStream>;
|
||||
getDisplayMedia (constraints: MediaStreamConstraints)
|
||||
: Promise<MediaStream>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -541,7 +541,7 @@ async function initCreateStatusBridge (opts: Options) {
|
||||
*/
|
||||
function onStatusBridgeDisconnect () {
|
||||
// Notify shims for receiver availability
|
||||
for (const [ , receiver ] of statusBridgeReceivers) {
|
||||
for (const [, receiver ] of statusBridgeReceivers) {
|
||||
for (const [, shim ] of shimMap) {
|
||||
shim.port.postMessage({
|
||||
subject: "shim:/serviceDown"
|
||||
@@ -752,7 +752,8 @@ async function onConnectShim (port: browser.runtime.Port) {
|
||||
case "main:/selectReceiverBegin": {
|
||||
receiverSelector.open(
|
||||
Array.from(statusBridgeReceivers.values())
|
||||
, message.data.defaultMediaType);
|
||||
, message.data.defaultMediaType
|
||||
, message.data.availableMediaTypes);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ export default class NativeMacReceiverSelector
|
||||
|
||||
public async open (
|
||||
receivers: Receiver[]
|
||||
, defaultMediaType: ReceiverSelectorMediaType): Promise<void> {
|
||||
, defaultMediaType: ReceiverSelectorMediaType
|
||||
, availableMediaTypes: ReceiverSelectorMediaType): Promise<void> {
|
||||
|
||||
const applicationName = await options.get("bridgeApplicationName");
|
||||
this.bridgePort = nativeMessaging.connectNative(applicationName);
|
||||
@@ -62,6 +63,7 @@ export default class NativeMacReceiverSelector
|
||||
, data: JSON.stringify({
|
||||
receivers
|
||||
, defaultMediaType
|
||||
, availableMediaTypes
|
||||
|
||||
, i18n_extensionName: _("extensionName")
|
||||
, i18n_castButtonTitle: _("popupCastButtonTitle")
|
||||
|
||||
@@ -17,6 +17,7 @@ export default class PopupReceiverSelector
|
||||
|
||||
private receivers: Receiver[];
|
||||
private defaultMediaType: ReceiverSelectorMediaType;
|
||||
private availableMediaTypes: ReceiverSelectorMediaType;
|
||||
|
||||
private wasReceiverSelected: boolean = false;
|
||||
|
||||
@@ -53,6 +54,7 @@ export default class PopupReceiverSelector
|
||||
, data: {
|
||||
receivers: this.receivers
|
||||
, defaultMediaType: this.defaultMediaType
|
||||
, availableMediaTypes: this.availableMediaTypes
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -61,7 +63,8 @@ export default class PopupReceiverSelector
|
||||
|
||||
public async open (
|
||||
receivers: Receiver[]
|
||||
, defaultMediaType: ReceiverSelectorMediaType): Promise<void> {
|
||||
, defaultMediaType: ReceiverSelectorMediaType
|
||||
, availableMediaTypes: ReceiverSelectorMediaType): Promise<void> {
|
||||
|
||||
// If popup already exists, close it
|
||||
if (this.windowId) {
|
||||
@@ -70,6 +73,7 @@ export default class PopupReceiverSelector
|
||||
|
||||
this.receivers = receivers;
|
||||
this.defaultMediaType = defaultMediaType;
|
||||
this.availableMediaTypes = availableMediaTypes;
|
||||
|
||||
// Current window to base centered position on
|
||||
const openerWindow = await browser.windows.getCurrent();
|
||||
|
||||
@@ -4,9 +4,9 @@ import { Receiver } from "../types";
|
||||
|
||||
|
||||
export enum ReceiverSelectorMediaType {
|
||||
App
|
||||
, Tab
|
||||
, Screen
|
||||
App = 1
|
||||
, Tab = 2
|
||||
, Screen = 4
|
||||
}
|
||||
|
||||
export interface ReceiverSelection {
|
||||
@@ -21,7 +21,8 @@ export type ReceiverSelectorCancelledEvent = CustomEvent;
|
||||
|
||||
export default interface ReceiverSelector extends EventTarget {
|
||||
open (receivers: Receiver[]
|
||||
, defaultMediaType: ReceiverSelectorMediaType): void;
|
||||
, defaultMediaType: ReceiverSelectorMediaType
|
||||
, availableMediaTypes: ReceiverSelectorMediaType): void;
|
||||
|
||||
close (): void;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,21 @@ let peerConnection: RTCPeerConnection;
|
||||
let drawWindowIntervalId: number;
|
||||
|
||||
|
||||
let availableMediaTypes =
|
||||
ReceiverSelectorMediaType.Screen
|
||||
| ReceiverSelectorMediaType.Tab;
|
||||
|
||||
/**
|
||||
* Remove "Screen" option when on an insecure origin as
|
||||
* MediaDevices.getDisplayMedia will not exist (and legacy
|
||||
* MediaDevices.getUserMedia mediaSource constraint will
|
||||
* fail).
|
||||
*/
|
||||
if (typeof navigator.mediaDevices.getDisplayMedia === "undefined") {
|
||||
availableMediaTypes &= ~ReceiverSelectorMediaType.Screen;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a message to the fx_cast app running on the
|
||||
* receiver device.
|
||||
@@ -70,7 +85,6 @@ async function onRequestSessionSuccess (
|
||||
|
||||
switch (newSelectedMedia) {
|
||||
case ReceiverSelectorMediaType.Tab: {
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
@@ -118,7 +132,6 @@ async function onRequestSessionSuccess (
|
||||
}
|
||||
|
||||
case ReceiverSelectorMediaType.Screen: {
|
||||
|
||||
const stream = await navigator.mediaDevices.getDisplayMedia({
|
||||
video: { cursor: "motion" }
|
||||
, audio: false
|
||||
@@ -142,8 +155,11 @@ async function onRequestSessionSuccess (
|
||||
function receiverListener (availability: string) {
|
||||
cast.logMessage("receiverListener");
|
||||
|
||||
if (!wasSessionRequested
|
||||
&& availability === cast.ReceiverAvailability.AVAILABLE) {
|
||||
if (wasSessionRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (availability === cast.ReceiverAvailability.AVAILABLE) {
|
||||
wasSessionRequested = true;
|
||||
cast.requestSession(
|
||||
onRequestSessionSuccess
|
||||
@@ -181,7 +197,8 @@ init().then(async bridgeInfo => {
|
||||
, sessionListener
|
||||
, receiverListener
|
||||
, undefined, undefined
|
||||
, selectedMedia);
|
||||
, selectedMedia
|
||||
, availableMediaTypes);
|
||||
|
||||
cast.initialize(apiConfig
|
||||
, onInitializeSuccess
|
||||
|
||||
@@ -26,7 +26,11 @@ export default class ApiConfig {
|
||||
= DefaultActionPolicy.CREATE_SESSION
|
||||
|
||||
// TODO: Remove awful hack for mirror casting
|
||||
, public _selectedMedia: ReceiverSelectorMediaType
|
||||
= ReceiverSelectorMediaType.App) {
|
||||
, public _defaultMediaType: ReceiverSelectorMediaType
|
||||
= ReceiverSelectorMediaType.App
|
||||
, public _availableMediaTypes: ReceiverSelectorMediaType
|
||||
= ReceiverSelectorMediaType.App
|
||||
| ReceiverSelectorMediaType.Tab
|
||||
| ReceiverSelectorMediaType.Screen) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,8 @@ export function requestSession (
|
||||
sendMessageResponse({
|
||||
subject: "main:/selectReceiverBegin"
|
||||
, data: {
|
||||
defaultMediaType: apiConfig._selectedMedia
|
||||
defaultMediaType: apiConfig._defaultMediaType
|
||||
, availableMediaTypes: apiConfig._availableMediaTypes
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
import { onMessageResponse, sendMessage } from "./eventMessageChannel";
|
||||
import { loadScript } from "../lib/utils";
|
||||
import { onMessageResponse, sendMessage } from "./eventMessageChannel";
|
||||
|
||||
|
||||
const { isFramework }
|
||||
|
||||
@@ -28,6 +28,7 @@ browser.runtime.getPlatformInfo()
|
||||
interface PopupAppState {
|
||||
receivers: Receiver[];
|
||||
mediaType: ReceiverSelectorMediaType;
|
||||
availableMediaTypes: ReceiverSelectorMediaType;
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
@@ -41,6 +42,7 @@ class PopupApp extends Component<{}, PopupAppState> {
|
||||
this.state = {
|
||||
receivers: []
|
||||
, mediaType: ReceiverSelectorMediaType.App
|
||||
, availableMediaTypes: ReceiverSelectorMediaType.App
|
||||
, isLoading: false
|
||||
};
|
||||
|
||||
@@ -64,6 +66,7 @@ class PopupApp extends Component<{}, PopupAppState> {
|
||||
this.setState({
|
||||
receivers: message.data.receivers
|
||||
, mediaType: message.data.defaultMediaType
|
||||
, availableMediaTypes: message.data.availableMediaTypes
|
||||
});
|
||||
|
||||
break;
|
||||
@@ -90,10 +93,6 @@ class PopupApp extends Component<{}, PopupAppState> {
|
||||
}
|
||||
|
||||
public render () {
|
||||
const shareMedia =
|
||||
this.state.mediaType === ReceiverSelectorMediaType.Tab
|
||||
|| this.state.mediaType === ReceiverSelectorMediaType.Screen;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="media-select">
|
||||
@@ -102,15 +101,18 @@ class PopupApp extends Component<{}, PopupAppState> {
|
||||
onChange={ this.onSelectChange }
|
||||
className="media-select-dropdown">
|
||||
<option value={ ReceiverSelectorMediaType.App }
|
||||
disabled={ shareMedia }>
|
||||
disabled={ !(this.state.availableMediaTypes
|
||||
& ReceiverSelectorMediaType.App) }>
|
||||
{ _("popupMediaTypeApp") }
|
||||
</option>
|
||||
<option value={ ReceiverSelectorMediaType.Tab }
|
||||
disabled={ !shareMedia }>
|
||||
disabled={ !(this.state.availableMediaTypes
|
||||
& ReceiverSelectorMediaType.Tab) }>
|
||||
{ _("popupMediaTypeTab") }
|
||||
</option>
|
||||
<option value={ ReceiverSelectorMediaType.Screen }
|
||||
disabled={ !shareMedia }>
|
||||
disabled={ !(this.state.availableMediaTypes
|
||||
& ReceiverSelectorMediaType.Screen) }>
|
||||
{ _("popupMediaTypeScreen") }
|
||||
</option>
|
||||
</select>
|
||||
|
||||
@@ -2,4 +2,7 @@
|
||||
"extends": [
|
||||
"../common/tslint.json"
|
||||
]
|
||||
, "rules": {
|
||||
"no-bitwise": false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user