Providing a service to another package


#1

I’d like to trigger the screen-recorder package from a new package of mine.

I’ve forked screen-recordre and created a new branch:

(if you clone it, the changes are in the “provided-services” branch)

Here are the changes I’ve made to provide access to the text area recording and to the stop command:

diff --git a/lib/screen-recorder.coffee b/lib/screen-recorder.coffee
index 8350b32..ea6f566 100644
--- a/lib/screen-recorder.coffee
+++ b/lib/screen-recorder.coffee
@@ -124,3 +124,8 @@ module.exports = ScreenRecorder =
 
     @recordingsList.init()
     @recordingsList.toggle()
+
+  provideScreenRecorder: ->
+    console.log('the screen-recorder provider has been called')
+    recordActiveTexteditor: @recordActiveTexteditor.bind(@recorderManager)
+    stopRecording: @stopRecording.bind(@recorderManager)
diff --git a/package.json b/package.json
index 5f033ff..78ac2cf 100644
--- a/package.json
+++ b/package.json
@@ -39,5 +39,13 @@
         "^1.0.0": "consumeStatusBar"
       }
     }
+  },
+  "providedServices": {
+    "screen-recorder": {
+      "description": "Record your atom editor into a gif",
+      "versions": {
+        "1.5.0": "provideScreenRecorder"
+      }
+    }
   }
 }

I’ve created a new package that should consume the new service:

Sadly, my consumeStatusBar() function is never called.

Trying to consume the “status-bar” services from my new package seems to work, so I suppose the issue is with the way I’ve added the “providing” code.

I’ve already asked the same question slack and pe.lallemant helped me to find where the issue is… but no chance until now…

Does anybody have a clue, what is wrong?


#2

After a further discussion on Slack, it seems to be clear that having activationCommands in package.json delays the activation of the package until one of the listed commands is triggered.

A few more details are in the documentation: http://flight-manual.atom.io/hacking-atom/sections/package-modifying-text/#trigger-the-command

Until one of the commands is triggered, the service is not provided.

I’m browsing the internet and the documentation to see if I can try to activate the “lazy loading” package from my package…

https://atom.io/docs/api/v1.24.0/PackageManager seems to say in the introduction that it should be possible. But, then, I cannot find the command to do so.

Stay tuned…


#3

You can remove activationCommands. It’s not necessary, and actually counter to the way a lot of packages are intended to work.


#4

I’m just starting with Atom packages, but from what I understood from the documentation, the activationCommands are a good way to make Atom faster…

And it’s probably a good idea to use them, for commands that are not used often (like starting a screen cast).

For my personal use, I’m more than fine, with removing the condition, but I’m not sure that the original author of the package will agree with it.


#5

Here’s another option: add a new entry to activationCommands that leads to a command that doesn’t actually do anything (maybe it could issue a console.log() to let you know it’s been triggered). This will allow you to have your package use atom.commands.dispatch() when it activates to make the recorder accessible. In all other cases, the original behavior would be unchanged.


#6

Yes, @DamnedScholar, this mostly works:

    editor = atom.workspace.getActiveTextEditor()
    atom.commands.dispatch(atom.views.getView(editor), 'screen-recorder:record-active-texteditor')

    // this should run synchronously...
    atom.commands.dispatch(atom.views.getView(editor), 'atom-autotype:start')

    atom.commands.dispatch(atom.views.getView(editor), 'screen-recorder:stop-recording')

Now I just have to find out how to run the middle command in a synchronous way…


#7

So, this is what I came up with:

The problem is that two of the commands are to be run asynchronously and the one in between must be synchronous (that is the third must wait for the second to be finished before stopping everything)

Currently, the stop command is just never run and I get some sort of stack overflow.

Any hint how to get this to work?

The alternative will be to copy over parts of screen-recorder into my packages… but that code is not trivial at all…


#8

Are you positive it needs to be synchronous? Nodejs uses emitters to help with timing functions such that they occur after a certain event. You could set up an emitter to emit when the second function is finished, and register the third function as a callback when the emitter fires.

For example, instead of creating a promise and waiting for it to resolve, you could just emit an event inside the setTimeout function.

const { Emitter } = require("atom");

let myEmitter = new Emitter();
myEmitter.on("time-up", () => {
  // do something when timer finishes
});

setTimeout(() => { myEmitter.emit("time-up"); }, 2000);

#9

@Aerijo, no, it does not have to be synchronous… but it would probably make things simpler.

If you have a solution for starting the first command in an async way, start the second command and call the third command when the second command is over… then don’t hesitate to point me in the right direction!

… should I emit an autotype:stopping signal when autotype is over? mmm…


#10

I cannot get the Emitter to work… can I emit and “catch” in two different packages?


#11

I somehow gave up.

Now my package starts the first service and the second in async way.

I run the third one manually to stop the recording once I see that the second one is over.

Not really the right thing, but it works for now.


#12

No, don’t do that. Have your neutral activation command in the activate() method in your package’s primary file. That way, it will run at the same time that your package is activated (or maybe just after, depending on how the timing works out).