Teletype SCENE x OP, users of that OP chime in!

So the SCENE x OP loads new scene, right. But exactly how? Or more precisely exactly where will tt pick up execution after the SCENE x? Right after SCENE x, in a fresh M cycle?

Turns out (took me a lot of head scratching) it will execute the rest of the line in the old scene and pick up execution on the next line number in new scene (maybe read that again)!!!
EDIT: more precise description here

So there were some discussion on discord what we think of this. Some were fine with it (but argued it should be clearly documented), others argued it’s a bug. We all agreed that a super tight switch (as is possible now) should be possible in a possibly new behavior.

So let’s hear it! Anyone switching SCENE? Got bittin by this? How exactly do you think it should work? Please provide very clear descriptions and preferably examples, since the devil is really in the detail here!!!

I’ll give an example from my daily life: wacht the tt screen at 1:25 (just before the camera angle changes): you’ll see the tt switching scene and filling the screen with new content, in a new tempo, new init state, without missing as much as a single ms!!!

2 Likes

nb: any SCRIPT / $ remaining on that line from the old scene will call the new scene’s script! Very useful for calling init from the new script.

This was news to me! Is this true regardless of whether the SCENE call happens in a numbered script vs. metro/init?

The intuitive mode of operation, IMHO, would be “finish this line from the calling script but abandon the attempt to read the remaining lines from either script”.

This doesn’t feel totally intuitive to me, but I can see how it would be useful.

I’ve never actually used the SCENE op so I don’t really have any skin in this game, but to me, the most intuitive behavior would be to stop execution of the current script as soon as a SCENE op is executed, i.e. to treat it like a BREAK, as @scanner_darkly put it in Discord.

A close second in terms of intuitiveness would be for the scene change to happen immediately after the current script finishes executing, so you could think of the SCENE op as cueing up the next scene. If the op worked that way and you didn’t want the rest of the script to run, you could call BREAK after SCENE.

1 Like

And then the crucial question: exactly happens then? Will anything else happen in this M cycle? What will be the first thing in next M cycle? If i call init in new scene and M there is changed, will the new M cycle happen after the old M ms or the new M ms?

That’s a fair point and it allows for both MOs depending on what the script is trying to achieve

How is this different to calling a new scene manually? This should act the same way, no?

it just occurred to me that this could get pretty weird with a pair of scenes like this – scene 1:

#1
IF >= T 16: SCENE 2
SCRIPT 2
TR.P 1

#2
T + T 1

scene 2:

#1
IF <= T 0: SCENE 1
SCRIPT 2
TR.P 2

#2
T - T 1

