(num bars visible)
How about this: As a first order approximation I would only enlarge the timeline by checking whether the end of an object is beyond the right-most point of the timeline whenever an object is inserted or moved. Shrinking would require to loop over all object to determine the right-most one. Also, I would check after moving any object because determining which one is "last" might be tricky and scale badly for a large number of them. E.g. one could have a 10 minute audio track starting at the first bar and countless others added on top of it at various other locations.
avoiding looping over every object is a good idea although I need to benchmark it - I think it won't be noticeable even with thousands of objects (assuming the loop is only done at the end of every action and not during dragging)
I made it loop through every object at the end of every action (when it is recorded in the undo stack), with some exceptions when moving/creating/duplicating objects (only the affected objects are checked) and when no objects are affected (e.g., moving a track)
it's still missing some exceptions, I'll add them as we discover them