Skip to content

Commit c07fe8f

Browse files
committedDec 12, 2016
Initial commit
0 parents  commit c07fe8f

15 files changed

+622
-0
lines changed
 

‎.eslintignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# The build artifacts of the jitsi-meet project.
2+
build/*
3+
4+
# ESLint will by default ignore its own configuration file. However, there does
5+
# not seem to be a reason why we will want to risk being inconsistent with our
6+
# remaining JavaScript source code.
7+
!.eslintrc.js

‎.eslintrc.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
module.exports = {
2+
'env': {
3+
'browser': true,
4+
'commonjs': true,
5+
'es6': true
6+
},
7+
'extends': 'eslint:recommended',
8+
'globals': {
9+
// The globals that (1) are accessed but not defined within many of our
10+
// files, (2) are certainly defined, and (3) we would like to use
11+
// without explicitly specifying them (using a comment) inside of our
12+
// files.
13+
'__filename': false
14+
},
15+
'parserOptions': {
16+
'ecmaFeatures': {
17+
'experimentalObjectRestSpread': true
18+
},
19+
'sourceType': 'module'
20+
},
21+
'rules': {
22+
'new-cap': [
23+
'error',
24+
{
25+
'capIsNew': false // Behave like JSHint's newcap.
26+
}
27+
],
28+
// While it is considered a best practice to avoid using methods on
29+
// console in JavaScript that is designed to be executed in the browser
30+
// and ESLint includes the rule among its set of recommended rules, (1)
31+
// the general practice is to strip such calls before pushing to
32+
// production and (2) we prefer to utilize console in lib-jitsi-meet
33+
// (and jitsi-meet).
34+
'no-console': 'off',
35+
'semi': 'error'
36+
}
37+
};

‎.gitignore

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
*.swp
2+
.*.tmp
3+
.remote-sync.json
4+
.sync-config.cson
5+
.electron-gyp
6+
.npmrc
7+
8+
.DS_Store
9+
10+
# node.js
11+
#
12+
node_modules/
13+
npm-debug.log

‎.jshintignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

‎.jshintrc

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"node": true,
3+
4+
"curly": true,
5+
"latedef": true,
6+
"quotmark": true,
7+
"undef": true,
8+
"unused": true,
9+
"trailing": true
10+
}

‎LICENSE

+202
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
Apache License
2+
Version 2.0, January 2004
3+
http://www.apache.org/licenses/
4+
5+
6+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7+
8+
1. Definitions.
9+
10+
"License" shall mean the terms and conditions for use, reproduction,
11+
and distribution as defined by Sections 1 through 9 of this document.
12+
13+
"Licensor" shall mean the copyright owner or entity authorized by
14+
the copyright owner that is granting the License.
15+
16+
"Legal Entity" shall mean the union of the acting entity and all
17+
other entities that control, are controlled by, or are under common
18+
control with that entity. For the purposes of this definition,
19+
"control" means (i) the power, direct or indirect, to cause the
20+
direction or management of such entity, whether by contract or
21+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
22+
outstanding shares, or (iii) beneficial ownership of such entity.
23+
24+
"You" (or "Your") shall mean an individual or Legal Entity
25+
exercising permissions granted by this License.
26+
27+
"Source" form shall mean the preferred form for making modifications,
28+
including but not limited to software source code, documentation
29+
source, and configuration files.
30+
31+
"Object" form shall mean any form resulting from mechanical
32+
transformation or translation of a Source form, including but
33+
not limited to compiled object code, generated documentation,
34+
and conversions to other media types.
35+
36+
"Work" shall mean the work of authorship, whether in Source or
37+
Object form, made available under the License, as indicated by a
38+
copyright notice that is included in or attached to the work
39+
(an example is provided in the Appendix below).
40+
41+
"Derivative Works" shall mean any work, whether in Source or Object
42+
form, that is based on (or derived from) the Work and for which the
43+
editorial revisions, annotations, elaborations, or other modifications
44+
represent, as a whole, an original work of authorship. For the purposes
45+
of this License, Derivative Works shall not include works that remain
46+
separable from, or merely link (or bind by name) to the interfaces of,
47+
the Work and Derivative Works thereof.
48+
49+
"Contribution" shall mean any work of authorship, including
50+
the original version of the Work and any modifications or additions
51+
to that Work or Derivative Works thereof, that is intentionally
52+
submitted to Licensor for inclusion in the Work by the copyright owner
53+
or by an individual or Legal Entity authorized to submit on behalf of
54+
the copyright owner. For the purposes of this definition, "submitted"
55+
means any form of electronic, verbal, or written communication sent
56+
to the Licensor or its representatives, including but not limited to
57+
communication on electronic mailing lists, source code control systems,
58+
and issue tracking systems that are managed by, or on behalf of, the
59+
Licensor for the purpose of discussing and improving the Work, but
60+
excluding communication that is conspicuously marked or otherwise
61+
designated in writing by the copyright owner as "Not a Contribution."
62+
63+
"Contributor" shall mean Licensor and any individual or Legal Entity
64+
on behalf of whom a Contribution has been received by Licensor and
65+
subsequently incorporated within the Work.
66+
67+
2. Grant of Copyright License. Subject to the terms and conditions of
68+
this License, each Contributor hereby grants to You a perpetual,
69+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70+
copyright license to reproduce, prepare Derivative Works of,
71+
publicly display, publicly perform, sublicense, and distribute the
72+
Work and such Derivative Works in Source or Object form.
73+
74+
3. Grant of Patent License. Subject to the terms and conditions of
75+
this License, each Contributor hereby grants to You a perpetual,
76+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77+
(except as stated in this section) patent license to make, have made,
78+
use, offer to sell, sell, import, and otherwise transfer the Work,
79+
where such license applies only to those patent claims licensable
80+
by such Contributor that are necessarily infringed by their
81+
Contribution(s) alone or by combination of their Contribution(s)
82+
with the Work to which such Contribution(s) was submitted. If You
83+
institute patent litigation against any entity (including a
84+
cross-claim or counterclaim in a lawsuit) alleging that the Work
85+
or a Contribution incorporated within the Work constitutes direct
86+
or contributory patent infringement, then any patent licenses
87+
granted to You under this License for that Work shall terminate
88+
as of the date such litigation is filed.
89+
90+
4. Redistribution. You may reproduce and distribute copies of the
91+
Work or Derivative Works thereof in any medium, with or without
92+
modifications, and in Source or Object form, provided that You
93+
meet the following conditions:
94+
95+
(a) You must give any other recipients of the Work or
96+
Derivative Works a copy of this License; and
97+
98+
(b) You must cause any modified files to carry prominent notices
99+
stating that You changed the files; and
100+
101+
(c) You must retain, in the Source form of any Derivative Works
102+
that You distribute, all copyright, patent, trademark, and
103+
attribution notices from the Source form of the Work,
104+
excluding those notices that do not pertain to any part of
105+
the Derivative Works; and
106+
107+
(d) If the Work includes a "NOTICE" text file as part of its
108+
distribution, then any Derivative Works that You distribute must
109+
include a readable copy of the attribution notices contained
110+
within such NOTICE file, excluding those notices that do not
111+
pertain to any part of the Derivative Works, in at least one
112+
of the following places: within a NOTICE text file distributed
113+
as part of the Derivative Works; within the Source form or
114+
documentation, if provided along with the Derivative Works; or,
115+
within a display generated by the Derivative Works, if and
116+
wherever such third-party notices normally appear. The contents
117+
of the NOTICE file are for informational purposes only and
118+
do not modify the License. You may add Your own attribution
119+
notices within Derivative Works that You distribute, alongside
120+
or as an addendum to the NOTICE text from the Work, provided
121+
that such additional attribution notices cannot be construed
122+
as modifying the License.
123+
124+
You may add Your own copyright statement to Your modifications and
125+
may provide additional or different license terms and conditions
126+
for use, reproduction, or distribution of Your modifications, or
127+
for any such Derivative Works as a whole, provided Your use,
128+
reproduction, and distribution of the Work otherwise complies with
129+
the conditions stated in this License.
130+
131+
5. Submission of Contributions. Unless You explicitly state otherwise,
132+
any Contribution intentionally submitted for inclusion in the Work
133+
by You to the Licensor shall be under the terms and conditions of
134+
this License, without any additional terms or conditions.
135+
Notwithstanding the above, nothing herein shall supersede or modify
136+
the terms of any separate license agreement you may have executed
137+
with Licensor regarding such Contributions.
138+
139+
6. Trademarks. This License does not grant permission to use the trade
140+
names, trademarks, service marks, or product names of the Licensor,
141+
except as required for reasonable and customary use in describing the
142+
origin of the Work and reproducing the content of the NOTICE file.
143+
144+
7. Disclaimer of Warranty. Unless required by applicable law or
145+
agreed to in writing, Licensor provides the Work (and each
146+
Contributor provides its Contributions) on an "AS IS" BASIS,
147+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148+
implied, including, without limitation, any warranties or conditions
149+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150+
PARTICULAR PURPOSE. You are solely responsible for determining the
151+
appropriateness of using or redistributing the Work and assume any
152+
risks associated with Your exercise of permissions under this License.
153+
154+
8. Limitation of Liability. In no event and under no legal theory,
155+
whether in tort (including negligence), contract, or otherwise,
156+
unless required by applicable law (such as deliberate and grossly
157+
negligent acts) or agreed to in writing, shall any Contributor be
158+
liable to You for damages, including any direct, indirect, special,
159+
incidental, or consequential damages of any character arising as a
160+
result of this License or out of the use or inability to use the
161+
Work (including but not limited to damages for loss of goodwill,
162+
work stoppage, computer failure or malfunction, or any and all
163+
other commercial damages or losses), even if such Contributor
164+
has been advised of the possibility of such damages.
165+
166+
9. Accepting Warranty or Additional Liability. While redistributing
167+
the Work or Derivative Works thereof, You may choose to offer,
168+
and charge a fee for, acceptance of support, warranty, indemnity,
169+
or other liability obligations and/or rights consistent with this
170+
License. However, in accepting such obligations, You may act only
171+
on Your own behalf and on Your sole responsibility, not on behalf
172+
of any other Contributor, and only if You agree to indemnify,
173+
defend, and hold each Contributor harmless for any liability
174+
incurred by, or claims asserted against, such Contributor by reason
175+
of your accepting any such warranty or additional liability.
176+
177+
END OF TERMS AND CONDITIONS
178+
179+
APPENDIX: How to apply the Apache License to your work.
180+
181+
To apply the Apache License to your work, attach the following
182+
boilerplate notice, with the fields enclosed by brackets "[]"
183+
replaced with your own identifying information. (Don't include
184+
the brackets!) The text should be enclosed in the appropriate
185+
comment syntax for the file format. We also recommend that a
186+
file or class name and description of purpose be included on the
187+
same "printed page" as the copyright notice for easier
188+
identification within third-party archives.
189+
190+
Copyright [yyyy] [name of copyright owner]
191+
192+
Licensed under the Apache License, Version 2.0 (the "License");
193+
you may not use this file except in compliance with the License.
194+
You may obtain a copy of the License at
195+
196+
http://www.apache.org/licenses/LICENSE-2.0
197+
198+
Unless required by applicable law or agreed to in writing, software
199+
distributed under the License is distributed on an "AS IS" BASIS,
200+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201+
See the License for the specific language governing permissions and
202+
limitations under the License.

‎README.md

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Jitsi Meet Electron
2+
====
3+
Electron application for [Jitsi Meet](https://github.com/jitsi/jitsi-meet).
4+
5+
## Configuration
6+
You can change the Jitsi Meet deployment url with the jitsiMeetURL property
7+
from config.js
8+
9+
## Building the sources
10+
```bash
11+
npm run build
12+
```
13+
14+
## Statring the application
15+
```bash
16+
npm start
17+
```
18+
19+
## Discuss
20+
Please use the [Jitsi dev mailing list](http://lists.jitsi.org/pipermail/dev/) to discuss feature requests before opening an issue on Github.

‎config.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
jitsiMeetURL: "https://hristo.jitsi.net/"
3+
};

‎electron_npm_rebuild

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Electron's version.
2+
export npm_config_target=1.4.7
3+
# The architecture of Electron, can be ia32 or x64.
4+
export npm_config_arch=x64
5+
export npm_config_target_arch=x64
6+
# Download headers for Electron.
7+
export npm_config_disturl=https://atom.io/download/electron
8+
# Tell node-pre-gyp that we are building for Electron.
9+
export npm_config_runtime=electron
10+
# Tell node-pre-gyp to build module from source code.
11+
export npm_config_build_from_source=true
12+
13+
14+
HOME=./.electron-gyp npm install

‎main.js

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//Electron includes
2+
const electron = require("electron");
3+
const APP = electron.app;
4+
const BrowserWindow = electron.BrowserWindow;
5+
6+
const path = require("path");
7+
const url = require("url");
8+
9+
/**
10+
* URL for index.html which will be our entry point.
11+
*/
12+
const indexURL = url.format({
13+
pathname: path.join(__dirname, "windows", "jitsi-meet", "index.html"),
14+
protocol: "file:",
15+
slashes: true
16+
});
17+
18+
/**
19+
* The window object that will load the iframe with Jitsi Meet.
20+
* IMPORTANT: Must be defined as global in order to not be garbage collected
21+
* acidentally.
22+
*/
23+
let jitsiMeetWindow = null;
24+
25+
/**
26+
* Sets the APP object listeners.
27+
*/
28+
function setAPPListeners () {
29+
APP.on("ready", createJitsiMeetWindow);
30+
APP.on("window-all-closed", () => {
31+
// Don"t quit the application for Mac OS
32+
if (process.platform !== "darwin") {
33+
APP.quit();
34+
}
35+
});
36+
APP.on("activate", () => {
37+
if (jitsiMeetWindow === null) {
38+
createJitsiMeetWindow();
39+
}
40+
});
41+
}
42+
43+
/**
44+
* Opens new window with index.html(Jitsi Meet is loaded in iframe there).
45+
*/
46+
function createJitsiMeetWindow () {
47+
jitsiMeetWindow = new BrowserWindow({width: 800, height: 600});
48+
jitsiMeetWindow.loadURL(indexURL);
49+
50+
jitsiMeetWindow.on("closed", () => {
51+
jitsiMeetWindow = null;
52+
});
53+
}
54+
55+
//Start the application:
56+
setAPPListeners();

