Random playback, DVD Studio Pro scripting, random play all no repeat

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:

goto 1

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.

Happy scripting!

15 thoughts on “Random playback, DVD Studio Pro scripting, random play all no repeat

  • 14 March, 2008 at 1:26 pm
    Permalink

    Hi Hal,

    Thanks for your very helpful tutorials. This one, however, is stumping me. It may be that I don’t have a programmer’s mind. You mentioned that you’d add this as a project to your .mac space if you had time. I wouldn’t expect you to have all 16 movie files played randomly, 3 would be plenty.

    Many thanks,
    Mark

  • 15 March, 2008 at 10:53 pm
    Permalink

    Hi Mark – don’t forget that this script is for stories and not tracks. If you were only doing this with three clips then I’d approach it in a different way – after all, there are only so many variations you can get with three!

    The second thing to consider is to let the user choose the payback order themselves – have a video jukebox. The script I made available for that has been around a long time now, but there are various versions too. This might be a step too far right now, of course.

    So, in your situation I’d be tempted not to script this too extensively, but to use a different mechanism – if your clips are reasonably short put them in a single track one after the other and add markers between them, use stories to hold the different combinations of playback (i.e. track, 1, 2, 3 would be one story, track 1, 3, 2 would be another story, track 2, 3, 1 would be a third story and so on) and then jump to one of the stories each time (much more simple than using the above script). By my reckoning, you would need six stories with the clips in the following orders:

    1 2 3
    1 3 2
    2 3 1
    2 1 3
    3 1 2
    3 2 1

    To set this up is a piece of cake then… use a single track, set three markers between the clips and then simply add six stories. Add the markers in the orders above (yes, you can add them in any order, and even repeat them if you need to) and then you have got just six possible combinations. Now create a single script and point the ‘random playback’ button to this script:

    ran GPRM0, 65535
    mod GPRM0, 6
    Jump story1 If (GPRMO = 0)
    Jump story2 If (GPRMO = 1)
    Jump story3 If (GPRMO = 2)
    Jump story4 If (GPRMO = 3)
    Jump story5 If (GPRMO = 4)
    Jump story6 If (GPRMO = 5)

    Now, set the end jump of each story to go to the menu again, and also set the menu call to go there as well.

    You can still play the clips one at a time, by adding three more stories with one chapter in each and pointing to those.

    The beauty of this is that you won’t have more than three clips in the single track, as stories are simply like play lists. Also, this has got to be easier than setting up a random play engine for just three clips.

    Just to try it out, I’ve made a sample project for you which you can download by clicking here. Let me know if it is what you needed.

  • 20 March, 2008 at 4:07 am
    Permalink

    Hi Hal,

    Thanks for the sample project. It looks like a better way of having a random play than what I was trying to achieve.

    I was getting Tracks and Stories confused and it took me a while to understand that each GPRM had the ability to have up to 16 partitions. I did, however, work it out in the end and have my own sample project based on your teachings that uses Tracks instead of Stories that you can download from here…

    http://www.clockworkbeehive.com/samples/random_no_repeat.zip

    I hope this can help other people who are faced with the same problem.

    Mark

  • 25 July, 2008 at 2:59 pm
    Permalink

    Hey guys…

    Hopefully you’re still tracking this thread… I am about to tackle my own dvd project in which I have 18 items I want to shuffle when played. I’m a total newbie to DVD Studio Pro but fairly familiar with other apps that it’s not seeming too overwhelming yet… But I’m wondering if you guys might suggest which might be the better approach given I’m beyond the 16 that Hal’s script explains. I see you suggest it can be expanded, but I wonder, am I better off with Mark’s method given I’m over the 16? Is it just a bit cleaner? I’m just wondering who’s suggestion I should begin investing my time trying to understand.

    Any help is greatly appreciated.

    -Rolyn

  • 25 August, 2008 at 3:34 am
    Permalink

    Hi Hal,

    This post has helped me considerably in designing a script that almost makes 75 tracks play randomly with no repeat. However, the one thing I didn’t understand and execute was setting up the mod of 16, since I needed to randomize 75 numbers.

    The script I set up, has partitions for each of the 75 potential videos, and instead of:
    Jump Menu_out If(GPRM2 = 16)
    ran GPRM0, 65535
    mod GPRM0, 16

    I plainly set it to be:
    Jump Menu_out If(GPRM2 = 75)
    ran GPRM0, 75

    It’s a bear of scripting project, since I had the split the scripts up due to the line limitations, (i.e. jump to “script a” if random holder <13; jump to “script b” if random holder <25, and so on) The entire script is a bit too heavy to post here right now but long story short, it work perfectly in the Simulator, but it seems to have problems on a built DVD. Specifically, when a number is called that has previously been called, the DVD freezes up. The script for this check is exactly how you set it up.

    I’m wondering if by avoiding the mod16 line, it’s breaking the DVD . I just don’t know how to do this with 75 video tracks. I feel like I got pretty close to making this thing work, at least within DVD Studio Pro. Any help would be appreciated.

    Thanks Hal!

  • 25 August, 2008 at 5:03 pm
    Permalink

    Hi Dave – the mod command is part of a set of commands that helps select the random number, and if you keep it you need to change it to read:

    Jump Menu_out If(GPRM2 = 75)
    ran GPRM0, 65535
    mod GPRM0, 75

    This will give you a value from 0 to 74. If you use the ran function you will get 1 to 75, but you will find it less random than you expect, which is why I use the system that I use.

    It’s been a while since I wrote this set of scripts out, and I think now I would advise using a different system. This one still works, mind you, but I have refined it somewhat, done away with pre-scripts (which cause other issues) and now use a lot of bitshifting and binary maths which saves heaps of lines of code. The maths gets more intense, but the scripts get far shorter and there is no need to partition the registers from inside DVDSP.

    I am intrigued as to why your playback isn’t running correctly if the same number is chosen twice and a new random number is selected. I also think we can remove the need to move a value into GPRM1 and simply check the correct partition, so this bit:

    mov GPRM1, Story1Play
    Jump Story1 If(GPRM1 = 0)

    could easily become like this:

    Jump Story1 If(Story1Play = 0)

    Obviously it needs to change for each story/track that you are using.

    The first thing to try is to put the mod command back in place as I have it above and check payback then. If that doesn’t work then we need to work from a different angle.

  • 25 August, 2008 at 9:27 pm
    Permalink

    Dave, have a look at the following too – it shows the process for doing this with 40 clips but I must stress that it is theoretical. I haven’t had a chance to build this and test it. What I’ve one is go through using a tougher lot of maths, but a shorter set of scripts:

    http://www.dvdstudiopro.co.uk/scripting-advanced-random-playback/

  • 30 August, 2008 at 5:07 pm
    Permalink

    Hi Hal,

    Thanks for you help. I changed the script with mod75, and it seems to be playing fine now after burn.

    I’m still perplexed why it played fine in simulator, after build (I retested the script from the VideoTS folder directly from my drive again), but not completely working directly from a DVD disc. I thought it had to do with the prescripts. But it works for now so I’ll live with the crazy code.

    Thanks again!

  • 5 September, 2008 at 9:49 pm
    Permalink

    No problem – glad it helped and you’ve got it sorted 🙂

  • 10 December, 2008 at 5:56 pm
    Permalink

    Hey guys,

    I really need a script like this, except I don’t know how to create the scripts. Is this one script or three different ones? I have only done basic scripts like pay random and things like that so I’m not sure how this would look once in the build. Any hints would be great.

    cheers

    Justin

  • 18 December, 2008 at 8:49 am
    Permalink

    Hi – this is not a single script, no… more like a script for each story (setting the flag to say whether it has played or not) and a master script to control playback. The master script is called from the menu button, generates the random number, checks to see if the resulting clip has played and if not, plays the clip. At the end of the clip (story) you go to a script which sets the flag to say it has been played and increments the counter to keep track of how many have played.

    This system is OK, but it is a basic way of doing the job. There are far shorter scripting solutions which you might want to use, however this really gives you a basic grounding in the logic behind the script. The shorter scripts assume more prior knowledge and can be confusing if you’ve not scripted much before.

  • 7 February, 2010 at 2:59 pm
    Permalink

    And what should I do If I would like the same but with 99 tracks?
    What should i implement?

    Many thanks!!

    marie

  • 7 February, 2010 at 10:58 pm
    Permalink

    Marie – you will need to use 7 of your eight GPRMs just to have 99 slots available, but using this method you should still be OK. However, you will find that you run out of commands in your scripts as you repeat the ‘Jump’ sections.

    The way around this is to make the very last command a jump to another script, where you simply continue the Jump statements. Your ‘Goto’ commands have to be pointed to the first line of the first script in the series.

    You have to make sure the first line ‘If’ statement is for ’99’ and not ’16’, and make sure that in line 3 you change the mod to ’99’.

    The final thought I have is that this system really will take ages to play through the last available clips as more and more are played, the constant referral back to create a random number will result in multiple duplicates of the ‘used’ numbers. This will slow things down and ultimately take a very long time to get to the 99th possible clip. To get around this I would probably use a different system, one that picks random numbers from set ranges… however DVDSP won’t allow you access to more than 8 GPRMs, and thus you won’t be able to achieve what you want unless we re-think the code.

    When you start to create random playback systems that don’t repeat you need to keep track of what has played. The above system was only ever designed for low numbers of clips, and to go much beyond it would require some different logic. For example, if you want to choose groups of 16 clips at a time, and randomise the playback within those sets until everything in the set has played, you can then move on to set 2, 3, 4 and so on until you get to set 7 (which will only have 3 clips in it). You can then re-use the same GPRM to keep track of what is playing, plus another GPRM to keep track of which set has played. The randomiser should be used to select the sets, and then the clip number in the set. You play 16 clips before randomly selecting another of the sets that has not played, and then the clips in that set. Repeating this until you’ve played all of the clips is reasonably simple, and you can effect 99 clips playing back randomly with about 3 or 4 GPRMs at the most (I think). A real benefit of doing it differently like this is that you won’t need nearly as many scripts, certainly no pre-scripts and the resulting playback should be quicker.

    You will realise of course that this is not a true random playback, and that you would do well to use stories to hold groups of markers from your tracks.. which means you can’t have 99 tracks and some additional stories. My advice would be to use less tracks and more stories – remember, you can have 99 markers in a track and 99 tracks and stories. Putting groups of markers from one track into stories, and randomly selecting the story group, then the marker number in the story group will be one way to achieve all of this.

Comments are closed.