Once scene 1, script 1 (call it 1#1) runs enough times for T to reach 16 and for the SCENE 2 op to execute, does the SCRIPT 2 on the next line run 1#2 (scene 1’s script 2) or 2#2? If it runs 1#2, then you no longer have the potentially useful ability to to run a scene 2 script from within scene 1. If it calls 2#2, then the expected behavior after 2#2 finishes executing would be to move on to line 3 of 1#1, which would require at least one of scene 1’s scripts to remain in memory during execution of one of scene 2’s scripts, which may not be possible…?


As for M behavior, I agree that it should act like you just loaded the new scene from the front panel.* The M and M.ACT values and metronome timer shouldn’t change or reset unless you change them explicitly – if M is set to 500 and you call SCENE 2 200ms after a metronome tick, the next metronome tick should happen 300ms later, and it should run scene 2’s M script.

*except without executing the I script for the new scene, in order to avoid an infinite loop (since that’s how the SCENE op works now)

I tend to agree.

So the current implementation is like this: When SCENE x is encountered:

  1. load new code into all scripts, including M
  2. execute the rest of the line that contains the SCENE x call (the line is buffered/“remembered” from the old scene, but any calls to other scripts like $ 10 will now use new scenes code)
  3. execute the rest of the line in M (could be an L-loop, then), all $ calls will run new scenes code
  4. continue M in next line (content of new scene)

Could be summed up as: SCENE x loads content of scene x, lines that are currently executing will finish executing with the old scenes code in that line (including lines in M).

What seems to be proposed in a future implementation: When SCENE x is encountered:

  1. execute the rest of the line (to be able to init new scene, init is not nessecarily in $ 10)
  2. stop all execution in current scene
  3. execute a complete M cycle immediately (so not waiting for next M)

This does not appear to be what SCENE does now, nor does this happen when you switch scenes from the front panel, unless your I script resets the metronome. And unless I’m misunderstanding what you mean by an “M cycle,” it seems to me you could do this with

SCENE 2; M.RESET; $ 9

or by including M.RESET; $ 9 in another script in scene 2 and running that script after SCENE.

Wait, this probably works already! Maybe no real change is needed to cover all these use cases (though obviously the documentation could improve). @a773 Does calling BRK on the same line as SCENE halt further execution of the new scene’s script?

Here’s something fun for yall

SCENE 1/2

#1
IF % T 4: BRK
SCENE + SCENE 1; $ 10

#2
TR.P 1

#3
IF == T 0: TR.P 2

#M
L 1 8: $ I
T + T 1

#I
M 500
T 0

SCENE 2/2

#1
IF % T 4: BRK
SCENE - SCENE 1; $ 10

#2
TR.P 1

#3
IF == T 0: TR.P 2

#M
L 1 8: $ I
T + T 1

#I
M 1000
T 0

scene_1_2.txt (1.1 KB)
scene_2_2.txt (1.1 KB)

Questions:

  1. what do expect to happen?
  2. what do you think ought to happen?
  3. load it unto your teletype!
  4. can you modify it to behave as you think it ought?

N.B. Let’s get concrete, load the thing on your teletype. Let’s stop speculating and talk about things that actually happen. If you never (really) used the SCENE OP, this is your chance. Please let’s make an effort here, load the thing on your teletype, or share your own code examples.

2 Likes

First, let me apologize for mixing "should"s, "could"s, and rampant speculation in what may have been a frustrating way. I hope I haven’t derailed your thread, and I hope others who actually do use the SCENE op regularly will chime in about how they’re actually using it and how well it’s working for them.

I just ran this pair of scenes and the results were in fact extra surprising – the surprise wasn’t where I expected the surprise to be, at all.

1. What do you expect to happen?

brain dump

load scene 1
M = 500, T = 0
M fires after 500ms:
1#1 runs: IF condition is false so SCENE is incremented and scene 2’s init script runs. M = 1000, T = 0
2#2 runs: TR.P 1
2#3 runs: TR.P 2
T is incremented
M fires after 1000ms:
2#1 runs: nothing
2#2 runs: TR.P 1
2#3 runs: nothing
T is incremented
repeat M cycle 2 more times
M fires again with T == 4
2#1 runs: IF condition is false so SCENE is decremented and scene 1’s init script runs. M = 500, T = 0
1#2 runs: TR.P 1
1#3 runs: TR.P 2
T is incremented
M fires after 500ms:
1#1 runs: nothing
1#2 runs: TR.P 1
1#3 runs: nothing
T is incremented
repeat M cycle 2 more times
M fires again with T == 4
repeat.

expected result after loading scene 1:
after 500ms, TR.P 1 and 2
after 1000ms, TR.P 1
after 1000ms, TR.P 1
after 1000ms, TR.P 1
after 1000ms, TR.P 1 and 2
after 500ms, TR.P 1
after 500ms, TR.P 1
after 500ms, TR.P 1
…repeat: after 500ms, TR.P 1 and 2, etc.

2. What do you think ought to happen?

brain dump

load scene 1
M = 500, T = 0
M fires after 500ms:
1#1 runs: IF condition is false so SCENE is incremented and scene 2’s init script runs. M = 1000, T = 0
At a gut level, I feel like the loop “should” stop there. That’s the “most intuitive” behavior I described earlier.
M fires after 1000ms:
2#1 runs IF condition is false so SCENE is decremented and scene 1’s init script runs. M = 500, T = 0
and so on.

I feel like L execution should stop when a new scene is loaded, so the scenes would just switch between one another, with scene 1 jumping to scene 2 after 500ms, and scene 2 jumping to scene 1 after 1000ms. No trigger outs. Not very useful, but also not very confusing (to me).

3. Load it, what actually happens?

Surprising surprise: it does almost what I expected it to do in question 1, but the delay after trigger outs 1 and 2 pulse together is always 500ms.

So setting M doesn’t behave the way I expected it to. It seems as though when M is 500, setting M to 1000 does not delay the next M script execution (which feels wrong); and when M is 1000, setting M to 500 does make the next M script execution happen sooner (which feels right).

4. Can you modify it to behave as you think it ought?

I don’t think it’s possible to interrupt the L loop, so no, I can’t make my useless-but-minimally-confusing version from question 2 happen. But adding M.RESET at the ends of the I scripts for both scenes makes this pair of scenes work the way I described for question 1, with four M’s of 1000ms and four M’s of 500ms.


Takeaways for me:

  • SCENE op behavior is weirder than I would have guessed before today, but its weirdness makes a kind of sense.
  • M setter / metronome behavior is weirder than I knew before this evening, and… I don’t know why.
  • I’ve been using this as a convenient distraction from “real” work and should probably step back for a minute :no_mouth:
3 Likes

I recall once giving the advice, “always M.RESET after you change M in script M,” and then shrugging when someone asked why. Now I remember :joy:

1 Like

Thanks a lot for taking the time to be surprised. I think your expectations align pretty well with mine, as well as your surprise.

Actually: if someone is gonna change SCENE, I think it could be very useful to work out a few scenes (simple as this one) with a clear expected behavior, and drive the development with tests against these scenes!

EDIT: The plot thickens

PRM 1/2

#1
Z 1

#2
X 1
PARAM.SCALE 0 1
IF || ! PRM % T 4: BRK
SCENE + SCENE PRM; $ 10; BRK
C 1

#3
TR.P 1

#4
IF ! % T 4: TR.P 2
D 1

#5
TR.P 3

#M
Y % T 4
L 1 4: $ I
T + T 1

#I
M 500; T 0; A 1
B 1


PRM 2/2

#1
Z 2

#2
X 2
PARAM.SCALE -1 0
IF || ! PRM % T 4: BRK
SCENE + SCENE PRM; $ 10; BRK
C 2

#3
TR.P 1

#4
IF ! % T 4: TR.P 2
D 2

#5
TR.P 3

#M
Y % T 4
L 1 5: $ I
T + T 1
TR.P 4

#I
M 1000; T 0; A 2; M.RESET
B 2

prm_1_2.txt (1.1 KB)
prm_2_2.txt (1.2 KB)

EDIT2: additional test in Z should make it quite clear how the current implementation works :slight_smile:

EDIT3: additional test, with different content of M…

Here’s a summary of current operation and (as far as I understand it) the (a?) proposed new operation:

This part of the proposal is causing me the most concern. I think maybe the M timer shouldn’t be disturbed unless the user chooses to do so. It seems like $ 9; M.RESET would just need to be in the calling line from the old scene, or init script of the new scene (presuming it is called on the old scene’s line).

I don’t think the M script is special in this regard. It’s probably more noticeable because you are in a situation where M is calling your scene-changing script and therefore both M and that script are incomplete when the scene changes.

A lot of the possible scene-switching will happen asynchronously (i.e. externally triggered). Hence my wariness about any adjustment of timers or metros…

Cool. Could you formulate a proposed new operation, then?

:heavy_plus_sign:

  • do not execute remaining lines of previously-active scripts in new scene

Cool! Could you also modify the PRM scenes to work with this imaginary implementation?

We want to make sure it’s possible to mimic current behavior + it would be awesome to have a test driven coding sprint on this one…

Sorry, I haven’t reviewed the PRM scripts and I’m away from my Teletype. Can you summarize the unexpected outcome here?

Nothing is unexpected in those two. When/if you have the time, throw them unto the teletype, it’ll all make sense!!!

I thought we were specifically looking to drop the “execute remaining lines of previously-active scripts when arriving in new scene” current behavior?

The “see for yourself” approach is fine but I’d like to give this some thought today and I am many, many hours from accessing my synth. Can you just tell me whether the BRK in script 2 line 4 actually prevents line 5 from executing in either scene?