Refine more about desktop capturer API.
* Simplify the coffeescript code. * Add more options in desktopCapturer.startUpdating.
This commit is contained in:
parent
1e69ef79de
commit
36c0ad7fda
8 changed files with 104 additions and 84 deletions
10
atom.gyp
10
atom.gyp
|
@ -278,11 +278,6 @@
|
|||
'-lwinmm.lib',
|
||||
],
|
||||
},
|
||||
'defines': [
|
||||
# The usage of "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
# is required to see this macro.
|
||||
'WEBRTC_WIN',
|
||||
],
|
||||
'dependencies': [
|
||||
# Node is built as static_library on Windows, so we also need to
|
||||
# include its dependencies here.
|
||||
|
@ -296,11 +291,6 @@
|
|||
],
|
||||
}], # OS=="win"
|
||||
['OS=="mac"', {
|
||||
'defines': [
|
||||
# The usage of "webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
# is required to see this macro.
|
||||
'WEBRTC_MAC',
|
||||
],
|
||||
'dependencies': [
|
||||
'vendor/crashpad/client/client.gyp:crashpad_client',
|
||||
'vendor/crashpad/handler/handler.gyp:crashpad_handler',
|
||||
|
|
|
@ -14,30 +14,13 @@
|
|||
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<DesktopMediaList::Source> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const DesktopMediaList::Source& source) {
|
||||
mate::Dictionary dict(isolate, v8::Object::New(isolate));
|
||||
content::DesktopMediaID id = source.id;
|
||||
dict.Set("name", base::UTF16ToUTF8(source.name));
|
||||
dict.Set("id", id.ToString());
|
||||
dict.Set(
|
||||
"thumbnail",
|
||||
atom::api::NativeImage::Create(isolate, gfx::Image(source.thumbnail)));
|
||||
return ConvertToV8(isolate, dict);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
// Refresh every second.
|
||||
const int kUpdatePeriod = 1000;
|
||||
const int kThumbnailWidth = 150;
|
||||
const int kThumbnailHeight = 150;
|
||||
} // namespace
|
||||
|
@ -48,7 +31,11 @@ DesktopCapturer::DesktopCapturer() {
|
|||
DesktopCapturer::~DesktopCapturer() {
|
||||
}
|
||||
|
||||
void DesktopCapturer::StartUpdating(const std::vector<std::string>& sources) {
|
||||
void DesktopCapturer::StartUpdating(const mate::Dictionary& args) {
|
||||
std::vector<std::string> sources;
|
||||
if (!args.Get("types", &sources))
|
||||
return;
|
||||
|
||||
bool show_screens = false;
|
||||
bool show_windows = false;
|
||||
for (const auto& source_type : sources) {
|
||||
|
@ -80,7 +67,16 @@ void DesktopCapturer::StartUpdating(const std::vector<std::string>& sources) {
|
|||
show_windows ? webrtc::WindowCapturer::Create(options) : nullptr);
|
||||
media_list_.reset(new NativeDesktopMediaList(screen_capturer.Pass(),
|
||||
window_capturer.Pass()));
|
||||
media_list_->SetThumbnailSize(gfx::Size(kThumbnailWidth, kThumbnailHeight));
|
||||
|
||||
int update_period = kUpdatePeriod;
|
||||
int thumbnail_width = kThumbnailWidth, thumbnail_height = kThumbnailHeight;
|
||||
args.Get("updatePeriod", &update_period);
|
||||
args.Get("thumbnailWidth", &thumbnail_width);
|
||||
args.Get("thumbnailHeight", &thumbnail_height);
|
||||
|
||||
media_list_->SetUpdatePeriod(base::TimeDelta::FromMilliseconds(
|
||||
update_period));
|
||||
media_list_->SetThumbnailSize(gfx::Size(thumbnail_width, thumbnail_height));
|
||||
media_list_->StartUpdating(this);
|
||||
}
|
||||
|
||||
|
@ -89,22 +85,40 @@ void DesktopCapturer::StopUpdating() {
|
|||
}
|
||||
|
||||
void DesktopCapturer::OnSourceAdded(int index) {
|
||||
Emit("source-added", media_list_->GetSource(index));
|
||||
EmitDesktopCapturerEvent("source-added", index, false);
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceRemoved(int index) {
|
||||
Emit("source-removed", media_list_->GetSource(index));
|
||||
EmitDesktopCapturerEvent("source-removed", index, false);
|
||||
}
|
||||
|
||||
// Ignore this event.
|
||||
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceNameChanged(int index) {
|
||||
Emit("source-name-changed", media_list_->GetSource(index));
|
||||
EmitDesktopCapturerEvent("source-removed", index, false);
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceThumbnailChanged(int index) {
|
||||
Emit("source-thumbnail-changed", media_list_->GetSource(index));
|
||||
EmitDesktopCapturerEvent("source-thumbnail-changed", index, true);
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnRefreshFinished() {
|
||||
Emit("refresh-finished");
|
||||
}
|
||||
|
||||
void DesktopCapturer::EmitDesktopCapturerEvent(
|
||||
const std::string& event_name, int index, bool with_thumbnail) {
|
||||
const DesktopMediaList::Source& source = media_list_->GetSource(index);
|
||||
content::DesktopMediaID id = source.id;
|
||||
if (!with_thumbnail)
|
||||
Emit(event_name, id.ToString(), base::UTF16ToUTF8(source.name));
|
||||
else {
|
||||
Emit(event_name, id.ToString(), base::UTF16ToUTF8(source.name),
|
||||
atom::api::NativeImage::Create(isolate(),
|
||||
gfx::Image(source.thumbnail)));
|
||||
}
|
||||
}
|
||||
|
||||
mate::ObjectTemplateBuilder DesktopCapturer::GetObjectTemplateBuilder(
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
#include "chrome/browser/media/native_desktop_media_list.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace mate {
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
@ -23,7 +27,8 @@ class DesktopCapturer: public mate::EventEmitter,
|
|||
public:
|
||||
static mate::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
|
||||
|
||||
void StartUpdating(const std::vector<std::string>& sources);
|
||||
void StartUpdating(const mate::Dictionary& args);
|
||||
|
||||
void StopUpdating();
|
||||
|
||||
protected:
|
||||
|
@ -36,8 +41,11 @@ class DesktopCapturer: public mate::EventEmitter,
|
|||
void OnSourceMoved(int old_index, int new_index) override;
|
||||
void OnSourceNameChanged(int index) override;
|
||||
void OnSourceThumbnailChanged(int index) override;
|
||||
void OnRefreshFinished() override;
|
||||
|
||||
private:
|
||||
void EmitDesktopCapturerEvent(
|
||||
const std::string& event_name, int index, bool with_thumbnail);
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
ipc = require 'ipc'
|
||||
BrowserWindow = require 'browser-window'
|
||||
EventEmitter = require('events').EventEmitter
|
||||
|
||||
# The browser module manages all desktop-capturer moduels in renderer process.
|
||||
desktopCapturer = process.atomBinding('desktop_capturer').desktopCapturer
|
||||
desktopCapturer.__proto__ = EventEmitter.prototype
|
||||
|
||||
getWebContentsFromId = (id) ->
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
|
@ -15,28 +13,26 @@ webContentsIds = new Set
|
|||
|
||||
stopDesktopCapture = (id) ->
|
||||
webContentsIds.delete id
|
||||
# Stop updating if no renderer process listens the desktop capturer.
|
||||
if webContentsIds.size is 0
|
||||
desktopCapturer.stopUpdating()
|
||||
|
||||
ipc.on 'ATOM_BROWSER_DESKTOP_CAPTURER_REQUIRED', (event) ->
|
||||
id = event.sender.getId()
|
||||
# Remove the tracked webContents when it is destroyed.
|
||||
getWebContentsFromId(id).on 'destroyed', ()->
|
||||
stopDesktopCapture id
|
||||
event.returnValue = 'done'
|
||||
|
||||
# Handle `desktopCapturer.startUpdating` API.
|
||||
ipc.on 'ATOM_BROWSER_DESKTOP_CAPTURER_START_UPDATING', (event, args) ->
|
||||
id = event.sender.getId()
|
||||
if not webContentsIds.has id
|
||||
# Stop sending desktop capturer events to the destroyed webContents.
|
||||
event.sender.on 'destroyed', ()->
|
||||
stopDesktopCapture id
|
||||
# Start updating the desktopCapturer if it doesn't.
|
||||
if webContentsIds.size is 0
|
||||
desktopCapturer.startUpdating args
|
||||
webContentsIds.add id
|
||||
desktopCapturer.startUpdating args
|
||||
|
||||
# Handle `desktopCapturer.stopUpdating` API.
|
||||
ipc.on 'ATOM_BROWSER_DESKTOP_CAPTURER_STOP_UPDATING', (event) ->
|
||||
stopDesktopCapture event.sender.getId()
|
||||
|
||||
for event_name in ['source-added', 'source-removed', 'source-name-changed', "source-thumbnail-changed"]
|
||||
do (event_name) ->
|
||||
desktopCapturer.on event_name, (event, source) ->
|
||||
webContentsIds.forEach (id) ->
|
||||
getWebContentsFromId(id).send event_name, { id: source.id, name: source.name, dataUrl: source.thumbnail.toDataUrl() }
|
||||
desktopCapturer.emit = (event_name, event, desktopId, name, thumbnail) ->
|
||||
webContentsIds.forEach (id) ->
|
||||
getWebContentsFromId(id).send 'ATOM_RENDERER_DESKTOP_CAPTURER', event_name, desktopId, name, thumbnail?.toDataUrl()
|
||||
|
|
|
@ -5,18 +5,15 @@ NativeImage = require 'native-image'
|
|||
EventEmitter = require('events').EventEmitter
|
||||
desktopCapturer = new EventEmitter
|
||||
|
||||
# Tells main process the renderer is requiring 'desktop-capture' module.
|
||||
ipc.sendSync 'ATOM_BROWSER_DESKTOP_CAPTURER_REQUIRED'
|
||||
|
||||
desktopCapturer.startUpdating = (args) ->
|
||||
ipc.send 'ATOM_BROWSER_DESKTOP_CAPTURER_START_UPDATING', args
|
||||
|
||||
desktopCapturer.stopUpdating = () ->
|
||||
ipc.send 'ATOM_BROWSER_DESKTOP_CAPTURER_STOP_UPDATING'
|
||||
|
||||
for event_name in ['source-added', 'source-removed', 'source-name-changed', "source-thumbnail-changed"]
|
||||
do (event_name) ->
|
||||
ipc.on event_name, (source) ->
|
||||
desktopCapturer.emit event_name, { id: source.id, name: source.name, thumbnail: NativeImage.createFromDataUrl source.dataUrl }
|
||||
ipc.on 'ATOM_RENDERER_DESKTOP_CAPTURER', (event_name, id, name, thumbnail) ->
|
||||
if not thumbnail
|
||||
return desktopCapturer.emit event_name, id, name
|
||||
desktopCapturer.emit event_name, id, name, NativeImage.createFromDataUrl thumbnail
|
||||
|
||||
module.exports = desktopCapturer
|
||||
|
|
|
@ -14,6 +14,7 @@ class DesktopMediaListObserver {
|
|||
virtual void OnSourceMoved(int old_index, int new_index) = 0;
|
||||
virtual void OnSourceNameChanged(int index) = 0;
|
||||
virtual void OnSourceThumbnailChanged(int index) = 0;
|
||||
virtual void OnRefreshFinished() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~DesktopMediaListObserver() {}
|
||||
|
|
|
@ -358,6 +358,7 @@ void NativeDesktopMediaList::OnSourceThumbnail(
|
|||
}
|
||||
|
||||
void NativeDesktopMediaList::OnRefreshFinished() {
|
||||
observer_->OnRefreshFinished();
|
||||
BrowserThread::PostDelayedTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&NativeDesktopMediaList::Refresh,
|
||||
|
|
|
@ -7,13 +7,13 @@ screen and individual app windows.
|
|||
// In the renderer process.
|
||||
var desktopCapturer = require('desktop-capturer');
|
||||
|
||||
desktopCapturer.on('source-added', function(source) {
|
||||
console.log("source " + source.name + " is added.");
|
||||
// source.thumbnail is not ready to use here and webkitGetUserMedia neither.
|
||||
desktopCapturer.on('source-added', function(id, name) {
|
||||
console.log("source " + name + " is added.");
|
||||
// navigator.webkitGetUserMedia is not ready for use now.
|
||||
});
|
||||
|
||||
desktopCapturer.on('source-thumbnail-changed', function(source) {
|
||||
if (source.name == "Electron") {
|
||||
desktopCapturer.on('source-thumbnail-changed', function(id, name, thumbnail) {
|
||||
if (name == "Electron") {
|
||||
// stopUpdating since we have found the window that we want to capture.
|
||||
desktopCapturer.stopUpdating();
|
||||
|
||||
|
@ -23,7 +23,7 @@ desktopCapturer.on('source-thumbnail-changed', function(source) {
|
|||
video: {
|
||||
mandatory: {
|
||||
chromeMediaSource: 'desktop',
|
||||
chromeMediaSourceId: source.id,
|
||||
chromeMediaSourceId: id,
|
||||
minWidth: 1280,
|
||||
maxWidth: 1280,
|
||||
minHeight: 720,
|
||||
|
@ -50,42 +50,65 @@ function getUserMediaError(e) {
|
|||
|
||||
### Event: 'source-added'
|
||||
|
||||
* `source` Source
|
||||
* `id` String - The id of the captured window or screen used in
|
||||
`navigator.webkitGetUserMedia`. The format looks like 'window:XX' or
|
||||
'screen:XX' where XX is a random generated number.
|
||||
* `name` String - The descriped name of the capturing screen or window. If the
|
||||
source is a screen, the name will be 'Entire Screen' or 'Screen <index>'; if
|
||||
it is a window, the name will be the window's title.
|
||||
|
||||
Emits when there is a new source added, usually a new window is created,
|
||||
a new screen is attached.
|
||||
Emits when there is a new source added, usually a new window is created or a new
|
||||
screen is attached.
|
||||
|
||||
**Note:** The thumbnail of the source is not ready for use when 'source-added'
|
||||
event is emitted, and `navigator.webkitGetUserMedia` neither.
|
||||
**Note:** `navigator.webkitGetUserMedia` is not ready for use in this event.
|
||||
|
||||
### Event: 'source-removed'
|
||||
|
||||
* `source` Source
|
||||
* `id` String - The id of the captured window or screen used in
|
||||
`navigator.webkitGetUserMedia`.
|
||||
* `name` String - The descriped name of the capturing screen or window.
|
||||
|
||||
Emits when there is a source removed.
|
||||
|
||||
### Event: 'source-name-changed'
|
||||
|
||||
* `source` Source
|
||||
* `id` String - The id of the captured window or screen used in
|
||||
`navigator.webkitGetUserMedia`.
|
||||
* `name` String - The descriped name of the capturing screen or window.
|
||||
|
||||
Emits when the name of source is changed.
|
||||
|
||||
### Event: 'source-thumbnail-changed'
|
||||
|
||||
* `source` Source
|
||||
* `id` String - The id of the captured window or screen used in
|
||||
`navigator.webkitGetUserMedia`.
|
||||
* `name` String - The descriped name of the capturing screen or window.
|
||||
* `thumbnail` [NativeImage](NativeImage.md) - A thumbnail image.
|
||||
|
||||
Emits when the thumbnail of source is changed. `desktopCapturer` will refresh
|
||||
all sources every second.
|
||||
|
||||
### Event: 'refresh-finished'
|
||||
|
||||
Emits when `desktopCapturer` finishes a refresh.
|
||||
|
||||
## Methods
|
||||
|
||||
The `desktopCapturer` module has the following methods:
|
||||
|
||||
### `desktopCapturer.startUpdating(options)`
|
||||
|
||||
* `options` Array - An array of String that enums the types of desktop sources.
|
||||
`options` Object, properties:
|
||||
|
||||
* `types` Array - An array of String that enums the types of desktop sources.
|
||||
* `screen` String - Screen
|
||||
* `window` String - Individual window
|
||||
* `updatePeriod` Integer (optional) - The update period in milliseconds. By
|
||||
default, `desktopCapturer` updates every second.
|
||||
* `thumbnailWidth` Integer (optional) - The width of thumbnail. By default, it
|
||||
is 150px.
|
||||
* `thumbnailHeight` Integer (optional) - The height of thumbnail. By default, it
|
||||
is 150px.
|
||||
|
||||
Starts updating desktopCapturer. The events of `desktopCapturer` will only be
|
||||
emitted after `startUpdating` API is invoked.
|
||||
|
@ -104,15 +127,5 @@ Stops updating desktopCapturer. The events of `desktopCapturer` will not be
|
|||
emitted after the API is invoked.
|
||||
|
||||
**Note:** It is a good practice to call `stopUpdating` when you do not need
|
||||
getting any infomation of sources, usually after passing a id of source to
|
||||
getting any infomation of sources, usually after passing a id to
|
||||
`navigator.webkitGetUserMedia`.
|
||||
|
||||
## Source
|
||||
|
||||
`Source` is an object represents a captured screen or individual window. It has
|
||||
following properties:
|
||||
|
||||
* `id` String - The id of the capturing window or screen used in
|
||||
`navigator.webkitGetUserMedia`.
|
||||
* `name` String - The descriped name of the capturing screen or window.
|
||||
* `thumbnail` [NativeImage](NativeImage.md) - A thumbnail image.
|
||||
|
|
Loading…
Reference in a new issue