Convert ISO639 codes to Decimal, DVD Studio Pro Language settings, SPRM0 values

Have you ever wanted to know what the language codes are for a DVD? They are held as a decimal number in SPRM0 and you can use this value in lots of ways.

For example, knowing the setting for the language code in a DVD player means that you can force your DVD to start up in that language. However, knowing the values your authoring app uses for language codes is also valuable.

Working in DVD Studio Pro it is easy enough to change the simulation preferences to display a different language for the project. You can then examine that value when the simulation takes place, but given the sheer number of different languages it would take someone with the patience of a saint to switch all of the preferences one at a time and then see what the values were.

If you use an application like Haxor (Mac only), you can easily convert ASCII to decimal… but only one at a time. Equally frustrating as a job, and also not converting them to the values that DVDs use.

So I talked with Alex Blanc at Ultralab and he wrote a PHP script to do the job – I supplied the text file with the language codes in ASCII characters, and we were able to export a comma separated list which went in to Excel.

Now, for whatever reason, DVD Studio Pro (and DVD Lab Pro on a PC, and probably ALL authoring apps) add 8224 to the decimal value of the letters. Why? I have no idea!

It was a simple matter to have Excel add that value to every entry and then output the necessary numbers.

OK – I’ll agree with you – not a fantastic market for this piece of knowledge, but all the same it’s another piece of the jigsaw for those wanting to fill in the gaps.

Download the resulting file (in pdf format) here.

DVD Studio Pro, Play All, DVDSP scripting

I have been thinking more about how to create a ‘play all’ scenario on a DVD Studio Pro project and reduce the number of scripts to achieve it.

For those who haven’t yet got there, you can achieve a ‘Play All’ system by using stories in your project as long as your footage is all in one track. If, like lots of folk, you have several different tracks that you want to link together in a ‘Play All’ system you have to use scripts.

My advice is first of all to not use lots of tracks, it makes a lot more sense to keep everything in one place and go from there, but if you have already got it set up, this is what you need to do.

First off, understand the principle here. When a user selects ‘play all’ from your menu you need to set up a ‘flag’ so that when a track finishes the player knows that you came from the ‘play all’ button and will go to the next track in the sequence. Easy enough… set the play all button to go to the following script:

mov GPRM0, 1
Jump Track 1

I assume you have not yet used this GPRM, but if you have (and you need to keep it for that use), just choose another free one from the 8 available.

When the track finishes playing the ‘end jump’ will normally take you back to the menu. However, we need to set it to go to a script which first looks to see if the ‘play all flag’ is set. If it is then you need to go to the next track, but if not you go to the menu button for that track. Again, this is easy enough… but could get tedious to set up if you have a lot of tracks.

Here’s where it gets interesting. Imagine a menu with four buttons in a project with three tracks. Each of the first three buttons plays the relevant track, but the fourth button is the play all button. We can use the button number to help us decide if we are in a play all situation or not. Furthermore, DVD Studio Pro has a feature called ‘GPRM based button jumps’. What this means is that you can automatically insert the button number into a script to avoid using lots of script lines and ‘if’ statements. Very handy!

So now, instead of setting a simple flag when a menu button is selected, try setting every menu button to go to this script instead:

mov GPRM0, SPRM8
div GPRM0, 1024
goto 8 If(GPRM0 = 4)
mov GPRM1, 0
Jump Track 1 If(GPRM0 = 1)
Jump Track 2 If(GPRM0 = 2)
Jump Track 3 If(GPRM0 = 3)
mov GPRM1, 1
Jump Track 1

“What the heck is it doing?” I hear you ask!

OK, in this script we are using the automatic button number tracking to tell us which button you came from. SPRM8 is the system register which keeps track of which menu button has been used, and it starts at a value of 1024 for the first button, increasing in jumps of 1024 at a time. So in line 1 we place the value of the button into a register (in this case GPRM0) and then in line 2 we divide it to get single digit integers (1, 2, 3 or 4) to relate to the actual button number on the menu.

If you came from button 4 then you would jump ahead in the script to the place where GPRM1 is set to indicate this is a ‘play all’ situation – GPRM1 is set to ‘1’ and track 1 plays. However, if you are *not* in a play all situation you will have come from any other button, so reading the button number means the track attached to that button will play (this is what lines 4-7 are doing). Just to be sure, line 4 is setting GPRM1 to have no value, and this is important later on.

Now, the end jump for each track can go to a small script which looks to see if GPRM1 has a value in it. If it does, the next track plays, if not you go back to the menu and the button that you came from. For the end jump of Track 1 this will be:

Jump Track 2 If(GPRM1 = 1)
Jump MainMenu [GPRM0]

Line 1 here will take you on to the second track only if you came from the play all button (if you did then GPRM1 would be 1). If you didn’t, then line 2 kicks into action and this is where the GPRM based button jump comes in. Remember in the big script at the top where we put the button value into GPRM0? Well, it stays in there until something changes it. Nothing has changed it because we’ve only played the track, so the value is as it was. If you came from button 1 on the menu, you now go back to that button on the menu. You *could* get it to advance one button if you want so that all the viewer has to do is press ‘play’ on their handset, but I prefer to return them to where they were. It just seems more logical, somehow.