‎modules/remotecontrol/index.js

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
let robot = require("robotjs");
2+
3+
/**
4+
* Attaching to the window for debug purposes.
5+
* We should remove this in production.
6+
*/
7+
window.robot = robot;
8+
9+
/**
10+
* Width/Heught for the screen.
11+
*/
12+
const {width, height} = robot.getScreenSize();
13+
14+
/**
15+
* Mouse button mapping between the values in remote-control-event and robotjs
16+
* methods.
17+
*/
18+
const MOUSE_BUTTONS = {
19+
1: "left",
20+
2: "middle",
21+
3: "right"
22+
};
23+
24+
/**
25+
* Mouse actions mapping between the values in remote-control-event and robotjs
26+
* methods.
27+
*/
28+
const MOUSE_ACTIONS_FROM_EVENT_TYPE = {
29+
"mousedown": "down",
30+
"mouseup": "up"
31+
};
32+
33+
/**
34+
* Key actions mapping between the values in remote-control-event and robotjs
35+
* methods.
36+
*/
37+
const KEY_ACTIONS_FROM_EVENT_TYPE = {
38+
"keydown": "down",
39+
"keyup": "up"
40+
};
41+
42+
/**
43+
* The status ("up"/"down") of the mouse button.
44+
* FIXME: Assuming that one button at a time can be pressed. Haven't noticed
45+
* any issues but maybe we should store the status for every mouse button
46+
* that we are processing.
47+
*/
48+
let mouseButtonStatus = "up";
49+
50+
/**
51+
* Parses the remote-control-events and executes them via robotjs.
52+
*/
53+
class RemoteControl {
54+
/**
55+
* Construcs new instance.
56+
* @constructor
57+
*/
58+
constructor() {
59+
this.started = false;
60+
}
61+
62+
/**
63+
* Starts processing the events.
64+
*/
65+
start() {
66+
this.started = true;
67+
}
68+
69+
/**
70+
* Stops processing the events.
71+
*/
72+
stop() {
73+
this.started = false;
74+
}
75+
76+
/**
77+
* Executes the passed event.
78+
* @param {Object} event the remote-control-event.
79+
*/
80+
executeRemoteControlEvent(event) {
81+
if(!this.started) {
82+
return;
83+
}
84+
switch(event.type) {
85+
case "mousemove":
86+
const x = event.x * width, y = event.y * height;
87+
if(mouseButtonStatus === "down") {
88+
robot.dragMouse(x, y);
89+
} else {
90+
robot.moveMouse(x, y);
91+
}
92+
break;
93+
case "mousedown":
94+
case "mouseup":
95+
mouseButtonStatus = MOUSE_ACTIONS_FROM_EVENT_TYPE[event.type];
96+
robot.mouseToggle(
97+
mouseButtonStatus,
98+
(event.button ? MOUSE_BUTTONS[event.button] : undefined));
99+
break;
100+
case "mousedblclick":
101+
robot.mouseClick(
102+
(event.button ? MOUSE_BUTTONS[event.button] : undefined),
103+
true);
104+
break;
105+
case "mousescroll":
106+
//FIXME: implement horizontal scrolling
107+
if(event.y !== 0) {
108+
robot.scrollMouse(
109+
Math.abs(event.y),
110+
event.y > 0 ? "down" : "up"
111+
);
112+
}
113+
break;
114+
case "keydown":
115+
case "keyup":
116+
robot.keyToggle(event.key,
117+
KEY_ACTIONS_FROM_EVENT_TYPE[event.type], event.modifiers);
118+
break;
119+
default:
120+
console.error("Unknown event type!");
121+
}
122+
}
123+
}
124+
125+
module.exports = new RemoteControl();

