> For the complete documentation index, see [llms.txt](https://docs.lmms.io/developer-guides/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.lmms.io/developer-guides/core/how-lmms-renders-audio/stage-1-process-automation-and-midi-events.md).

# Stage 1: collect play handles and process automation

### Collecting play handles

There are two major sources for play handles:

* User interaction: If users trigger an play action, UI classes or MIDI event processors call `AudioEngine::addPlayHandle` if needed
* Playing song: `AudioEngine::renderNextBuffer` calls `Song::processNextBuffer` to get play handles for the current playback position

To avoid threading issues, `AudioEngine::addPlayHandle` doesn't add play handles directly; it only queues play handles to process into `m_newPlayHandles`. Those play handles are added to the play handle list at once at this stage.

`AudioEngine::removePlayHandle` also work similarly when trying to remove play handles created from the mixer thread in user threads.

### Processing automation

* `Song::processNextBuffer` calls `Song::processAutomations` to process automation. This function calls proper override of `TrackContainer::automatedValuesAt` and they call `TrackContainer::automatedValuesFromTracks` with proper arguments.
