Over the weekend I regained my broadband connection, having lost it for three to four weeks. Boy! What a lot of posts were on the Apple discussion forums for DVD Studio Pro when I looked there!
One that struck me as worthy of a detailed reply was asking about setting up random playback of all of the stories in the project, not repeating any of them. The user had 16 stories and was using DVDSP v4 (which made life easier).
When you do this kind of scripting, you need to do two things. First off, you’ll have to partition a memory register so that all of your clips can be ‘stored’ in either a played or unplayed state. Secondly, you’ll need to track which have played and/or keep track of how many have played.
I chose to build a system which did all of that.
The way I did it (being one of several methods) was as follows. Firstly, each story needs a pre-script which sets a value into your partitioned register at the appropriate bit slot. Secondly, the pre-script needs to add ‘1’ to another register so that we can track the number of times a story has played.
If the partitioned register has 16 slots in it, they can each be named something unique. For ease, I suggested a system that uses ‘Story1play’, changing the number to reflect the number of the story each time. Now, when story4 plays, the fourth slot in the partitioned register will get a ‘1’ instead of being a ‘0’… and so on. The pre-scripts on the stories look like this:
mov Story1Play, 1 add GPRM2, 1 exit prescript
Now, we are ready to create the random number generator and all of the code to determine if a story has already played. We can also add a line to see if there have been 16 stories played (as a kind of ‘belt and braces’ approach). To start with, you don’t want to get stuck in a loop for too long, so make the first line the one that checks to see if 16 stories have played, if they have, jump out to a menu. If not, generate a random number:
Jump Menu_out If(GPRM2 = 16) ran GPRM0, 65535 mod GPRM0, 16
OK- those three lines are pretty important – the random number is generated up to the maximum a 16 bit register can hold. You then apply a modulo operation in order to get a number we can use that relates to the 16 possible register slots. Modulo returns values starting at zero – so a mod of 16 should give us 0-15 as a result.
Now we have the random number in GPRM0, and GPRM2 is tracking the number of stories played (so far, none have, so it should be at 0 too). We can now set up the possible operations to take place. The idea here is to create 16 versions of the same thing, so we can simply repeat blocks of code and change the numbers each time.
In order to check to see if the story has already played back we have to first see what value is held in the bit slot. It should be a zero if the story hasn’t played yet, and a ‘1’ if it has. However, in order for this script to work we need to copy the value into a temporary location, otherwise we could break the script. We copy it to GPRM1:
mov GPRM1, Story1Play Jump Story1 If(GPRM1 = 0)
These two lines move the value into GPRM1, then jump to the story *only* if that value is zero. If it is not zero, the story must already have played (because the pre-script will have changed the value to a 1) and so the jump to the story will not take place. If that’s the case, we need to make a new random number:
OK, so far, so good. We now need to repeat that over sixteen times, and then add in the correct number of ‘goto’ commands so that when the script runs from the top, if the random number is 14, you go to the 14th section and do that bit, skipping over all of the other possibilities. Don’t forget that each section is a repeat of the first one, but with the relevant number for the story and the bit slot. Putting all this together, the random script now looks like this:
Jump menu_out If (GPRM2 = 16) ran GPRM0, 65535 mod GPRM0, 16 goto 20 If(GPRM0 = 0) goto 23 If(GPRM0 = 1) goto 26 If(GPRM0 = 2) goto 29 If(GPRM0 = 3) goto 32 If(GPRM0 = 4) goto 35 If(GPRM0 = 5) goto 38 If(GPRM0 = 6) goto 41 If(GPRM0 = 7) goto 44 If(GPRM0 = 8 ) goto 47 If(GPRM0 = 9) goto 50 If(GPRM0 = 10) goto 53 If(GPRM0 = 11) goto 56 If(GPRM0 = 12) goto 59 If(GPRM0 = 13) goto 62 If(GPRM0 = 14) goto 65 If(GPRM0 = 15) mov GPRM1, Story1Play Jump Story1 If(GPRM1 = 0) goto 1 mov GPRM1, Story2Play Jump Story2 If(GPRM1 = 0) goto 1 mov GPRM1, Story3Play Jump Story3 If(GPRM1 = 0) goto 1 mov GPRM1, Story4Play Jump Story4 If(GPRM1 = 0) goto 1 mov GPRM1, Story5Play Jump Story5 If(GPRM1 = 0) goto 1 mov GPRM1, Story6Play Jump Story6 If(GPRM1 = 0) goto 1 mov GPRM1, Story7Play Jump Story7 If(GPRM1 = 0) goto 1 mov GPRM1, Story8Play Jump Story8 If(GPRM1 = 0) goto 1 mov GPRM1, Story9Play Jump Story9 If(GPRM1 = 0) goto 1 mov GPRM1, Story10Play Jump Story10 If(GPRM1 = 0) goto 1 mov GPRM1, Story11Play Jump Story11 If(GPRM1 = 0) goto 1 mov GPRM1, Story12Play Jump Story12 If(GPRM1 = 0) goto 1 mov GPRM1, Story13Play Jump Story13 If(GPRM1 = 0) goto 1 mov GPRM1, Story14Play Jump Story14 If(GPRM1 = 0) goto 1 mov GPRM1, Story15Play Jump Story15 If(GPRM1 = 0) goto 1 mov GPRM1, Story16Play Jump Story16 If(GPRM1 = 0) goto 1
Now, when you get to the ‘menu_out’ menu, the user needs to have an option to play it all over again or return to the main menu. You need to re-set ALL of the registers back to zero whatever happens. If you don’t, then the playback will fail because all of the bit slots will hold a ‘1’ and so nothing will play.
You can either do this as a pre-script to the menu, or a better way (in my opinion) would be to set the ‘play it again’ button to go to a script which clears all registers (all sixteen bit slots in the register you partitioned, GPRM0, 1 and 2) and then goes on to the randomiser script.
The end jump of the stories needs to point to the randomiser script as well, otherwise when the story has played back another won’t follow on. The menu call and title call can go to a menu as normal, except you need to think about why a user would have opted out of the playback. You can either place a ‘resume’ button on the menu they land on or you can exit the random playback by again going to the script to re-set the registers and on to another destination. The resume feature will return you to the track with the stories in, and *should* continue where you left off – all register values will be intact, so it should still work. The only question I have about that is whether the resume will put you back in a story or not. If you are not in a story then you could end up simply moving through the track in sequence. That’ll need to be tested to see what happens… I’ve not done that bit yet!
So there you are – random playback of 16 stories, with no repeats.
There are other ways to do this too – but this seems to be an easy way to visualise what needs to happen. I’ll add this project to my .mac space when I get a chance and link to it from here as well.