Just thought I’d add a further technical note with reference to the discussion above of “push” versus “pull” based metronomes, in case it is helpful to any one. Basically, I’m addressing the inter-related questions of why EspGrid uses the representation of metre it does, and why it uses a (mostly) poll/pull system rather than pushing out pulses/beats.
A basic “problem” with sending (pushing) a message (ie. a metronome pulse) whose interpretation is “do something now” is that the message always takes time to deliver and process. This time can be quite non-deterministic - essentially the “now” of your pulse is not quite as defined as one might imagine from the concept “now”. A common solution within the push paradigm is to add a time tag to the pulse/trigger so that things happen at a slightly later but better synchronized moment. However, with such a solution, the interpretation of the message is no longer “do this now” but rather “do this at this time” - the exact time that the message is delivered is no longer pertinent, and we are already moving towards representing the metre rather than “performing” it as an event.
A second “problem” with sending (pushing) such a pulse message is that if you need to do things between the pulses you need, one way or another, to have information about the metric grid beyond “this pulse happens at this time”. To get this info in a push-based system either you track the time between the pulses yourself and infer the information, or you add the information to the pulse message itself. The former case is not without its merits (after all, in some sense its what we do when we hear beats), but its a bit strange to infer something that is (elsewhere) already known, and it also doesn’t cover edge cases like drastic changes in tempo (which also take us by surprise perceptually). In the latter case, as with the first “problem”, you are again moving towards providing a constant representation of the alignment of the metric grid.
Basically, both compensating for the latency of moving messages around and doing things in between the beats leads towards sharing metre as declarative representations of a temporal grid rather than imperative “do this now” commands.
A third set of considerations motivates the normal way of getting this metre representation from EspGrid, whereby “clients” (ie. Tidal, SuperCollider quark, etc) send a message to poll EspGrid for the metre and then get a response. Since responses are only sent when requested you don’t have the problem of zombie processes getting messages they will never consume (eg. when a consuming application is closed or crashes). Also it is a simple way of giving metre-consuming applications control over when and how they want this information. Repeated polling is a basic strategy against lost packets as well. The messages use only the most basic and universal parts of the OSC spec - which is why, for example, time is represented as two int32s - anything else sacrifices either precision or universal transmissability (many OSC applications, including some very “fancy” ones, don’t grok int64 in their OSC code).
That said, chat and a few other non-tempo things in EspGrid do still use a subscription-based push system instead, at present. Part of me thinks it would be better to move everything over to the “pull” query-and-response system, though, for clarity/consistency.