Notifications over AMCP

Is there a way to get a notification over AMCP when the current video stops playing?

I am trying to make a simple client that plays videos in sequence one after another. My idea was to just feed them to the server via the LOADBG command, but I need to know when the current video stops so I can feed the next one.

For now I am planning to issue INFO 1 once a second, but that seems silly and I was wondering if there a better way…

I don’t mind using OSC for that if I have to, but I don’t know if there is a way to dynamically add OSC clients to the server.

You can add OSC clients over AMCP since 2.4.0.
Its probably not been added to the documentation, but the change is feat: add amcp commands to subscribe and unsubscribe to osc · CasparCG/server@8f05ef7 · GitHub

Thanks @Julusian. That seems to work.

Yeah, I didn’t see it in the wiki. Unless there is another place…

Hi! Very interesting!
@mint Are there any plans to implement new functionality to casparcg-connection?

From the code, that you linked to, I understand, that it is:

OSC SUBSCRIBE <port number>
OSC UNSUBSCRIBE <port number>

Or do I miss something? Does it need an IP address somewhere?

1 Like

Correct, it sends back to the ip address that opened the AMCP connection, and will automatically stop sending when the AMCP connection closes.

This is intended to be a substitute for how when opening an AMCP connection casparcg will start sending osc data to port I think 9250 (unless you enable disable-send-to-amcp-clients in the config), but that doesn’t work well if you are running multiple applications on one machine who want the osc.

1 Like

@dimitry_ishenko
by the way, what do you mean by dynamically adding clients?

For working with standard OSC protocol:
If you mean that you have several casparCG servers, then the approximate solution is that you need to have a list of current servers (and keep it up to date): this.connectionService.servers

Then, with each new message received on the OSC port, you check whether the sender’s address is your target CasparCG server and send a stop event to the media layer if it is completed…

Simplified example:

      const OSC_STATE_REGEX = /^\/channel\/1\/stage\/layer\/(\d+)\/foreground\/file\/time$/;
      
      const oscConnection = new OSC({
        plugin: new OSC.DatagramPlugin(),
      });
      oscConnection.on(
        '/channel/1/stage/layer/*/foreground/file/time',
        async (message: any, { address }) => {
          const server = this.connectionService.servers.find(
            (server) => server.playoutHost === address,
          );
          if (!server) return;

          try {
            const match = message.address.match(OSC_STATE_REGEX);
            if (!match) return;
            const layer = match[1];

            const currentTime = Math.floor(message.args[0]);
            const duration = Math.floor(message.args[1]);
            
            if (
              currentTime > duration ||
                (currentTime === duration && currentTime !== 0)
            ) {
              this.eventEmitter.emit(EVENT_SERVER.MEDIA.STOP, {
                serverId: server._id.toString(),
                layer,
              });
            }
          } catch (error) {
            this.loggingService.logError(error, {
              module: moduleName,
              function: 'oscListener',
            });
          }
        },
      );
      oscConnection.on('error', (error: any) => {
        this.loggingService.logError(error, {
          module: moduleName,
          function: 'oscListener',
        });
      });

      oscConnection.open({
        host: '0.0.0.0',
        port: +process.env.CASPAR_SETTINGS_OSC_PORT,
      });         

I hope this helps

@teo I have one server, but will connect from different machines with different IP addresses (DHCP), so I won’t be able to put all of them in casparcg.config to get OSC.

got it, so OSC protocol is definitely not for your case, as you said.
However, thanks for the topic, I learned about the new functionality.