‎modules/screensharing/index.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const electron = require("electron");
2+
/**
3+
* Adds screen sharing support. Prompts the user to choose screen, window or
4+
* tab to share (not implemented yet). And passes the chosen source to caller
5+
* of the method.
6+
* @param {Function} callback the success callback
7+
* @param {Function} errorCallback the callback for errors
8+
*/
9+
function obtainDesktopStream (callback, errorCallback) {
10+
//FIXME: add more types
11+
electron.desktopCapturer.getSources({types: ['screen']},
12+
(error, sources) => {
13+
if (error) {
14+
errorCallback(error);
15+
return;
16+
}
17+
//FIXME: Implement window picker instead of choosing always the
18+
// first sourceId
19+
callback(sources[0].id);
20+
});
21+
}
22+
23+
module.exports = function setupScreenSharingForWindow(pWindow) {
24+
pWindow.JitsiMeetElectron = {obtainDesktopStream};
25+
};

‎package.json

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "jitsi-meet-electron",
3+
"version": "0.0.0",
4+
"description": "Electron application for Jitsi Meet",
5+
"main": "main.js",
6+
"scripts": {
7+
"start": "electron .",
8+
"build": "./electron_npm_rebuild",
9+
"clean": "rm -r node_modules .electron-gyp",
10+
"lint": "eslint .",
11+
"validate": "npm ls"
12+
},
13+
"pre-commit": [
14+
"lint"
15+
],
16+
"repository": {
17+
"type": "git",
18+
"url": "git://github.com/jitsi/jitsi-meet-electron"
19+
},
20+
"keywords": [
21+
"jingle",
22+
"webrtc",
23+
"xmpp",
24+
"electron",
25+
"jitsi-meet"
26+
],
27+
"author": "",
28+
"readmeFilename": "README.md",
29+
"license": "Apache-2.0",
30+
"dependencies": {
31+
"robotjs": "hristoterezov/robotjs",
32+
"postis": "^2.2.0"
33+
},
34+
"devDependencies": {
35+
"electron": "1.4.7",
36+
"eslint": ">=3",
37+
"eslint-plugin-jsdoc": "*",
38+
"precommit-hook": "3.0.0"
39+
}
40+
}