Now, the really cool stuff happens when the viewer is watching a ‘play all’ situation and wants to have a break from it. They can press the menu button again if they want to (or the pause) and they will go back to the menu. If they are very savvy DVD watchers they will know that simply pressing the menu button a second time will return them to the place they were last at – no values get changed, everything continues as normal.

However, what if they are bored with watching Track 1 in the ‘play all’ and now want to skip ahead to play ONLY Track 2? Normally, the value in GPRM0 wouldn’t get changed, Track 2 would play and then go in to Track 3! Agh! BUT… in the script above, since every menu button points to it, the value *does* get changed if the user makes a new choice… and so the ‘Play All’ is stopped! The new choice only will play and then go back to the menu.

Phew! Lots of words to describe a very simple thing – certainly easier to do than to describe. The next bit will be to see if I can reduce this still further so that in one script we can set up a play all, remove it and automatically keep track of which track has played (which means no small end jump scripts… just one master script to control it all).

Watch this space!

DVD After Edit, DVDAfterEdit

I was recently very fortunate to receive an email from Larry Applegate who is the driving force behind the DVD AfterEdit software now, having bought out Trai Forrester’s interest. Larry invited me to use the software on the projects I do and I was thrilled to be a part of this development.

Simply put, DVDAfterEdit is a ‘post-build’ editor for the mac. It takes a VIDEO_TS folder from a built DVD and gives you access to every single feature, right down to the nav pack level, and enables you to alter each piece to make the project do things the authoring application wouldn’t let you do. You can also put right any mistakes you have made, such as incorrect button navigation, re-set the region coding and so on.

However, it is FAR more powerful than that. You can essentially strip out all of the commands that your application has created and re-build them from scratch, import pieces from other projects and discs, reset the navigation for the entire disc…. and much more. Why would you do this? Well, simply put, you can streamline the way the disc plays in a player and make it far more efficient, and include features you weren’t able to include when the project was first conceived.

DVDAfterEdit comes in different versions depending on what you want to do. Arguably the best version is the ‘Mastering Edition’ which gives you complete control of writing out to DLT before sending the project to replication. The tool set is simply enormous, and you’ll get far more info from visiting the web site. Incidentally, it’s Drupal based, so should immediately feel familiar if you are a drupal fan!

I do wish Trai the very best. He is a passionate advocate of DVD and has done so very much for the world’s community of DVD authors. At times he can be controversial, but in nurturing this software from an idea into a reality he has brought about something extremely useful which hundreds of authors use, and which has been used on hundreds of thousands of commercially released DVDs… who knows – you might even have one in your collection!

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!

Creating a quiz on a DVD

Over the weekend I was checking in on the Apple forums for DVD Studio Pro when a particular question caught my eye. The gist of it is that the poster wanted to create a quiz on a DVD where the questions were drawn at random. Easy enough, I hear you say… until we got into doing it and then it turned into a ‘random, but no repeats, please’ situation.

I decided to try to build a short project which did this with just five arbitrary questions. Using DVDSP v4 made things a bit easier since I could manually partition the memory register. I chose to use a very verbose scripting method which repeated sections of code.

In essence, the script first of all added 1 to the first register (I needed to count to five to make sure only five questions were asked) and then generated a random number (using 65,355 then modulo with a value of 5). Next it jumped to various lines depending on what the final random number was.

From there, within each section, I jumped on to the actual question *if* there was no value in the partitioned register which corresponded with that question. If there was a value there it meant the question had already been asked and so it went back to generate a new random number. If there wasn’t a value there I put one in place and then jumped to the question. Cunning, huh? 🙂

Keeping track of the score was easy – I simply had to see if the first register had been filled with a value of five. If it had I needed to jump to the exit screen, where I set up a button to clear all the registers and start again.

This was all pretty good to do, and as a proof of concept worked fine. However, with a lot of questions to ask (say, 50 or more) I would need to re-think the process – for two reasons:

1) first the questions were set into menu tiles, and whilst it is unlikely, it is possible to run out of space in the menu domain, which is limited to 1GB in DVDSP.
2) the scripting in sections would be far too long and unwieldy if there were many more questions to deal with. Also the regeneration of a new random number when a repeat was found could take a long time when you get to the end of a 50 question quiz. It would be better to use a system which generated a number and then altered it (by subtracting or adding ‘1’) until a unique number was arrived at. This would save a lot of time and re-iteration of the script.

The major problem with 2) is that when the random number generated is zero (as can happen with a mod command) you can still subtract ‘1’ from it, and end up with 65535 – which to all intents and purposes is an ‘illegal’ value for the script. It would need to add or subtract within a defined range for this to work securely every time.

Finally, a quiz needs a score. This is something I didn’t build in because I ran out of time. Since I have only used three registers it would be easy enough to do, but again there are things to consider. For example, would you only score a point if you got the answer right first time? The way I set this up was to give the user a repeating chance any time they were wrong. Eventually they would get it right (by process of elimination, if not dawning realisation), and then they could still score top marks… which would be a little misleading to say the least!

Anyway, if you want to have a look at the project file and scripting – or if you just want to play the quiz in your computer’s DVD player, click here to download.

Have fun with it, and remember it was written in a simplistic way – I am always happy to hear of better, shorter methods to do things, of course.