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