Refine API design: desktopCapturer.getSources.
This commit is contained in:
parent
36c0ad7fda
commit
dcb457e76e
7 changed files with 124 additions and 194 deletions
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "atom/common/api/atom_api_native_image.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/native_mate_converters/gfx_converter.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "chrome/browser/media/desktop_media_list.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
@ -14,13 +15,30 @@
|
|||
#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
|
||||
|
@ -31,7 +49,7 @@ DesktopCapturer::DesktopCapturer() {
|
|||
DesktopCapturer::~DesktopCapturer() {
|
||||
}
|
||||
|
||||
void DesktopCapturer::StartUpdating(const mate::Dictionary& args) {
|
||||
void DesktopCapturer::StartHandling(const mate::Dictionary& args) {
|
||||
std::vector<std::string> sources;
|
||||
if (!args.Get("types", &sources))
|
||||
return;
|
||||
|
@ -68,64 +86,41 @@ void DesktopCapturer::StartUpdating(const mate::Dictionary& args) {
|
|||
media_list_.reset(new NativeDesktopMediaList(screen_capturer.Pass(),
|
||||
window_capturer.Pass()));
|
||||
|
||||
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);
|
||||
gfx::Size thumbnail_size(kThumbnailWidth, kThumbnailHeight);
|
||||
args.Get("thumbnailSize", &thumbnail_size);
|
||||
|
||||
media_list_->SetUpdatePeriod(base::TimeDelta::FromMilliseconds(
|
||||
update_period));
|
||||
media_list_->SetThumbnailSize(gfx::Size(thumbnail_width, thumbnail_height));
|
||||
media_list_->SetThumbnailSize(thumbnail_size);
|
||||
media_list_->StartUpdating(this);
|
||||
}
|
||||
|
||||
void DesktopCapturer::StopUpdating() {
|
||||
media_list_.reset();
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceAdded(int index) {
|
||||
EmitDesktopCapturerEvent("source-added", index, false);
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceRemoved(int index) {
|
||||
EmitDesktopCapturerEvent("source-removed", index, false);
|
||||
}
|
||||
|
||||
// Ignore this event.
|
||||
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceNameChanged(int index) {
|
||||
EmitDesktopCapturerEvent("source-removed", index, false);
|
||||
}
|
||||
|
||||
void DesktopCapturer::OnSourceThumbnailChanged(int 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)));
|
||||
}
|
||||
bool DesktopCapturer::OnRefreshFinished() {
|
||||
std::vector<DesktopMediaList::Source> sources;
|
||||
for (int i = 0; i < media_list_->GetSourceCount(); ++i)
|
||||
sources.push_back(media_list_->GetSource(i));
|
||||
media_list_.reset();
|
||||
Emit("refresh-finished", sources);
|
||||
return false;
|
||||
}
|
||||
|
||||
mate::ObjectTemplateBuilder DesktopCapturer::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("startUpdating", &DesktopCapturer::StartUpdating)
|
||||
.SetMethod("stopUpdating", &DesktopCapturer::StopUpdating);
|
||||
.SetMethod("startHandling", &DesktopCapturer::StartHandling);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -27,9 +27,7 @@ class DesktopCapturer: public mate::EventEmitter,
|
|||
public:
|
||||
static mate::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
|
||||
|
||||
void StartUpdating(const mate::Dictionary& args);
|
||||
|
||||
void StopUpdating();
|
||||
void StartHandling(const mate::Dictionary& args);
|
||||
|
||||
protected:
|
||||
DesktopCapturer();
|
||||
|
@ -41,11 +39,9 @@ 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;
|
||||
bool 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,38 +1,38 @@
|
|||
ipc = require 'ipc'
|
||||
BrowserWindow = require 'browser-window'
|
||||
|
||||
# The browser module manages all desktop-capturer moduels in renderer process.
|
||||
desktopCapturer = process.atomBinding('desktop_capturer').desktopCapturer
|
||||
|
||||
getWebContentsFromId = (id) ->
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
return window.webContents for window in windows when window.webContents?.getId() == id
|
||||
isOptionsEqual = (opt1, opt2) ->
|
||||
return JSON.stringify opt1 is JSON.stringify opt2
|
||||
|
||||
# The set for tracking id of webContents.
|
||||
webContentsIds = new Set
|
||||
# A queue for holding all requests from renderer process.
|
||||
requestsQueue = []
|
||||
|
||||
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_GET_SOURCES', (event, options) ->
|
||||
request = { options: options, webContents: event.sender }
|
||||
desktopCapturer.startHandling options if requestsQueue.length is 0
|
||||
requestsQueue.push request
|
||||
# If the WebContents is destroyed before receiving result, just remove the
|
||||
# reference from requestsQueue to make the module not send the result to it.
|
||||
event.sender.once 'destroyed', () ->
|
||||
request.webContents = null
|
||||
|
||||
# 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.emit = (event_name, event, sources) ->
|
||||
# Receiving sources result from main process, now send them back to renderer.
|
||||
handledRequest = requestsQueue.shift 0
|
||||
result = ({ id: source.id, name: source.name, thumbnail: source.thumbnail.toDataUrl() } for source in sources)
|
||||
handledRequest.webContents?.send 'ATOM_REDNERER_DESKTOP_CAPTURER_RESULT', result
|
||||
|
||||
# Handle `desktopCapturer.stopUpdating` API.
|
||||
ipc.on 'ATOM_BROWSER_DESKTOP_CAPTURER_STOP_UPDATING', (event) ->
|
||||
stopDesktopCapture event.sender.getId()
|
||||
|
||||
desktopCapturer.emit = (event_name, event, desktopId, name, thumbnail) ->
|
||||
webContentsIds.forEach (id) ->
|
||||
getWebContentsFromId(id).send 'ATOM_RENDERER_DESKTOP_CAPTURER', event_name, desktopId, name, thumbnail?.toDataUrl()
|
||||
# Check the queue to see whether there is other same request. If has, handle
|
||||
# it for reducing redunplicated `desktopCaptuer.startHandling` calls.
|
||||
unhandledRequestsQueue = []
|
||||
for request in requestsQueue
|
||||
if isOptionsEqual handledRequest.options, request.options
|
||||
request.webContents?.send 'ATOM_REDNERER_DESKTOP_CAPTURER_RESULT', result
|
||||
else
|
||||
unhandledRequestsQueue.push request
|
||||
requestsQueue = unhandledRequestsQueue
|
||||
# If the requestsQueue is not empty, start a new request handling.
|
||||
if requestsQueue.length > 0
|
||||
desktopCapturer.startHandling requestsQueue[0].options
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue