desktop-capturer.ts 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. const { createDesktopCapturer } = process._linkedBinding('electron_browser_desktop_capturer');
  2. const deepEqual = (a: ElectronInternal.GetSourcesOptions, b: ElectronInternal.GetSourcesOptions) => JSON.stringify(a) === JSON.stringify(b);
  3. let currentlyRunning: {
  4. options: ElectronInternal.GetSourcesOptions;
  5. getSources: Promise<ElectronInternal.GetSourcesResult[]>;
  6. }[] = [];
  7. // |options.types| can't be empty and must be an array
  8. function isValid (options: Electron.SourcesOptions) {
  9. return Array.isArray(options?.types);
  10. }
  11. export async function getSources (args: Electron.SourcesOptions) {
  12. if (!isValid(args)) throw new Error('Invalid options');
  13. const captureWindow = args.types.includes('window');
  14. const captureScreen = args.types.includes('screen');
  15. const { thumbnailSize = { width: 150, height: 150 } } = args;
  16. const { fetchWindowIcons = false } = args;
  17. const options = {
  18. captureWindow,
  19. captureScreen,
  20. thumbnailSize,
  21. fetchWindowIcons
  22. };
  23. for (const running of currentlyRunning) {
  24. if (deepEqual(running.options, options)) {
  25. // If a request is currently running for the same options
  26. // return that promise
  27. return running.getSources;
  28. }
  29. }
  30. const getSources = new Promise<ElectronInternal.GetSourcesResult[]>((resolve, reject) => {
  31. let capturer: ElectronInternal.DesktopCapturer | null = createDesktopCapturer();
  32. const stopRunning = () => {
  33. if (capturer) {
  34. delete capturer._onerror;
  35. delete capturer._onfinished;
  36. capturer = null;
  37. }
  38. // Remove from currentlyRunning once we resolve or reject
  39. currentlyRunning = currentlyRunning.filter(running => running.options !== options);
  40. };
  41. capturer._onerror = (error: string) => {
  42. stopRunning();
  43. reject(error);
  44. };
  45. capturer._onfinished = (sources: Electron.DesktopCapturerSource[]) => {
  46. stopRunning();
  47. resolve(sources);
  48. };
  49. capturer.startHandling(captureWindow, captureScreen, thumbnailSize, fetchWindowIcons);
  50. });
  51. currentlyRunning.push({
  52. options,
  53. getSources
  54. });
  55. return getSources;
  56. }