‎windows/jitsi-meet/index.html

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<style>
5+
body, html {
6+
margin: 0;
7+
height: 100%;
8+
overflow: hidden;
9+
}
10+
body {
11+
-webkit-app-region: drag
12+
}
13+
iframe {
14+
width: 100%;
15+
height: 100%;
16+
border: 0 none;
17+
}
18+
</style>
19+
</head>
20+
<body>
21+
<script>
22+
require('./render.js');
23+
</script>
24+
</body>
25+
</html>

‎windows/jitsi-meet/render.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const remoteControl = require("../../modules/remotecontrol");
2+
let postis = require("postis");
3+
const setupScreenSharingForWindow = require("../../modules/screensharing");
4+
const config = require("../../config.js");
5+
6+
/**
7+
* The postis channel.
8+
*/
9+
let channel;
10+
11+
/**
12+
* Cteates the iframe that will load Jitsi Meet.
13+
*/
14+
let iframe = document.createElement('iframe');
15+
iframe.src = config.jitsiMeetURL;
16+
iframe.allowFullscreen = true;
17+
iframe.onload = onload;
18+
document.body.appendChild(iframe);
19+
20+
/**
21+
* Initializes the remote control functionality.
22+
*/
23+
function initRemoteControl() {
24+
remoteControl.start();
25+
channel.ready(() =>
26+
channel.listen('remote-control-event',
27+
event => remoteControl.executeRemoteControlEvent(event))
28+
);
29+
}
30+
31+
/**
32+
* Handles loaded event for iframe:
33+
* Enables screen sharing functionality to the iframe webpage.
34+
* Initializes postis.
35+
* Initializes remote control.
36+
*/
37+
function onload() {
38+
setupScreenSharingForWindow(iframe.contentWindow);
39+
channel = postis({
40+
window: iframe.contentWindow,
41+
windowForEventListening: window
42+
});
43+
initRemoteControl();
44+
}

0 commit comments

Comments
 (0)
Please sign in to comment.